blob: 8319a21562ec644187c36a0b56bb3406499d974f [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
tommie4f96502015-10-20 23:00:48 -070015#include "webrtc/base/trace_event.h"
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000016#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010017#include "webrtc/modules/include/module_common_types.h"
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000018#include "webrtc/modules/video_capture/video_capture_config.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010019#include "webrtc/system_wrappers/include/clock.h"
20#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
21#include "webrtc/system_wrappers/include/logging.h"
22#include "webrtc/system_wrappers/include/ref_count.h"
23#include "webrtc/system_wrappers/include/tick_util.h"
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000024
niklase@google.com470e71d2011-07-07 08:21:25 +000025namespace webrtc
26{
guoweis@webrtc.org1226e922015-02-11 18:37:54 +000027
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000028namespace videocapturemodule
niklase@google.com470e71d2011-07-07 08:21:25 +000029{
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000030VideoCaptureModule* VideoCaptureImpl::Create(
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000031 const int32_t id,
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000032 VideoCaptureExternal*& externalCapture)
33{
34 RefCountImpl<VideoCaptureImpl>* implementation =
35 new RefCountImpl<VideoCaptureImpl>(id);
niklase@google.com470e71d2011-07-07 08:21:25 +000036 externalCapture = implementation;
37 return implementation;
38}
39
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000040const char* VideoCaptureImpl::CurrentDeviceName() const
niklase@google.com470e71d2011-07-07 08:21:25 +000041{
42 return _deviceUniqueId;
43}
44
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000045// static
46int32_t VideoCaptureImpl::RotationFromDegrees(int degrees,
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000047 VideoRotation* rotation) {
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000048 switch (degrees) {
49 case 0:
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000050 *rotation = kVideoRotation_0;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000051 return 0;
52 case 90:
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000053 *rotation = kVideoRotation_90;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000054 return 0;
55 case 180:
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000056 *rotation = kVideoRotation_180;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000057 return 0;
58 case 270:
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000059 *rotation = kVideoRotation_270;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000060 return 0;
61 default:
62 return -1;;
63 }
64}
65
66// static
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000067int32_t VideoCaptureImpl::RotationInDegrees(VideoRotation rotation,
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000068 int* degrees) {
69 switch (rotation) {
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000070 case kVideoRotation_0:
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000071 *degrees = 0;
72 return 0;
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000073 case kVideoRotation_90:
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000074 *degrees = 90;
75 return 0;
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000076 case kVideoRotation_180:
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000077 *degrees = 180;
78 return 0;
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000079 case kVideoRotation_270:
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000080 *degrees = 270;
81 return 0;
82 }
83 return -1;
84}
85
niklase@google.com470e71d2011-07-07 08:21:25 +000086// returns the number of milliseconds until the module want a worker thread to call Process
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000087int64_t VideoCaptureImpl::TimeUntilNextProcess()
niklase@google.com470e71d2011-07-07 08:21:25 +000088{
perkj@webrtc.orgc2fde802012-08-08 14:01:09 +000089 CriticalSectionScoped cs(&_callBackCs);
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000090 const int64_t kProcessIntervalMs = 300;
91 return kProcessIntervalMs -
92 (TickTime::Now() - _lastProcessTime).Milliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +000093}
94
95// Process any pending tasks such as timeouts
pbosa26ac922016-02-25 04:50:01 -080096void VideoCaptureImpl::Process()
niklase@google.com470e71d2011-07-07 08:21:25 +000097{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +000098 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +000099
100 const TickTime now = TickTime::Now();
101 _lastProcessTime = TickTime::Now();
102
103 // Handle No picture alarm
104
105 if (_lastProcessFrameCount.Ticks() == _incomingFrameTimes[0].Ticks() &&
106 _captureAlarm != Raised)
107 {
108 if (_noPictureAlarmCallBack && _captureCallBack)
109 {
110 _captureAlarm = Raised;
111 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
112 }
113 }
114 else if (_lastProcessFrameCount.Ticks() != _incomingFrameTimes[0].Ticks() &&
115 _captureAlarm != Cleared)
116 {
117 if (_noPictureAlarmCallBack && _captureCallBack)
118 {
119 _captureAlarm = Cleared;
120 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
121
122 }
123 }
124
125 // Handle frame rate callback
126 if ((now - _lastFrameRateCallbackTime).Milliseconds()
127 > kFrameRateCallbackInterval)
128 {
129 if (_frameRateCallBack && _captureCallBack)
130 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000131 const uint32_t frameRate = CalculateFrameRate(now);
niklase@google.com470e71d2011-07-07 08:21:25 +0000132 _captureCallBack->OnCaptureFrameRate(_id, frameRate);
133 }
134 _lastFrameRateCallbackTime = now; // Can be set by EnableFrameRateCallback
135
136 }
137
138 _lastProcessFrameCount = _incomingFrameTimes[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000139}
140
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000141VideoCaptureImpl::VideoCaptureImpl(const int32_t id)
pbos@webrtc.org504af452013-07-02 10:15:43 +0000142 : _id(id),
143 _deviceUniqueId(NULL),
144 _apiCs(*CriticalSectionWrapper::CreateCriticalSection()),
145 _captureDelay(0),
146 _requestedCapability(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000147 _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()),
148 _lastProcessTime(TickTime::Now()),
pbos@webrtc.org504af452013-07-02 10:15:43 +0000149 _lastFrameRateCallbackTime(TickTime::Now()),
150 _frameRateCallBack(false),
151 _noPictureAlarmCallBack(false),
152 _captureAlarm(Cleared),
153 _setCaptureDelay(0),
154 _dataCallBack(NULL),
155 _captureCallBack(NULL),
156 _lastProcessFrameCount(TickTime::Now()),
guoweis@webrtc.org59140d62015-03-09 17:07:31 +0000157 _rotateFrame(kVideoRotation_0),
deadbeeff5629ad2016-03-18 11:38:26 -0700158 apply_rotation_(false) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000159 _requestedCapability.width = kDefaultWidth;
160 _requestedCapability.height = kDefaultHeight;
161 _requestedCapability.maxFPS = 30;
162 _requestedCapability.rawType = kVideoI420;
163 _requestedCapability.codecType = kVideoCodecUnknown;
164 memset(_incomingFrameTimes, 0, sizeof(_incomingFrameTimes));
165}
166
167VideoCaptureImpl::~VideoCaptureImpl()
168{
169 DeRegisterCaptureDataCallback();
170 DeRegisterCaptureCallback();
171 delete &_callBackCs;
172 delete &_apiCs;
173
174 if (_deviceUniqueId)
175 delete[] _deviceUniqueId;
176}
177
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000178void VideoCaptureImpl::RegisterCaptureDataCallback(
179 VideoCaptureDataCallback& dataCallBack) {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000180 CriticalSectionScoped cs(&_apiCs);
181 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000182 _dataCallBack = &dataCallBack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000183}
184
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000185void VideoCaptureImpl::DeRegisterCaptureDataCallback() {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000186 CriticalSectionScoped cs(&_apiCs);
187 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000188 _dataCallBack = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000189}
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000190void VideoCaptureImpl::RegisterCaptureCallback(VideoCaptureFeedBack& callBack) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000191
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000192 CriticalSectionScoped cs(&_apiCs);
193 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000194 _captureCallBack = &callBack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000196void VideoCaptureImpl::DeRegisterCaptureCallback() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000197
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000198 CriticalSectionScoped cs(&_apiCs);
199 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000200 _captureCallBack = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201}
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000202void VideoCaptureImpl::SetCaptureDelay(int32_t delayMS) {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000203 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000204 _captureDelay = delayMS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000205}
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000206int32_t VideoCaptureImpl::CaptureDelay()
niklase@google.com470e71d2011-07-07 08:21:25 +0000207{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000208 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000209 return _setCaptureDelay;
210}
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000211
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700212int32_t VideoCaptureImpl::DeliverCapturedFrame(VideoFrame& captureFrame) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000213 UpdateFrameCount(); // frame count used for local frame rate callback.
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000214
215 const bool callOnCaptureDelayChanged = _setCaptureDelay != _captureDelay;
216 // Capture delay changed
217 if (_setCaptureDelay != _captureDelay) {
218 _setCaptureDelay = _captureDelay;
219 }
220
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000221 if (_dataCallBack) {
222 if (callOnCaptureDelayChanged) {
223 _dataCallBack->OnCaptureDelayChanged(_id, _captureDelay);
224 }
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000225 _dataCallBack->OnIncomingCapturedFrame(_id, captureFrame);
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000226 }
227
228 return 0;
229}
230
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000231int32_t VideoCaptureImpl::IncomingFrame(
232 uint8_t* videoFrame,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000233 size_t videoFrameLength,
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000234 const VideoCaptureCapability& frameInfo,
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000235 int64_t captureTime/*=0*/)
niklase@google.com470e71d2011-07-07 08:21:25 +0000236{
fischman@webrtc.org42694c52014-06-06 18:28:28 +0000237 CriticalSectionScoped cs(&_apiCs);
238 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000239
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000240 const int32_t width = frameInfo.width;
241 const int32_t height = frameInfo.height;
niklase@google.com470e71d2011-07-07 08:21:25 +0000242
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000243 TRACE_EVENT1("webrtc", "VC::IncomingFrame", "capture_time", captureTime);
244
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000245 if (frameInfo.codecType == kVideoCodecUnknown)
niklase@google.com470e71d2011-07-07 08:21:25 +0000246 {
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000247 // Not encoded, convert to I420.
mikhal@webrtc.orge39de162011-12-27 23:45:30 +0000248 const VideoType commonVideoType =
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000249 RawVideoTypeToCommonVideoVideoType(frameInfo.rawType);
250
251 if (frameInfo.rawType != kVideoMJPEG &&
elham@webrtc.org5f49dba2012-04-23 21:24:02 +0000252 CalcBufferSize(commonVideoType, width,
253 abs(height)) != videoFrameLength)
niklase@google.com470e71d2011-07-07 08:21:25 +0000254 {
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +0000255 LOG(LS_ERROR) << "Wrong incoming frame length.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000256 return -1;
257 }
258
mikhal@webrtc.org4c4d01d2012-11-21 22:18:32 +0000259 int stride_y = width;
260 int stride_uv = (width + 1) / 2;
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000261 int target_width = width;
262 int target_height = height;
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000263
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700264 // SetApplyRotation doesn't take any lock. Make a local copy here.
265 bool apply_rotation = apply_rotation_;
266
267 if (apply_rotation) {
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000268 // Rotating resolution when for 90/270 degree rotations.
guoweis@webrtc.org59140d62015-03-09 17:07:31 +0000269 if (_rotateFrame == kVideoRotation_90 ||
270 _rotateFrame == kVideoRotation_270) {
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000271 target_width = abs(height);
272 target_height = width;
273 }
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000274 }
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000275
mikhal@webrtc.org4c4d01d2012-11-21 22:18:32 +0000276 // TODO(mikhal): Update correct aligned stride values.
277 //Calc16ByteAlignedStride(target_width, &stride_y, &stride_uv);
mikhal@webrtc.org2f4ff892012-09-24 21:09:54 +0000278 // Setting absolute height (in case it was negative).
279 // In Windows, the image starts bottom left, instead of top left.
280 // Setting a negative source height, inverts the image (within LibYuv).
Niels Möller739fcb92016-02-29 13:11:45 +0100281 _captureFrame.CreateEmptyFrame(target_width,
282 abs(target_height),
283 stride_y,
284 stride_uv, stride_uv);
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000285 const int conversionResult = ConvertToI420(
286 commonVideoType, videoFrame, 0, 0, // No cropping
287 width, height, videoFrameLength,
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700288 apply_rotation ? _rotateFrame : kVideoRotation_0, &_captureFrame);
mikhal@webrtc.org2ab104e2011-12-09 02:46:22 +0000289 if (conversionResult < 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000290 {
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +0000291 LOG(LS_ERROR) << "Failed to convert capture frame from type "
292 << frameInfo.rawType << "to I420.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000293 return -1;
294 }
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000295
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700296 if (!apply_rotation) {
guoweis@webrtc.org59140d62015-03-09 17:07:31 +0000297 _captureFrame.set_rotation(_rotateFrame);
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000298 } else {
299 _captureFrame.set_rotation(kVideoRotation_0);
300 }
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000301 _captureFrame.set_ntp_time_ms(captureTime);
302 _captureFrame.set_render_time_ms(TickTime::MillisecondTimestamp());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000303
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000304 DeliverCapturedFrame(_captureFrame);
niklase@google.com470e71d2011-07-07 08:21:25 +0000305 }
306 else // Encoded format
307 {
mflodman@webrtc.org3ba883f2013-06-07 13:57:57 +0000308 assert(false);
309 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310 }
311
niklase@google.com470e71d2011-07-07 08:21:25 +0000312 return 0;
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000313}
niklase@google.com470e71d2011-07-07 08:21:25 +0000314
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +0000315int32_t VideoCaptureImpl::SetCaptureRotation(VideoRotation rotation) {
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000316 CriticalSectionScoped cs(&_apiCs);
317 CriticalSectionScoped cs2(&_callBackCs);
guoweis@webrtc.org59140d62015-03-09 17:07:31 +0000318 _rotateFrame = rotation;
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000319 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320}
321
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000322void VideoCaptureImpl::EnableFrameRateCallback(const bool enable) {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000323 CriticalSectionScoped cs(&_apiCs);
324 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000325 _frameRateCallBack = enable;
326 if (enable)
327 {
328 _lastFrameRateCallbackTime = TickTime::Now();
329 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000330}
331
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000332bool VideoCaptureImpl::SetApplyRotation(bool enable) {
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700333 // We can't take any lock here as it'll cause deadlock with IncomingFrame.
334
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000335 // The effect of this is the last caller wins.
336 apply_rotation_ = enable;
337 return true;
338}
339
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000340void VideoCaptureImpl::EnableNoPictureAlarm(const bool enable) {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000341 CriticalSectionScoped cs(&_apiCs);
342 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000343 _noPictureAlarmCallBack = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000344}
345
346void VideoCaptureImpl::UpdateFrameCount()
347{
348 if (_incomingFrameTimes[0].MicrosecondTimestamp() == 0)
349 {
350 // first no shift
351 }
352 else
353 {
354 // shift
355 for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--)
356 {
357 _incomingFrameTimes[i + 1] = _incomingFrameTimes[i];
358 }
359 }
360 _incomingFrameTimes[0] = TickTime::Now();
361}
362
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000363uint32_t VideoCaptureImpl::CalculateFrameRate(const TickTime& now)
niklase@google.com470e71d2011-07-07 08:21:25 +0000364{
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000365 int32_t num = 0;
366 int32_t nrOfFrames = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000367 for (num = 1; num < (kFrameRateCountHistorySize - 1); num++)
368 {
369 if (_incomingFrameTimes[num].Ticks() <= 0
370 || (now - _incomingFrameTimes[num]).Milliseconds() > kFrameRateHistoryWindowMs) // don't use data older than 2sec
371 {
372 break;
373 }
374 else
375 {
376 nrOfFrames++;
377 }
378 }
379 if (num > 1)
380 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000381 int64_t diff = (now - _incomingFrameTimes[num - 1]).Milliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000382 if (diff > 0)
383 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000384 return uint32_t((nrOfFrames * 1000.0f / diff) + 0.5f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000385 }
386 }
387
388 return nrOfFrames;
389}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000390} // namespace videocapturemodule
391} // namespace webrtc