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

Unified Diff: remoting/codec/video_encoder_vpx.cc

Issue 1908203002: Adapt encoder behavior to target bitrate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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
« no previous file with comments | « remoting/codec/video_encoder_vpx.h ('k') | remoting/proto/video.proto » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/codec/video_encoder_vpx.cc
diff --git a/remoting/codec/video_encoder_vpx.cc b/remoting/codec/video_encoder_vpx.cc
index e281ef58efbc9c9e092c3b2efadf04b528dbebdf..ea557b94818f8f31e86301657921517ce51b2c39 100644
--- a/remoting/codec/video_encoder_vpx.cc
+++ b/remoting/codec/video_encoder_vpx.cc
@@ -42,11 +42,13 @@ const int kVp9I444ProfileNumber = 1;
const int kVp9AqModeNone = 0;
const int kVp9AqModeCyclicRefresh = 3;
+const int kDefaultTargetBitrateKbps = 1000;
+
void SetCommonCodecParameters(vpx_codec_enc_cfg_t* config,
const webrtc::DesktopSize& size) {
// Use millisecond granularity time base.
config->g_timebase.num = 1;
- config->g_timebase.den = 1000;
+ config->g_timebase.den = base::Time::kMicrosecondsPerSecond;
config->g_w = size.width();
config->g_h = size.height();
@@ -61,19 +63,20 @@ void SetCommonCodecParameters(vpx_codec_enc_cfg_t* config,
config->kf_min_dist = 10000;
config->kf_max_dist = 10000;
- // Using 2 threads gives a great boost in performance for most systems with
- // adequate processing power. NB: Going to multiple threads on low end
- // windows systems can really hurt performance.
- // http://crbug.com/99179
- config->g_threads = (base::SysInfo::NumberOfProcessors() > 2) ? 2 : 1;
+ // Allow multiple cores on a system to be used for encoding for
+ // performance while at the same time ensuring we do not saturate.
+ config->g_threads = (base::SysInfo::NumberOfProcessors() + 1) / 2;
+
+ // Do not drop any frames at encoder.
+ config->rc_dropframe_thresh = 0;
+ // We do not want variations in bandwidth.
+ config->rc_end_usage = VPX_CBR;
+ config->rc_undershoot_pct = 100;
+ config->rc_overshoot_pct = 15;
}
void SetVp8CodecParameters(vpx_codec_enc_cfg_t* config,
const webrtc::DesktopSize& size) {
- // Adjust default target bit-rate to account for actual desktop size.
- config->rc_target_bitrate = size.width() * size.height() *
- config->rc_target_bitrate / config->g_w / config->g_h;
-
SetCommonCodecParameters(config, size);
// Value of 2 means using the real time profile. This is basically a
@@ -81,9 +84,11 @@ void SetVp8CodecParameters(vpx_codec_enc_cfg_t* config,
// encoding.
config->g_profile = 2;
- // Clamping the quantizer constrains the worst-case quality and CPU usage.
+ // To enable remoting to be highly interactive and allow the target bitrate
+ // to be met, we relax the max quantizer. The quality will get topped-off
+ // in subsequent frames.
config->rc_min_quantizer = 20;
- config->rc_max_quantizer = 30;
+ config->rc_max_quantizer = 63;
}
void SetVp9CodecParameters(vpx_codec_enc_cfg_t* config,
@@ -268,14 +273,34 @@ void VideoEncoderVpx::SetLosslessColor(bool want_lossless) {
}
}
+void VideoEncoderVpx::UpdateTargetBitrate(uint32_t new_bitrate) {
+ target_bitrate_kbps_ = new_bitrate;
+ // Configuration not initialized.
+ if (config_.g_timebase.den == 0)
+ return;
+
+ if (config_.rc_target_bitrate == new_bitrate)
+ return;
+ config_.rc_target_bitrate = new_bitrate;
+
+ // 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";
+}
+
std::unique_ptr<VideoPacket> VideoEncoderVpx::Encode(
const webrtc::DesktopFrame& frame,
uint32_t flags) {
DCHECK_LE(32, frame.size().width());
DCHECK_LE(32, frame.size().height());
- // If there is nothing to encode, and nothing to top-off, then return nothing.
- if (frame.updated_region().is_empty() && !encode_unchanged_frame_)
+ // VP8: Encode top-off is controlled at the call site.
+ // VP9: Based on information fetching active map, we return here if there is
+ // nothing
+ // to top-off.
Sergey Ulanov 2016/04/21 22:55:49 nit: comment formatting
+ if (use_vp9_ && frame.updated_region().is_empty() && !encode_unchanged_frame_)
return nullptr;
// Create or reconfigure the codec to match the size of |frame|.
@@ -285,29 +310,31 @@ std::unique_ptr<VideoPacket> VideoEncoderVpx::Encode(
Configure(frame.size());
}
- // Convert the updated capture data ready for encode.
- webrtc::DesktopRegion updated_region;
- PrepareImage(frame, &updated_region);
-
- // Update active map based on updated region.
- SetActiveMapFromRegion(updated_region);
-
- // Apply active map to the encoder.
vpx_active_map_t act_map;
act_map.rows = active_map_size_.height();
act_map.cols = active_map_size_.width();
act_map.active_map = active_map_.get();
- if (vpx_codec_control(codec_.get(), VP8E_SET_ACTIVEMAP, &act_map)) {
- LOG(ERROR) << "Unable to apply active map";
- }
- if (flags & REQUEST_KEY_FRAME)
- vpx_codec_control(codec_.get(), VP8E_SET_FRAME_FLAGS, VPX_EFLAG_FORCE_KF);
+ webrtc::DesktopRegion updated_region;
+ if (!frame.updated_region().is_empty()) {
+ // Convert the updated capture data ready for encode.
+ PrepareImage(frame, &updated_region);
+
+ // Update active map based on updated region.
+ 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";
+ }
+ }
- // Do the actual encoding.
- int timestamp = (clock_->NowTicks() - timestamp_base_).InMilliseconds();
+ // Frame rate is adapted based on how well the encoder meets the target
+ // bandwidth requiremetn. We specify a target rate of 1 / 15 fps here.
vpx_codec_err_t ret = vpx_codec_encode(
- codec_.get(), image_.get(), timestamp, 1, 0, VPX_DL_REALTIME);
+ codec_.get(), image_.get(), 0, 66666,
+ (flags & REQUEST_KEY_FRAME) ? VPX_EFLAG_FORCE_KF : 0, VPX_DL_REALTIME);
DCHECK_EQ(ret, VPX_CODEC_OK)
<< "Encoding error: " << vpx_codec_err_to_string(ret) << "\n"
<< "Details: " << vpx_codec_error(codec_.get()) << "\n"
@@ -340,11 +367,16 @@ std::unique_ptr<VideoPacket> VideoEncoderVpx::Encode(
if (!vpx_packet)
continue;
+ int quantizer = -1;
switch (vpx_packet->kind) {
case VPX_CODEC_CX_FRAME_PKT:
got_data = true;
packet->set_data(vpx_packet->data.frame.buf, vpx_packet->data.frame.sz);
packet->set_key_frame(vpx_packet->data.frame.flags & VPX_FRAME_IS_KEY);
+ CHECK_EQ(vpx_codec_control(codec_.get(), VP8E_GET_LAST_QUANTIZER_64,
+ &quantizer),
+ VPX_CODEC_OK);
+ packet->set_quantizer(quantizer);
break;
default:
break;
@@ -356,8 +388,12 @@ std::unique_ptr<VideoPacket> VideoEncoderVpx::Encode(
VideoEncoderVpx::VideoEncoderVpx(bool use_vp9)
: use_vp9_(use_vp9),
+ target_bitrate_kbps_(kDefaultTargetBitrateKbps),
encode_unchanged_frame_(false),
- clock_(&default_tick_clock_) {}
+ clock_(&default_tick_clock_) {
+ // Indicates config is still uninitialized.
+ config_.g_timebase.den = 0;
+}
void VideoEncoderVpx::Configure(const webrtc::DesktopSize& size) {
DCHECK(use_vp9_ || !lossless_color_);
@@ -385,32 +421,27 @@ void VideoEncoderVpx::Configure(const webrtc::DesktopSize& size) {
}
}
- // (Re)Set the base for frame timestamps if the codec is being (re)created.
- if (!codec_) {
- timestamp_base_ = clock_->NowTicks();
- }
-
// Fetch a default configuration for the desired codec.
const vpx_codec_iface_t* interface =
use_vp9_ ? vpx_codec_vp9_cx() : vpx_codec_vp8_cx();
- vpx_codec_enc_cfg_t config;
- vpx_codec_err_t ret = vpx_codec_enc_config_default(interface, &config, 0);
+ vpx_codec_err_t ret = vpx_codec_enc_config_default(interface, &config_, 0);
DCHECK_EQ(VPX_CODEC_OK, ret) << "Failed to fetch default configuration";
// Customize the default configuration to our needs.
if (use_vp9_) {
- SetVp9CodecParameters(&config, size, lossless_color_, lossless_encode_);
+ SetVp9CodecParameters(&config_, size, lossless_color_, lossless_encode_);
} else {
- SetVp8CodecParameters(&config, size);
+ SetVp8CodecParameters(&config_, size);
}
+ config_.rc_target_bitrate = target_bitrate_kbps_;
// Initialize or re-configure the codec with the custom configuration.
if (!codec_) {
codec_.reset(new vpx_codec_ctx_t);
- ret = vpx_codec_enc_init(codec_.get(), interface, &config, 0);
+ ret = vpx_codec_enc_init(codec_.get(), interface, &config_, 0);
CHECK_EQ(VPX_CODEC_OK, ret) << "Failed to initialize codec";
} else {
- ret = vpx_codec_enc_config_set(codec_.get(), &config);
+ ret = vpx_codec_enc_config_set(codec_.get(), &config_);
CHECK_EQ(VPX_CODEC_OK, ret) << "Failed to reconfigure codec";
}
« no previous file with comments | « remoting/codec/video_encoder_vpx.h ('k') | remoting/proto/video.proto » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698