summaryrefslogtreecommitdiff
path: root/chromium/third_party/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc')
-rw-r--r--chromium/third_party/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc113
1 files changed, 76 insertions, 37 deletions
diff --git a/chromium/third_party/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc b/chromium/third_party/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
index abb54b6b932..a09a7d944b3 100644
--- a/chromium/third_party/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
+++ b/chromium/third_party/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
@@ -54,7 +54,7 @@ constexpr double kLowRateFactor = 1.0;
constexpr double kHighRateFactor = 2.0;
// These settings correspond to the settings in vpx_codec_enc_cfg.
-struct Vp8RateSettings {
+struct Vp9RateSettings {
uint32_t rc_undershoot_pct;
uint32_t rc_overshoot_pct;
uint32_t rc_buf_sz;
@@ -161,9 +161,9 @@ uint32_t Interpolate(uint32_t low,
return static_cast<uint32_t>(((1.0 - factor) * low) + (factor * high) + 0.5);
}
-Vp8RateSettings GetRateSettings(double bandwidth_headroom_factor) {
- static const Vp8RateSettings low_settings{1000u, 0u, 100u, 30u, 40u};
- static const Vp8RateSettings high_settings{100u, 15u, 1000u, 600u, 5u};
+Vp9RateSettings GetRateSettings(double bandwidth_headroom_factor) {
+ static const Vp9RateSettings low_settings{100u, 0u, 100u, 33u, 40u};
+ static const Vp9RateSettings high_settings{50u, 50u, 1000u, 700u, 5u};
if (bandwidth_headroom_factor <= kLowRateFactor) {
return low_settings;
@@ -171,7 +171,7 @@ Vp8RateSettings GetRateSettings(double bandwidth_headroom_factor) {
return high_settings;
}
- Vp8RateSettings settings;
+ Vp9RateSettings settings;
settings.rc_undershoot_pct =
Interpolate(low_settings.rc_undershoot_pct,
high_settings.rc_undershoot_pct, bandwidth_headroom_factor);
@@ -191,7 +191,7 @@ Vp8RateSettings GetRateSettings(double bandwidth_headroom_factor) {
}
void UpdateRateSettings(vpx_codec_enc_cfg_t* config,
- const Vp8RateSettings& new_settings) {
+ const Vp9RateSettings& new_settings) {
config->rc_undershoot_pct = new_settings.rc_undershoot_pct;
config->rc_overshoot_pct = new_settings.rc_overshoot_pct;
config->rc_buf_sz = new_settings.rc_buf_sz;
@@ -316,8 +316,7 @@ bool VP9EncoderImpl::SetSvcRates(
}
framerate_controller_[sl_idx].SetTargetRate(
- std::min(static_cast<float>(codec_.maxFramerate),
- codec_.spatialLayers[sl_idx].maxFramerate));
+ codec_.spatialLayers[sl_idx].maxFramerate);
}
} else {
float rate_ratio[VPX_MAX_LAYERS] = {0};
@@ -535,24 +534,18 @@ int VP9EncoderImpl::InitEncode(const VideoCodec* inst,
inter_layer_pred_ = inst->VP9().interLayerPred;
- different_framerates_used_ = false;
- for (size_t sl_idx = 1; sl_idx < num_spatial_layers_; ++sl_idx) {
- if (std::abs(codec_.spatialLayers[sl_idx].maxFramerate -
- codec_.spatialLayers[0].maxFramerate) > 1e-9) {
- different_framerates_used_ = true;
- }
- }
-
- if (different_framerates_used_ && !is_flexible_mode_) {
- RTC_LOG(LS_ERROR) << "Flexible mode required for different framerates on "
- "different spatial layers";
+ if (num_spatial_layers_ > 1 &&
+ codec_.mode == VideoCodecMode::kScreensharing && !is_flexible_mode_) {
+ RTC_LOG(LS_ERROR) << "Flexible mode is required for screenshare with "
+ "several spatial layers";
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
}
// External reference control is required for different frame rate on spatial
// layers because libvpx generates rtp incompatible references in this case.
external_ref_control_ = field_trial::IsEnabled("WebRTC-Vp9ExternalRefCtrl") ||
- different_framerates_used_ ||
+ (num_spatial_layers_ > 1 &&
+ codec_.mode == VideoCodecMode::kScreensharing) ||
inter_layer_pred_ == InterLayerPredMode::kOn;
if (num_temporal_layers_ == 1) {
@@ -589,7 +582,8 @@ int VP9EncoderImpl::InitEncode(const VideoCodec* inst,
if (external_ref_control_) {
config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
- if (num_temporal_layers_ > 1 && different_framerates_used_) {
+ if (num_temporal_layers_ > 1 && num_spatial_layers_ > 1 &&
+ codec_.mode == VideoCodecMode::kScreensharing) {
// External reference control for several temporal layers with different
// frame rates on spatial layers is not implemented yet.
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
@@ -717,18 +711,35 @@ int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) {
RTC_NOTREACHED();
}
- // Configure encoder to drop entire superframe whenever it needs to drop
- // a layer. This mode is prefered over per-layer dropping which causes
- // quality flickering and is not compatible with RTP non-flexible mode.
- vpx_svc_frame_drop_t svc_drop_frame;
- memset(&svc_drop_frame, 0, sizeof(svc_drop_frame));
- svc_drop_frame.framedrop_mode =
- full_superframe_drop_ ? FULL_SUPERFRAME_DROP : CONSTRAINED_LAYER_DROP;
- svc_drop_frame.max_consec_drop = std::numeric_limits<int>::max();
- for (size_t i = 0; i < num_spatial_layers_; ++i) {
- svc_drop_frame.framedrop_thresh[i] = config_->rc_dropframe_thresh;
+ memset(&svc_drop_frame_, 0, sizeof(svc_drop_frame_));
+ dropping_only_base_layer_ = inter_layer_pred_ == InterLayerPredMode::kOn &&
+ codec_.mode == VideoCodecMode::kScreensharing &&
+ num_spatial_layers_ > 1;
+ if (dropping_only_base_layer_) {
+ // Screenshare dropping mode: only the base spatial layer
+ // can be dropped and it doesn't affect other spatial layers.
+ // This mode is preferable because base layer has low bitrate targets
+ // and more likely to drop frames. It shouldn't reduce framerate on other
+ // layers.
+ svc_drop_frame_.framedrop_mode = LAYER_DROP;
+ svc_drop_frame_.max_consec_drop = 5;
+ svc_drop_frame_.framedrop_thresh[0] = config_->rc_dropframe_thresh;
+ for (size_t i = 1; i < num_spatial_layers_; ++i) {
+ svc_drop_frame_.framedrop_thresh[i] = 0;
+ }
+ } else {
+ // Configure encoder to drop entire superframe whenever it needs to drop
+ // a layer. This mode is preferred over per-layer dropping which causes
+ // quality flickering and is not compatible with RTP non-flexible mode.
+ svc_drop_frame_.framedrop_mode =
+ full_superframe_drop_ ? FULL_SUPERFRAME_DROP : CONSTRAINED_LAYER_DROP;
+ svc_drop_frame_.max_consec_drop = std::numeric_limits<int>::max();
+ for (size_t i = 0; i < num_spatial_layers_; ++i) {
+ svc_drop_frame_.framedrop_thresh[i] = config_->rc_dropframe_thresh;
+ }
}
- vpx_codec_control(encoder_, VP9E_SET_SVC_FRAME_DROP_LAYER, &svc_drop_frame);
+ vpx_codec_control(encoder_, VP9E_SET_SVC_FRAME_DROP_LAYER,
+ &svc_drop_frame_);
}
// Register callback for getting each spatial layer.
@@ -894,9 +905,22 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
if (less_layers_requested || more_layers_requested) {
ss_info_needed_ = true;
}
+ if (more_layers_requested && !force_key_frame_) {
+ // Prohibit drop of all layers for the next frame, so newly enabled
+ // layer would have a valid spatial reference.
+ for (size_t i = 0; i < num_spatial_layers_; ++i) {
+ svc_drop_frame_.framedrop_thresh[i] = 0;
+ }
+ }
}
}
+ if (num_spatial_layers_ > 1) {
+ // Update frame dropping settings as they may change on per-frame basis.
+ vpx_codec_control(encoder_, VP9E_SET_SVC_FRAME_DROP_LAYER,
+ &svc_drop_frame_);
+ }
+
if (vpx_codec_enc_config_set(encoder_, config_)) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
@@ -964,7 +988,8 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
if (VideoCodecMode::kScreensharing == codec_.mode) {
for (uint8_t sl_idx = 0; sl_idx < num_active_spatial_layers_; ++sl_idx) {
ref_config.duration[sl_idx] = static_cast<int64_t>(
- 90000 / framerate_controller_[sl_idx].GetTargetRate());
+ 90000 / (std::min(static_cast<float>(codec_.maxFramerate),
+ framerate_controller_[sl_idx].GetTargetRate())));
}
}
@@ -983,8 +1008,9 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
RTC_DCHECK_GE(framerate_controller_.size(), num_active_spatial_layers_);
float target_framerate_fps =
(codec_.mode == VideoCodecMode::kScreensharing)
- ? framerate_controller_[num_active_spatial_layers_ - 1]
- .GetTargetRate()
+ ? std::min(static_cast<float>(codec_.maxFramerate),
+ framerate_controller_[num_active_spatial_layers_ - 1]
+ .GetTargetRate())
: codec_.maxFramerate;
uint32_t duration = static_cast<uint32_t>(90000 / target_framerate_fps);
const vpx_codec_err_t rv = vpx_codec_encode(encoder_, raw_, timestamp_,
@@ -1199,6 +1225,8 @@ void VP9EncoderImpl::FillReferenceIndices(const vpx_codec_cx_pkt& pkt,
// It is safe to ignore this requirement if inter-layer prediction is
// enabled for all frames when all base frames are relayed to receiver.
RTC_DCHECK_EQ(ref_buf.spatial_layer_id, layer_id.spatial_layer_id);
+ } else {
+ RTC_DCHECK_LE(ref_buf.spatial_layer_id, layer_id.spatial_layer_id);
}
RTC_DCHECK_LE(ref_buf.temporal_layer_id, layer_id.temporal_layer_id);
@@ -1318,7 +1346,7 @@ vpx_svc_ref_frame_config_t VP9EncoderImpl::SetReferences(
const bool same_spatial_layer =
ref_buf_[buf_idx].spatial_layer_id == sl_idx;
bool correct_pid = false;
- if (different_framerates_used_) {
+ if (is_flexible_mode_) {
correct_pid = pid_diff < kMaxAllowedPidDIff;
} else {
// Below code assumes single temporal referecence.
@@ -1442,6 +1470,16 @@ int VP9EncoderImpl::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) {
void VP9EncoderImpl::DeliverBufferedFrame(bool end_of_picture) {
if (encoded_image_.size() > 0) {
+ if (num_spatial_layers_ > 1) {
+ // Restore frame dropping settings, as dropping may be temporary forbidden
+ // due to dynamically enabled layers.
+ svc_drop_frame_.framedrop_thresh[0] = config_->rc_dropframe_thresh;
+ for (size_t i = 1; i < num_spatial_layers_; ++i) {
+ svc_drop_frame_.framedrop_thresh[i] =
+ dropping_only_base_layer_ ? 0 : config_->rc_dropframe_thresh;
+ }
+ }
+
codec_specific_.codecSpecific.VP9.end_of_picture = end_of_picture;
// No data partitioning in VP9, so 1 partition only.
@@ -1519,7 +1557,8 @@ size_t VP9EncoderImpl::SteadyStateSize(int sid, int tid) {
const size_t bitrate_bps = current_bitrate_allocation_.GetBitrate(
sid, tid == kNoTemporalIdx ? 0 : tid);
const float fps = (codec_.mode == VideoCodecMode::kScreensharing)
- ? framerate_controller_[sid].GetTargetRate()
+ ? std::min(static_cast<float>(codec_.maxFramerate),
+ framerate_controller_[sid].GetTargetRate())
: codec_.maxFramerate;
return static_cast<size_t>(
bitrate_bps / (8 * fps) *