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

Unified Diff: content/renderer/pepper/video_encoder_shim.cc

Issue 1132833002: pepper: add software vp9 encoder support to PPB_VideoEncoder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Tune VP9 parameters Created 5 years, 4 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
Index: content/renderer/pepper/video_encoder_shim.cc
diff --git a/content/renderer/pepper/video_encoder_shim.cc b/content/renderer/pepper/video_encoder_shim.cc
index d28744fd76fdced6433c43cea3315bb3aacaaf20..5e75c29d2e5dde4874716d4fa6570b6b3ae507c0 100644
--- a/content/renderer/pepper/video_encoder_shim.cc
+++ b/content/renderer/pepper/video_encoder_shim.cc
@@ -30,20 +30,149 @@ namespace content {
const int32_t kMaxWidth = 1920;
const int32_t kMaxHeight = 1088;
-// Default speed for the encoder (same as WebRTC). Increases the CPU
-// usage as the value is more negative (VP8 valid range: -16..16).
-const int32_t kDefaultCpuUsed = -6;
-
-// Default quantizer min/max values.
-const int32_t kDefaultMinQuantizer = 2;
-const int32_t kDefaultMaxQuantizer = 52;
-
// Bitstream buffer size.
const uint32_t kBitstreamBufferSize = 2 * 1024 * 1024;
// Number of frames needs at any given time.
const uint32_t kInputFrameCount = 1;
+namespace {
+
+class CodecConfig {
bbudge 2015/08/05 02:07:45 This seems like an awful lot of machinery just to
llandwerlin-old 2015/08/05 14:55:17 Went back to the previous iteration just holding i
+ public:
+ virtual ~CodecConfig() {}
+
+ bool InitializeEncoder(vpx_codec_ctx_t* encoder,
+ const gfx::Size& size,
+ uint32 initial_bitrate,
+ uint32* initial_framerate,
+ bool* encoder_initialized);
+
+ bool UpdateBitrate(vpx_codec_ctx_t* encoder, uint32 bitrate);
+
+ protected:
+ CodecConfig(vpx_codec_iface_t* vpx_codec,
+ int32_t cpu_used,
+ uint32_t min_quantizer,
+ uint32_t max_quantizer);
+
+ // A special initialization phase to be defined per codec.
+ virtual bool InitializeEncoderForCodec(vpx_codec_ctx_t* encoder) = 0;
+
+ // Libvpx codec interface.
+ vpx_codec_iface_t* vpx_codec_;
+
+ // Libvpx configuration parameters of the codec.
+ vpx_codec_enc_cfg_t vpx_config_;
+
+ // Default speed for the encoder. Increases the CPU usage as the
+ // value is more negative (VP8 valid range: -16..16, VP9 valid
+ // range: -8..8).
+ int32_t cpu_used_;
+
+ // Default quantizer min/max values.
+ uint32_t min_quantizer_;
+ uint32_t max_quantizer_;
+};
+
+CodecConfig::CodecConfig(vpx_codec_iface_t* vpx_codec,
+ int32_t cpu_used,
+ uint32_t min_quantizer,
+ uint32_t max_quantizer)
+ : vpx_codec_(vpx_codec),
+ cpu_used_(cpu_used),
+ min_quantizer_(min_quantizer),
+ max_quantizer_(max_quantizer) {
+ vpx_codec_err_t err =
+ vpx_codec_enc_config_default(vpx_codec_, &vpx_config_, 0);
+ DCHECK_EQ(VPX_CODEC_OK, err);
+}
+
+bool CodecConfig::InitializeEncoder(vpx_codec_ctx_t* encoder,
+ const gfx::Size& size,
+ uint32 initial_bitrate,
+ uint32* initial_framerate,
+ bool* encoder_initialized) {
+ *initial_framerate = vpx_config_.g_timebase.den;
+
+ vpx_config_.g_w = size.width();
+ vpx_config_.g_h = size.height();
+
+ vpx_config_.g_lag_in_frames = 0;
+ vpx_config_.g_timebase.num = 1;
+ vpx_config_.g_timebase.den = base::Time::kMicrosecondsPerSecond;
+ vpx_config_.rc_target_bitrate = initial_bitrate / 1000;
+ vpx_config_.rc_min_quantizer = min_quantizer_;
+ vpx_config_.rc_max_quantizer = max_quantizer_;
+
+ vpx_codec_flags_t flags = 0;
+ if (vpx_codec_enc_init(encoder, vpx_codec_, &vpx_config_, flags) !=
+ VPX_CODEC_OK) {
+ return false;
+ }
+ *encoder_initialized = true;
+
+ if (vpx_codec_enc_config_set(encoder, &vpx_config_) != VPX_CODEC_OK)
+ return false;
+
+ if (vpx_codec_control(encoder, VP8E_SET_CPUUSED, cpu_used_) != VPX_CODEC_OK) {
+ return false;
+ }
+
+ return InitializeEncoderForCodec(encoder);
+}
+
+bool CodecConfig::UpdateBitrate(vpx_codec_ctx_t* encoder, uint32 bitrate) {
+ uint32 bitrate_kbit = bitrate / 1000;
+ if (vpx_config_.rc_target_bitrate == bitrate_kbit)
+ return true;
+
+ vpx_config_.rc_target_bitrate = bitrate_kbit;
+ return vpx_codec_enc_config_set(encoder, &vpx_config_) == VPX_CODEC_OK;
+}
+
+// VP8 configuration.
+class Vp8CodecConfig : public CodecConfig {
+ public:
+ Vp8CodecConfig() : CodecConfig(vpx_codec_vp8_cx(), -6, 2, 52) {}
+ ~Vp8CodecConfig() override {}
+
+ private:
+ bool InitializeEncoderForCodec(vpx_codec_ctx_t* encoder) override {
+ return true;
+ }
+};
+
+// VP9 configuration.
+class Vp9CodecConfig : public CodecConfig {
+ public:
+ Vp9CodecConfig() : CodecConfig(vpx_codec_vp9_cx(), 6, 20, 30) {}
+ ~Vp9CodecConfig() override {}
+
+ private:
+ bool InitializeEncoderForCodec(vpx_codec_ctx_t* encoder) override;
+};
+
+bool Vp9CodecConfig::InitializeEncoderForCodec(vpx_codec_ctx_t* encoder) {
+ return vpx_codec_control(encoder, VP9E_SET_AQ_MODE, 3) == VPX_CODEC_OK;
+}
+
+scoped_ptr<CodecConfig> PP_ToVpxVideoCodecIface(
+ media::VideoCodecProfile codec) {
+ switch (codec) {
+ case media::VP8PROFILE_ANY:
+ // Using same parameters as WebRTC (see media/cast/sender).
+ return make_scoped_ptr(new Vp8CodecConfig());
+ case media::VP9PROFILE_ANY:
+ return make_scoped_ptr(new Vp9CodecConfig());
+ ;
+ default:
+ return scoped_ptr<CodecConfig>();
+ }
+}
+
+} // namespace
+
class VideoEncoderShim::EncoderImpl {
public:
explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& shim);
@@ -51,7 +180,7 @@ class VideoEncoderShim::EncoderImpl {
void Initialize(media::VideoPixelFormat input_format,
const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
+ CodecConfig* codec_config,
uint32 initial_bitrate);
void Encode(const scoped_refptr<media::VideoFrame>& frame,
bool force_keyframe);
@@ -86,12 +215,11 @@ class VideoEncoderShim::EncoderImpl {
base::WeakPtr<VideoEncoderShim> shim_;
scoped_refptr<base::SingleThreadTaskRunner> renderer_task_runner_;
- bool initialized_;
-
- // Libvpx internal objects. Only valid if |initialized_| is true.
- vpx_codec_enc_cfg_t config_;
+ // Libvpx internal objects. Only valid if |codec_config_| is not null.
vpx_codec_ctx_t encoder_;
+ scoped_ptr<CodecConfig> codec_config_;
+
uint32 framerate_;
std::deque<PendingEncode> frames_;
@@ -100,59 +228,29 @@ class VideoEncoderShim::EncoderImpl {
VideoEncoderShim::EncoderImpl::EncoderImpl(
const base::WeakPtr<VideoEncoderShim>& shim)
- : shim_(shim),
- renderer_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- initialized_(false) {
-}
+ : shim_(shim), renderer_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
VideoEncoderShim::EncoderImpl::~EncoderImpl() {
- if (initialized_)
+ if (codec_config_)
vpx_codec_destroy(&encoder_);
}
void VideoEncoderShim::EncoderImpl::Initialize(
media::VideoPixelFormat input_format,
const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
+ CodecConfig* codec_config,
uint32 initial_bitrate) {
+ DCHECK(codec_config);
gfx::Size coded_size =
media::VideoFrame::PlaneSize(input_format, 0, input_visible_size);
- // Populate encoder configuration with default values.
- if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config_, 0) !=
- VPX_CODEC_OK) {
- NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
- return;
- }
-
- config_.g_threads = 1;
- config_.g_w = input_visible_size.width();
- config_.g_h = input_visible_size.height();
+ codec_config_.reset(codec_config);
- framerate_ = config_.g_timebase.den;
-
- config_.g_lag_in_frames = 0;
- config_.g_timebase.num = 1;
- config_.g_timebase.den = base::Time::kMicrosecondsPerSecond;
- config_.rc_target_bitrate = initial_bitrate / 1000;
- config_.rc_min_quantizer = kDefaultMinQuantizer;
- config_.rc_max_quantizer = kDefaultMaxQuantizer;
-
- vpx_codec_flags_t flags = 0;
- if (vpx_codec_enc_init(&encoder_, vpx_codec_vp8_cx(), &config_, flags) !=
- VPX_CODEC_OK) {
- NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
- return;
- }
- initialized_ = true;
-
- if (vpx_codec_enc_config_set(&encoder_, &config_) != VPX_CODEC_OK) {
- NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
- return;
- }
-
- if (vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, kDefaultCpuUsed) !=
- VPX_CODEC_OK) {
+ bool encoder_initialized = false;
+ if (!codec_config_->InitializeEncoder(&encoder_, coded_size, initial_bitrate,
+ &framerate_, &encoder_initialized)) {
+ if (!encoder_initialized)
+ codec_config_.reset();
NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
return;
}
@@ -182,12 +280,7 @@ void VideoEncoderShim::EncoderImpl::RequestEncodingParametersChange(
uint32 framerate) {
framerate_ = framerate;
- uint32 bitrate_kbit = bitrate / 1000;
- if (config_.rc_target_bitrate == bitrate_kbit)
- return;
-
- config_.rc_target_bitrate = bitrate_kbit;
- if (vpx_codec_enc_config_set(&encoder_, &config_) != VPX_CODEC_OK)
+ if (!codec_config_->UpdateBitrate(&encoder_, bitrate))
NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
}
@@ -312,6 +405,16 @@ VideoEncoderShim::GetSupportedProfiles() {
profiles.push_back(profile);
}
+ ret = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), &config, 0);
+ if (ret == VPX_CODEC_OK) {
+ media::VideoEncodeAccelerator::SupportedProfile profile;
+ profile.profile = media::VP9PROFILE_ANY;
+ profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight);
+ profile.max_framerate_numerator = config.g_timebase.den;
+ profile.max_framerate_denominator = config.g_timebase.num;
+ profiles.push_back(profile);
+ }
+
return profiles;
}
@@ -327,11 +430,15 @@ bool VideoEncoderShim::Initialize(
if (input_format != media::PIXEL_FORMAT_I420)
return false;
+ scoped_ptr<CodecConfig> codec_desc = PP_ToVpxVideoCodecIface(output_profile);
+ if (!codec_desc)
+ return false;
+
media_task_runner_->PostTask(
FROM_HERE,
base::Bind(&VideoEncoderShim::EncoderImpl::Initialize,
base::Unretained(encoder_impl_.get()), input_format,
- input_visible_size, output_profile, initial_bitrate));
+ input_visible_size, codec_desc.release(), initial_bitrate));
return true;
}
« no previous file with comments | « no previous file | native_client_sdk/src/examples/api/video_encode/video_encode.cc » ('j') | ppapi/tests/test_video_encoder.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698