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(); |
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 // Can be set by EnableFrameRateCallback |
| 133 _lastFrameRateCallbackTimeNanos = now_ns; |
131 | 134 |
132 } | 135 } |
133 | 136 |
134 _lastProcessFrameCount = _incomingFrameTimes[0]; | 137 _lastProcessFrameTimeNanos = _incomingFrameTimesNanos[0]; |
135 } | 138 } |
136 | 139 |
137 VideoCaptureImpl::VideoCaptureImpl(const int32_t id) | 140 VideoCaptureImpl::VideoCaptureImpl(const int32_t id) |
138 : _id(id), | 141 : _id(id), |
139 _deviceUniqueId(NULL), | 142 _deviceUniqueId(NULL), |
140 _apiCs(*CriticalSectionWrapper::CreateCriticalSection()), | 143 _apiCs(*CriticalSectionWrapper::CreateCriticalSection()), |
141 _captureDelay(0), | 144 _captureDelay(0), |
142 _requestedCapability(), | 145 _requestedCapability(), |
143 _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()), | 146 _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()), |
144 _lastProcessTime(TickTime::Now()), | 147 _lastProcessTimeNanos(rtc::TimeNanos()), |
145 _lastFrameRateCallbackTime(TickTime::Now()), | 148 _lastFrameRateCallbackTimeNanos(rtc::TimeNanos()), |
146 _frameRateCallBack(false), | 149 _frameRateCallBack(false), |
147 _noPictureAlarmCallBack(false), | 150 _noPictureAlarmCallBack(false), |
148 _captureAlarm(Cleared), | 151 _captureAlarm(Cleared), |
149 _setCaptureDelay(0), | 152 _setCaptureDelay(0), |
150 _dataCallBack(NULL), | 153 _dataCallBack(NULL), |
151 _captureCallBack(NULL), | 154 _captureCallBack(NULL), |
152 _lastProcessFrameCount(TickTime::Now()), | 155 _lastProcessFrameTimeNanos(rtc::TimeNanos()), |
153 _rotateFrame(kVideoRotation_0), | 156 _rotateFrame(kVideoRotation_0), |
154 apply_rotation_(false) { | 157 apply_rotation_(false) { |
155 _requestedCapability.width = kDefaultWidth; | 158 _requestedCapability.width = kDefaultWidth; |
156 _requestedCapability.height = kDefaultHeight; | 159 _requestedCapability.height = kDefaultHeight; |
157 _requestedCapability.maxFPS = 30; | 160 _requestedCapability.maxFPS = 30; |
158 _requestedCapability.rawType = kVideoI420; | 161 _requestedCapability.rawType = kVideoI420; |
159 _requestedCapability.codecType = kVideoCodecUnknown; | 162 _requestedCapability.codecType = kVideoCodecUnknown; |
160 memset(_incomingFrameTimes, 0, sizeof(_incomingFrameTimes)); | 163 memset(_incomingFrameTimesNanos, 0, sizeof(_incomingFrameTimesNanos)); |
161 } | 164 } |
162 | 165 |
163 VideoCaptureImpl::~VideoCaptureImpl() | 166 VideoCaptureImpl::~VideoCaptureImpl() |
164 { | 167 { |
165 DeRegisterCaptureDataCallback(); | 168 DeRegisterCaptureDataCallback(); |
166 DeRegisterCaptureCallback(); | 169 DeRegisterCaptureCallback(); |
167 delete &_callBackCs; | 170 delete &_callBackCs; |
168 delete &_apiCs; | 171 delete &_apiCs; |
169 | 172 |
170 if (_deviceUniqueId) | 173 if (_deviceUniqueId) |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 << frameInfo.rawType << "to I420."; | 291 << frameInfo.rawType << "to I420."; |
289 return -1; | 292 return -1; |
290 } | 293 } |
291 | 294 |
292 if (!apply_rotation) { | 295 if (!apply_rotation) { |
293 _captureFrame.set_rotation(_rotateFrame); | 296 _captureFrame.set_rotation(_rotateFrame); |
294 } else { | 297 } else { |
295 _captureFrame.set_rotation(kVideoRotation_0); | 298 _captureFrame.set_rotation(kVideoRotation_0); |
296 } | 299 } |
297 _captureFrame.set_ntp_time_ms(captureTime); | 300 _captureFrame.set_ntp_time_ms(captureTime); |
298 _captureFrame.set_render_time_ms(TickTime::MillisecondTimestamp()); | 301 _captureFrame.set_render_time_ms(rtc::TimeMillis()); |
299 | 302 |
300 DeliverCapturedFrame(_captureFrame); | 303 DeliverCapturedFrame(_captureFrame); |
301 } | 304 } |
302 else // Encoded format | 305 else // Encoded format |
303 { | 306 { |
304 assert(false); | 307 assert(false); |
305 return -1; | 308 return -1; |
306 } | 309 } |
307 | 310 |
308 return 0; | 311 return 0; |
309 } | 312 } |
310 | 313 |
311 int32_t VideoCaptureImpl::SetCaptureRotation(VideoRotation rotation) { | 314 int32_t VideoCaptureImpl::SetCaptureRotation(VideoRotation rotation) { |
312 CriticalSectionScoped cs(&_apiCs); | 315 CriticalSectionScoped cs(&_apiCs); |
313 CriticalSectionScoped cs2(&_callBackCs); | 316 CriticalSectionScoped cs2(&_callBackCs); |
314 _rotateFrame = rotation; | 317 _rotateFrame = rotation; |
315 return 0; | 318 return 0; |
316 } | 319 } |
317 | 320 |
318 void VideoCaptureImpl::EnableFrameRateCallback(const bool enable) { | 321 void VideoCaptureImpl::EnableFrameRateCallback(const bool enable) { |
319 CriticalSectionScoped cs(&_apiCs); | 322 CriticalSectionScoped cs(&_apiCs); |
320 CriticalSectionScoped cs2(&_callBackCs); | 323 CriticalSectionScoped cs2(&_callBackCs); |
321 _frameRateCallBack = enable; | 324 _frameRateCallBack = enable; |
322 if (enable) | 325 if (enable) |
323 { | 326 { |
324 _lastFrameRateCallbackTime = TickTime::Now(); | 327 _lastFrameRateCallbackTimeNanos = rtc::TimeNanos(); |
325 } | 328 } |
326 } | 329 } |
327 | 330 |
328 bool VideoCaptureImpl::SetApplyRotation(bool enable) { | 331 bool VideoCaptureImpl::SetApplyRotation(bool enable) { |
329 // We can't take any lock here as it'll cause deadlock with IncomingFrame. | 332 // We can't take any lock here as it'll cause deadlock with IncomingFrame. |
330 | 333 |
331 // The effect of this is the last caller wins. | 334 // The effect of this is the last caller wins. |
332 apply_rotation_ = enable; | 335 apply_rotation_ = enable; |
333 return true; | 336 return true; |
334 } | 337 } |
335 | 338 |
336 void VideoCaptureImpl::EnableNoPictureAlarm(const bool enable) { | 339 void VideoCaptureImpl::EnableNoPictureAlarm(const bool enable) { |
337 CriticalSectionScoped cs(&_apiCs); | 340 CriticalSectionScoped cs(&_apiCs); |
338 CriticalSectionScoped cs2(&_callBackCs); | 341 CriticalSectionScoped cs2(&_callBackCs); |
339 _noPictureAlarmCallBack = enable; | 342 _noPictureAlarmCallBack = enable; |
340 } | 343 } |
341 | 344 |
342 void VideoCaptureImpl::UpdateFrameCount() | 345 void VideoCaptureImpl::UpdateFrameCount() |
343 { | 346 { |
344 if (_incomingFrameTimes[0].MicrosecondTimestamp() == 0) | 347 if (_incomingFrameTimesNanos[0] / rtc::kNumNanosecsPerMicrosec == 0) |
345 { | 348 { |
346 // first no shift | 349 // first no shift |
347 } | 350 } |
348 else | 351 else |
349 { | 352 { |
350 // shift | 353 // shift |
351 for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--) | 354 for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--) |
352 { | 355 { |
353 _incomingFrameTimes[i + 1] = _incomingFrameTimes[i]; | 356 _incomingFrameTimesNanos[i + 1] = _incomingFrameTimesNanos[i]; |
354 } | 357 } |
355 } | 358 } |
356 _incomingFrameTimes[0] = TickTime::Now(); | 359 _incomingFrameTimesNanos[0] = rtc::TimeNanos(); |
357 } | 360 } |
358 | 361 |
359 uint32_t VideoCaptureImpl::CalculateFrameRate(const TickTime& now) | 362 uint32_t VideoCaptureImpl::CalculateFrameRate(int64_t now_ns) |
360 { | 363 { |
361 int32_t num = 0; | 364 int32_t num = 0; |
362 int32_t nrOfFrames = 0; | 365 int32_t nrOfFrames = 0; |
363 for (num = 1; num < (kFrameRateCountHistorySize - 1); num++) | 366 for (num = 1; num < (kFrameRateCountHistorySize - 1); num++) |
364 { | 367 { |
365 if (_incomingFrameTimes[num].Ticks() <= 0 | 368 if (_incomingFrameTimesNanos[num] <= 0 || |
366 || (now - _incomingFrameTimes[num]).Milliseconds() > kFrameRateHisto
ryWindowMs) // don't use data older than 2sec | 369 (now_ns - _incomingFrameTimesNanos[num]) / |
| 370 rtc::kNumNanosecsPerMillisec > |
| 371 kFrameRateHistoryWindowMs) // don't use data older than 2sec |
367 { | 372 { |
368 break; | 373 break; |
369 } | 374 } |
370 else | 375 else |
371 { | 376 { |
372 nrOfFrames++; | 377 nrOfFrames++; |
373 } | 378 } |
374 } | 379 } |
375 if (num > 1) | 380 if (num > 1) |
376 { | 381 { |
377 int64_t diff = (now - _incomingFrameTimes[num - 1]).Milliseconds(); | 382 int64_t diff = (now_ns - _incomingFrameTimesNanos[num - 1]) / |
| 383 rtc::kNumNanosecsPerMillisec; |
378 if (diff > 0) | 384 if (diff > 0) |
379 { | 385 { |
380 return uint32_t((nrOfFrames * 1000.0f / diff) + 0.5f); | 386 return uint32_t((nrOfFrames * 1000.0f / diff) + 0.5f); |
381 } | 387 } |
382 } | 388 } |
383 | 389 |
384 return nrOfFrames; | 390 return nrOfFrames; |
385 } | 391 } |
386 } // namespace videocapturemodule | 392 } // namespace videocapturemodule |
387 } // namespace webrtc | 393 } // namespace webrtc |
OLD | NEW |