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