1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1187c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/video_capture/video_capture_impl.h" 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stdlib.h> 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1587c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 1687c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/interface/module_common_types.h" 1787c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/video_capture/video_capture_config.h" 1887c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/clock.h" 1987c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 20fcdc5b570e11c02dde6833b9b2704316594e9f8fpbos@webrtc.org#include "webrtc/system_wrappers/interface/logging.h" 2187c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/ref_count.h" 2287c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h" 2387c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace_event.h" 2487c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace videocapturemodule 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVideoCaptureModule* VideoCaptureImpl::Create( 30f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org const int32_t id, 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VideoCaptureExternal*& externalCapture) 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RefCountImpl<VideoCaptureImpl>* implementation = 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org new RefCountImpl<VideoCaptureImpl>(id); 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org externalCapture = implementation; 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return implementation; 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst char* VideoCaptureImpl::CurrentDeviceName() const 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _deviceUniqueId; 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org// static 4581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgint32_t VideoCaptureImpl::RotationFromDegrees(int degrees, 4681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org VideoCaptureRotation* rotation) { 4781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org switch (degrees) { 4881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org case 0: 4981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org *rotation = kCameraRotate0; 5081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return 0; 5181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org case 90: 5281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org *rotation = kCameraRotate90; 5381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return 0; 5481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org case 180: 5581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org *rotation = kCameraRotate180; 5681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return 0; 5781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org case 270: 5881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org *rotation = kCameraRotate270; 5981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return 0; 6081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org default: 6181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return -1;; 6281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org } 6381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org} 6481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org 6581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org// static 6681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgint32_t VideoCaptureImpl::RotationInDegrees(VideoCaptureRotation rotation, 6781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org int* degrees) { 6881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org switch (rotation) { 6981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org case kCameraRotate0: 7081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org *degrees = 0; 7181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return 0; 7281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org case kCameraRotate90: 7381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org *degrees = 90; 7481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return 0; 7581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org case kCameraRotate180: 7681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org *degrees = 180; 7781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return 0; 7881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org case kCameraRotate270: 7981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org *degrees = 270; 8081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return 0; 8181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org } 8281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return -1; 8381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org} 8481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org 85f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureImpl::ChangeUniqueId(const int32_t id) 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id = id; 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// returns the number of milliseconds until the module want a worker thread to call Process 92f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureImpl::TimeUntilNextProcess() 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_callBackCs); 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 96f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org int32_t timeToNormalProcess = kProcessInterval 97f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org - (int32_t)((TickTime::Now() - _lastProcessTime).Milliseconds()); 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return timeToNormalProcess; 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Process any pending tasks such as timeouts 103f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureImpl::Process() 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_callBackCs); 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const TickTime now = TickTime::Now(); 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastProcessTime = TickTime::Now(); 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Handle No picture alarm 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_lastProcessFrameCount.Ticks() == _incomingFrameTimes[0].Ticks() && 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureAlarm != Raised) 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_noPictureAlarmCallBack && _captureCallBack) 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureAlarm = Raised; 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm); 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (_lastProcessFrameCount.Ticks() != _incomingFrameTimes[0].Ticks() && 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureAlarm != Cleared) 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_noPictureAlarmCallBack && _captureCallBack) 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureAlarm = Cleared; 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm); 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Handle frame rate callback 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((now - _lastFrameRateCallbackTime).Milliseconds() 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org > kFrameRateCallbackInterval) 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_frameRateCallBack && _captureCallBack) 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 138f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org const uint32_t frameRate = CalculateFrameRate(now); 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCallBack->OnCaptureFrameRate(_id, frameRate); 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastFrameRateCallbackTime = now; // Can be set by EnableFrameRateCallback 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastProcessFrameCount = _incomingFrameTimes[0]; 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 150f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgVideoCaptureImpl::VideoCaptureImpl(const int32_t id) 1515cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org : _id(id), 1525cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _deviceUniqueId(NULL), 1535cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _apiCs(*CriticalSectionWrapper::CreateCriticalSection()), 1545cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _captureDelay(0), 1555cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _requestedCapability(), 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()), 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastProcessTime(TickTime::Now()), 1585cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _lastFrameRateCallbackTime(TickTime::Now()), 1595cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _frameRateCallBack(false), 1605cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _noPictureAlarmCallBack(false), 1615cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _captureAlarm(Cleared), 1625cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _setCaptureDelay(0), 1635cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _dataCallBack(NULL), 1645cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _captureCallBack(NULL), 1655cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _lastProcessFrameCount(TickTime::Now()), 1665cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org _rotateFrame(kRotateNone), 167c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org last_capture_time_(0), 1685cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org delta_ntp_internal_ms_( 1695cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() - 1705cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org TickTime::MillisecondTimestamp()) { 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _requestedCapability.width = kDefaultWidth; 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _requestedCapability.height = kDefaultHeight; 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _requestedCapability.maxFPS = 30; 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _requestedCapability.rawType = kVideoI420; 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _requestedCapability.codecType = kVideoCodecUnknown; 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(_incomingFrameTimes, 0, sizeof(_incomingFrameTimes)); 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVideoCaptureImpl::~VideoCaptureImpl() 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DeRegisterCaptureDataCallback(); 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DeRegisterCaptureCallback(); 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete &_callBackCs; 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete &_apiCs; 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_deviceUniqueId) 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete[] _deviceUniqueId; 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1907dc751458e1d5a3576065763737480e5f3f5a15bmallinath@webrtc.orgvoid VideoCaptureImpl::RegisterCaptureDataCallback( 1917dc751458e1d5a3576065763737480e5f3f5a15bmallinath@webrtc.org VideoCaptureDataCallback& dataCallBack) { 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_apiCs); 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs2(&_callBackCs); 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _dataCallBack = &dataCallBack; 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1977dc751458e1d5a3576065763737480e5f3f5a15bmallinath@webrtc.orgvoid VideoCaptureImpl::DeRegisterCaptureDataCallback() { 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_apiCs); 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs2(&_callBackCs); 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _dataCallBack = NULL; 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2027dc751458e1d5a3576065763737480e5f3f5a15bmallinath@webrtc.orgvoid VideoCaptureImpl::RegisterCaptureCallback(VideoCaptureFeedBack& callBack) { 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_apiCs); 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs2(&_callBackCs); 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCallBack = &callBack; 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2087dc751458e1d5a3576065763737480e5f3f5a15bmallinath@webrtc.orgvoid VideoCaptureImpl::DeRegisterCaptureCallback() { 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_apiCs); 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs2(&_callBackCs); 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCallBack = NULL; 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2147dc751458e1d5a3576065763737480e5f3f5a15bmallinath@webrtc.orgvoid VideoCaptureImpl::SetCaptureDelay(int32_t delayMS) { 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_apiCs); 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureDelay = delayMS; 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 218f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureImpl::CaptureDelay() 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_apiCs); 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _setCaptureDelay; 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 224f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureImpl::DeliverCapturedFrame(I420VideoFrame& captureFrame, 225f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org int64_t capture_time) { 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UpdateFrameCount(); // frame count used for local frame rate callback. 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const bool callOnCaptureDelayChanged = _setCaptureDelay != _captureDelay; 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Capture delay changed 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_setCaptureDelay != _captureDelay) { 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _setCaptureDelay = _captureDelay; 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the capture time 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (capture_time != 0) { 2367a21a64c17db24f7cf8a37dfeb22dd57bef46c25andresp@webrtc.org captureFrame.set_render_time_ms(capture_time - delta_ntp_internal_ms_); 2375cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org } else { 2385cf0fd1dd5f8203e887e0553dd3d1fd14802312bpbos@webrtc.org captureFrame.set_render_time_ms(TickTime::MillisecondTimestamp()); 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2413bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org if (captureFrame.render_time_ms() == last_capture_time_) { 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We don't allow the same capture time for two frames, drop this one. 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2453bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org last_capture_time_ = captureFrame.render_time_ms(); 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_dataCallBack) { 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (callOnCaptureDelayChanged) { 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _dataCallBack->OnCaptureDelayChanged(_id, _captureDelay); 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 25143b21821dccec02f463a0912a4726a31ee62ac96mikhal@webrtc.org _dataCallBack->OnIncomingCapturedFrame(_id, captureFrame); 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 257f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureImpl::IncomingFrame( 258f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org uint8_t* videoFrame, 259f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org int32_t videoFrameLength, 260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const VideoCaptureCapability& frameInfo, 261f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org int64_t captureTime/*=0*/) 262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2635befd8b0eef77a2c5a3f8d1f20d167766372ace3fischman@webrtc.org CriticalSectionScoped cs(&_apiCs); 2645befd8b0eef77a2c5a3f8d1f20d167766372ace3fischman@webrtc.org CriticalSectionScoped cs2(&_callBackCs); 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 266f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org const int32_t width = frameInfo.width; 267f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org const int32_t height = frameInfo.height; 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 26974472fe9852769d834e135bde1229c24ab844244hclam@chromium.org TRACE_EVENT1("webrtc", "VC::IncomingFrame", "capture_time", captureTime); 27074472fe9852769d834e135bde1229c24ab844244hclam@chromium.org 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (frameInfo.codecType == kVideoCodecUnknown) 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Not encoded, convert to I420. 274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const VideoType commonVideoType = 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RawVideoTypeToCommonVideoVideoType(frameInfo.rawType); 276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (frameInfo.rawType != kVideoMJPEG && 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CalcBufferSize(commonVideoType, width, 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org abs(height)) != videoFrameLength) 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 281fcdc5b570e11c02dde6833b9b2704316594e9f8fpbos@webrtc.org LOG(LS_ERROR) << "Wrong incoming frame length."; 282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 285e9059218c8f61a31174b54ca8a57a841fbd47d94mikhal@webrtc.org int stride_y = width; 286e9059218c8f61a31174b54ca8a57a841fbd47d94mikhal@webrtc.org int stride_uv = (width + 1) / 2; 28730820033520b4379b468c317779728383df0aff9mikhal@webrtc.org int target_width = width; 28830820033520b4379b468c317779728383df0aff9mikhal@webrtc.org int target_height = height; 28930820033520b4379b468c317779728383df0aff9mikhal@webrtc.org // Rotating resolution when for 90/270 degree rotations. 29030820033520b4379b468c317779728383df0aff9mikhal@webrtc.org if (_rotateFrame == kRotate90 || _rotateFrame == kRotate270) { 29130820033520b4379b468c317779728383df0aff9mikhal@webrtc.org target_width = abs(height); 29230820033520b4379b468c317779728383df0aff9mikhal@webrtc.org target_height = width; 29330820033520b4379b468c317779728383df0aff9mikhal@webrtc.org } 294e9059218c8f61a31174b54ca8a57a841fbd47d94mikhal@webrtc.org // TODO(mikhal): Update correct aligned stride values. 295e9059218c8f61a31174b54ca8a57a841fbd47d94mikhal@webrtc.org //Calc16ByteAlignedStride(target_width, &stride_y, &stride_uv); 2963bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org // Setting absolute height (in case it was negative). 2973bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org // In Windows, the image starts bottom left, instead of top left. 2983bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org // Setting a negative source height, inverts the image (within LibYuv). 299af92d3e0e5501885b1a61c97af4bd09571f93ab6sheu@chromium.org int ret = _captureFrame.CreateEmptyFrame(target_width, 300af92d3e0e5501885b1a61c97af4bd09571f93ab6sheu@chromium.org abs(target_height), 301af92d3e0e5501885b1a61c97af4bd09571f93ab6sheu@chromium.org stride_y, 302af92d3e0e5501885b1a61c97af4bd09571f93ab6sheu@chromium.org stride_uv, stride_uv); 3033bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org if (ret < 0) 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 305fcdc5b570e11c02dde6833b9b2704316594e9f8fpbos@webrtc.org LOG(LS_ERROR) << "Failed to create empty frame, this should only " 306fcdc5b570e11c02dde6833b9b2704316594e9f8fpbos@webrtc.org "happen due to bad parameters."; 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int conversionResult = ConvertToI420(commonVideoType, 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org videoFrame, 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 0, // No cropping 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org width, height, 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org videoFrameLength, 314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rotateFrame, 315af92d3e0e5501885b1a61c97af4bd09571f93ab6sheu@chromium.org &_captureFrame); 316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (conversionResult < 0) 317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 318fcdc5b570e11c02dde6833b9b2704316594e9f8fpbos@webrtc.org LOG(LS_ERROR) << "Failed to convert capture frame from type " 319fcdc5b570e11c02dde6833b9b2704316594e9f8fpbos@webrtc.org << frameInfo.rawType << "to I420."; 320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 322af92d3e0e5501885b1a61c97af4bd09571f93ab6sheu@chromium.org DeliverCapturedFrame(_captureFrame, captureTime); 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else // Encoded format 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 326a18c6e5b2811221b60e3d7e72516aa20927e13ddmflodman@webrtc.org assert(false); 327a18c6e5b2811221b60e3d7e72516aa20927e13ddmflodman@webrtc.org return -1; 328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 33350293f5d7d3084d1d1389ccda3970cf8e6d4dc9fpbos@webrtc.orgint32_t VideoCaptureImpl::IncomingI420VideoFrame(I420VideoFrame* video_frame, 33450293f5d7d3084d1d1389ccda3970cf8e6d4dc9fpbos@webrtc.org int64_t captureTime) { 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3365befd8b0eef77a2c5a3f8d1f20d167766372ace3fischman@webrtc.org CriticalSectionScoped cs(&_apiCs); 3375befd8b0eef77a2c5a3f8d1f20d167766372ace3fischman@webrtc.org CriticalSectionScoped cs2(&_callBackCs); 33850293f5d7d3084d1d1389ccda3970cf8e6d4dc9fpbos@webrtc.org DeliverCapturedFrame(*video_frame, captureTime); 339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 343f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureImpl::SetCaptureRotation(VideoCaptureRotation rotation) { 34430820033520b4379b468c317779728383df0aff9mikhal@webrtc.org CriticalSectionScoped cs(&_apiCs); 34530820033520b4379b468c317779728383df0aff9mikhal@webrtc.org CriticalSectionScoped cs2(&_callBackCs); 34630820033520b4379b468c317779728383df0aff9mikhal@webrtc.org switch (rotation){ 34730820033520b4379b468c317779728383df0aff9mikhal@webrtc.org case kCameraRotate0: 34830820033520b4379b468c317779728383df0aff9mikhal@webrtc.org _rotateFrame = kRotateNone; 34930820033520b4379b468c317779728383df0aff9mikhal@webrtc.org break; 35030820033520b4379b468c317779728383df0aff9mikhal@webrtc.org case kCameraRotate90: 35130820033520b4379b468c317779728383df0aff9mikhal@webrtc.org _rotateFrame = kRotate90; 35230820033520b4379b468c317779728383df0aff9mikhal@webrtc.org break; 35330820033520b4379b468c317779728383df0aff9mikhal@webrtc.org case kCameraRotate180: 35430820033520b4379b468c317779728383df0aff9mikhal@webrtc.org _rotateFrame = kRotate180; 35530820033520b4379b468c317779728383df0aff9mikhal@webrtc.org break; 35630820033520b4379b468c317779728383df0aff9mikhal@webrtc.org case kCameraRotate270: 35730820033520b4379b468c317779728383df0aff9mikhal@webrtc.org _rotateFrame = kRotate270; 35830820033520b4379b468c317779728383df0aff9mikhal@webrtc.org break; 35981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org default: 36081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org return -1; 36130820033520b4379b468c317779728383df0aff9mikhal@webrtc.org } 36230820033520b4379b468c317779728383df0aff9mikhal@webrtc.org return 0; 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3657dc751458e1d5a3576065763737480e5f3f5a15bmallinath@webrtc.orgvoid VideoCaptureImpl::EnableFrameRateCallback(const bool enable) { 366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_apiCs); 367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs2(&_callBackCs); 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _frameRateCallBack = enable; 369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (enable) 370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastFrameRateCallbackTime = TickTime::Now(); 372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3757dc751458e1d5a3576065763737480e5f3f5a15bmallinath@webrtc.orgvoid VideoCaptureImpl::EnableNoPictureAlarm(const bool enable) { 376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_apiCs); 377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs2(&_callBackCs); 378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _noPictureAlarmCallBack = enable; 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid VideoCaptureImpl::UpdateFrameCount() 382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_incomingFrameTimes[0].MicrosecondTimestamp() == 0) 384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // first no shift 386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // shift 390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--) 391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _incomingFrameTimes[i + 1] = _incomingFrameTimes[i]; 393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _incomingFrameTimes[0] = TickTime::Now(); 396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 398f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orguint32_t VideoCaptureImpl::CalculateFrameRate(const TickTime& now) 399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 400f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org int32_t num = 0; 401f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org int32_t nrOfFrames = 0; 402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (num = 1; num < (kFrameRateCountHistorySize - 1); num++) 403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_incomingFrameTimes[num].Ticks() <= 0 405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org || (now - _incomingFrameTimes[num]).Milliseconds() > kFrameRateHistoryWindowMs) // don't use data older than 2sec 406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org nrOfFrames++; 412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (num > 1) 415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 416f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org int64_t diff = (now - _incomingFrameTimes[num - 1]).Milliseconds(); 417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (diff > 0) 418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 419f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org return uint32_t((nrOfFrames * 1000.0f / diff) + 0.5f); 420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return nrOfFrames; 424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4253b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org} // namespace videocapturemodule 4263b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org} // namespace webrtc 427