blob: 1b780c4cba6e80f34a22f0ed56a0db800c6263fc [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{
guoweis@webrtc.org1226e922015-02-11 18:37:54 +000027
28// Converting the rotation mode from capturemodule's to I420VideoFrame's define.
29VideoRotation ConvertRotation(VideoRotationMode rotation) {
30 switch (rotation) {
31 case kRotateNone:
32 return kVideoRotation_0;
33 case kRotate90:
34 return kVideoRotation_90;
35 case kRotate180:
36 return kVideoRotation_180;
37 case kRotate270:
38 return kVideoRotation_270;
39 }
40 assert(false);
41 return kVideoRotation_0;
42}
43
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000044namespace videocapturemodule
niklase@google.com470e71d2011-07-07 08:21:25 +000045{
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000046VideoCaptureModule* VideoCaptureImpl::Create(
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000047 const int32_t id,
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000048 VideoCaptureExternal*& externalCapture)
49{
50 RefCountImpl<VideoCaptureImpl>* implementation =
51 new RefCountImpl<VideoCaptureImpl>(id);
niklase@google.com470e71d2011-07-07 08:21:25 +000052 externalCapture = implementation;
53 return implementation;
54}
55
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000056const char* VideoCaptureImpl::CurrentDeviceName() const
niklase@google.com470e71d2011-07-07 08:21:25 +000057{
58 return _deviceUniqueId;
59}
60
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000061// static
62int32_t VideoCaptureImpl::RotationFromDegrees(int degrees,
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000063 VideoRotation* rotation) {
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000064 switch (degrees) {
65 case 0:
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000066 *rotation = kVideoRotation_0;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000067 return 0;
68 case 90:
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000069 *rotation = kVideoRotation_90;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000070 return 0;
71 case 180:
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000072 *rotation = kVideoRotation_180;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000073 return 0;
74 case 270:
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000075 *rotation = kVideoRotation_270;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000076 return 0;
77 default:
78 return -1;;
79 }
80}
81
82// static
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000083int32_t VideoCaptureImpl::RotationInDegrees(VideoRotation rotation,
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000084 int* degrees) {
85 switch (rotation) {
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000086 case kVideoRotation_0:
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000087 *degrees = 0;
88 return 0;
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000089 case kVideoRotation_90:
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000090 *degrees = 90;
91 return 0;
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000092 case kVideoRotation_180:
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000093 *degrees = 180;
94 return 0;
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +000095 case kVideoRotation_270:
fischman@webrtc.org4e65e072013-10-03 18:23:13 +000096 *degrees = 270;
97 return 0;
98 }
99 return -1;
100}
101
niklase@google.com470e71d2011-07-07 08:21:25 +0000102// returns the number of milliseconds until the module want a worker thread to call Process
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +0000103int64_t VideoCaptureImpl::TimeUntilNextProcess()
niklase@google.com470e71d2011-07-07 08:21:25 +0000104{
perkj@webrtc.orgc2fde802012-08-08 14:01:09 +0000105 CriticalSectionScoped cs(&_callBackCs);
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +0000106 const int64_t kProcessIntervalMs = 300;
107 return kProcessIntervalMs -
108 (TickTime::Now() - _lastProcessTime).Milliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000109}
110
111// Process any pending tasks such as timeouts
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000112int32_t VideoCaptureImpl::Process()
niklase@google.com470e71d2011-07-07 08:21:25 +0000113{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000114 CriticalSectionScoped cs(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000115
116 const TickTime now = TickTime::Now();
117 _lastProcessTime = TickTime::Now();
118
119 // Handle No picture alarm
120
121 if (_lastProcessFrameCount.Ticks() == _incomingFrameTimes[0].Ticks() &&
122 _captureAlarm != Raised)
123 {
124 if (_noPictureAlarmCallBack && _captureCallBack)
125 {
126 _captureAlarm = Raised;
127 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
128 }
129 }
130 else if (_lastProcessFrameCount.Ticks() != _incomingFrameTimes[0].Ticks() &&
131 _captureAlarm != Cleared)
132 {
133 if (_noPictureAlarmCallBack && _captureCallBack)
134 {
135 _captureAlarm = Cleared;
136 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm);
137
138 }
139 }
140
141 // Handle frame rate callback
142 if ((now - _lastFrameRateCallbackTime).Milliseconds()
143 > kFrameRateCallbackInterval)
144 {
145 if (_frameRateCallBack && _captureCallBack)
146 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000147 const uint32_t frameRate = CalculateFrameRate(now);
niklase@google.com470e71d2011-07-07 08:21:25 +0000148 _captureCallBack->OnCaptureFrameRate(_id, frameRate);
149 }
150 _lastFrameRateCallbackTime = now; // Can be set by EnableFrameRateCallback
151
152 }
153
154 _lastProcessFrameCount = _incomingFrameTimes[0];
155
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 return 0;
157}
158
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000159VideoCaptureImpl::VideoCaptureImpl(const int32_t id)
pbos@webrtc.org504af452013-07-02 10:15:43 +0000160 : _id(id),
161 _deviceUniqueId(NULL),
162 _apiCs(*CriticalSectionWrapper::CreateCriticalSection()),
163 _captureDelay(0),
164 _requestedCapability(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000165 _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()),
166 _lastProcessTime(TickTime::Now()),
pbos@webrtc.org504af452013-07-02 10:15:43 +0000167 _lastFrameRateCallbackTime(TickTime::Now()),
168 _frameRateCallBack(false),
169 _noPictureAlarmCallBack(false),
170 _captureAlarm(Cleared),
171 _setCaptureDelay(0),
172 _dataCallBack(NULL),
173 _captureCallBack(NULL),
174 _lastProcessFrameCount(TickTime::Now()),
175 _rotateFrame(kRotateNone),
pbos@webrtc.orge0536292013-10-21 09:02:30 +0000176 last_capture_time_(0),
pbos@webrtc.org504af452013-07-02 10:15:43 +0000177 delta_ntp_internal_ms_(
178 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() -
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000179 TickTime::MillisecondTimestamp()),
180 apply_rotation_(true) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000181 _requestedCapability.width = kDefaultWidth;
182 _requestedCapability.height = kDefaultHeight;
183 _requestedCapability.maxFPS = 30;
184 _requestedCapability.rawType = kVideoI420;
185 _requestedCapability.codecType = kVideoCodecUnknown;
186 memset(_incomingFrameTimes, 0, sizeof(_incomingFrameTimes));
187}
188
189VideoCaptureImpl::~VideoCaptureImpl()
190{
191 DeRegisterCaptureDataCallback();
192 DeRegisterCaptureCallback();
193 delete &_callBackCs;
194 delete &_apiCs;
195
196 if (_deviceUniqueId)
197 delete[] _deviceUniqueId;
198}
199
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000200void VideoCaptureImpl::RegisterCaptureDataCallback(
201 VideoCaptureDataCallback& dataCallBack) {
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 = &dataCallBack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000205}
206
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000207void VideoCaptureImpl::DeRegisterCaptureDataCallback() {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000208 CriticalSectionScoped cs(&_apiCs);
209 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000210 _dataCallBack = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211}
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000212void VideoCaptureImpl::RegisterCaptureCallback(VideoCaptureFeedBack& callBack) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000213
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000214 CriticalSectionScoped cs(&_apiCs);
215 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000216 _captureCallBack = &callBack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000217}
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000218void VideoCaptureImpl::DeRegisterCaptureCallback() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000219
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000220 CriticalSectionScoped cs(&_apiCs);
221 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000222 _captureCallBack = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000223}
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000224void VideoCaptureImpl::SetCaptureDelay(int32_t delayMS) {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000225 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000226 _captureDelay = delayMS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000227}
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000228int32_t VideoCaptureImpl::CaptureDelay()
niklase@google.com470e71d2011-07-07 08:21:25 +0000229{
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000230 CriticalSectionScoped cs(&_apiCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 return _setCaptureDelay;
232}
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000233
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000234int32_t VideoCaptureImpl::DeliverCapturedFrame(I420VideoFrame& captureFrame,
235 int64_t capture_time) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000236 UpdateFrameCount(); // frame count used for local frame rate callback.
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000237
238 const bool callOnCaptureDelayChanged = _setCaptureDelay != _captureDelay;
239 // Capture delay changed
240 if (_setCaptureDelay != _captureDelay) {
241 _setCaptureDelay = _captureDelay;
242 }
243
244 // Set the capture time
245 if (capture_time != 0) {
andresp@webrtc.org77bf5c22013-09-04 11:35:43 +0000246 captureFrame.set_render_time_ms(capture_time - delta_ntp_internal_ms_);
pbos@webrtc.org504af452013-07-02 10:15:43 +0000247 } else {
248 captureFrame.set_render_time_ms(TickTime::MillisecondTimestamp());
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000249 }
250
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000251 if (captureFrame.render_time_ms() == last_capture_time_) {
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000252 // We don't allow the same capture time for two frames, drop this one.
253 return -1;
254 }
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000255 last_capture_time_ = captureFrame.render_time_ms();
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000256
257 if (_dataCallBack) {
258 if (callOnCaptureDelayChanged) {
259 _dataCallBack->OnCaptureDelayChanged(_id, _captureDelay);
260 }
mikhal@webrtc.orge83d3112012-10-29 15:59:40 +0000261 _dataCallBack->OnIncomingCapturedFrame(_id, captureFrame);
mikhal@webrtc.org80f14d22012-10-11 15:03:53 +0000262 }
263
264 return 0;
265}
266
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000267int32_t VideoCaptureImpl::IncomingFrame(
268 uint8_t* videoFrame,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000269 size_t videoFrameLength,
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000270 const VideoCaptureCapability& frameInfo,
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000271 int64_t captureTime/*=0*/)
niklase@google.com470e71d2011-07-07 08:21:25 +0000272{
fischman@webrtc.org42694c52014-06-06 18:28:28 +0000273 CriticalSectionScoped cs(&_apiCs);
274 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000275
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000276 const int32_t width = frameInfo.width;
277 const int32_t height = frameInfo.height;
niklase@google.com470e71d2011-07-07 08:21:25 +0000278
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000279 TRACE_EVENT1("webrtc", "VC::IncomingFrame", "capture_time", captureTime);
280
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000281 if (frameInfo.codecType == kVideoCodecUnknown)
niklase@google.com470e71d2011-07-07 08:21:25 +0000282 {
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000283 // Not encoded, convert to I420.
mikhal@webrtc.orge39de162011-12-27 23:45:30 +0000284 const VideoType commonVideoType =
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000285 RawVideoTypeToCommonVideoVideoType(frameInfo.rawType);
286
287 if (frameInfo.rawType != kVideoMJPEG &&
elham@webrtc.org5f49dba2012-04-23 21:24:02 +0000288 CalcBufferSize(commonVideoType, width,
289 abs(height)) != videoFrameLength)
niklase@google.com470e71d2011-07-07 08:21:25 +0000290 {
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +0000291 LOG(LS_ERROR) << "Wrong incoming frame length.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000292 return -1;
293 }
294
mikhal@webrtc.org4c4d01d2012-11-21 22:18:32 +0000295 int stride_y = width;
296 int stride_uv = (width + 1) / 2;
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000297 int target_width = width;
298 int target_height = height;
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000299
300 if (apply_rotation_) {
301 // Rotating resolution when for 90/270 degree rotations.
302 if (_rotateFrame == kRotate90 || _rotateFrame == kRotate270) {
303 target_width = abs(height);
304 target_height = width;
305 }
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000306 }
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000307
mikhal@webrtc.org4c4d01d2012-11-21 22:18:32 +0000308 // TODO(mikhal): Update correct aligned stride values.
309 //Calc16ByteAlignedStride(target_width, &stride_y, &stride_uv);
mikhal@webrtc.org2f4ff892012-09-24 21:09:54 +0000310 // Setting absolute height (in case it was negative).
311 // In Windows, the image starts bottom left, instead of top left.
312 // Setting a negative source height, inverts the image (within LibYuv).
sheu@chromium.org5dd2ecb2013-10-31 23:41:04 +0000313 int ret = _captureFrame.CreateEmptyFrame(target_width,
314 abs(target_height),
315 stride_y,
316 stride_uv, stride_uv);
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000317 if (ret < 0)
318 {
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +0000319 LOG(LS_ERROR) << "Failed to create empty frame, this should only "
320 "happen due to bad parameters.";
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000321 return -1;
322 }
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000323 const int conversionResult = ConvertToI420(
324 commonVideoType, videoFrame, 0, 0, // No cropping
325 width, height, videoFrameLength,
326 apply_rotation_ ? _rotateFrame : kRotateNone,
327 &_captureFrame);
mikhal@webrtc.org2ab104e2011-12-09 02:46:22 +0000328 if (conversionResult < 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000329 {
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +0000330 LOG(LS_ERROR) << "Failed to convert capture frame from type "
331 << frameInfo.rawType << "to I420.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000332 return -1;
333 }
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000334
335 if (!apply_rotation_) {
336 _captureFrame.set_rotation(ConvertRotation(_rotateFrame));
337 } else {
338 _captureFrame.set_rotation(kVideoRotation_0);
339 }
340
sheu@chromium.org5dd2ecb2013-10-31 23:41:04 +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
niklase@google.com470e71d2011-07-07 08:21:25 +0000349 return 0;
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000350}
niklase@google.com470e71d2011-07-07 08:21:25 +0000351
pbos@webrtc.org2ffb1492013-11-22 13:10:13 +0000352int32_t VideoCaptureImpl::IncomingI420VideoFrame(I420VideoFrame* video_frame,
353 int64_t captureTime) {
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000354
fischman@webrtc.org42694c52014-06-06 18:28:28 +0000355 CriticalSectionScoped cs(&_apiCs);
356 CriticalSectionScoped cs2(&_callBackCs);
pbos@webrtc.org2ffb1492013-11-22 13:10:13 +0000357 DeliverCapturedFrame(*video_frame, captureTime);
wu@webrtc.orgf10ea312011-10-14 17:16:04 +0000358
359 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000360}
361
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +0000362int32_t VideoCaptureImpl::SetCaptureRotation(VideoRotation rotation) {
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000363 CriticalSectionScoped cs(&_apiCs);
364 CriticalSectionScoped cs2(&_callBackCs);
365 switch (rotation){
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +0000366 case kVideoRotation_0:
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000367 _rotateFrame = kRotateNone;
368 break;
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +0000369 case kVideoRotation_90:
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000370 _rotateFrame = kRotate90;
371 break;
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +0000372 case kVideoRotation_180:
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000373 _rotateFrame = kRotate180;
374 break;
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +0000375 case kVideoRotation_270:
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000376 _rotateFrame = kRotate270;
377 break;
fischman@webrtc.org4e65e072013-10-03 18:23:13 +0000378 default:
379 return -1;
mikhal@webrtc.org0f34fd72012-11-19 21:15:35 +0000380 }
381 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000382}
383
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000384void VideoCaptureImpl::EnableFrameRateCallback(const bool enable) {
mflodman@webrtc.org7845d072012-03-08 08:09:17 +0000385 CriticalSectionScoped cs(&_apiCs);
386 CriticalSectionScoped cs2(&_callBackCs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000387 _frameRateCallBack = enable;
388 if (enable)
389 {
390 _lastFrameRateCallbackTime = TickTime::Now();
391 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000392}
393
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000394bool VideoCaptureImpl::SetApplyRotation(bool enable) {
395 CriticalSectionScoped cs(&_apiCs);
396 CriticalSectionScoped cs2(&_callBackCs);
397 // The effect of this is the last caller wins.
398 apply_rotation_ = enable;
399 return true;
400}
401
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000402void VideoCaptureImpl::EnableNoPictureAlarm(const bool enable) {
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 _noPictureAlarmCallBack = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000406}
407
408void VideoCaptureImpl::UpdateFrameCount()
409{
410 if (_incomingFrameTimes[0].MicrosecondTimestamp() == 0)
411 {
412 // first no shift
413 }
414 else
415 {
416 // shift
417 for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--)
418 {
419 _incomingFrameTimes[i + 1] = _incomingFrameTimes[i];
420 }
421 }
422 _incomingFrameTimes[0] = TickTime::Now();
423}
424
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000425uint32_t VideoCaptureImpl::CalculateFrameRate(const TickTime& now)
niklase@google.com470e71d2011-07-07 08:21:25 +0000426{
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000427 int32_t num = 0;
428 int32_t nrOfFrames = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000429 for (num = 1; num < (kFrameRateCountHistorySize - 1); num++)
430 {
431 if (_incomingFrameTimes[num].Ticks() <= 0
432 || (now - _incomingFrameTimes[num]).Milliseconds() > kFrameRateHistoryWindowMs) // don't use data older than 2sec
433 {
434 break;
435 }
436 else
437 {
438 nrOfFrames++;
439 }
440 }
441 if (num > 1)
442 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000443 int64_t diff = (now - _incomingFrameTimes[num - 1]).Milliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000444 if (diff > 0)
445 {
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000446 return uint32_t((nrOfFrames * 1000.0f / diff) + 0.5f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000447 }
448 }
449
450 return nrOfFrames;
451}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000452} // namespace videocapturemodule
453} // namespace webrtc