Index: webrtc/video/vie_encoder.cc |
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc |
index 203d1c405a8813d05b627cd464803bb9df39f645..d144b2035762266d2dc53e373fc0418d5de3dd87 100644 |
--- a/webrtc/video/vie_encoder.cc |
+++ b/webrtc/video/vie_encoder.cc |
@@ -44,24 +44,12 @@ const int64_t kFrameLogIntervalMs = 60000; |
// See https://bugs.chromium.org/p/webrtc/issues/detail?id=7206 |
const int kMinPixelsPerFrame = 320 * 180; |
const int kMinFramerateFps = 2; |
+const int kMaxFramerateFps = 120; |
// The maximum number of frames to drop at beginning of stream |
// to try and achieve desired bitrate. |
const int kMaxInitialFramedrop = 4; |
-// TODO(pbos): Lower these thresholds (to closer to 100%) when we handle |
-// pipelining encoders better (multiple input frames before something comes |
-// out). This should effectively turn off CPU adaptations for systems that |
-// remotely cope with the load right now. |
-CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { |
- CpuOveruseOptions options; |
- if (full_overuse_time) { |
- options.low_encode_usage_threshold_percent = 150; |
- options.high_encode_usage_threshold_percent = 200; |
- } |
- return options; |
-} |
- |
uint32_t MaximumFrameSizeForBitrate(uint32_t kbps) { |
if (kbps > 0) { |
if (kbps < 300 /* qvga */) { |
@@ -249,10 +237,11 @@ class ViEEncoder::VideoSourceProxy { |
return true; |
} |
- bool RequestFramerateLowerThan(int fps) { |
+ int RequestFramerateLowerThan(int fps) { |
// Called on the encoder task queue. |
// The input video frame rate will be scaled down to 2/3, rounding down. |
- return RestrictFramerate((fps * 2) / 3); |
+ int framerate_wanted = (fps * 2) / 3; |
+ return RestrictFramerate(framerate_wanted) ? framerate_wanted : -1; |
} |
bool RequestHigherResolutionThan(int pixel_count) { |
@@ -289,14 +278,18 @@ class ViEEncoder::VideoSourceProxy { |
return true; |
} |
- bool RequestHigherFramerateThan(int fps) { |
+ // Request upgrade in framerate. Returns the new requested frame, or -1 if |
+ // no change requested. Note that maxint may be returned if limits due to |
+ // adaptation requests are removed completely. In that case, consider |
+ // |max_framerate_| to be the current limit (assuming the capturer complies). |
+ int RequestHigherFramerateThan(int fps) { |
// Called on the encoder task queue. |
// The input frame rate will be scaled up to the last step, with rounding. |
int framerate_wanted = fps; |
if (fps != std::numeric_limits<int>::max()) |
framerate_wanted = (fps * 3) / 2; |
- return IncreaseFramerate(framerate_wanted); |
+ return IncreaseFramerate(framerate_wanted) ? framerate_wanted : -1; |
} |
bool RestrictFramerate(int fps) { |
@@ -347,7 +340,8 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
SendStatisticsProxy* stats_proxy, |
const VideoSendStream::Config::EncoderSettings& settings, |
rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, |
- EncodedFrameObserver* encoder_timing) |
+ EncodedFrameObserver* encoder_timing, |
+ std::unique_ptr<OveruseFrameDetector> overuse_detector) |
: shutdown_event_(true /* manual_reset */, false), |
number_of_cores_(number_of_cores), |
initial_rampup_(0), |
@@ -357,13 +351,18 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
codec_type_(PayloadNameToCodecType(settings.payload_name) |
.value_or(VideoCodecType::kVideoCodecUnknown)), |
video_sender_(Clock::GetRealTimeClock(), this, this), |
- overuse_detector_(GetCpuOveruseOptions(settings.full_overuse_time), |
- this, |
- encoder_timing, |
- stats_proxy), |
+ overuse_detector_( |
+ overuse_detector.get() |
+ ? overuse_detector.release() |
+ : new OveruseFrameDetector( |
+ GetCpuOveruseOptions(settings.full_overuse_time), |
+ this, |
+ encoder_timing, |
+ stats_proxy)), |
stats_proxy_(stats_proxy), |
pre_encode_callback_(pre_encode_callback), |
module_process_thread_(nullptr), |
+ max_framerate_(-1), |
pending_encoder_reconfiguration_(false), |
encoder_start_bitrate_bps_(0), |
max_data_payload_length_(0), |
@@ -384,7 +383,7 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
RTC_DCHECK(stats_proxy); |
encoder_queue_.PostTask([this] { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
- overuse_detector_.StartCheckForOveruse(); |
+ overuse_detector_->StartCheckForOveruse(); |
video_sender_.RegisterExternalEncoder( |
settings_.encoder, settings_.payload_type, settings_.internal_source); |
}); |
@@ -396,12 +395,25 @@ ViEEncoder::~ViEEncoder() { |
<< "Must call ::Stop() before destruction."; |
} |
+// TODO(pbos): Lower these thresholds (to closer to 100%) when we handle |
+// pipelining encoders better (multiple input frames before something comes |
+// out). This should effectively turn off CPU adaptations for systems that |
+// remotely cope with the load right now. |
+CpuOveruseOptions ViEEncoder::GetCpuOveruseOptions(bool full_overuse_time) { |
+ CpuOveruseOptions options; |
+ if (full_overuse_time) { |
+ options.low_encode_usage_threshold_percent = 150; |
+ options.high_encode_usage_threshold_percent = 200; |
+ } |
+ return options; |
+} |
+ |
void ViEEncoder::Stop() { |
RTC_DCHECK_RUN_ON(&thread_checker_); |
source_proxy_->SetSource(nullptr, VideoSendStream::DegradationPreference()); |
encoder_queue_.PostTask([this] { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
- overuse_detector_.StopCheckForOveruse(); |
+ overuse_detector_->StopCheckForOveruse(); |
rate_allocator_.reset(); |
bitrate_observer_ = nullptr; |
video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type, |
@@ -452,6 +464,12 @@ void ViEEncoder::SetSource( |
bool allow_scaling = IsResolutionScalingEnabled(degradation_preference_); |
initial_rampup_ = allow_scaling ? 0 : kMaxInitialFramedrop; |
ConfigureQualityScaler(); |
+ if (!IsFramerateScalingEnabled(degradation_preference) && |
+ max_framerate_ != -1) { |
+ // If frame rate scaling is no longer allowed, remove any potential |
+ // allowance for longer frame intervals. |
+ overuse_detector_->OnTargetFramerateUpdated(max_framerate_); |
+ } |
}); |
} |
@@ -521,6 +539,8 @@ void ViEEncoder::ReconfigureEncoder() { |
std::max(encoder_start_bitrate_bps_ / 1000, codec.minBitrate); |
codec.startBitrate = std::min(codec.startBitrate, codec.maxBitrate); |
codec.expect_encode_from_texture = last_frame_info_->is_texture; |
+ max_framerate_ = codec.maxFramerate; |
+ RTC_DCHECK_LE(max_framerate_, kMaxFramerateFps); |
bool success = video_sender_.RegisterSendCodec( |
&codec, number_of_cores_, |
@@ -533,19 +553,35 @@ void ViEEncoder::ReconfigureEncoder() { |
video_sender_.UpdateChannelParemeters(rate_allocator_.get(), |
bitrate_observer_); |
- int framerate = stats_proxy_->GetSendFrameRate(); |
- if (framerate == 0) |
- framerate = codec.maxFramerate; |
+ // Get the current actual framerate, as measured by the stats proxy. This is |
+ // used to get the correct bitrate layer allocation. |
+ int current_framerate = stats_proxy_->GetSendFrameRate(); |
+ if (current_framerate == 0) |
+ current_framerate = codec.maxFramerate; |
stats_proxy_->OnEncoderReconfigured( |
- encoder_config_, rate_allocator_.get() |
- ? rate_allocator_->GetPreferredBitrateBps(framerate) |
- : codec.maxBitrate); |
+ encoder_config_, |
+ rate_allocator_.get() |
+ ? rate_allocator_->GetPreferredBitrateBps(current_framerate) |
+ : codec.maxBitrate); |
pending_encoder_reconfiguration_ = false; |
sink_->OnEncoderConfigurationChanged( |
std::move(streams), encoder_config_.min_transmit_bitrate_bps); |
+ // Get the current target framerate, ie the maximum framerate as specified by |
+ // the current codec configuration, or any limit imposed by cpu adaption in |
+ // maintain-resolution or balanced mode. This is used to make sure overuse |
+ // detection doesn't needlessly trigger in low and/or variable framerate |
+ // scenarios. |
+ int target_framerate = max_framerate_; |
+ if (last_adaptation_request_ && |
+ last_adaptation_request_->selected_framerate_fps_) { |
åsapersson
2017/06/14 10:50:26
would it be better to get sink_wants_.max_framerat
sprang_webrtc
2017/06/14 13:41:28
Sure, I'll expose a getter that can be used.
|
+ target_framerate = std::min( |
+ target_framerate, *last_adaptation_request_->selected_framerate_fps_); |
+ } |
+ overuse_detector_->OnTargetFramerateUpdated(target_framerate); |
+ |
ConfigureQualityScaler(); |
} |
@@ -694,7 +730,7 @@ void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame, |
TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(), |
"Encode"); |
- overuse_detector_.FrameCaptured(video_frame, time_when_posted_us); |
+ overuse_detector_->FrameCaptured(video_frame, time_when_posted_us); |
video_sender_.AddVideoFrame(video_frame, nullptr); |
} |
@@ -725,7 +761,7 @@ EncodedImageCallback::Result ViEEncoder::OnEncodedImage( |
const int qp = encoded_image.qp_; |
encoder_queue_.PostTask([this, timestamp, time_sent_us, qp] { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
- overuse_detector_.FrameSent(timestamp, time_sent_us); |
+ overuse_detector_->FrameSent(timestamp, time_sent_us); |
if (quality_scaler_ && qp >= 0) |
quality_scaler_->ReportQP(qp); |
}); |
@@ -796,7 +832,7 @@ void ViEEncoder::AdaptDown(AdaptReason reason) { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
AdaptationRequest adaptation_request = { |
last_frame_info_->pixel_count(), |
- stats_proxy_->GetStats().input_frame_rate, |
+ stats_proxy_->GetStats().input_frame_rate, rtc::Optional<int>(), |
AdaptationRequest::Mode::kAdaptDown}; |
bool downgrade_requested = |
@@ -851,14 +887,18 @@ void ViEEncoder::AdaptDown(AdaptReason reason) { |
} |
GetAdaptCounter().IncrementResolution(reason, 1); |
break; |
- case VideoSendStream::DegradationPreference::kMaintainResolution: |
+ case VideoSendStream::DegradationPreference::kMaintainResolution: { |
// Scale down framerate. |
- if (!source_proxy_->RequestFramerateLowerThan( |
- adaptation_request.framerate_fps_)) { |
+ const int requested_framerate = source_proxy_->RequestFramerateLowerThan( |
+ adaptation_request.framerate_fps_); |
+ if (requested_framerate == -1) |
return; |
- } |
+ adaptation_request.selected_framerate_fps_.emplace(requested_framerate); |
+ overuse_detector_->OnTargetFramerateUpdated( |
+ std::min(max_framerate_, requested_framerate)); |
GetAdaptCounter().IncrementFramerate(reason, 1); |
break; |
+ } |
case VideoSendStream::DegradationPreference::kDegradationDisabled: |
RTC_NOTREACHED(); |
} |
@@ -881,7 +921,7 @@ void ViEEncoder::AdaptUp(AdaptReason reason) { |
AdaptationRequest adaptation_request = { |
last_frame_info_->pixel_count(), |
- stats_proxy_->GetStats().input_frame_rate, |
+ stats_proxy_->GetStats().input_frame_rate, rtc::Optional<int>(), |
AdaptationRequest::Mode::kAdaptUp}; |
bool adapt_up_requested = |
@@ -930,8 +970,16 @@ void ViEEncoder::AdaptUp(AdaptReason reason) { |
LOG(LS_INFO) << "Removing framerate down-scaling setting."; |
fps = std::numeric_limits<int>::max(); |
} |
- if (!source_proxy_->RequestHigherFramerateThan(fps)) |
+ |
+ const int requested_framerate = |
+ source_proxy_->RequestHigherFramerateThan(fps); |
+ if (requested_framerate == -1) { |
+ overuse_detector_->OnTargetFramerateUpdated(max_framerate_); |
return; |
+ } |
+ adaptation_request.selected_framerate_fps_.emplace(requested_framerate); |
+ overuse_detector_->OnTargetFramerateUpdated( |
+ std::min(max_framerate_, requested_framerate)); |
GetAdaptCounter().IncrementFramerate(reason, -1); |
break; |
} |