blob: eb2b4aad26cca69dc9f0cf559daa9acc70bbbef4 [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"
hclam@chromium.org806dc3b2013-04-09 19:54:10 +000019#include "trace_event.h"
mikhal@webrtc.orge39de162011-12-27 23:45:30 +000020#include "video_capture_config.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000021
elham@webrtc.org5f49dba2012-04-23 21:24:02 +000022#include <stdlib.h>
23
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc
25{
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000026namespace videocapturemodule
niklase@google.com470e71d2011-07-07 08:21:25 +000027{
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000028VideoCaptureModule* VideoCaptureImpl::Create(
29 const WebRtc_Word32 id,
30 VideoCaptureExternal*& externalCapture)
31{
32 RefCountImpl<VideoCaptureImpl>* implementation =
33 new RefCountImpl<VideoCaptureImpl>(id);
niklase@google.com470e71d2011-07-07 08:21:25 +000034 externalCapture = implementation;
35 return implementation;
36}
37
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000038const char* VideoCaptureImpl::CurrentDeviceName() const
niklase@google.com470e71d2011-07-07 08:21:25 +000039{
40 return _deviceUniqueId;
41}
42
43WebRtc_Word32 VideoCaptureImpl::ChangeUniqueId(const WebRtc_Word32 id)
44{
45 _id = id;
46 return 0;
47}
48
49// returns the number of milliseconds until the module want a worker thread to call Process
50WebRtc_Word32 VideoCaptureImpl::TimeUntilNextProcess()
51{
perkj@webrtc.orgc2fde802012-08-08 14:01:09 +000052 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +000053
54 WebRtc_Word32 timeToNormalProcess = kProcessInterval
55 - (WebRtc_Word32)((TickTime::Now() - _lastProcessTime).Milliseconds());
mikhal@webrtc.org9a5b9042012-10-19 16:44:35 +000056
57 return timeToNormalProcess;
niklase@google.com470e71d2011-07-07 08:21:25 +000058}
59
60// Process any pending tasks such as timeouts
61WebRtc_Word32 VideoCaptureImpl::Process()
62{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +000063 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +000064
65 const TickTime now = TickTime::Now();
66 _lastProcessTime = TickTime::Now();
67
68 // Handle No picture alarm
69
70 if (_lastProcessFrameCount.Ticks() == _incomingFrameTimes[0].Ticks() &&
71 _captureAlarm != Raised)
72 {
73 if (_noPictureAlarmCallBack && _captureCallBack)
74 {
75 _captureAlarm = Raised;
76 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
77 }
78 }
79 else if (_lastProcessFrameCount.Ticks() != _incomingFrameTimes[0].Ticks() &&
80 _captureAlarm != Cleared)
81 {
82 if (_noPictureAlarmCallBack && _captureCallBack)
83 {
84 _captureAlarm = Cleared;
85 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
86
87 }
88 }
89
90 // Handle frame rate callback
91 if ((now - _lastFrameRateCallbackTime).Milliseconds()
92 > kFrameRateCallbackInterval)
93 {
94 if (_frameRateCallBack && _captureCallBack)
95 {
96 const WebRtc_UWord32 frameRate = CalculateFrameRate(now);
97 _captureCallBack->OnCaptureFrameRate(_id, frameRate);
98 }
99 _lastFrameRateCallbackTime = now; // Can be set by EnableFrameRateCallback
100
101 }
102
103 _lastProcessFrameCount = _incomingFrameTimes[0];
104
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 return 0;
106}
107
108VideoCaptureImpl::VideoCaptureImpl(const WebRtc_Word32 id)
109 : _id(id), _deviceUniqueId(NULL), _apiCs(*CriticalSectionWrapper::CreateCriticalSection()),
110 _captureDelay(0), _requestedCapability(),
111 _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()),
112 _lastProcessTime(TickTime::Now()),
113 _lastFrameRateCallbackTime(TickTime::Now()), _frameRateCallBack(false),
114 _noPictureAlarmCallBack(false), _captureAlarm(Cleared), _setCaptureDelay(0),
mallinath@webrtc.org12984f02012-02-16 18:18:21 +0000115 _dataCallBack(NULL), _captureCallBack(NULL),
mflodman@webrtc.org29d75b32011-11-01 17:10:49 +0000116 _lastProcessFrameCount(TickTime::Now()), _rotateFrame(kRotateNone),
117 last_capture_time_(TickTime::MillisecondTimestamp())
niklase@google.com470e71d2011-07-07 08:21:25 +0000118
119{
120 _requestedCapability.width = kDefaultWidth;
121 _requestedCapability.height = kDefaultHeight;
122 _requestedCapability.maxFPS = 30;
123 _requestedCapability.rawType = kVideoI420;
124 _requestedCapability.codecType = kVideoCodecUnknown;
125 memset(_incomingFrameTimes, 0, sizeof(_incomingFrameTimes));
126}
127
128VideoCaptureImpl::~VideoCaptureImpl()
129{
130 DeRegisterCaptureDataCallback();
131 DeRegisterCaptureCallback();
132 delete &_callBackCs;
133 delete &_apiCs;
134
135 if (_deviceUniqueId)
136 delete[] _deviceUniqueId;
137}
138
139WebRtc_Word32 VideoCaptureImpl::RegisterCaptureDataCallback(
140 VideoCaptureDataCallback& dataCallBack)
141{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000142 CriticalSectionScoped cs(&_apiCs);
143 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000144 _dataCallBack = &dataCallBack;
145
146 return 0;
147}
148
149WebRtc_Word32 VideoCaptureImpl::DeRegisterCaptureDataCallback()
150{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000151 CriticalSectionScoped cs(&_apiCs);
152 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000153 _dataCallBack = NULL;
154 return 0;
155}
156WebRtc_Word32 VideoCaptureImpl::RegisterCaptureCallback(VideoCaptureFeedBack& callBack)
157{
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000159 CriticalSectionScoped cs(&_apiCs);
160 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000161 _captureCallBack = &callBack;
162 return 0;
163}
164WebRtc_Word32 VideoCaptureImpl::DeRegisterCaptureCallback()
165{
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000167 CriticalSectionScoped cs(&_apiCs);
168 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000169 _captureCallBack = NULL;
170 return 0;
171
172}
173WebRtc_Word32 VideoCaptureImpl::SetCaptureDelay(WebRtc_Word32 delayMS)
174{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000175 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000176 _captureDelay = delayMS;
177 return 0;
178}
179WebRtc_Word32 VideoCaptureImpl::CaptureDelay()
180{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000181 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000182 return _setCaptureDelay;
183}
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000184
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000185WebRtc_Word32 VideoCaptureImpl::DeliverCapturedFrame(I420VideoFrame&
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000186 captureFrame, WebRtc_Word64 capture_time) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000187 UpdateFrameCount(); // frame count used for local frame rate callback.
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000188
189 const bool callOnCaptureDelayChanged = _setCaptureDelay != _captureDelay;
190 // Capture delay changed
191 if (_setCaptureDelay != _captureDelay) {
192 _setCaptureDelay = _captureDelay;
193 }
194
195 // Set the capture time
196 if (capture_time != 0) {
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000197 captureFrame.set_render_time_ms(capture_time);
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000198 }
199 else {
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000200 captureFrame.set_render_time_ms(TickTime::MillisecondTimestamp());
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000201 }
202
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000203 TRACE_EVENT1("webrtc", "VC::DeliverCapturedFrame",
204 "capture_time", capture_time);
205
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000206 if (captureFrame.render_time_ms() == last_capture_time_) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000207 // We don't allow the same capture time for two frames, drop this one.
208 return -1;
209 }
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000210 last_capture_time_ = captureFrame.render_time_ms();
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000211
212 if (_dataCallBack) {
213 if (callOnCaptureDelayChanged) {
214 _dataCallBack->OnCaptureDelayChanged(_id, _captureDelay);
215 }
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000216 _dataCallBack->OnIncomingCapturedFrame(_id, captureFrame);
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000217 }
218
219 return 0;
220}
221
222WebRtc_Word32 VideoCaptureImpl::DeliverEncodedCapturedFrame(
mikhal@webrtc.orgac993fe2012-11-07 17:18:04 +0000223 VideoFrame& captureFrame, WebRtc_Word64 capture_time,
224 VideoCodecType codecType) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000225 UpdateFrameCount(); // frame count used for local frame rate callback.
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000226
227 const bool callOnCaptureDelayChanged = _setCaptureDelay != _captureDelay;
228 // Capture delay changed
229 if (_setCaptureDelay != _captureDelay) {
230 _setCaptureDelay = _captureDelay;
231 }
232
233 // Set the capture time
234 if (capture_time != 0) {
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000235 captureFrame.SetRenderTime(capture_time);
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000236 }
237 else {
238 captureFrame.SetRenderTime(TickTime::MillisecondTimestamp());
239 }
240
mflodman@webrtc.org29d75b32011-11-01 17:10:49 +0000241 if (captureFrame.RenderTimeMs() == last_capture_time_) {
242 // We don't allow the same capture time for two frames, drop this one.
243 return -1;
244 }
245 last_capture_time_ = captureFrame.RenderTimeMs();
246
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000247 if (_dataCallBack) {
248 if (callOnCaptureDelayChanged) {
249 _dataCallBack->OnCaptureDelayChanged(_id, _captureDelay);
250 }
mikhal@webrtc.orgac993fe2012-11-07 17:18:04 +0000251 _dataCallBack->OnIncomingCapturedEncodedFrame(_id, captureFrame, codecType);
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000252 }
253
254 return 0;
255}
256
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000257WebRtc_Word32 VideoCaptureImpl::IncomingFrame(
258 WebRtc_UWord8* videoFrame,
259 WebRtc_Word32 videoFrameLength,
260 const VideoCaptureCapability& frameInfo,
261 WebRtc_Word64 captureTime/*=0*/)
niklase@google.com470e71d2011-07-07 08:21:25 +0000262{
263 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideoCapture, _id,
264 "IncomingFrame width %d, height %d", (int) frameInfo.width,
265 (int) frameInfo.height);
266
267 TickTime startProcessTime = TickTime::Now();
268
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000269 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000270
271 const WebRtc_Word32 width = frameInfo.width;
272 const WebRtc_Word32 height = frameInfo.height;
273
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000274 TRACE_EVENT1("webrtc", "VC::IncomingFrame", "capture_time", captureTime);
275
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000276 if (frameInfo.codecType == kVideoCodecUnknown)
niklase@google.com470e71d2011-07-07 08:21:25 +0000277 {
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000278 // Not encoded, convert to I420.
mikhal@webrtc.orge39de162011-12-27 23:45:30 +0000279 const VideoType commonVideoType =
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000280 RawVideoTypeToCommonVideoVideoType(frameInfo.rawType);
281
282 if (frameInfo.rawType != kVideoMJPEG &&
elham@webrtc.org5f49dba2012-04-23 21:24:02 +0000283 CalcBufferSize(commonVideoType, width,
284 abs(height)) != videoFrameLength)
niklase@google.com470e71d2011-07-07 08:21:25 +0000285 {
286 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000287 "Wrong incoming frame length.");
niklase@google.com470e71d2011-07-07 08:21:25 +0000288 return -1;
289 }
290
mikhal@webrtc.org4c4d01d2012-11-21 22:18:32 +0000291 int stride_y = width;
292 int stride_uv = (width + 1) / 2;
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000293 int target_width = width;
294 int target_height = height;
295 // Rotating resolution when for 90/270 degree rotations.
296 if (_rotateFrame == kRotate90 || _rotateFrame == kRotate270) {
297 target_width = abs(height);
298 target_height = width;
299 }
mikhal@webrtc.org4c4d01d2012-11-21 22:18:32 +0000300 // TODO(mikhal): Update correct aligned stride values.
301 //Calc16ByteAlignedStride(target_width, &stride_y, &stride_uv);
mikhal@webrtc.org2f4ff892012-09-24 21:09:54 +0000302 // Setting absolute height (in case it was negative).
303 // In Windows, the image starts bottom left, instead of top left.
304 // Setting a negative source height, inverts the image (within LibYuv).
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000305 int ret = _captureFrame.CreateEmptyFrame(target_width,
306 abs(target_height),
mikhal@webrtc.org91a03402012-10-30 19:19:32 +0000307 stride_y,
308 stride_uv, stride_uv);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000309 if (ret < 0)
310 {
311 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
312 "Failed to allocate I420 frame.");
313 return -1;
314 }
mikhal@webrtc.orga58888d2012-01-04 19:23:24 +0000315 const int conversionResult = ConvertToI420(commonVideoType,
316 videoFrame,
317 0, 0, // No cropping
318 width, height,
mflodman@webrtc.orgf3811192012-02-27 08:10:17 +0000319 videoFrameLength,
mikhal@webrtc.orga58888d2012-01-04 19:23:24 +0000320 _rotateFrame,
mikhal@webrtc.org2f4ff892012-09-24 21:09:54 +0000321 &_captureFrame);
mikhal@webrtc.org2ab104e2011-12-09 02:46:22 +0000322 if (conversionResult < 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000323 {
324 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
325 "Failed to convert capture frame from type %d to I420",
326 frameInfo.rawType);
327 return -1;
328 }
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000329 DeliverCapturedFrame(_captureFrame, captureTime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000330 }
331 else // Encoded format
332 {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000333 if (_capture_encoded_frame.CopyFrame(videoFrameLength, videoFrame) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000334 {
335 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000336 "Failed to copy captured frame of length %d",
337 static_cast<int>(videoFrameLength));
niklase@google.com470e71d2011-07-07 08:21:25 +0000338 }
mikhal@webrtc.orgac993fe2012-11-07 17:18:04 +0000339 DeliverEncodedCapturedFrame(_capture_encoded_frame, captureTime,
340 frameInfo.codecType);
niklase@google.com470e71d2011-07-07 08:21:25 +0000341 }
342
niklase@google.com470e71d2011-07-07 08:21:25 +0000343 const WebRtc_UWord32 processTime =
344 (WebRtc_UWord32)(TickTime::Now() - startProcessTime).Milliseconds();
345 if (processTime > 10) // If the process time is too long MJPG will not work well.
346 {
347 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id,
348 "Too long processing time of Incoming frame: %ums",
349 (unsigned int) processTime);
350 }
351
352 return 0;
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000353}
niklase@google.com470e71d2011-07-07 08:21:25 +0000354
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000355WebRtc_Word32 VideoCaptureImpl::IncomingFrameI420(
356 const VideoFrameI420& video_frame, WebRtc_Word64 captureTime) {
357
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000358 CriticalSectionScoped cs(&_callBackCs);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000359 int size_y = video_frame.height * video_frame.y_pitch;
mikhal@webrtc.org701567a2012-11-09 18:45:12 +0000360 int size_u = video_frame.u_pitch * ((video_frame.height + 1) / 2);
361 int size_v = video_frame.v_pitch * ((video_frame.height + 1) / 2);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000362 // TODO(mikhal): Can we use Swap here? This will do a memcpy.
363 int ret = _captureFrame.CreateFrame(size_y, video_frame.y_plane,
364 size_u, video_frame.u_plane,
365 size_v, video_frame.v_plane,
366 video_frame.width, video_frame.height,
367 video_frame.y_pitch, video_frame.u_pitch,
368 video_frame.v_pitch);
369 if (ret < 0) {
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000370 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000371 "Failed to create I420VideoFrame");
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000372 return -1;
373 }
374
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000375 DeliverCapturedFrame(_captureFrame, captureTime);
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000376
377 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000378}
379
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000380WebRtc_Word32 VideoCaptureImpl::SetCaptureRotation(VideoCaptureRotation
381 rotation) {
382 CriticalSectionScoped cs(&_apiCs);
383 CriticalSectionScoped cs2(&_callBackCs);
384 switch (rotation){
385 case kCameraRotate0:
386 _rotateFrame = kRotateNone;
387 break;
388 case kCameraRotate90:
389 _rotateFrame = kRotate90;
390 break;
391 case kCameraRotate180:
392 _rotateFrame = kRotate180;
393 break;
394 case kCameraRotate270:
395 _rotateFrame = kRotate270;
396 break;
397 }
398 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000399}
400
niklase@google.com470e71d2011-07-07 08:21:25 +0000401WebRtc_Word32 VideoCaptureImpl::EnableFrameRateCallback(const bool enable)
402{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000403 CriticalSectionScoped cs(&_apiCs);
404 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000405 _frameRateCallBack = enable;
406 if (enable)
407 {
408 _lastFrameRateCallbackTime = TickTime::Now();
409 }
410 return 0;
411}
412
413WebRtc_Word32 VideoCaptureImpl::EnableNoPictureAlarm(const bool enable)
414{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000415 CriticalSectionScoped cs(&_apiCs);
416 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000417 _noPictureAlarmCallBack = enable;
418 return 0;
419}
420
421void VideoCaptureImpl::UpdateFrameCount()
422{
423 if (_incomingFrameTimes[0].MicrosecondTimestamp() == 0)
424 {
425 // first no shift
426 }
427 else
428 {
429 // shift
430 for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--)
431 {
432 _incomingFrameTimes[i + 1] = _incomingFrameTimes[i];
433 }
434 }
435 _incomingFrameTimes[0] = TickTime::Now();
436}
437
438WebRtc_UWord32 VideoCaptureImpl::CalculateFrameRate(const TickTime& now)
439{
440 WebRtc_Word32 num = 0;
441 WebRtc_Word32 nrOfFrames = 0;
442 for (num = 1; num < (kFrameRateCountHistorySize - 1); num++)
443 {
444 if (_incomingFrameTimes[num].Ticks() <= 0
445 || (now - _incomingFrameTimes[num]).Milliseconds() > kFrameRateHistoryWindowMs) // don't use data older than 2sec
446 {
447 break;
448 }
449 else
450 {
451 nrOfFrames++;
452 }
453 }
454 if (num > 1)
455 {
456 WebRtc_Word64 diff = (now - _incomingFrameTimes[num - 1]).Milliseconds();
457 if (diff > 0)
458 {
459 return WebRtc_UWord32((nrOfFrames * 1000.0f / diff) + 0.5f);
460 }
461 }
462
463 return nrOfFrames;
464}
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +0000465} // namespace videocapturemodule
niklase@google.com470e71d2011-07-07 08:21:25 +0000466} // namespace webrtc