diff options
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.cc | 113 |
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) * |