blob: f4abecb1989c5ebaeb7f2e1949879d224327854e [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"
20#include "webrtc/system_wrappers/interface/ref_count.h"
21#include "webrtc/system_wrappers/interface/tick_util.h"
22#include "webrtc/system_wrappers/interface/trace.h"
23#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
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000085int32_t VideoCaptureImpl::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000086{
87 _id = id;
88 return 0;
89}
90
91// returns the number of milliseconds until the module want a worker thread to call Process
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000092int32_t VideoCaptureImpl::TimeUntilNextProcess()
niklase@google.com470e71d2011-07-07 08:21:25 +000093{
perkj@webrtc.orgc2fde802012-08-08 14:01:09 +000094 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +000095
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000096 int32_t timeToNormalProcess = kProcessInterval
97 - (int32_t)((TickTime::Now() - _lastProcessTime).Milliseconds());
mikhal@webrtc.org9a5b9042012-10-19 16:44:35 +000098
99 return timeToNormalProcess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000100}
101
102// Process any pending tasks such as timeouts
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000103int32_t VideoCaptureImpl::Process()
niklase@google.com470e71d2011-07-07 08:21:25 +0000104{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000105 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000106
107 const TickTime now = TickTime::Now();
108 _lastProcessTime = TickTime::Now();
109
110 // Handle No picture alarm
111
112 if (_lastProcessFrameCount.Ticks() == _incomingFrameTimes[0].Ticks() &&
113 _captureAlarm != Raised)
114 {
115 if (_noPictureAlarmCallBack && _captureCallBack)
116 {
117 _captureAlarm = Raised;
118 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
119 }
120 }
121 else if (_lastProcessFrameCount.Ticks() != _incomingFrameTimes[0].Ticks() &&
122 _captureAlarm != Cleared)
123 {
124 if (_noPictureAlarmCallBack && _captureCallBack)
125 {
126 _captureAlarm = Cleared;
127 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
128
129 }
130 }
131
132 // Handle frame rate callback
133 if ((now - _lastFrameRateCallbackTime).Milliseconds()
134 > kFrameRateCallbackInterval)
135 {
136 if (_frameRateCallBack && _captureCallBack)
137 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000138 const uint32_t frameRate = CalculateFrameRate(now);
niklase@google.com470e71d2011-07-07 08:21:25 +0000139 _captureCallBack->OnCaptureFrameRate(_id, frameRate);
140 }
141 _lastFrameRateCallbackTime = now; // Can be set by EnableFrameRateCallback
142
143 }
144
145 _lastProcessFrameCount = _incomingFrameTimes[0];
146
niklase@google.com470e71d2011-07-07 08:21:25 +0000147 return 0;
148}
149
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000150VideoCaptureImpl::VideoCaptureImpl(const int32_t id)
pbos@webrtc.org504af452013-07-02 10:15:43 +0000151 : _id(id),
152 _deviceUniqueId(NULL),
153 _apiCs(*CriticalSectionWrapper::CreateCriticalSection()),
154 _captureDelay(0),
155 _requestedCapability(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()),
157 _lastProcessTime(TickTime::Now()),
pbos@webrtc.org504af452013-07-02 10:15:43 +0000158 _lastFrameRateCallbackTime(TickTime::Now()),
159 _frameRateCallBack(false),
160 _noPictureAlarmCallBack(false),
161 _captureAlarm(Cleared),
162 _setCaptureDelay(0),
163 _dataCallBack(NULL),
164 _captureCallBack(NULL),
165 _lastProcessFrameCount(TickTime::Now()),
166 _rotateFrame(kRotateNone),
167 last_capture_time_(TickTime::MillisecondTimestamp()),
168 delta_ntp_internal_ms_(
169 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() -
170 TickTime::MillisecondTimestamp()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000171 _requestedCapability.width = kDefaultWidth;
172 _requestedCapability.height = kDefaultHeight;
173 _requestedCapability.maxFPS = 30;
174 _requestedCapability.rawType = kVideoI420;
175 _requestedCapability.codecType = kVideoCodecUnknown;
176 memset(_incomingFrameTimes, 0, sizeof(_incomingFrameTimes));
177}
178
179VideoCaptureImpl::~VideoCaptureImpl()
180{
181 DeRegisterCaptureDataCallback();
182 DeRegisterCaptureCallback();
183 delete &_callBackCs;
184 delete &_apiCs;
185
186 if (_deviceUniqueId)
187 delete[] _deviceUniqueId;
188}
189
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000190int32_t VideoCaptureImpl::RegisterCaptureDataCallback(
niklase@google.com470e71d2011-07-07 08:21:25 +0000191 VideoCaptureDataCallback& dataCallBack)
192{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000193 CriticalSectionScoped cs(&_apiCs);
194 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000195 _dataCallBack = &dataCallBack;
196
197 return 0;
198}
199
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000200int32_t VideoCaptureImpl::DeRegisterCaptureDataCallback()
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 _dataCallBack = NULL;
205 return 0;
206}
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000207int32_t VideoCaptureImpl::RegisterCaptureCallback(VideoCaptureFeedBack& callBack)
niklase@google.com470e71d2011-07-07 08:21:25 +0000208{
niklase@google.com470e71d2011-07-07 08:21:25 +0000209
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000210 CriticalSectionScoped cs(&_apiCs);
211 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000212 _captureCallBack = &callBack;
213 return 0;
214}
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000215int32_t VideoCaptureImpl::DeRegisterCaptureCallback()
niklase@google.com470e71d2011-07-07 08:21:25 +0000216{
niklase@google.com470e71d2011-07-07 08:21:25 +0000217
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000218 CriticalSectionScoped cs(&_apiCs);
219 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000220 _captureCallBack = NULL;
221 return 0;
222
223}
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000224int32_t VideoCaptureImpl::SetCaptureDelay(int32_t delayMS)
niklase@google.com470e71d2011-07-07 08:21:25 +0000225{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000226 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000227 _captureDelay = delayMS;
228 return 0;
229}
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000230int32_t VideoCaptureImpl::CaptureDelay()
niklase@google.com470e71d2011-07-07 08:21:25 +0000231{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000232 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000233 return _setCaptureDelay;
234}
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000235
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000236int32_t VideoCaptureImpl::DeliverCapturedFrame(I420VideoFrame& captureFrame,
237 int64_t capture_time) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000238 UpdateFrameCount(); // frame count used for local frame rate callback.
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000239
240 const bool callOnCaptureDelayChanged = _setCaptureDelay != _captureDelay;
241 // Capture delay changed
242 if (_setCaptureDelay != _captureDelay) {
243 _setCaptureDelay = _captureDelay;
244 }
245
246 // Set the capture time
247 if (capture_time != 0) {
andresp@webrtc.org77bf5c22013-09-04 11:35:43 +0000248 captureFrame.set_render_time_ms(capture_time - delta_ntp_internal_ms_);
pbos@webrtc.org504af452013-07-02 10:15:43 +0000249 } else {
250 captureFrame.set_render_time_ms(TickTime::MillisecondTimestamp());
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000251 }
252
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000253 if (captureFrame.render_time_ms() == last_capture_time_) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000254 // We don't allow the same capture time for two frames, drop this one.
255 return -1;
256 }
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000257 last_capture_time_ = captureFrame.render_time_ms();
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000258
259 if (_dataCallBack) {
260 if (callOnCaptureDelayChanged) {
261 _dataCallBack->OnCaptureDelayChanged(_id, _captureDelay);
262 }
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000263 _dataCallBack->OnIncomingCapturedFrame(_id, captureFrame);
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000264 }
265
266 return 0;
267}
268
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000269int32_t VideoCaptureImpl::IncomingFrame(
270 uint8_t* videoFrame,
271 int32_t videoFrameLength,
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000272 const VideoCaptureCapability& frameInfo,
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000273 int64_t captureTime/*=0*/)
niklase@google.com470e71d2011-07-07 08:21:25 +0000274{
275 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideoCapture, _id,
276 "IncomingFrame width %d, height %d", (int) frameInfo.width,
277 (int) frameInfo.height);
278
279 TickTime startProcessTime = TickTime::Now();
280
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000281 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000282
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000283 const int32_t width = frameInfo.width;
284 const int32_t height = frameInfo.height;
niklase@google.com470e71d2011-07-07 08:21:25 +0000285
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000286 TRACE_EVENT1("webrtc", "VC::IncomingFrame", "capture_time", captureTime);
287
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000288 if (frameInfo.codecType == kVideoCodecUnknown)
niklase@google.com470e71d2011-07-07 08:21:25 +0000289 {
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000290 // Not encoded, convert to I420.
mikhal@webrtc.orge39de162011-12-27 23:45:30 +0000291 const VideoType commonVideoType =
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000292 RawVideoTypeToCommonVideoVideoType(frameInfo.rawType);
293
294 if (frameInfo.rawType != kVideoMJPEG &&
elham@webrtc.org5f49dba2012-04-23 21:24:02 +0000295 CalcBufferSize(commonVideoType, width,
296 abs(height)) != videoFrameLength)
niklase@google.com470e71d2011-07-07 08:21:25 +0000297 {
298 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000299 "Wrong incoming frame length.");
niklase@google.com470e71d2011-07-07 08:21:25 +0000300 return -1;
301 }
302
mikhal@webrtc.org4c4d01d2012-11-21 22:18:32 +0000303 int stride_y = width;
304 int stride_uv = (width + 1) / 2;
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000305 int target_width = width;
306 int target_height = height;
307 // Rotating resolution when for 90/270 degree rotations.
308 if (_rotateFrame == kRotate90 || _rotateFrame == kRotate270) {
309 target_width = abs(height);
310 target_height = width;
311 }
mikhal@webrtc.org4c4d01d2012-11-21 22:18:32 +0000312 // TODO(mikhal): Update correct aligned stride values.
313 //Calc16ByteAlignedStride(target_width, &stride_y, &stride_uv);
mikhal@webrtc.org2f4ff892012-09-24 21:09:54 +0000314 // Setting absolute height (in case it was negative).
315 // In Windows, the image starts bottom left, instead of top left.
316 // Setting a negative source height, inverts the image (within LibYuv).
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000317 int ret = _captureFrame.CreateEmptyFrame(target_width,
318 abs(target_height),
mikhal@webrtc.org91a03402012-10-30 19:19:32 +0000319 stride_y,
320 stride_uv, stride_uv);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000321 if (ret < 0)
322 {
323 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
324 "Failed to allocate I420 frame.");
325 return -1;
326 }
mikhal@webrtc.orga58888d2012-01-04 19:23:24 +0000327 const int conversionResult = ConvertToI420(commonVideoType,
328 videoFrame,
329 0, 0, // No cropping
330 width, height,
mflodman@webrtc.orgf3811192012-02-27 08:10:17 +0000331 videoFrameLength,
mikhal@webrtc.orga58888d2012-01-04 19:23:24 +0000332 _rotateFrame,
mikhal@webrtc.org2f4ff892012-09-24 21:09:54 +0000333 &_captureFrame);
mikhal@webrtc.org2ab104e2011-12-09 02:46:22 +0000334 if (conversionResult < 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000335 {
336 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
337 "Failed to convert capture frame from type %d to I420",
338 frameInfo.rawType);
339 return -1;
340 }
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000341 DeliverCapturedFrame(_captureFrame, captureTime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000342 }
343 else // Encoded format
344 {
mflodman@webrtc.org3ba883f2013-06-07 13:57:57 +0000345 assert(false);
346 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000347 }
348
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000349 const uint32_t processTime =
350 (uint32_t)(TickTime::Now() - startProcessTime).Milliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000351 if (processTime > 10) // If the process time is too long MJPG will not work well.
352 {
353 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id,
354 "Too long processing time of Incoming frame: %ums",
355 (unsigned int) processTime);
356 }
357
358 return 0;
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000359}
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000361int32_t VideoCaptureImpl::IncomingFrameI420(
362 const VideoFrameI420& video_frame, int64_t captureTime) {
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000363
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000364 CriticalSectionScoped cs(&_callBackCs);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000365 int size_y = video_frame.height * video_frame.y_pitch;
mikhal@webrtc.org701567a2012-11-09 18:45:12 +0000366 int size_u = video_frame.u_pitch * ((video_frame.height + 1) / 2);
367 int size_v = video_frame.v_pitch * ((video_frame.height + 1) / 2);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000368 // TODO(mikhal): Can we use Swap here? This will do a memcpy.
369 int ret = _captureFrame.CreateFrame(size_y, video_frame.y_plane,
370 size_u, video_frame.u_plane,
371 size_v, video_frame.v_plane,
372 video_frame.width, video_frame.height,
373 video_frame.y_pitch, video_frame.u_pitch,
374 video_frame.v_pitch);
375 if (ret < 0) {
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000376 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000377 "Failed to create I420VideoFrame");
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000378 return -1;
379 }
380
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000381 DeliverCapturedFrame(_captureFrame, captureTime);
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000382
383 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000384}
385
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000386int32_t VideoCaptureImpl::SetCaptureRotation(VideoCaptureRotation rotation) {
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000387 CriticalSectionScoped cs(&_apiCs);
388 CriticalSectionScoped cs2(&_callBackCs);
389 switch (rotation){
390 case kCameraRotate0:
391 _rotateFrame = kRotateNone;
392 break;
393 case kCameraRotate90:
394 _rotateFrame = kRotate90;
395 break;
396 case kCameraRotate180:
397 _rotateFrame = kRotate180;
398 break;
399 case kCameraRotate270:
400 _rotateFrame = kRotate270;
401 break;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +0000402 default:
403 return -1;
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000404 }
405 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000406}
407
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000408int32_t VideoCaptureImpl::EnableFrameRateCallback(const bool enable)
niklase@google.com470e71d2011-07-07 08:21:25 +0000409{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000410 CriticalSectionScoped cs(&_apiCs);
411 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 _frameRateCallBack = enable;
413 if (enable)
414 {
415 _lastFrameRateCallbackTime = TickTime::Now();
416 }
417 return 0;
418}
419
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000420int32_t VideoCaptureImpl::EnableNoPictureAlarm(const bool enable)
niklase@google.com470e71d2011-07-07 08:21:25 +0000421{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000422 CriticalSectionScoped cs(&_apiCs);
423 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000424 _noPictureAlarmCallBack = enable;
425 return 0;
426}
427
428void VideoCaptureImpl::UpdateFrameCount()
429{
430 if (_incomingFrameTimes[0].MicrosecondTimestamp() == 0)
431 {
432 // first no shift
433 }
434 else
435 {
436 // shift
437 for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--)
438 {
439 _incomingFrameTimes[i + 1] = _incomingFrameTimes[i];
440 }
441 }
442 _incomingFrameTimes[0] = TickTime::Now();
443}
444
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000445uint32_t VideoCaptureImpl::CalculateFrameRate(const TickTime& now)
niklase@google.com470e71d2011-07-07 08:21:25 +0000446{
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000447 int32_t num = 0;
448 int32_t nrOfFrames = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000449 for (num = 1; num < (kFrameRateCountHistorySize - 1); num++)
450 {
451 if (_incomingFrameTimes[num].Ticks() <= 0
452 || (now - _incomingFrameTimes[num]).Milliseconds() > kFrameRateHistoryWindowMs) // don't use data older than 2sec
453 {
454 break;
455 }
456 else
457 {
458 nrOfFrames++;
459 }
460 }
461 if (num > 1)
462 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000463 int64_t diff = (now - _incomingFrameTimes[num - 1]).Milliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000464 if (diff > 0)
465 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000466 return uint32_t((nrOfFrames * 1000.0f / diff) + 0.5f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000467 }
468 }
469
470 return nrOfFrames;
471}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000472} // namespace videocapturemodule
473} // namespace webrtc