diff options
author | wez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-09 02:16:22 +0000 |
---|---|---|
committer | wez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-09 02:16:22 +0000 |
commit | 19fa2d9552faf1fb8c505e69f4683579239cd94f (patch) | |
tree | c672266b2f753d9c558e4c69c8a23a7bd309d5a1 /remoting/codec | |
parent | 22d2209e2359574649fe2ce52f3290c931b19209 (diff) | |
download | chromium_src-19fa2d9552faf1fb8c505e69f4683579239cd94f.zip chromium_src-19fa2d9552faf1fb8c505e69f4683579239cd94f.tar.gz chromium_src-19fa2d9552faf1fb8c505e69f4683579239cd94f.tar.bz2 |
Clean up common parts of VPX codec initialization.
This includes some improvements & fixes:
- VP9 is now initialized for multi-threaded encode.
- Frame timestamp base is correctly set to milliseconds.
- Frame timestamps are now set based on elapsed time.
Review URL: https://codereview.chromium.org/265113002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269151 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/codec')
-rw-r--r-- | remoting/codec/video_encoder_vpx.cc | 72 | ||||
-rw-r--r-- | remoting/codec/video_encoder_vpx.h | 3 |
2 files changed, 41 insertions, 34 deletions
diff --git a/remoting/codec/video_encoder_vpx.cc b/remoting/codec/video_encoder_vpx.cc index cee7994..59bb5dc 100644 --- a/remoting/codec/video_encoder_vpx.cc +++ b/remoting/codec/video_encoder_vpx.cc @@ -7,7 +7,6 @@ #include "base/bind.h" #include "base/logging.h" #include "base/sys_info.h" -#include "base/time/time.h" #include "media/base/yuv_convert.h" #include "remoting/base/util.h" #include "remoting/proto/video.pb.h" @@ -29,6 +28,30 @@ namespace { // map for the encoder. const int kMacroBlockSize = 16; +void SetCommonCodecParameters(const webrtc::DesktopSize& size, + vpx_codec_enc_cfg_t* config) { + // Use millisecond granularity time base. + config->g_timebase.num = 1; + config->g_timebase.den = 1000; + + // 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; + + config->g_w = size.width(); + config->g_h = size.height(); + config->g_pass = VPX_RC_ONE_PASS; + + // Start emitting packets immediately. + config->g_lag_in_frames = 0; + + // 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; +} + ScopedVpxCodec CreateVP8Codec(const webrtc::DesktopSize& size) { ScopedVpxCodec codec(new vpx_codec_ctx_t); @@ -40,26 +63,16 @@ ScopedVpxCodec CreateVP8Codec(const webrtc::DesktopSize& size) { if (ret != VPX_CODEC_OK) return ScopedVpxCodec(); - config.rc_target_bitrate = size.width() * size.height() * - config.rc_target_bitrate / config.g_w / config.g_h; - config.g_w = size.width(); - config.g_h = size.height(); - config.g_pass = VPX_RC_ONE_PASS; + SetCommonCodecParameters(size, &config); // Value of 2 means using the real time profile. This is basically a // redundant option since we explicitly select real time mode when doing // encoding. config.g_profile = 2; - // 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; + // Clamping the quantizer constrains the worst-case quality and CPU usage. config.rc_min_quantizer = 20; config.rc_max_quantizer = 30; - config.g_timebase.num = 1; - config.g_timebase.den = 20; if (vpx_codec_enc_init(codec.get(), algo, &config, 0)) return ScopedVpxCodec(); @@ -88,19 +101,13 @@ ScopedVpxCodec CreateVP9Codec(const webrtc::DesktopSize& size) { if (ret != VPX_CODEC_OK) return ScopedVpxCodec(); - //config.rc_target_bitrate = size.width() * size.height() * - // config.rc_target_bitrate / config.g_w / config.g_h; - config.g_w = size.width(); - config.g_h = size.height(); - config.g_pass = VPX_RC_ONE_PASS; + SetCommonCodecParameters(size, &config); - // Only the default profile is currently supported for VP9 encoding. + // Configure VP9 for I420 source frames. config.g_profile = 0; - // Start emitting packets immediately. - config.g_lag_in_frames = 0; - - // Prevent VP9 from ruining output quality with quantization. + // Disable quantization entirely, putting the encoder in "lossless" mode. + config.rc_min_quantizer = 0; config.rc_max_quantizer = 0; if (vpx_codec_enc_init(codec.get(), algo, &config, 0)) @@ -142,13 +149,16 @@ scoped_ptr<VideoPacket> VideoEncoderVpx::Encode( DCHECK_LE(32, frame.size().width()); DCHECK_LE(32, frame.size().height()); - base::Time encode_start_time = base::Time::Now(); + base::TimeTicks encode_start_time = base::TimeTicks::Now(); if (!codec_ || !frame.size().equals(webrtc::DesktopSize(image_->w, image_->h))) { bool ret = Initialize(frame.size()); // TODO(hclam): Handle error better. CHECK(ret) << "Initialization of encoder failed"; + + // Set now as the base for timestamp calculation. + timestamp_base_ = encode_start_time; } // Convert the updated capture data ready for encode. @@ -168,17 +178,14 @@ scoped_ptr<VideoPacket> VideoEncoderVpx::Encode( } // Do the actual encoding. - vpx_codec_err_t ret = vpx_codec_encode(codec_.get(), image_.get(), - last_timestamp_, - 1, 0, VPX_DL_REALTIME); + int timestamp = (encode_start_time - timestamp_base_).InMilliseconds(); + vpx_codec_err_t ret = vpx_codec_encode( + codec_.get(), image_.get(), timestamp, 1, 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" << vpx_codec_error_detail(codec_.get()); - // TODO(hclam): Apply the proper timestamp here. - last_timestamp_ += 50; - // Read the encoded data. vpx_codec_iter_t iter = NULL; bool got_data = false; @@ -209,7 +216,7 @@ scoped_ptr<VideoPacket> VideoEncoderVpx::Encode( packet->mutable_format()->set_screen_height(frame.size().height()); packet->set_capture_time_ms(frame.capture_time_ms()); packet->set_encode_time_ms( - (base::Time::Now() - encode_start_time).InMillisecondsRoundedUp()); + (base::TimeTicks::Now() - encode_start_time).InMillisecondsRoundedUp()); if (!frame.dpi().is_zero()) { packet->mutable_format()->set_x_dpi(frame.dpi().x()); packet->mutable_format()->set_y_dpi(frame.dpi().y()); @@ -229,8 +236,7 @@ scoped_ptr<VideoPacket> VideoEncoderVpx::Encode( VideoEncoderVpx::VideoEncoderVpx(const InitializeCodecCallback& init_codec) : init_codec_(init_codec), active_map_width_(0), - active_map_height_(0), - last_timestamp_(0) { + active_map_height_(0) { } bool VideoEncoderVpx::Initialize(const webrtc::DesktopSize& size) { diff --git a/remoting/codec/video_encoder_vpx.h b/remoting/codec/video_encoder_vpx.h index 286745f..dd7fb2e 100644 --- a/remoting/codec/video_encoder_vpx.h +++ b/remoting/codec/video_encoder_vpx.h @@ -6,6 +6,7 @@ #define REMOTING_CODEC_VIDEO_ENCODER_VPX_H_ #include "base/callback.h" +#include "base/time/time.h" #include "remoting/codec/scoped_vpx_codec.h" #include "remoting/codec/video_encoder.h" @@ -55,7 +56,7 @@ class VideoEncoderVpx : public VideoEncoder { scoped_ptr<uint8[]> active_map_; int active_map_width_; int active_map_height_; - int last_timestamp_; + base::TimeTicks timestamp_base_; // Buffer for storing the yuv image. scoped_ptr<uint8[]> yuv_image_; |