OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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/common_types.h" | 11 #include "webrtc/common_types.h" |
12 | 12 |
13 #include <algorithm> // std::max | 13 #include <algorithm> // std::max |
14 | 14 |
15 #include "webrtc/base/checks.h" | 15 #include "webrtc/base/checks.h" |
16 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 16 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
17 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" | 17 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" |
18 #include "webrtc/modules/video_coding/main/source/encoded_frame.h" | 18 #include "webrtc/modules/video_coding/main/source/encoded_frame.h" |
19 #include "webrtc/modules/video_coding/main/source/video_coding_impl.h" | 19 #include "webrtc/modules/video_coding/main/source/video_coding_impl.h" |
20 #include "webrtc/modules/video_coding/utility/include/quality_scaler.h" | 20 #include "webrtc/modules/video_coding/utility/include/quality_scaler.h" |
21 #include "webrtc/system_wrappers/interface/clock.h" | 21 #include "webrtc/system_wrappers/interface/clock.h" |
22 #include "webrtc/system_wrappers/interface/logging.h" | 22 #include "webrtc/system_wrappers/interface/logging.h" |
| 23 #include "webrtc/system_wrappers/interface/metrics.h" |
23 | 24 |
24 namespace webrtc { | 25 namespace webrtc { |
25 namespace vcm { | 26 namespace vcm { |
26 | 27 |
27 VideoSender::VideoSender(Clock* clock, | 28 VideoSender::VideoSender(Clock* clock, |
28 EncodedImageCallback* post_encode_callback, | 29 EncodedImageCallback* post_encode_callback, |
29 VideoEncoderRateObserver* encoder_rate_observer, | 30 VideoEncoderRateObserver* encoder_rate_observer, |
30 VCMQMSettingsCallback* qm_settings_callback) | 31 VCMQMSettingsCallback* qm_settings_callback) |
31 : clock_(clock), | 32 : clock_(clock), |
32 process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), | 33 process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), |
(...skipping 11 matching lines...) Expand all Loading... |
44 protection_callback_(nullptr) { | 45 protection_callback_(nullptr) { |
45 // Allow VideoSender to be created on one thread but used on another, post | 46 // Allow VideoSender to be created on one thread but used on another, post |
46 // construction. This is currently how this class is being used by at least | 47 // construction. This is currently how this class is being used by at least |
47 // one external project (diffractor). | 48 // one external project (diffractor). |
48 _mediaOpt.EnableQM(qm_settings_callback_ != nullptr); | 49 _mediaOpt.EnableQM(qm_settings_callback_ != nullptr); |
49 _mediaOpt.Reset(); | 50 _mediaOpt.Reset(); |
50 main_thread_.DetachFromThread(); | 51 main_thread_.DetachFromThread(); |
51 } | 52 } |
52 | 53 |
53 VideoSender::~VideoSender() { | 54 VideoSender::~VideoSender() { |
| 55 UpdateHistograms(); |
54 delete _sendCritSect; | 56 delete _sendCritSect; |
55 } | 57 } |
56 | 58 |
| 59 void VideoSender::UpdateHistograms() { |
| 60 int avg_encode_time_ms; |
| 61 int max_encode_time_ms; |
| 62 { |
| 63 CriticalSectionScoped cs(_sendCritSect); |
| 64 avg_encode_time_ms = stats_.AvgEncodeTimeMs(); |
| 65 max_encode_time_ms = stats_.MaxEncodeTimeMs(); |
| 66 } |
| 67 if (avg_encode_time_ms != -1) { |
| 68 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.AvgEncodeTimeInMs", |
| 69 avg_encode_time_ms); |
| 70 } |
| 71 if (max_encode_time_ms != -1) { |
| 72 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.MaxEncodeTimeInMs", |
| 73 max_encode_time_ms); |
| 74 } |
| 75 } |
| 76 |
57 int32_t VideoSender::Process() { | 77 int32_t VideoSender::Process() { |
58 int32_t returnValue = VCM_OK; | 78 int32_t returnValue = VCM_OK; |
59 | 79 |
60 if (_sendStatsTimer.TimeUntilProcess() == 0) { | 80 if (_sendStatsTimer.TimeUntilProcess() == 0) { |
61 _sendStatsTimer.Processed(); | 81 _sendStatsTimer.Processed(); |
62 CriticalSectionScoped cs(process_crit_sect_.get()); | 82 CriticalSectionScoped cs(process_crit_sect_.get()); |
63 if (_sendStatsCallback != nullptr) { | 83 if (_sendStatsCallback != nullptr) { |
64 uint32_t bitRate = _mediaOpt.SentBitRate(); | 84 uint32_t bitRate = _mediaOpt.SentBitRate(); |
65 uint32_t frameRate = _mediaOpt.SentFrameRate(); | 85 uint32_t frameRate = _mediaOpt.SentFrameRate(); |
66 _sendStatsCallback->SendStatistics(bitRate, frameRate); | 86 _sendStatsCallback->SendStatistics(bitRate, frameRate); |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 return VCM_PARAMETER_ERROR; | 342 return VCM_PARAMETER_ERROR; |
323 } | 343 } |
324 VideoFrame converted_frame = videoFrame; | 344 VideoFrame converted_frame = videoFrame; |
325 if (converted_frame.native_handle() && !_encoder->SupportsNativeHandle()) { | 345 if (converted_frame.native_handle() && !_encoder->SupportsNativeHandle()) { |
326 // This module only supports software encoding. | 346 // This module only supports software encoding. |
327 // TODO(pbos): Offload conversion from the encoder thread. | 347 // TODO(pbos): Offload conversion from the encoder thread. |
328 converted_frame = converted_frame.ConvertNativeToI420Frame(); | 348 converted_frame = converted_frame.ConvertNativeToI420Frame(); |
329 CHECK(!converted_frame.IsZeroSize()) | 349 CHECK(!converted_frame.IsZeroSize()) |
330 << "Frame conversion failed, won't be able to encode frame."; | 350 << "Frame conversion failed, won't be able to encode frame."; |
331 } | 351 } |
| 352 int64_t encode_start_time_ms = clock_->TimeInMilliseconds(); |
332 int32_t ret = | 353 int32_t ret = |
333 _encoder->Encode(converted_frame, codecSpecificInfo, _nextFrameTypes); | 354 _encoder->Encode(converted_frame, codecSpecificInfo, _nextFrameTypes); |
334 if (ret < 0) { | 355 if (ret < 0) { |
335 LOG(LS_ERROR) << "Failed to encode frame. Error code: " << ret; | 356 LOG(LS_ERROR) << "Failed to encode frame. Error code: " << ret; |
336 return ret; | 357 return ret; |
337 } | 358 } |
| 359 stats_.Update(clock_->TimeInMilliseconds() - encode_start_time_ms); |
| 360 |
338 for (size_t i = 0; i < _nextFrameTypes.size(); ++i) { | 361 for (size_t i = 0; i < _nextFrameTypes.size(); ++i) { |
339 _nextFrameTypes[i] = kVideoFrameDelta; // Default frame type. | 362 _nextFrameTypes[i] = kVideoFrameDelta; // Default frame type. |
340 } | 363 } |
341 return VCM_OK; | 364 return VCM_OK; |
342 } | 365 } |
343 | 366 |
344 int32_t VideoSender::IntraFrameRequest(int stream_index) { | 367 int32_t VideoSender::IntraFrameRequest(int stream_index) { |
345 CriticalSectionScoped cs(_sendCritSect); | 368 CriticalSectionScoped cs(_sendCritSect); |
346 if (stream_index < 0 || | 369 if (stream_index < 0 || |
347 static_cast<unsigned int>(stream_index) >= _nextFrameTypes.size()) { | 370 static_cast<unsigned int>(stream_index) >= _nextFrameTypes.size()) { |
(...skipping 28 matching lines...) Expand all Loading... |
376 // Set the hysteresis window to be at 10% of the threshold, but at least | 399 // Set the hysteresis window to be at 10% of the threshold, but at least |
377 // 10 kbps. | 400 // 10 kbps. |
378 int window_bps = std::max(threshold_bps / 10, 10000); | 401 int window_bps = std::max(threshold_bps / 10, 10000); |
379 _mediaOpt.SuspendBelowMinBitrate(threshold_bps, window_bps); | 402 _mediaOpt.SuspendBelowMinBitrate(threshold_bps, window_bps); |
380 } | 403 } |
381 | 404 |
382 bool VideoSender::VideoSuspended() const { | 405 bool VideoSender::VideoSuspended() const { |
383 CriticalSectionScoped cs(_sendCritSect); | 406 CriticalSectionScoped cs(_sendCritSect); |
384 return _mediaOpt.IsVideoSuspended(); | 407 return _mediaOpt.IsVideoSuspended(); |
385 } | 408 } |
| 409 |
| 410 void VideoSender::EncodedFrameStats::Update(int64_t encode_time_ms) { |
| 411 sum_encode_time_ms += encode_time_ms; |
| 412 max_encode_time_ms = std::max(max_encode_time_ms, encode_time_ms); |
| 413 ++encoded_frames; |
| 414 } |
386 } // namespace vcm | 415 } // namespace vcm |
387 } // namespace webrtc | 416 } // namespace webrtc |
OLD | NEW |