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

Unified Diff: webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc

Issue 2897983002: Don't boost QP after drop unless there is sufficient bandwidth (Closed)
Patch Set: Updated comment Created 3 years, 7 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/modules/video_coding/codecs/vp8/screenshare_layers.cc
diff --git a/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc b/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc
index d535c617cd19ae1e028d4dddde655477ac61b1b4..ab1fea641617c7e8d1a96ea713b9b691d4dd22c9 100644
--- a/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc
+++ b/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc
@@ -26,6 +26,7 @@ static const int kOneSecond90Khz = 90000;
static const int kMinTimeBetweenSyncs = kOneSecond90Khz * 5;
static const int kMaxTimeBetweenSyncs = kOneSecond90Khz * 10;
static const int kQpDeltaThresholdForSync = 8;
+static const int kMinBitrateKbpsForQpBoost = 500;
const double ScreenshareLayers::kMaxTL0FpsReduction = 2.5;
const double ScreenshareLayers::kAcceptableTargetOvershoot = 2.0;
@@ -33,8 +34,8 @@ const double ScreenshareLayers::kAcceptableTargetOvershoot = 2.0;
constexpr int ScreenshareLayers::kMaxNumTemporalLayers;
// Always emit a frame with certain interval, even if bitrate targets have
-// been exceeded.
-const int ScreenshareLayers::kMaxFrameIntervalMs = 2000;
+// been exceeded. This prevents needless keyframe requests.
+const int ScreenshareLayers::kMaxFrameIntervalMs = 3000;
webrtc::TemporalLayers* ScreenshareTemporalLayersFactory::Create(
int simulcast_id,
@@ -95,7 +96,7 @@ TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig(
// TODO(pbos): Consider updating only last, and not all buffers.
TemporalLayers::FrameConfig tl_config(
kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate);
- tl_config.pattern_idx = static_cast<int>(kTl1);
+ tl_config.pattern_idx = static_cast<int>(TemporalLayerState::kTl1);
return tl_config;
}
@@ -110,7 +111,19 @@ TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig(
stats_.first_frame_time_ms_ = now_ms;
int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
- TemporalLayerState layer_state = kDrop;
+ int64_t ts_diff;
+ if (last_timestamp_ == -1) {
+ ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_);
+ } else {
+ ts_diff = unwrapped_timestamp - last_timestamp_;
+ }
+ // Make sure both frame droppers leak out bits.
+ layers_[0].UpdateDebt(ts_diff / 90);
+ layers_[1].UpdateDebt(ts_diff / 90);
+ last_timestamp_ = timestamp;
+
+ TemporalLayerState layer_state = TemporalLayerState::kDrop;
+
if (active_layer_ == -1 ||
layers_[active_layer_].state != TemporalLayer::State::kDropped) {
if (last_emitted_tl0_timestamp_ != -1 &&
@@ -135,53 +148,43 @@ TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig(
switch (active_layer_) {
case 0:
- layer_state = kTl0;
+ layer_state = TemporalLayerState::kTl0;
last_emitted_tl0_timestamp_ = unwrapped_timestamp;
break;
case 1:
if (TimeToSync(unwrapped_timestamp)) {
last_sync_timestamp_ = unwrapped_timestamp;
- layer_state = kTl1Sync;
+ layer_state = TemporalLayerState::kTl1Sync;
} else {
- layer_state = kTl1;
+ layer_state = TemporalLayerState::kTl1;
}
break;
case -1:
- layer_state = kDrop;
+ layer_state = TemporalLayerState::kDrop;
++stats_.num_dropped_frames_;
break;
default:
RTC_NOTREACHED();
}
- int64_t ts_diff;
- if (last_timestamp_ == -1) {
- ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_);
- } else {
- ts_diff = unwrapped_timestamp - last_timestamp_;
- }
- // Make sure both frame droppers leak out bits.
- layers_[0].UpdateDebt(ts_diff / 90);
- layers_[1].UpdateDebt(ts_diff / 90);
- last_timestamp_ = timestamp;
TemporalLayers::FrameConfig tl_config;
// TODO(pbos): Consider referencing but not updating the 'alt' buffer for all
// layers.
switch (layer_state) {
- case kDrop:
+ case TemporalLayerState::kDrop:
tl_config = TemporalLayers::FrameConfig(kNone, kNone, kNone);
break;
- case kTl0:
+ case TemporalLayerState::kTl0:
// TL0 only references and updates 'last'.
tl_config =
TemporalLayers::FrameConfig(kReferenceAndUpdate, kNone, kNone);
break;
- case kTl1:
+ case TemporalLayerState::kTl1:
// TL1 references both 'last' and 'golden' but only updates 'golden'.
tl_config =
TemporalLayers::FrameConfig(kReference, kReferenceAndUpdate, kNone);
break;
- case kTl1Sync:
+ case TemporalLayerState::kTl1Sync:
// Predict from only TL0 to allow participants to switch to the high
// bitrate stream. Updates 'golden' so that TL1 can continue to refer to
// and update 'golden' from this point on.
@@ -275,14 +278,14 @@ void ScreenshareLayers::PopulateCodecSpecific(
TemporalLayerState layer_state =
static_cast<TemporalLayerState>(tl_config.pattern_idx);
switch (layer_state) {
- case kDrop:
+ case TemporalLayerState::kDrop:
RTC_NOTREACHED();
break;
- case kTl0:
+ case TemporalLayerState::kTl0:
vp8_info->temporalIdx = 0;
break;
- case kTl1:
- case kTl1Sync:
+ case TemporalLayerState::kTl1:
+ case TemporalLayerState::kTl1Sync:
vp8_info->temporalIdx = 1;
break;
}
@@ -358,17 +361,30 @@ bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) {
max_qp_ = cfg->rc_max_quantizer;
// After a dropped frame, a frame with max qp will be encoded and the
// quality will then ramp up from there. To boost the speed of recovery,
- // encode the next frame with lower max qp. TL0 is the most important to
- // improve since the errors in this layer will propagate to TL1.
+ // encode the next frame with lower max qp, if there is sufficient
+ // bandwidth to do so without causing excessive delay.
+ // TL0 is the most important to improve since the errors in this layer
+ // will propagate to TL1.
// Currently, reduce max qp by 20% for TL0 and 15% for TL1.
- layers_[0].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 80) / 100);
- layers_[1].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 85) / 100);
+ if (layers_[1].target_rate_kbps_ >= kMinBitrateKbpsForQpBoost) {
+ layers_[0].enhanced_max_qp =
+ min_qp_ + (((max_qp_ - min_qp_) * 80) / 100);
+ layers_[1].enhanced_max_qp =
+ min_qp_ + (((max_qp_ - min_qp_) * 85) / 100);
+ } else {
+ layers_[0].enhanced_max_qp = -1;
+ layers_[1].enhanced_max_qp = -1;
+ }
}
if (capture_framerate_) {
int avg_frame_size =
(target_bitrate_kbps * 1000) / (8 * *capture_framerate_);
- max_debt_bytes_ = 4 * avg_frame_size;
+ // Allow max debt to be the size of a single optimal frame.
+ // TODO(sprang): Determine if this needs to be adjusted by some factor.
+ // (Lower values may cause more frame drops, higher may lead to queuing
+ // delays.)
+ max_debt_bytes_ = avg_frame_size;
}
bitrate_updated_ = false;
@@ -391,8 +407,6 @@ bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) {
adjusted_max_qp = layers_[active_layer_].enhanced_max_qp;
layers_[active_layer_].state = TemporalLayer::State::kNormal;
} else {
- if (max_qp_ == -1)
- return cfg_updated;
adjusted_max_qp = max_qp_; // Set the normal max qp.
}

Powered by Google App Engine
This is Rietveld 408576698