Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Unified Diff: webrtc/video/vie_encoder.cc

Issue 2716643002: Add framerate to VideoSinkWants and ability to signal on overuse (Closed)
Patch Set: Fix wireup, keep scale state per degradation pref Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/video/vie_encoder.cc
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc
index 1458af266f68efb6692756205f2296b6cd217e20..c147440b8fa8bdb5ab5d4930da4cb94eda164ad6 100644
--- a/webrtc/video/vie_encoder.cc
+++ b/webrtc/video/vie_encoder.cc
@@ -43,6 +43,7 @@ const int kMinPixelsPerFrame = 320 * 180;
#else
const int kMinPixelsPerFrame = 120 * 90;
#endif
+const int kMinFramerateFps = 2;
// The maximum number of frames to drop at beginning of stream
// to try and achieve desired bitrate.
@@ -162,10 +163,23 @@ class ViEEncoder::VideoSourceProxy {
rtc::VideoSinkWants wants;
{
rtc::CritScope lock(&crit_);
+ wants = sink_wants_;
+ // If changing degradation preference, clear any constraints from the
+ // current sink wants that will no longer apply.
+ if (degradation_preference_ != degradation_preference) {
+ switch (degradation_preference) {
+ case DegradationPreference::kBalanced:
+ wants.max_framerate_fps_.reset();
+ break;
+ case DegradationPreference::kMaintainResolution:
+ wants.max_pixel_count.reset();
+ wants.target_pixel_count.reset();
+ break;
+ }
+ }
+ degradation_preference_ = degradation_preference;
old_source = source_;
source_ = source;
- degradation_preference_ = degradation_preference;
- wants = current_wants();
}
if (old_source != source && old_source != nullptr) {
@@ -182,10 +196,8 @@ class ViEEncoder::VideoSourceProxy {
void SetWantsRotationApplied(bool rotation_applied) {
rtc::CritScope lock(&crit_);
sink_wants_.rotation_applied = rotation_applied;
- disabled_scaling_sink_wants_.rotation_applied = rotation_applied;
- if (source_) {
- source_->AddOrUpdateSink(vie_encoder_, current_wants());
- }
+ if (source_)
+ source_->AddOrUpdateSink(vie_encoder_, sink_wants_);
}
void RequestResolutionLowerThan(int pixel_count) {
@@ -209,6 +221,24 @@ class ViEEncoder::VideoSourceProxy {
source_->AddOrUpdateSink(vie_encoder_, sink_wants_);
}
+ void RequestFramerateLowerThan(int framerate_fps) {
+ // Called on the encoder task queue.
+ rtc::CritScope lock(&crit_);
+ if (!IsFramerateScalingEnabledLocked()) {
+ // This can happen since |degradation_preference_| is set on
+ // libjingle's worker thread but the adaptation is done on the encoder
+ // task queue.
+ return;
+ }
+ // The input video frame rate will be scaled down to
+ const int framerate_wanted = (framerate_fps * 2) / 3;
+ if (framerate_fps < kMinFramerateFps)
magjed_webrtc 2017/02/27 09:30:35 Shouldn't it be 'framerate_wanted < kMinFramerateF
sprang_webrtc 2017/02/27 12:51:49 I think I intended it to be framerate_fps, but pla
magjed_webrtc 2017/02/28 14:21:55 Hmm, maybe just do: framerate_wanted = max(kMinFra
sprang_webrtc 2017/02/28 15:15:30 Done.
+ return;
+ sink_wants_.max_framerate_fps_.emplace(framerate_wanted);
+ if (source_)
+ source_->AddOrUpdateSink(vie_encoder_, sink_wants_);
+ }
+
void RequestHigherResolutionThan(int pixel_count) {
rtc::CritScope lock(&crit_);
if (!IsResolutionScalingEnabledLocked()) {
@@ -229,6 +259,22 @@ class ViEEncoder::VideoSourceProxy {
source_->AddOrUpdateSink(vie_encoder_, sink_wants_);
}
+ void RequestHigherFramerateThan(int framerate_fps) {
+ // Called on the encoder task queue.
+ rtc::CritScope lock(&crit_);
+ if (!IsFramerateScalingEnabledLocked()) {
+ // This can happen since |degradation_preference_| is set on
+ // libjingle's worker thread but the adaptation is done on the encoder
+ // task queue.
+ return;
+ }
+ // The input video frame rate will be scaled up to
+ const int framerate_wanted = (framerate_fps * 3) / 2;
+ sink_wants_.max_framerate_fps_.emplace(framerate_wanted);
+ if (source_)
+ source_->AddOrUpdateSink(vie_encoder_, sink_wants_);
+ }
+
private:
bool IsResolutionScalingEnabledLocked() const
EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
@@ -236,17 +282,16 @@ class ViEEncoder::VideoSourceProxy {
DegradationPreference::kMaintainResolution;
}
- const rtc::VideoSinkWants& current_wants() const
+ bool IsFramerateScalingEnabledLocked() const
EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
- return IsResolutionScalingEnabledLocked() ? sink_wants_
- : disabled_scaling_sink_wants_;
+ return degradation_preference_ ==
+ DegradationPreference::kMaintainResolution;
}
rtc::CriticalSection crit_;
rtc::SequencedTaskChecker main_checker_;
ViEEncoder* const vie_encoder_;
rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_);
- rtc::VideoSinkWants disabled_scaling_sink_wants_ GUARDED_BY(&crit_);
DegradationPreference degradation_preference_ GUARDED_BY(&crit_);
rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_);
@@ -285,7 +330,6 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores,
has_received_rpsi_(false),
picture_id_rpsi_(0),
clock_(Clock::GetRealTimeClock()),
- scale_counter_(kScaleReasonSize, 0),
degradation_preference_(DegradationPreference::kMaintainResolution),
last_captured_timestamp_(0),
delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() -
@@ -302,6 +346,9 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores,
video_sender_.RegisterExternalEncoder(
settings_.encoder, settings_.payload_type, settings_.internal_source);
});
+
+ for (size_t i = 0; i < VideoSendStream::kNumDegradationPreferences; ++i)
+ scale_counter_[i].resize(kScaleReasonSize);
}
ViEEncoder::~ViEEncoder() {
@@ -476,9 +523,11 @@ void ViEEncoder::ConfigureQualityScaler() {
quality_scaler_.reset(nullptr);
initial_rampup_ = kMaxInitialFramedrop;
}
+ const std::vector<int>& scale_counter =
+ scale_counter_[static_cast<size_t>(degradation_preference_)];
stats_proxy_->SetResolutionRestrictionStats(
- degradation_preference_allows_scaling, scale_counter_[kCpu] > 0,
- scale_counter_[kQuality]);
+ degradation_preference_allows_scaling, scale_counter[kCpu] > 0,
+ scale_counter[kQuality]);
}
void ViEEncoder::OnFrame(const VideoFrame& video_frame) {
@@ -741,77 +790,132 @@ void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps,
void ViEEncoder::AdaptDown(AdaptReason reason) {
RTC_DCHECK_RUN_ON(&encoder_queue_);
- if (degradation_preference_ != DegradationPreference::kBalanced)
- return;
- RTC_DCHECK(static_cast<bool>(last_frame_info_));
- int current_pixel_count = last_frame_info_->pixel_count();
+ AdaptationRequest adaptation_request = {
+ last_frame_info_->pixel_count(),
+ stats_proxy_->GetStats().input_frame_rate,
+ AdaptationRequest::Mode::kAdaptDown};
+
if (last_adaptation_request_ &&
- last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown &&
- current_pixel_count >= last_adaptation_request_->input_pixel_count_) {
- // Don't request lower resolution if the current resolution is not lower
- // than the last time we asked for the resolution to be lowered.
- return;
+ last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown) {
+ switch (degradation_preference_) {
+ case DegradationPreference::kBalanced:
+ if (adaptation_request.input_pixel_count_ >=
+ last_adaptation_request_->input_pixel_count_) {
+ // Don't request lower resolution if the current resolution is not
magjed_webrtc 2017/02/27 09:30:35 Reflow comment.
sprang_webrtc 2017/02/27 12:51:49 Done.
+ // lower
+ // than the last time we asked for the resolution to be lowered.
+ return;
+ }
+ break;
+ case DegradationPreference::kMaintainResolution:
+ if (adaptation_request.framerate_fps_ <= 1) {
+ // Don't request lower framerate if we don't have a valid frame rate.
+ // Since framerate, unlike resolution, is a measure we have to
+ // estimate, and can fluctuate naturally over time, don't make the
+ // same kind of limitations as for resolution, but trust the overuse
+ // detector to not trigger too often.
+ return;
+ }
+ break;
+ }
}
- last_adaptation_request_.emplace(AdaptationRequest{
- current_pixel_count, AdaptationRequest::Mode::kAdaptDown});
+
+ last_adaptation_request_.emplace(adaptation_request);
+ std::vector<int>* scale_counter =
+ &scale_counter_[static_cast<size_t>(degradation_preference_)];
switch (reason) {
case kQuality:
stats_proxy_->OnQualityRestrictedResolutionChanged(
- scale_counter_[reason] + 1);
+ (*scale_counter)[reason] + 1);
break;
case kCpu:
- if (scale_counter_[reason] >= kMaxCpuDowngrades)
+ if ((*scale_counter)[reason] >= kMaxCpuDowngrades)
return;
// Update stats accordingly.
stats_proxy_->OnCpuRestrictedResolutionChanged(true);
break;
}
- ++scale_counter_[reason];
- source_proxy_->RequestResolutionLowerThan(current_pixel_count);
+ ++(*scale_counter)[reason];
+
+ switch (degradation_preference_) {
+ case DegradationPreference::kBalanced:
+ source_proxy_->RequestResolutionLowerThan(
+ adaptation_request.input_pixel_count_);
+ LOG(LS_INFO) << "Scaling down resolution.";
+ break;
+ case DegradationPreference::kMaintainResolution:
+ source_proxy_->RequestFramerateLowerThan(
+ adaptation_request.framerate_fps_);
+ LOG(LS_INFO) << "Scaling down framerate.";
+ break;
+ }
+
LOG(LS_INFO) << "Scaling down resolution.";
for (size_t i = 0; i < kScaleReasonSize; ++i) {
- LOG(LS_INFO) << "Scaled " << scale_counter_[i]
+ LOG(LS_INFO) << "Scaled " << (*scale_counter)[i]
<< " times for reason: " << (i ? "cpu" : "quality");
}
}
void ViEEncoder::AdaptUp(AdaptReason reason) {
RTC_DCHECK_RUN_ON(&encoder_queue_);
- if (scale_counter_[reason] == 0 ||
- degradation_preference_ != DegradationPreference::kBalanced) {
+ std::vector<int>* scale_counter =
+ &scale_counter_[static_cast<size_t>(degradation_preference_)];
+ if ((*scale_counter)[reason] == 0)
return;
- }
- // Only scale if resolution is higher than last time we requested higher
- // resolution.
- RTC_DCHECK(static_cast<bool>(last_frame_info_));
- int current_pixel_count = last_frame_info_->pixel_count();
+ AdaptationRequest adaptation_request = {
+ last_frame_info_->pixel_count(),
+ stats_proxy_->GetStats().input_frame_rate,
+ AdaptationRequest::Mode::kAdaptUp};
+
if (last_adaptation_request_ &&
- last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp &&
- current_pixel_count <= last_adaptation_request_->input_pixel_count_) {
- // Don't request higher resolution if the current resolution is not higher
- // than the last time we asked for the resolution to be higher.
- return;
+ last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp) {
+ switch (degradation_preference_) {
+ case DegradationPreference::kBalanced:
+ if (adaptation_request.input_pixel_count_ <=
+ last_adaptation_request_->input_pixel_count_) {
+ // Don't request higher resolution if the current resolution is not
+ // higher than the last time we asked for the resolution to be higher.
+ return;
+ }
+ break;
+ case DegradationPreference::kMaintainResolution:
+ // TODO(sprang): Don't request higher framerate if we are already at
+ // max requested fps?
+ break;
+ }
}
- last_adaptation_request_.emplace(AdaptationRequest{
- current_pixel_count, AdaptationRequest::Mode::kAdaptUp});
switch (reason) {
case kQuality:
stats_proxy_->OnQualityRestrictedResolutionChanged(
- scale_counter_[reason] - 1);
+ (*scale_counter)[reason] - 1);
break;
case kCpu:
// Update stats accordingly.
- stats_proxy_->OnCpuRestrictedResolutionChanged(scale_counter_[reason] >
+ stats_proxy_->OnCpuRestrictedResolutionChanged((*scale_counter)[reason] >
1);
break;
}
- --scale_counter_[reason];
- source_proxy_->RequestHigherResolutionThan(current_pixel_count);
+ --(*scale_counter)[reason];
+
+ switch (degradation_preference_) {
+ case DegradationPreference::kBalanced:
+ source_proxy_->RequestHigherResolutionThan(
+ adaptation_request.input_pixel_count_);
+ LOG(LS_INFO) << "Scaling up resolution.";
+ break;
+ case DegradationPreference::kMaintainResolution:
+ source_proxy_->RequestHigherFramerateThan(
+ adaptation_request.framerate_fps_);
+ LOG(LS_INFO) << "Scaling up framerate.";
+ break;
+ }
+
LOG(LS_INFO) << "Scaling up resolution.";
for (size_t i = 0; i < kScaleReasonSize; ++i) {
- LOG(LS_INFO) << "Scaled " << scale_counter_[i]
+ LOG(LS_INFO) << "Scaled " << (*scale_counter)[i]
<< " times for reason: " << (i ? "cpu" : "quality");
}
}

Powered by Google App Engine
This is Rietveld 408576698