blob: e73b67233dab1b4e66027d8a819ff3b669c32851 [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
11#include "video_capture_impl.h"
mikhal@webrtc.orge39de162011-12-27 23:45:30 +000012
andrew@webrtc.orgc1354bd2012-07-27 18:21:16 +000013#include "common_video/libyuv/include/webrtc_libyuv.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000014#include "critical_section_wrapper.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000015#include "module_common_types.h"
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000016#include "ref_count.h"
mikhal@webrtc.orge39de162011-12-27 23:45:30 +000017#include "tick_util.h"
18#include "trace.h"
19#include "video_capture_config.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000020
elham@webrtc.org5f49dba2012-04-23 21:24:02 +000021#include <stdlib.h>
22
niklase@google.com470e71d2011-07-07 08:21:25 +000023namespace webrtc
24{
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000025namespace videocapturemodule
niklase@google.com470e71d2011-07-07 08:21:25 +000026{
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000027VideoCaptureModule* VideoCaptureImpl::Create(
28 const WebRtc_Word32 id,
29 VideoCaptureExternal*& externalCapture)
30{
31 RefCountImpl<VideoCaptureImpl>* implementation =
32 new RefCountImpl<VideoCaptureImpl>(id);
niklase@google.com470e71d2011-07-07 08:21:25 +000033 externalCapture = implementation;
34 return implementation;
35}
36
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000037const char* VideoCaptureImpl::CurrentDeviceName() const
niklase@google.com470e71d2011-07-07 08:21:25 +000038{
39 return _deviceUniqueId;
40}
41
42WebRtc_Word32 VideoCaptureImpl::ChangeUniqueId(const WebRtc_Word32 id)
43{
44 _id = id;
45 return 0;
46}
47
48// returns the number of milliseconds until the module want a worker thread to call Process
49WebRtc_Word32 VideoCaptureImpl::TimeUntilNextProcess()
50{
perkj@webrtc.orgc2fde802012-08-08 14:01:09 +000051 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +000052
53 WebRtc_Word32 timeToNormalProcess = kProcessInterval
54 - (WebRtc_Word32)((TickTime::Now() - _lastProcessTime).Milliseconds());
mikhal@webrtc.org9a5b9042012-10-19 16:44:35 +000055
56 return timeToNormalProcess;
niklase@google.com470e71d2011-07-07 08:21:25 +000057}
58
59// Process any pending tasks such as timeouts
60WebRtc_Word32 VideoCaptureImpl::Process()
61{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +000062 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +000063
64 const TickTime now = TickTime::Now();
65 _lastProcessTime = TickTime::Now();
66
67 // Handle No picture alarm
68
69 if (_lastProcessFrameCount.Ticks() == _incomingFrameTimes[0].Ticks() &&
70 _captureAlarm != Raised)
71 {
72 if (_noPictureAlarmCallBack && _captureCallBack)
73 {
74 _captureAlarm = Raised;
75 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
76 }
77 }
78 else if (_lastProcessFrameCount.Ticks() != _incomingFrameTimes[0].Ticks() &&
79 _captureAlarm != Cleared)
80 {
81 if (_noPictureAlarmCallBack && _captureCallBack)
82 {
83 _captureAlarm = Cleared;
84 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
85
86 }
87 }
88
89 // Handle frame rate callback
90 if ((now - _lastFrameRateCallbackTime).Milliseconds()
91 > kFrameRateCallbackInterval)
92 {
93 if (_frameRateCallBack && _captureCallBack)
94 {
95 const WebRtc_UWord32 frameRate = CalculateFrameRate(now);
96 _captureCallBack->OnCaptureFrameRate(_id, frameRate);
97 }
98 _lastFrameRateCallbackTime = now; // Can be set by EnableFrameRateCallback
99
100 }
101
102 _lastProcessFrameCount = _incomingFrameTimes[0];
103
niklase@google.com470e71d2011-07-07 08:21:25 +0000104 return 0;
105}
106
107VideoCaptureImpl::VideoCaptureImpl(const WebRtc_Word32 id)
108 : _id(id), _deviceUniqueId(NULL), _apiCs(*CriticalSectionWrapper::CreateCriticalSection()),
109 _captureDelay(0), _requestedCapability(),
110 _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()),
111 _lastProcessTime(TickTime::Now()),
112 _lastFrameRateCallbackTime(TickTime::Now()), _frameRateCallBack(false),
113 _noPictureAlarmCallBack(false), _captureAlarm(Cleared), _setCaptureDelay(0),
mallinath@webrtc.org12984f02012-02-16 18:18:21 +0000114 _dataCallBack(NULL), _captureCallBack(NULL),
mflodman@webrtc.org29d75b32011-11-01 17:10:49 +0000115 _lastProcessFrameCount(TickTime::Now()), _rotateFrame(kRotateNone),
116 last_capture_time_(TickTime::MillisecondTimestamp())
niklase@google.com470e71d2011-07-07 08:21:25 +0000117
118{
119 _requestedCapability.width = kDefaultWidth;
120 _requestedCapability.height = kDefaultHeight;
121 _requestedCapability.maxFPS = 30;
122 _requestedCapability.rawType = kVideoI420;
123 _requestedCapability.codecType = kVideoCodecUnknown;
124 memset(_incomingFrameTimes, 0, sizeof(_incomingFrameTimes));
125}
126
127VideoCaptureImpl::~VideoCaptureImpl()
128{
129 DeRegisterCaptureDataCallback();
130 DeRegisterCaptureCallback();
131 delete &_callBackCs;
132 delete &_apiCs;
133
134 if (_deviceUniqueId)
135 delete[] _deviceUniqueId;
136}
137
138WebRtc_Word32 VideoCaptureImpl::RegisterCaptureDataCallback(
139 VideoCaptureDataCallback& dataCallBack)
140{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000141 CriticalSectionScoped cs(&_apiCs);
142 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000143 _dataCallBack = &dataCallBack;
144
145 return 0;
146}
147
148WebRtc_Word32 VideoCaptureImpl::DeRegisterCaptureDataCallback()
149{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000150 CriticalSectionScoped cs(&_apiCs);
151 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000152 _dataCallBack = NULL;
153 return 0;
154}
155WebRtc_Word32 VideoCaptureImpl::RegisterCaptureCallback(VideoCaptureFeedBack& callBack)
156{
niklase@google.com470e71d2011-07-07 08:21:25 +0000157
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000158 CriticalSectionScoped cs(&_apiCs);
159 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000160 _captureCallBack = &callBack;
161 return 0;
162}
163WebRtc_Word32 VideoCaptureImpl::DeRegisterCaptureCallback()
164{
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000166 CriticalSectionScoped cs(&_apiCs);
167 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000168 _captureCallBack = NULL;
169 return 0;
170
171}
172WebRtc_Word32 VideoCaptureImpl::SetCaptureDelay(WebRtc_Word32 delayMS)
173{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000174 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000175 _captureDelay = delayMS;
176 return 0;
177}
178WebRtc_Word32 VideoCaptureImpl::CaptureDelay()
179{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000180 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000181 return _setCaptureDelay;
182}
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000183
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000184WebRtc_Word32 VideoCaptureImpl::DeliverCapturedFrame(I420VideoFrame&
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000185 captureFrame, WebRtc_Word64 capture_time) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000186 UpdateFrameCount(); // frame count used for local frame rate callback.
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000187
188 const bool callOnCaptureDelayChanged = _setCaptureDelay != _captureDelay;
189 // Capture delay changed
190 if (_setCaptureDelay != _captureDelay) {
191 _setCaptureDelay = _captureDelay;
192 }
193
194 // Set the capture time
195 if (capture_time != 0) {
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000196 captureFrame.set_render_time_ms(capture_time);
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000197 }
198 else {
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000199 captureFrame.set_render_time_ms(TickTime::MillisecondTimestamp());
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000200 }
201
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000202 if (captureFrame.render_time_ms() == last_capture_time_) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000203 // We don't allow the same capture time for two frames, drop this one.
204 return -1;
205 }
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000206 last_capture_time_ = captureFrame.render_time_ms();
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000207
208 if (_dataCallBack) {
209 if (callOnCaptureDelayChanged) {
210 _dataCallBack->OnCaptureDelayChanged(_id, _captureDelay);
211 }
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000212 _dataCallBack->OnIncomingCapturedFrame(_id, captureFrame);
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000213 }
214
215 return 0;
216}
217
218WebRtc_Word32 VideoCaptureImpl::DeliverEncodedCapturedFrame(
mikhal@webrtc.orgac993fe2012-11-07 17:18:04 +0000219 VideoFrame& captureFrame, WebRtc_Word64 capture_time,
220 VideoCodecType codecType) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000221 UpdateFrameCount(); // frame count used for local frame rate callback.
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000222
223 const bool callOnCaptureDelayChanged = _setCaptureDelay != _captureDelay;
224 // Capture delay changed
225 if (_setCaptureDelay != _captureDelay) {
226 _setCaptureDelay = _captureDelay;
227 }
228
229 // Set the capture time
230 if (capture_time != 0) {
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000231 captureFrame.SetRenderTime(capture_time);
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000232 }
233 else {
234 captureFrame.SetRenderTime(TickTime::MillisecondTimestamp());
235 }
236
mflodman@webrtc.org29d75b32011-11-01 17:10:49 +0000237 if (captureFrame.RenderTimeMs() == last_capture_time_) {
238 // We don't allow the same capture time for two frames, drop this one.
239 return -1;
240 }
241 last_capture_time_ = captureFrame.RenderTimeMs();
242
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000243 if (_dataCallBack) {
244 if (callOnCaptureDelayChanged) {
245 _dataCallBack->OnCaptureDelayChanged(_id, _captureDelay);
246 }
mikhal@webrtc.orgac993fe2012-11-07 17:18:04 +0000247 _dataCallBack->OnIncomingCapturedEncodedFrame(_id, captureFrame, codecType);
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000248 }
249
250 return 0;
251}
252
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000253WebRtc_Word32 VideoCaptureImpl::IncomingFrame(
254 WebRtc_UWord8* videoFrame,
255 WebRtc_Word32 videoFrameLength,
256 const VideoCaptureCapability& frameInfo,
257 WebRtc_Word64 captureTime/*=0*/)
niklase@google.com470e71d2011-07-07 08:21:25 +0000258{
259 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideoCapture, _id,
260 "IncomingFrame width %d, height %d", (int) frameInfo.width,
261 (int) frameInfo.height);
262
263 TickTime startProcessTime = TickTime::Now();
264
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000265 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000266
267 const WebRtc_Word32 width = frameInfo.width;
268 const WebRtc_Word32 height = frameInfo.height;
269
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000270 if (frameInfo.codecType == kVideoCodecUnknown)
niklase@google.com470e71d2011-07-07 08:21:25 +0000271 {
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000272 // Not encoded, convert to I420.
mikhal@webrtc.orge39de162011-12-27 23:45:30 +0000273 const VideoType commonVideoType =
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000274 RawVideoTypeToCommonVideoVideoType(frameInfo.rawType);
275
276 if (frameInfo.rawType != kVideoMJPEG &&
elham@webrtc.org5f49dba2012-04-23 21:24:02 +0000277 CalcBufferSize(commonVideoType, width,
278 abs(height)) != videoFrameLength)
niklase@google.com470e71d2011-07-07 08:21:25 +0000279 {
280 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000281 "Wrong incoming frame length.");
niklase@google.com470e71d2011-07-07 08:21:25 +0000282 return -1;
283 }
284
mikhal@webrtc.org2f4ff892012-09-24 21:09:54 +0000285 // Setting absolute height (in case it was negative).
286 // In Windows, the image starts bottom left, instead of top left.
287 // Setting a negative source height, inverts the image (within LibYuv).
mikhal@webrtc.org91a03402012-10-30 19:19:32 +0000288 int stride_y = 0;
289 int stride_uv = 0;
290 Calc16ByteAlignedStride(width, &stride_y, &stride_uv);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000291 int ret = _captureFrame.CreateEmptyFrame(width, abs(height),
mikhal@webrtc.org91a03402012-10-30 19:19:32 +0000292 stride_y,
293 stride_uv, stride_uv);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000294 if (ret < 0)
295 {
296 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
297 "Failed to allocate I420 frame.");
298 return -1;
299 }
mikhal@webrtc.orga58888d2012-01-04 19:23:24 +0000300 const int conversionResult = ConvertToI420(commonVideoType,
301 videoFrame,
302 0, 0, // No cropping
303 width, height,
mflodman@webrtc.orgf3811192012-02-27 08:10:17 +0000304 videoFrameLength,
mikhal@webrtc.orga58888d2012-01-04 19:23:24 +0000305 _rotateFrame,
mikhal@webrtc.org2f4ff892012-09-24 21:09:54 +0000306 &_captureFrame);
mikhal@webrtc.org2ab104e2011-12-09 02:46:22 +0000307 if (conversionResult < 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000308 {
309 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
310 "Failed to convert capture frame from type %d to I420",
311 frameInfo.rawType);
312 return -1;
313 }
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000314 DeliverCapturedFrame(_captureFrame, captureTime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000315 }
316 else // Encoded format
317 {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000318 if (_capture_encoded_frame.CopyFrame(videoFrameLength, videoFrame) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000319 {
320 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000321 "Failed to copy captured frame of length %d",
322 static_cast<int>(videoFrameLength));
niklase@google.com470e71d2011-07-07 08:21:25 +0000323 }
mikhal@webrtc.orgac993fe2012-11-07 17:18:04 +0000324 DeliverEncodedCapturedFrame(_capture_encoded_frame, captureTime,
325 frameInfo.codecType);
niklase@google.com470e71d2011-07-07 08:21:25 +0000326 }
327
niklase@google.com470e71d2011-07-07 08:21:25 +0000328 const WebRtc_UWord32 processTime =
329 (WebRtc_UWord32)(TickTime::Now() - startProcessTime).Milliseconds();
330 if (processTime > 10) // If the process time is too long MJPG will not work well.
331 {
332 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id,
333 "Too long processing time of Incoming frame: %ums",
334 (unsigned int) processTime);
335 }
336
337 return 0;
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000338}
niklase@google.com470e71d2011-07-07 08:21:25 +0000339
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000340WebRtc_Word32 VideoCaptureImpl::IncomingFrameI420(
341 const VideoFrameI420& video_frame, WebRtc_Word64 captureTime) {
342
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000343 CriticalSectionScoped cs(&_callBackCs);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000344 int size_y = video_frame.height * video_frame.y_pitch;
mikhal@webrtc.org701567a2012-11-09 18:45:12 +0000345 int size_u = video_frame.u_pitch * ((video_frame.height + 1) / 2);
346 int size_v = video_frame.v_pitch * ((video_frame.height + 1) / 2);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000347 // TODO(mikhal): Can we use Swap here? This will do a memcpy.
348 int ret = _captureFrame.CreateFrame(size_y, video_frame.y_plane,
349 size_u, video_frame.u_plane,
350 size_v, video_frame.v_plane,
351 video_frame.width, video_frame.height,
352 video_frame.y_pitch, video_frame.u_pitch,
353 video_frame.v_pitch);
354 if (ret < 0) {
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000355 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000356 "Failed to create I420VideoFrame");
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000357 return -1;
358 }
359
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000360 DeliverCapturedFrame(_captureFrame, captureTime);
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000361
362 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000363}
364
365WebRtc_Word32 VideoCaptureImpl::SetCaptureRotation(VideoCaptureRotation rotation)
366{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000367 CriticalSectionScoped cs(&_apiCs);
368 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000369 switch (rotation)
370 {
371 case kCameraRotate0:
372 _rotateFrame = kRotateNone;
373 break;
374 case kCameraRotate90:
mikhal@webrtc.org2ab104e2011-12-09 02:46:22 +0000375 _rotateFrame = kRotate90;
niklase@google.com470e71d2011-07-07 08:21:25 +0000376 break;
377 case kCameraRotate180:
378 _rotateFrame = kRotate180;
379 break;
380 case kCameraRotate270:
mikhal@webrtc.org2ab104e2011-12-09 02:46:22 +0000381 _rotateFrame = kRotate270;
niklase@google.com470e71d2011-07-07 08:21:25 +0000382 break;
383 }
384 return 0;
385}
386
niklase@google.com470e71d2011-07-07 08:21:25 +0000387WebRtc_Word32 VideoCaptureImpl::EnableFrameRateCallback(const bool enable)
388{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000389 CriticalSectionScoped cs(&_apiCs);
390 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000391 _frameRateCallBack = enable;
392 if (enable)
393 {
394 _lastFrameRateCallbackTime = TickTime::Now();
395 }
396 return 0;
397}
398
399WebRtc_Word32 VideoCaptureImpl::EnableNoPictureAlarm(const bool enable)
400{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000401 CriticalSectionScoped cs(&_apiCs);
402 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000403 _noPictureAlarmCallBack = enable;
404 return 0;
405}
406
407void VideoCaptureImpl::UpdateFrameCount()
408{
409 if (_incomingFrameTimes[0].MicrosecondTimestamp() == 0)
410 {
411 // first no shift
412 }
413 else
414 {
415 // shift
416 for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--)
417 {
418 _incomingFrameTimes[i + 1] = _incomingFrameTimes[i];
419 }
420 }
421 _incomingFrameTimes[0] = TickTime::Now();
422}
423
424WebRtc_UWord32 VideoCaptureImpl::CalculateFrameRate(const TickTime& now)
425{
426 WebRtc_Word32 num = 0;
427 WebRtc_Word32 nrOfFrames = 0;
428 for (num = 1; num < (kFrameRateCountHistorySize - 1); num++)
429 {
430 if (_incomingFrameTimes[num].Ticks() <= 0
431 || (now - _incomingFrameTimes[num]).Milliseconds() > kFrameRateHistoryWindowMs) // don't use data older than 2sec
432 {
433 break;
434 }
435 else
436 {
437 nrOfFrames++;
438 }
439 }
440 if (num > 1)
441 {
442 WebRtc_Word64 diff = (now - _incomingFrameTimes[num - 1]).Milliseconds();
443 if (diff > 0)
444 {
445 return WebRtc_UWord32((nrOfFrames * 1000.0f / diff) + 0.5f);
446 }
447 }
448
449 return nrOfFrames;
450}
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +0000451} // namespace videocapturemodule
niklase@google.com470e71d2011-07-07 08:21:25 +0000452} // namespace webrtc