Chromium Code Reviews| Index: remoting/codec/webrtc_video_encoder_vpx.cc |
| diff --git a/remoting/codec/webrtc_video_encoder_vpx.cc b/remoting/codec/webrtc_video_encoder_vpx.cc |
| index 658a7bcc7ac66f95b6871ec41337e17c74bfe32a..dcd2a7a657347040c188953681d69386cd67640f 100644 |
| --- a/remoting/codec/webrtc_video_encoder_vpx.cc |
| +++ b/remoting/codec/webrtc_video_encoder_vpx.cc |
| @@ -44,9 +44,6 @@ const int kVp9AqModeCyclicRefresh = 3; |
| const int kDefaultTargetBitrateKbps = 1000; |
| -// Target quantizer at which stop the encoding top-off. |
| -const int kTargetQuantizerForVp8TopOff = 30; |
| - |
| void SetCommonCodecParameters(vpx_codec_enc_cfg_t* config, |
| const webrtc::DesktopSize& size) { |
| // Use millisecond granularity time base. |
| @@ -282,13 +279,6 @@ std::unique_ptr<WebrtcVideoEncoder::EncodedFrame> WebrtcVideoEncoderVpx::Encode( |
| DCHECK_LE(32, frame.size().width()); |
| DCHECK_LE(32, frame.size().height()); |
| - // Based on information fetching active map, we return here if there is |
| - // nothing to top-off. |
| - if (frame.updated_region().is_empty() && !encode_unchanged_frame_ && |
| - !params.key_frame) { |
| - return nullptr; |
| - } |
| - |
| // Create or reconfigure the codec to match the size of |frame|. |
| if (!codec_ || |
| (image_ && |
| @@ -296,7 +286,7 @@ std::unique_ptr<WebrtcVideoEncoder::EncodedFrame> WebrtcVideoEncoderVpx::Encode( |
| Configure(frame.size()); |
| } |
| - UpdateTargetBitrate(params.bitrate_kbps); |
| + UpdateConfig(params); |
| vpx_active_map_t act_map; |
| act_map.rows = active_map_size_.height(); |
| @@ -304,18 +294,17 @@ std::unique_ptr<WebrtcVideoEncoder::EncodedFrame> WebrtcVideoEncoderVpx::Encode( |
| act_map.active_map = active_map_.get(); |
| webrtc::DesktopRegion updated_region; |
| - if (!frame.updated_region().is_empty()) { |
| - // Convert the updated capture data ready for encode. |
| - PrepareImage(frame, &updated_region); |
| + // Convert the updated capture data ready for encode. |
| + PrepareImage(frame, &updated_region); |
| - // Update active map based on updated region. |
| - SetActiveMapFromRegion(updated_region); |
| + // Update active map based on updated region. |
| + if (params.clear_active_map) |
| + ClearActiveMap(); |
| + SetActiveMapFromRegion(updated_region); |
| - // Apply active map to the encoder. |
| - |
| - if (vpx_codec_control(codec_.get(), VP8E_SET_ACTIVEMAP, &act_map)) { |
| - LOG(ERROR) << "Unable to apply active map"; |
| - } |
| + // Apply active map to the encoder. |
| + if (vpx_codec_control(codec_.get(), VP8E_SET_ACTIVEMAP, &act_map)) { |
| + LOG(ERROR) << "Unable to apply active map"; |
| } |
| vpx_codec_err_t ret = vpx_codec_encode( |
| @@ -334,13 +323,6 @@ std::unique_ptr<WebrtcVideoEncoder::EncodedFrame> WebrtcVideoEncoderVpx::Encode( |
| DCHECK_EQ(ret, VPX_CODEC_OK) |
| << "Failed to fetch active map: " << vpx_codec_err_to_string(ret) |
| << "\n"; |
| - |
| - // If the encoder output no changes then there's nothing left to top-off. |
| - encode_unchanged_frame_ = !updated_region.is_empty(); |
| - } else { |
| - // Always set |encode_unchanged_frame_| when using VP8. It will be reset |
| - // below once the target quantizer value is reached. |
| - encode_unchanged_frame_ = true; |
| } |
| UpdateRegionFromActiveMap(&updated_region); |
| @@ -368,13 +350,9 @@ std::unique_ptr<WebrtcVideoEncoder::EncodedFrame> WebrtcVideoEncoderVpx::Encode( |
| vpx_packet->data.frame.sz); |
| encoded_frame->key_frame = |
| vpx_packet->data.frame.flags & VPX_FRAME_IS_KEY; |
| - int quantizer = -1; |
| CHECK_EQ(vpx_codec_control(codec_.get(), VP8E_GET_LAST_QUANTIZER_64, |
| - &quantizer), |
| + &(encoded_frame->quantizer)), |
| VPX_CODEC_OK); |
| - // VP8: Stop top-off as soon as the target quantizer value is reached. |
| - if (!use_vp9_ && quantizer <= kTargetQuantizerForVp8TopOff) |
| - encode_unchanged_frame_ = false; |
| break; |
| } |
| default: |
| @@ -387,8 +365,6 @@ std::unique_ptr<WebrtcVideoEncoder::EncodedFrame> WebrtcVideoEncoderVpx::Encode( |
| WebrtcVideoEncoderVpx::WebrtcVideoEncoderVpx(bool use_vp9) |
| : use_vp9_(use_vp9), |
| - target_bitrate_kbps_(kDefaultTargetBitrateKbps), |
| - encode_unchanged_frame_(false), |
| clock_(&default_tick_clock_) { |
| // Indicates config is still uninitialized. |
| config_.g_timebase.den = 0; |
| @@ -409,6 +385,7 @@ void WebrtcVideoEncoderVpx::Configure(const webrtc::DesktopSize& size) { |
| (size.height() + kMacroBlockSize - 1) / kMacroBlockSize); |
| active_map_.reset( |
| new uint8_t[active_map_size_.width() * active_map_size_.height()]); |
| + ClearActiveMap(); |
| // TODO(wez): Remove this hack once VPX can handle frame size reconfiguration. |
| // See https://code.google.com/p/webm/issues/detail?id=912. |
| @@ -432,7 +409,8 @@ void WebrtcVideoEncoderVpx::Configure(const webrtc::DesktopSize& size) { |
| } else { |
| SetVp8CodecParameters(&config_, size); |
| } |
| - config_.rc_target_bitrate = target_bitrate_kbps_; |
| + |
| + config_.rc_target_bitrate = kDefaultTargetBitrateKbps; |
| // Initialize or re-configure the codec with the custom configuration. |
| if (!codec_) { |
| @@ -452,22 +430,41 @@ void WebrtcVideoEncoderVpx::Configure(const webrtc::DesktopSize& size) { |
| } |
| } |
| -void WebrtcVideoEncoderVpx::UpdateTargetBitrate(int new_bitrate_kbps) { |
| - target_bitrate_kbps_ = new_bitrate_kbps; |
| - |
| +void WebrtcVideoEncoderVpx::UpdateConfig(const FrameParams& params) { |
| // Configuration not initialized. |
| if (config_.g_timebase.den == 0) |
| return; |
| - if (config_.rc_target_bitrate == static_cast<unsigned int>(new_bitrate_kbps)) |
| + bool changed = false; |
| + |
| + if (params.bitrate_kbps >= 0 && |
| + config_.rc_target_bitrate != |
| + static_cast<unsigned int>(params.bitrate_kbps)) { |
| + config_.rc_target_bitrate = params.bitrate_kbps; |
| + changed = true; |
| + } |
| + |
| + if (params.vpx_min_quantizer >= 0 && |
| + config_.rc_min_quantizer != |
| + static_cast<unsigned int>(params.vpx_min_quantizer)) { |
| + config_.rc_min_quantizer = params.vpx_min_quantizer; |
| + changed = true; |
| + } |
| + |
| + if (params.vpx_max_quantizer >= 0 && |
| + config_.rc_max_quantizer != |
| + static_cast<unsigned int>(params.vpx_max_quantizer)) { |
| + config_.rc_max_quantizer = params.vpx_max_quantizer; |
| + changed = true; |
| + } |
| + |
| + if (!changed) |
| return; |
| - config_.rc_target_bitrate = new_bitrate_kbps; |
| // Update encoder context. |
| if (vpx_codec_enc_config_set(codec_.get(), &config_)) |
| NOTREACHED() << "Unable to set encoder config"; |
| - VLOG(1) << "New rc_target_bitrate: " << new_bitrate_kbps << " kbps"; |
| } |
| void WebrtcVideoEncoderVpx::PrepareImage( |
| @@ -480,8 +477,8 @@ void WebrtcVideoEncoderVpx::PrepareImage( |
| updated_region->Clear(); |
| if (image_) { |
| - // Pad each rectangle to avoid the block-artefact filters in libvpx from |
| - // introducing artefacts; VP9 includes up to 8px either side, and VP8 up to |
| + // Pad each rectangle to avoid the block-artifact filters in libvpx from |
| + // introducing artifacts; VP9 includes up to 8px either side, and VP8 up to |
| // 3px, so unchanged pixels up to that far out may still be affected by the |
| // changes in the updated region, and so must be listed in the active map. |
| // After padding we align each rectangle to 16x16 active-map macroblocks. |
| @@ -552,12 +549,14 @@ void WebrtcVideoEncoderVpx::PrepareImage( |
| } |
| } |
| -void WebrtcVideoEncoderVpx::SetActiveMapFromRegion( |
| - const webrtc::DesktopRegion& updated_region) { |
| +void WebrtcVideoEncoderVpx::ClearActiveMap() { |
| // Clear active map first. |
|
Irfan
2016/09/14 20:01:29
DCHECK(active_map_) ?
Sergey Ulanov
2016/09/16 00:02:47
Done.
|
| memset(active_map_.get(), 0, |
| active_map_size_.width() * active_map_size_.height()); |
| +} |
| +void WebrtcVideoEncoderVpx::SetActiveMapFromRegion( |
| + const webrtc::DesktopRegion& updated_region) { |
| // Mark updated areas active. |
| for (webrtc::DesktopRegion::Iterator r(updated_region); !r.IsAtEnd(); |
| r.Advance()) { |