blob: d7a6642044de375828fa62c29923c8da835c8d7a [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mallinath@webrtc.org12984f02012-02-16 18:18:21 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000011#include "webrtc/modules/video_capture/video_capture_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
elham@webrtc.org5f49dba2012-04-23 21:24:02 +000013#include <stdlib.h>
14
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000015#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
16#include "webrtc/modules/interface/module_common_types.h"
17#include "webrtc/modules/video_capture/video_capture_config.h"
18#include "webrtc/system_wrappers/interface/clock.h"
19#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +000020#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000021#include "webrtc/system_wrappers/interface/ref_count.h"
22#include "webrtc/system_wrappers/interface/tick_util.h"
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000023#include "webrtc/system_wrappers/interface/trace_event.h"
24
niklase@google.com470e71d2011-07-07 08:21:25 +000025namespace webrtc
26{
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000027namespace videocapturemodule
niklase@google.com470e71d2011-07-07 08:21:25 +000028{
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000029VideoCaptureModule* VideoCaptureImpl::Create(
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000030 const int32_t id,
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000031 VideoCaptureExternal*& externalCapture)
32{
33 RefCountImpl<VideoCaptureImpl>* implementation =
34 new RefCountImpl<VideoCaptureImpl>(id);
niklase@google.com470e71d2011-07-07 08:21:25 +000035 externalCapture = implementation;
36 return implementation;
37}
38
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000039const char* VideoCaptureImpl::CurrentDeviceName() const
niklase@google.com470e71d2011-07-07 08:21:25 +000040{
41 return _deviceUniqueId;
42}
43
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000044// static
45int32_t VideoCaptureImpl::RotationFromDegrees(int degrees,
46 VideoCaptureRotation* rotation) {
47 switch (degrees) {
48 case 0:
49 *rotation = kCameraRotate0;
50 return 0;
51 case 90:
52 *rotation = kCameraRotate90;
53 return 0;
54 case 180:
55 *rotation = kCameraRotate180;
56 return 0;
57 case 270:
58 *rotation = kCameraRotate270;
59 return 0;
60 default:
61 return -1;;
62 }
63}
64
65// static
66int32_t VideoCaptureImpl::RotationInDegrees(VideoCaptureRotation rotation,
67 int* degrees) {
68 switch (rotation) {
69 case kCameraRotate0:
70 *degrees = 0;
71 return 0;
72 case kCameraRotate90:
73 *degrees = 90;
74 return 0;
75 case kCameraRotate180:
76 *degrees = 180;
77 return 0;
78 case kCameraRotate270:
79 *degrees = 270;
80 return 0;
81 }
82 return -1;
83}
84
niklase@google.com470e71d2011-07-07 08:21:25 +000085// returns the number of milliseconds until the module want a worker thread to call Process
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000086int64_t VideoCaptureImpl::TimeUntilNextProcess()
niklase@google.com470e71d2011-07-07 08:21:25 +000087{
perkj@webrtc.orgc2fde802012-08-08 14:01:09 +000088 CriticalSectionScoped cs(&_callBackCs);
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000089 const int64_t kProcessIntervalMs = 300;
90 return kProcessIntervalMs -
91 (TickTime::Now() - _lastProcessTime).Milliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +000092}
93
94// Process any pending tasks such as timeouts
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000095int32_t VideoCaptureImpl::Process()
niklase@google.com470e71d2011-07-07 08:21:25 +000096{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +000097 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +000098
99 const TickTime now = TickTime::Now();
100 _lastProcessTime = TickTime::Now();
101
102 // Handle No picture alarm
103
104 if (_lastProcessFrameCount.Ticks() == _incomingFrameTimes[0].Ticks() &&
105 _captureAlarm != Raised)
106 {
107 if (_noPictureAlarmCallBack && _captureCallBack)
108 {
109 _captureAlarm = Raised;
110 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
111 }
112 }
113 else if (_lastProcessFrameCount.Ticks() != _incomingFrameTimes[0].Ticks() &&
114 _captureAlarm != Cleared)
115 {
116 if (_noPictureAlarmCallBack && _captureCallBack)
117 {
118 _captureAlarm = Cleared;
119 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
120
121 }
122 }
123
124 // Handle frame rate callback
125 if ((now - _lastFrameRateCallbackTime).Milliseconds()
126 > kFrameRateCallbackInterval)
127 {
128 if (_frameRateCallBack && _captureCallBack)
129 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000130 const uint32_t frameRate = CalculateFrameRate(now);
niklase@google.com470e71d2011-07-07 08:21:25 +0000131 _captureCallBack->OnCaptureFrameRate(_id, frameRate);
132 }
133 _lastFrameRateCallbackTime = now; // Can be set by EnableFrameRateCallback
134
135 }
136
137 _lastProcessFrameCount = _incomingFrameTimes[0];
138
niklase@google.com470e71d2011-07-07 08:21:25 +0000139 return 0;
140}
141
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000142VideoCaptureImpl::VideoCaptureImpl(const int32_t id)
pbos@webrtc.org504af452013-07-02 10:15:43 +0000143 : _id(id),
144 _deviceUniqueId(NULL),
145 _apiCs(*CriticalSectionWrapper::CreateCriticalSection()),
146 _captureDelay(0),
147 _requestedCapability(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000148 _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()),
149 _lastProcessTime(TickTime::Now()),
pbos@webrtc.org504af452013-07-02 10:15:43 +0000150 _lastFrameRateCallbackTime(TickTime::Now()),
151 _frameRateCallBack(false),
152 _noPictureAlarmCallBack(false),
153 _captureAlarm(Cleared),
154 _setCaptureDelay(0),
155 _dataCallBack(NULL),
156 _captureCallBack(NULL),
157 _lastProcessFrameCount(TickTime::Now()),
158 _rotateFrame(kRotateNone),
pbos@webrtc.orge0536292013-10-21 09:02:30 +0000159 last_capture_time_(0),
pbos@webrtc.org504af452013-07-02 10:15:43 +0000160 delta_ntp_internal_ms_(
161 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() -
guoweis@webrtc.orgdc7b0222015-02-11 18:05:12 +0000162 TickTime::MillisecondTimestamp()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000163 _requestedCapability.width = kDefaultWidth;
164 _requestedCapability.height = kDefaultHeight;
165 _requestedCapability.maxFPS = 30;
166 _requestedCapability.rawType = kVideoI420;
167 _requestedCapability.codecType = kVideoCodecUnknown;
168 memset(_incomingFrameTimes, 0, sizeof(_incomingFrameTimes));
169}
170
171VideoCaptureImpl::~VideoCaptureImpl()
172{
173 DeRegisterCaptureDataCallback();
174 DeRegisterCaptureCallback();
175 delete &_callBackCs;
176 delete &_apiCs;
177
178 if (_deviceUniqueId)
179 delete[] _deviceUniqueId;
180}
181
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000182void VideoCaptureImpl::RegisterCaptureDataCallback(
183 VideoCaptureDataCallback& dataCallBack) {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000184 CriticalSectionScoped cs(&_apiCs);
185 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000186 _dataCallBack = &dataCallBack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000187}
188
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000189void VideoCaptureImpl::DeRegisterCaptureDataCallback() {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000190 CriticalSectionScoped cs(&_apiCs);
191 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000192 _dataCallBack = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000193}
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000194void VideoCaptureImpl::RegisterCaptureCallback(VideoCaptureFeedBack& callBack) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000195
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000196 CriticalSectionScoped cs(&_apiCs);
197 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000198 _captureCallBack = &callBack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000199}
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000200void VideoCaptureImpl::DeRegisterCaptureCallback() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000201
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000202 CriticalSectionScoped cs(&_apiCs);
203 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000204 _captureCallBack = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000205}
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000206void VideoCaptureImpl::SetCaptureDelay(int32_t delayMS) {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000207 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000208 _captureDelay = delayMS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000209}
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000210int32_t VideoCaptureImpl::CaptureDelay()
niklase@google.com470e71d2011-07-07 08:21:25 +0000211{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000212 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 return _setCaptureDelay;
214}
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000215
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000216int32_t VideoCaptureImpl::DeliverCapturedFrame(I420VideoFrame& captureFrame,
217 int64_t capture_time) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000218 UpdateFrameCount(); // frame count used for local frame rate callback.
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000219
220 const bool callOnCaptureDelayChanged = _setCaptureDelay != _captureDelay;
221 // Capture delay changed
222 if (_setCaptureDelay != _captureDelay) {
223 _setCaptureDelay = _captureDelay;
224 }
225
226 // Set the capture time
227 if (capture_time != 0) {
andresp@webrtc.org77bf5c22013-09-04 11:35:43 +0000228 captureFrame.set_render_time_ms(capture_time - delta_ntp_internal_ms_);
pbos@webrtc.org504af452013-07-02 10:15:43 +0000229 } else {
230 captureFrame.set_render_time_ms(TickTime::MillisecondTimestamp());
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000231 }
232
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000233 if (captureFrame.render_time_ms() == last_capture_time_) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000234 // We don't allow the same capture time for two frames, drop this one.
235 return -1;
236 }
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000237 last_capture_time_ = captureFrame.render_time_ms();
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000238
239 if (_dataCallBack) {
240 if (callOnCaptureDelayChanged) {
241 _dataCallBack->OnCaptureDelayChanged(_id, _captureDelay);
242 }
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000243 _dataCallBack->OnIncomingCapturedFrame(_id, captureFrame);
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000244 }
245
246 return 0;
247}
248
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000249int32_t VideoCaptureImpl::IncomingFrame(
250 uint8_t* videoFrame,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000251 size_t videoFrameLength,
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000252 const VideoCaptureCapability& frameInfo,
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000253 int64_t captureTime/*=0*/)
niklase@google.com470e71d2011-07-07 08:21:25 +0000254{
fischman@webrtc.org42694c52014-06-06 18:28:28 +0000255 CriticalSectionScoped cs(&_apiCs);
256 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000257
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000258 const int32_t width = frameInfo.width;
259 const int32_t height = frameInfo.height;
niklase@google.com470e71d2011-07-07 08:21:25 +0000260
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000261 TRACE_EVENT1("webrtc", "VC::IncomingFrame", "capture_time", captureTime);
262
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000263 if (frameInfo.codecType == kVideoCodecUnknown)
niklase@google.com470e71d2011-07-07 08:21:25 +0000264 {
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000265 // Not encoded, convert to I420.
mikhal@webrtc.orge39de162011-12-27 23:45:30 +0000266 const VideoType commonVideoType =
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000267 RawVideoTypeToCommonVideoVideoType(frameInfo.rawType);
268
269 if (frameInfo.rawType != kVideoMJPEG &&
elham@webrtc.org5f49dba2012-04-23 21:24:02 +0000270 CalcBufferSize(commonVideoType, width,
271 abs(height)) != videoFrameLength)
niklase@google.com470e71d2011-07-07 08:21:25 +0000272 {
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +0000273 LOG(LS_ERROR) << "Wrong incoming frame length.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000274 return -1;
275 }
276
mikhal@webrtc.org4c4d01d2012-11-21 22:18:32 +0000277 int stride_y = width;
278 int stride_uv = (width + 1) / 2;
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000279 int target_width = width;
280 int target_height = height;
guoweis@webrtc.orgdc7b0222015-02-11 18:05:12 +0000281 // Rotating resolution when for 90/270 degree rotations.
282 if (_rotateFrame == kRotate90 || _rotateFrame == kRotate270) {
283 target_width = abs(height);
284 target_height = width;
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000285 }
mikhal@webrtc.org4c4d01d2012-11-21 22:18:32 +0000286 // TODO(mikhal): Update correct aligned stride values.
287 //Calc16ByteAlignedStride(target_width, &stride_y, &stride_uv);
mikhal@webrtc.org2f4ff892012-09-24 21:09:54 +0000288 // Setting absolute height (in case it was negative).
289 // In Windows, the image starts bottom left, instead of top left.
290 // Setting a negative source height, inverts the image (within LibYuv).
sheu@chromium.org5dd2ecb2013-10-31 23:41:04 +0000291 int ret = _captureFrame.CreateEmptyFrame(target_width,
292 abs(target_height),
293 stride_y,
294 stride_uv, stride_uv);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000295 if (ret < 0)
296 {
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +0000297 LOG(LS_ERROR) << "Failed to create empty frame, this should only "
298 "happen due to bad parameters.";
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000299 return -1;
300 }
guoweis@webrtc.orgdc7b0222015-02-11 18:05:12 +0000301 const int conversionResult = ConvertToI420(commonVideoType,
302 videoFrame,
303 0, 0, // No cropping
304 width, height,
305 videoFrameLength,
306 _rotateFrame,
307 &_captureFrame);
mikhal@webrtc.org2ab104e2011-12-09 02:46:22 +0000308 if (conversionResult < 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000309 {
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +0000310 LOG(LS_ERROR) << "Failed to convert capture frame from type "
311 << frameInfo.rawType << "to I420.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000312 return -1;
313 }
sheu@chromium.org5dd2ecb2013-10-31 23:41:04 +0000314 DeliverCapturedFrame(_captureFrame, captureTime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000315 }
316 else // Encoded format
317 {
mflodman@webrtc.org3ba883f2013-06-07 13:57:57 +0000318 assert(false);
319 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320 }
321
niklase@google.com470e71d2011-07-07 08:21:25 +0000322 return 0;
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000323}
niklase@google.com470e71d2011-07-07 08:21:25 +0000324
pbos@webrtc.org2ffb1492013-11-22 13:10:13 +0000325int32_t VideoCaptureImpl::IncomingI420VideoFrame(I420VideoFrame* video_frame,
326 int64_t captureTime) {
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000327
fischman@webrtc.org42694c52014-06-06 18:28:28 +0000328 CriticalSectionScoped cs(&_apiCs);
329 CriticalSectionScoped cs2(&_callBackCs);
pbos@webrtc.org2ffb1492013-11-22 13:10:13 +0000330 DeliverCapturedFrame(*video_frame, captureTime);
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000331
332 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000333}
334
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000335int32_t VideoCaptureImpl::SetCaptureRotation(VideoCaptureRotation rotation) {
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000336 CriticalSectionScoped cs(&_apiCs);
337 CriticalSectionScoped cs2(&_callBackCs);
338 switch (rotation){
339 case kCameraRotate0:
340 _rotateFrame = kRotateNone;
341 break;
342 case kCameraRotate90:
343 _rotateFrame = kRotate90;
344 break;
345 case kCameraRotate180:
346 _rotateFrame = kRotate180;
347 break;
348 case kCameraRotate270:
349 _rotateFrame = kRotate270;
350 break;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +0000351 default:
352 return -1;
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000353 }
354 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000355}
356
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000357void VideoCaptureImpl::EnableFrameRateCallback(const bool enable) {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000358 CriticalSectionScoped cs(&_apiCs);
359 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000360 _frameRateCallBack = enable;
361 if (enable)
362 {
363 _lastFrameRateCallbackTime = TickTime::Now();
364 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000365}
366
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000367void VideoCaptureImpl::EnableNoPictureAlarm(const bool enable) {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000368 CriticalSectionScoped cs(&_apiCs);
369 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000370 _noPictureAlarmCallBack = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000371}
372
373void VideoCaptureImpl::UpdateFrameCount()
374{
375 if (_incomingFrameTimes[0].MicrosecondTimestamp() == 0)
376 {
377 // first no shift
378 }
379 else
380 {
381 // shift
382 for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--)
383 {
384 _incomingFrameTimes[i + 1] = _incomingFrameTimes[i];
385 }
386 }
387 _incomingFrameTimes[0] = TickTime::Now();
388}
389
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000390uint32_t VideoCaptureImpl::CalculateFrameRate(const TickTime& now)
niklase@google.com470e71d2011-07-07 08:21:25 +0000391{
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000392 int32_t num = 0;
393 int32_t nrOfFrames = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000394 for (num = 1; num < (kFrameRateCountHistorySize - 1); num++)
395 {
396 if (_incomingFrameTimes[num].Ticks() <= 0
397 || (now - _incomingFrameTimes[num]).Milliseconds() > kFrameRateHistoryWindowMs) // don't use data older than 2sec
398 {
399 break;
400 }
401 else
402 {
403 nrOfFrames++;
404 }
405 }
406 if (num > 1)
407 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000408 int64_t diff = (now - _incomingFrameTimes[num - 1]).Milliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000409 if (diff > 0)
410 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000411 return uint32_t((nrOfFrames * 1000.0f / diff) + 0.5f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 }
413 }
414
415 return nrOfFrames;
416}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000417} // namespace videocapturemodule
418} // namespace webrtc