Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/modules/video_capture/video_capture_impl.h" | 11 #include "webrtc/modules/video_capture/video_capture_impl.h" |
| 12 | 12 |
| 13 #include <stdlib.h> | 13 #include <stdlib.h> |
| 14 | 14 |
| 15 #include "webrtc/base/refcount.h" | 15 #include "webrtc/base/refcount.h" |
| 16 #include "webrtc/base/timeutils.h" | |
| 16 #include "webrtc/base/trace_event.h" | 17 #include "webrtc/base/trace_event.h" |
| 17 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 18 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
| 18 #include "webrtc/modules/include/module_common_types.h" | 19 #include "webrtc/modules/include/module_common_types.h" |
| 19 #include "webrtc/modules/video_capture/video_capture_config.h" | 20 #include "webrtc/modules/video_capture/video_capture_config.h" |
| 20 #include "webrtc/system_wrappers/include/clock.h" | 21 #include "webrtc/system_wrappers/include/clock.h" |
| 21 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | 22 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" |
| 22 #include "webrtc/system_wrappers/include/logging.h" | 23 #include "webrtc/system_wrappers/include/logging.h" |
| 23 #include "webrtc/system_wrappers/include/tick_util.h" | |
| 24 | 24 |
| 25 namespace webrtc { | 25 namespace webrtc { |
| 26 namespace videocapturemodule { | 26 namespace videocapturemodule { |
| 27 rtc::scoped_refptr<VideoCaptureModule> VideoCaptureImpl::Create( | 27 rtc::scoped_refptr<VideoCaptureModule> VideoCaptureImpl::Create( |
| 28 const int32_t id, | 28 const int32_t id, |
| 29 VideoCaptureExternal*& externalCapture) { | 29 VideoCaptureExternal*& externalCapture) { |
| 30 rtc::scoped_refptr<VideoCaptureImpl> implementation( | 30 rtc::scoped_refptr<VideoCaptureImpl> implementation( |
| 31 new rtc::RefCountedObject<VideoCaptureImpl>(id)); | 31 new rtc::RefCountedObject<VideoCaptureImpl>(id)); |
| 32 externalCapture = implementation.get(); | 32 externalCapture = implementation.get(); |
| 33 return implementation; | 33 return implementation; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 } | 78 } |
| 79 return -1; | 79 return -1; |
| 80 } | 80 } |
| 81 | 81 |
| 82 // returns the number of milliseconds until the module want a worker thread to c all Process | 82 // returns the number of milliseconds until the module want a worker thread to c all Process |
| 83 int64_t VideoCaptureImpl::TimeUntilNextProcess() | 83 int64_t VideoCaptureImpl::TimeUntilNextProcess() |
| 84 { | 84 { |
| 85 CriticalSectionScoped cs(&_callBackCs); | 85 CriticalSectionScoped cs(&_callBackCs); |
| 86 const int64_t kProcessIntervalMs = 300; | 86 const int64_t kProcessIntervalMs = 300; |
| 87 return kProcessIntervalMs - | 87 return kProcessIntervalMs - |
| 88 (TickTime::Now() - _lastProcessTime).Milliseconds(); | 88 (rtc::TimeNanos() - _lastProcessTimeNanos) / |
| 89 rtc::kNumNanosecsPerMillisec; | |
| 89 } | 90 } |
| 90 | 91 |
| 91 // Process any pending tasks such as timeouts | 92 // Process any pending tasks such as timeouts |
| 92 void VideoCaptureImpl::Process() | 93 void VideoCaptureImpl::Process() |
| 93 { | 94 { |
| 94 CriticalSectionScoped cs(&_callBackCs); | 95 CriticalSectionScoped cs(&_callBackCs); |
| 95 | 96 |
| 96 const TickTime now = TickTime::Now(); | 97 const int64_t now_ns = rtc::TimeNanos(); |
|
stefan-webrtc
2016/04/19 12:40:47
Doesn't seem right that we store this in an int64_
nisse-webrtc
2016/04/19 13:48:51
I agree this isn't ideal, but it's no change: It's
| |
| 97 _lastProcessTime = TickTime::Now(); | 98 _lastProcessTimeNanos = rtc::TimeNanos(); |
| 98 | 99 |
| 99 // Handle No picture alarm | 100 // Handle No picture alarm |
| 100 | 101 |
| 101 if (_lastProcessFrameCount.Ticks() == _incomingFrameTimes[0].Ticks() && | 102 if (_lastProcessFrameTimeNanos == _incomingFrameTimesNanos[0] && |
| 102 _captureAlarm != Raised) | 103 _captureAlarm != Raised) |
| 103 { | 104 { |
| 104 if (_noPictureAlarmCallBack && _captureCallBack) | 105 if (_noPictureAlarmCallBack && _captureCallBack) |
| 105 { | 106 { |
| 106 _captureAlarm = Raised; | 107 _captureAlarm = Raised; |
| 107 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm); | 108 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm); |
| 108 } | 109 } |
| 109 } | 110 } |
| 110 else if (_lastProcessFrameCount.Ticks() != _incomingFrameTimes[0].Ticks() && | 111 else if (_lastProcessFrameTimeNanos != _incomingFrameTimesNanos[0] && |
| 111 _captureAlarm != Cleared) | 112 _captureAlarm != Cleared) |
| 112 { | 113 { |
| 113 if (_noPictureAlarmCallBack && _captureCallBack) | 114 if (_noPictureAlarmCallBack && _captureCallBack) |
| 114 { | 115 { |
| 115 _captureAlarm = Cleared; | 116 _captureAlarm = Cleared; |
| 116 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm); | 117 _captureCallBack->OnNoPictureAlarm(_id, _captureAlarm); |
| 117 | 118 |
| 118 } | 119 } |
| 119 } | 120 } |
| 120 | 121 |
| 121 // Handle frame rate callback | 122 // Handle frame rate callback |
| 122 if ((now - _lastFrameRateCallbackTime).Milliseconds() | 123 if ((now_ns - _lastFrameRateCallbackTimeNanos) / |
| 124 rtc::kNumNanosecsPerMillisec | |
| 123 > kFrameRateCallbackInterval) | 125 > kFrameRateCallbackInterval) |
| 124 { | 126 { |
| 125 if (_frameRateCallBack && _captureCallBack) | 127 if (_frameRateCallBack && _captureCallBack) |
| 126 { | 128 { |
| 127 const uint32_t frameRate = CalculateFrameRate(now); | 129 const uint32_t frameRate = CalculateFrameRate(now_ns); |
| 128 _captureCallBack->OnCaptureFrameRate(_id, frameRate); | 130 _captureCallBack->OnCaptureFrameRate(_id, frameRate); |
| 129 } | 131 } |
| 130 _lastFrameRateCallbackTime = now; // Can be set by EnableFrameRateCallba ck | 132 _lastFrameRateCallbackTimeNanos = now_ns; // Can be set by EnableFrameRa teCallback |
| 131 | 133 |
| 132 } | 134 } |
| 133 | 135 |
| 134 _lastProcessFrameCount = _incomingFrameTimes[0]; | 136 _lastProcessFrameTimeNanos = _incomingFrameTimesNanos[0]; |
| 135 } | 137 } |
| 136 | 138 |
| 137 VideoCaptureImpl::VideoCaptureImpl(const int32_t id) | 139 VideoCaptureImpl::VideoCaptureImpl(const int32_t id) |
| 138 : _id(id), | 140 : _id(id), |
| 139 _deviceUniqueId(NULL), | 141 _deviceUniqueId(NULL), |
| 140 _apiCs(*CriticalSectionWrapper::CreateCriticalSection()), | 142 _apiCs(*CriticalSectionWrapper::CreateCriticalSection()), |
| 141 _captureDelay(0), | 143 _captureDelay(0), |
| 142 _requestedCapability(), | 144 _requestedCapability(), |
| 143 _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()), | 145 _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()), |
| 144 _lastProcessTime(TickTime::Now()), | 146 _lastProcessTimeNanos(rtc::TimeNanos()), |
| 145 _lastFrameRateCallbackTime(TickTime::Now()), | 147 _lastFrameRateCallbackTimeNanos(rtc::TimeNanos()), |
| 146 _frameRateCallBack(false), | 148 _frameRateCallBack(false), |
| 147 _noPictureAlarmCallBack(false), | 149 _noPictureAlarmCallBack(false), |
| 148 _captureAlarm(Cleared), | 150 _captureAlarm(Cleared), |
| 149 _setCaptureDelay(0), | 151 _setCaptureDelay(0), |
| 150 _dataCallBack(NULL), | 152 _dataCallBack(NULL), |
| 151 _captureCallBack(NULL), | 153 _captureCallBack(NULL), |
| 152 _lastProcessFrameCount(TickTime::Now()), | 154 _lastProcessFrameTimeNanos(rtc::TimeNanos()), |
| 153 _rotateFrame(kVideoRotation_0), | 155 _rotateFrame(kVideoRotation_0), |
| 154 apply_rotation_(false) { | 156 apply_rotation_(false) { |
| 155 _requestedCapability.width = kDefaultWidth; | 157 _requestedCapability.width = kDefaultWidth; |
| 156 _requestedCapability.height = kDefaultHeight; | 158 _requestedCapability.height = kDefaultHeight; |
| 157 _requestedCapability.maxFPS = 30; | 159 _requestedCapability.maxFPS = 30; |
| 158 _requestedCapability.rawType = kVideoI420; | 160 _requestedCapability.rawType = kVideoI420; |
| 159 _requestedCapability.codecType = kVideoCodecUnknown; | 161 _requestedCapability.codecType = kVideoCodecUnknown; |
| 160 memset(_incomingFrameTimes, 0, sizeof(_incomingFrameTimes)); | 162 memset(_incomingFrameTimesNanos, 0, sizeof(_incomingFrameTimesNanos)); |
| 161 } | 163 } |
| 162 | 164 |
| 163 VideoCaptureImpl::~VideoCaptureImpl() | 165 VideoCaptureImpl::~VideoCaptureImpl() |
| 164 { | 166 { |
| 165 DeRegisterCaptureDataCallback(); | 167 DeRegisterCaptureDataCallback(); |
| 166 DeRegisterCaptureCallback(); | 168 DeRegisterCaptureCallback(); |
| 167 delete &_callBackCs; | 169 delete &_callBackCs; |
| 168 delete &_apiCs; | 170 delete &_apiCs; |
| 169 | 171 |
| 170 if (_deviceUniqueId) | 172 if (_deviceUniqueId) |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 288 << frameInfo.rawType << "to I420."; | 290 << frameInfo.rawType << "to I420."; |
| 289 return -1; | 291 return -1; |
| 290 } | 292 } |
| 291 | 293 |
| 292 if (!apply_rotation) { | 294 if (!apply_rotation) { |
| 293 _captureFrame.set_rotation(_rotateFrame); | 295 _captureFrame.set_rotation(_rotateFrame); |
| 294 } else { | 296 } else { |
| 295 _captureFrame.set_rotation(kVideoRotation_0); | 297 _captureFrame.set_rotation(kVideoRotation_0); |
| 296 } | 298 } |
| 297 _captureFrame.set_ntp_time_ms(captureTime); | 299 _captureFrame.set_ntp_time_ms(captureTime); |
| 298 _captureFrame.set_render_time_ms(TickTime::MillisecondTimestamp()); | 300 _captureFrame.set_render_time_ms(rtc::Time64()); |
| 299 | 301 |
| 300 DeliverCapturedFrame(_captureFrame); | 302 DeliverCapturedFrame(_captureFrame); |
| 301 } | 303 } |
| 302 else // Encoded format | 304 else // Encoded format |
| 303 { | 305 { |
| 304 assert(false); | 306 assert(false); |
| 305 return -1; | 307 return -1; |
| 306 } | 308 } |
| 307 | 309 |
| 308 return 0; | 310 return 0; |
| 309 } | 311 } |
| 310 | 312 |
| 311 int32_t VideoCaptureImpl::SetCaptureRotation(VideoRotation rotation) { | 313 int32_t VideoCaptureImpl::SetCaptureRotation(VideoRotation rotation) { |
| 312 CriticalSectionScoped cs(&_apiCs); | 314 CriticalSectionScoped cs(&_apiCs); |
| 313 CriticalSectionScoped cs2(&_callBackCs); | 315 CriticalSectionScoped cs2(&_callBackCs); |
| 314 _rotateFrame = rotation; | 316 _rotateFrame = rotation; |
| 315 return 0; | 317 return 0; |
| 316 } | 318 } |
| 317 | 319 |
| 318 void VideoCaptureImpl::EnableFrameRateCallback(const bool enable) { | 320 void VideoCaptureImpl::EnableFrameRateCallback(const bool enable) { |
| 319 CriticalSectionScoped cs(&_apiCs); | 321 CriticalSectionScoped cs(&_apiCs); |
| 320 CriticalSectionScoped cs2(&_callBackCs); | 322 CriticalSectionScoped cs2(&_callBackCs); |
| 321 _frameRateCallBack = enable; | 323 _frameRateCallBack = enable; |
| 322 if (enable) | 324 if (enable) |
| 323 { | 325 { |
| 324 _lastFrameRateCallbackTime = TickTime::Now(); | 326 _lastFrameRateCallbackTimeNanos = rtc::TimeNanos(); |
| 325 } | 327 } |
| 326 } | 328 } |
| 327 | 329 |
| 328 bool VideoCaptureImpl::SetApplyRotation(bool enable) { | 330 bool VideoCaptureImpl::SetApplyRotation(bool enable) { |
| 329 // We can't take any lock here as it'll cause deadlock with IncomingFrame. | 331 // We can't take any lock here as it'll cause deadlock with IncomingFrame. |
| 330 | 332 |
| 331 // The effect of this is the last caller wins. | 333 // The effect of this is the last caller wins. |
| 332 apply_rotation_ = enable; | 334 apply_rotation_ = enable; |
| 333 return true; | 335 return true; |
| 334 } | 336 } |
| 335 | 337 |
| 336 void VideoCaptureImpl::EnableNoPictureAlarm(const bool enable) { | 338 void VideoCaptureImpl::EnableNoPictureAlarm(const bool enable) { |
| 337 CriticalSectionScoped cs(&_apiCs); | 339 CriticalSectionScoped cs(&_apiCs); |
| 338 CriticalSectionScoped cs2(&_callBackCs); | 340 CriticalSectionScoped cs2(&_callBackCs); |
| 339 _noPictureAlarmCallBack = enable; | 341 _noPictureAlarmCallBack = enable; |
| 340 } | 342 } |
| 341 | 343 |
| 342 void VideoCaptureImpl::UpdateFrameCount() | 344 void VideoCaptureImpl::UpdateFrameCount() |
| 343 { | 345 { |
| 344 if (_incomingFrameTimes[0].MicrosecondTimestamp() == 0) | 346 if (_incomingFrameTimesNanos[0] / rtc::kNumNanosecsPerMicrosec == 0) |
| 345 { | 347 { |
| 346 // first no shift | 348 // first no shift |
| 347 } | 349 } |
| 348 else | 350 else |
| 349 { | 351 { |
| 350 // shift | 352 // shift |
| 351 for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--) | 353 for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--) |
| 352 { | 354 { |
| 353 _incomingFrameTimes[i + 1] = _incomingFrameTimes[i]; | 355 _incomingFrameTimesNanos[i + 1] = _incomingFrameTimesNanos[i]; |
| 354 } | 356 } |
| 355 } | 357 } |
| 356 _incomingFrameTimes[0] = TickTime::Now(); | 358 _incomingFrameTimesNanos[0] = rtc::TimeNanos(); |
| 357 } | 359 } |
| 358 | 360 |
| 359 uint32_t VideoCaptureImpl::CalculateFrameRate(const TickTime& now) | 361 uint32_t VideoCaptureImpl::CalculateFrameRate(int64_t now_ns) |
| 360 { | 362 { |
| 361 int32_t num = 0; | 363 int32_t num = 0; |
| 362 int32_t nrOfFrames = 0; | 364 int32_t nrOfFrames = 0; |
| 363 for (num = 1; num < (kFrameRateCountHistorySize - 1); num++) | 365 for (num = 1; num < (kFrameRateCountHistorySize - 1); num++) |
| 364 { | 366 { |
| 365 if (_incomingFrameTimes[num].Ticks() <= 0 | 367 if (_incomingFrameTimesNanos[num] <= 0 || |
| 366 || (now - _incomingFrameTimes[num]).Milliseconds() > kFrameRateHisto ryWindowMs) // don't use data older than 2sec | 368 (now_ns - _incomingFrameTimesNanos[num]) / |
| 369 rtc::kNumNanosecsPerMillisec > | |
| 370 kFrameRateHistoryWindowMs) // don't use data older than 2sec | |
| 367 { | 371 { |
| 368 break; | 372 break; |
| 369 } | 373 } |
| 370 else | 374 else |
| 371 { | 375 { |
| 372 nrOfFrames++; | 376 nrOfFrames++; |
| 373 } | 377 } |
| 374 } | 378 } |
| 375 if (num > 1) | 379 if (num > 1) |
| 376 { | 380 { |
| 377 int64_t diff = (now - _incomingFrameTimes[num - 1]).Milliseconds(); | 381 int64_t diff = (now_ns - _incomingFrameTimesNanos[num - 1]) / |
| 382 rtc::kNumNanosecsPerMillisec; | |
| 378 if (diff > 0) | 383 if (diff > 0) |
| 379 { | 384 { |
| 380 return uint32_t((nrOfFrames * 1000.0f / diff) + 0.5f); | 385 return uint32_t((nrOfFrames * 1000.0f / diff) + 0.5f); |
| 381 } | 386 } |
| 382 } | 387 } |
| 383 | 388 |
| 384 return nrOfFrames; | 389 return nrOfFrames; |
| 385 } | 390 } |
| 386 } // namespace videocapturemodule | 391 } // namespace videocapturemodule |
| 387 } // namespace webrtc | 392 } // namespace webrtc |
| OLD | NEW |