| 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 e8214974402f5a6903e4f71b0d3ee64363b531d7..d0c8b30e1e1b7efd4201651b59cfc74828b5e4d9 100644
|
| --- a/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc
|
| +++ b/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc
|
| @@ -51,6 +51,17 @@ const int ScreenshareLayers::kTl1SyncFlags =
|
| // been exceeded.
|
| const int ScreenshareLayers::kMaxFrameIntervalMs = 2000;
|
|
|
| +webrtc::TemporalLayers* ScreenshareTemporalLayersFactory::Create(
|
| + int simulcast_id,
|
| + int num_temporal_layers,
|
| + uint8_t initial_tl0_pic_idx) const {
|
| + webrtc::TemporalLayers* tl = new webrtc::ScreenshareLayers(
|
| + num_temporal_layers, rand(), webrtc::Clock::GetRealTimeClock());
|
| + if (listener_)
|
| + listener_->OnTemporalLayersCreated(simulcast_id, tl);
|
| + return tl;
|
| +}
|
| +
|
| ScreenshareLayers::ScreenshareLayers(int num_temporal_layers,
|
| uint8_t initial_tl0_pic_idx,
|
| Clock* clock)
|
| @@ -65,7 +76,8 @@ ScreenshareLayers::ScreenshareLayers(int num_temporal_layers,
|
| min_qp_(-1),
|
| max_qp_(-1),
|
| max_debt_bytes_(0),
|
| - frame_rate_(-1) {
|
| + framerate_(-1),
|
| + bitrate_updated_(false) {
|
| RTC_CHECK_GT(num_temporal_layers, 0);
|
| RTC_CHECK_LE(num_temporal_layers, 2);
|
| }
|
| @@ -136,7 +148,7 @@ int ScreenshareLayers::EncodeFlags(uint32_t timestamp) {
|
|
|
| int64_t ts_diff;
|
| if (last_timestamp_ == -1) {
|
| - ts_diff = kOneSecond90Khz / (frame_rate_ <= 0 ? 5 : frame_rate_);
|
| + ts_diff = kOneSecond90Khz / (framerate_ <= 0 ? 5 : framerate_);
|
| } else {
|
| ts_diff = unwrapped_timestamp - last_timestamp_;
|
| }
|
| @@ -147,47 +159,19 @@ int ScreenshareLayers::EncodeFlags(uint32_t timestamp) {
|
| return flags;
|
| }
|
|
|
| -bool ScreenshareLayers::ConfigureBitrates(int bitrate_kbps,
|
| - int max_bitrate_kbps,
|
| - int framerate,
|
| - vpx_codec_enc_cfg_t* cfg) {
|
| +std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps,
|
| + int max_bitrate_kbps,
|
| + int framerate) {
|
| layers_[0].target_rate_kbps_ = bitrate_kbps;
|
| layers_[1].target_rate_kbps_ = max_bitrate_kbps;
|
| -
|
| - int target_bitrate_kbps = bitrate_kbps;
|
| -
|
| - if (cfg != nullptr) {
|
| - if (number_of_temporal_layers_ > 1) {
|
| - // Calculate a codec target bitrate. This may be higher than TL0, gaining
|
| - // quality at the expense of frame rate at TL0. Constraints:
|
| - // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction.
|
| - // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate.
|
| - target_bitrate_kbps =
|
| - std::min(bitrate_kbps * kMaxTL0FpsReduction,
|
| - max_bitrate_kbps / kAcceptableTargetOvershoot);
|
| -
|
| - cfg->rc_target_bitrate = std::max(bitrate_kbps, target_bitrate_kbps);
|
| - }
|
| -
|
| - // Don't reconfigure qp limits during quality boost frames.
|
| - if (active_layer_ == -1 ||
|
| - layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) {
|
| - min_qp_ = cfg->rc_min_quantizer;
|
| - 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.
|
| - // 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);
|
| - }
|
| - }
|
| -
|
| - int avg_frame_size = (target_bitrate_kbps * 1000) / (8 * framerate);
|
| - max_debt_bytes_ = 4 * avg_frame_size;
|
| -
|
| - return true;
|
| + framerate_ = framerate;
|
| + bitrate_updated_ = true;
|
| +
|
| + std::vector<uint32_t> allocation;
|
| + allocation.push_back(bitrate_kbps);
|
| + if (max_bitrate_kbps > bitrate_kbps)
|
| + allocation.push_back(max_bitrate_kbps - bitrate_kbps);
|
| + return allocation;
|
| }
|
|
|
| void ScreenshareLayers::FrameEncoded(unsigned int size,
|
| @@ -279,9 +263,52 @@ bool ScreenshareLayers::TimeToSync(int64_t timestamp) const {
|
| }
|
|
|
| bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) {
|
| + bool cfg_updated = false;
|
| + if (bitrate_updated_) {
|
| + uint32_t target_bitrate_kbps = layers_[0].target_rate_kbps_;
|
| +
|
| + if (number_of_temporal_layers_ > 1) {
|
| + // Calculate a codec target bitrate. This may be higher than TL0, gaining
|
| + // quality at the expense of frame rate at TL0. Constraints:
|
| + // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction.
|
| + // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate.
|
| + target_bitrate_kbps =
|
| + std::min(layers_[0].target_rate_kbps_ * kMaxTL0FpsReduction,
|
| + layers_[1].target_rate_kbps_ / kAcceptableTargetOvershoot);
|
| +
|
| + cfg->rc_target_bitrate =
|
| + std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps);
|
| + }
|
| +
|
| + // Don't reconfigure qp limits during quality boost frames.
|
| + if (active_layer_ == -1 ||
|
| + layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) {
|
| + min_qp_ = cfg->rc_min_quantizer;
|
| + 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.
|
| + // 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 (framerate_ > 0) {
|
| + int avg_frame_size = (target_bitrate_kbps * 1000) / (8 * framerate_);
|
| + max_debt_bytes_ = 4 * avg_frame_size;
|
| + }
|
| +
|
| + bitrate_updated_ = false;
|
| + cfg_updated = true;
|
| + }
|
| +
|
| + // Don't try to update boosts state if not active yet.
|
| + if (active_layer_ == -1)
|
| + return cfg_updated;
|
| +
|
| if (max_qp_ == -1 || number_of_temporal_layers_ <= 1)
|
| - return false;
|
| - RTC_DCHECK_NE(-1, active_layer_);
|
| + return cfg_updated;
|
|
|
| // If layer is in the quality boost state (following a dropped frame), update
|
| // the configuration with the adjusted (lower) qp and set the state back to
|
| @@ -293,15 +320,16 @@ bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) {
|
| layers_[active_layer_].state = TemporalLayer::State::kNormal;
|
| } else {
|
| if (max_qp_ == -1)
|
| - return false;
|
| + return cfg_updated;
|
| adjusted_max_qp = max_qp_; // Set the normal max qp.
|
| }
|
|
|
| if (adjusted_max_qp == cfg->rc_max_quantizer)
|
| - return false;
|
| + return cfg_updated;
|
|
|
| cfg->rc_max_quantizer = adjusted_max_qp;
|
| - return true;
|
| + cfg_updated = true;
|
| + return cfg_updated;
|
| }
|
|
|
| void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) {
|
|
|