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..e4c0c95179beac46a7eaacde4089061b307ecf12 100644 |
--- a/content/renderer/pepper/video_encoder_shim.cc |
+++ b/content/renderer/pepper/video_encoder_shim.cc |
@@ -30,20 +30,67 @@ 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; |
+// Magic encoder constants for VP9 adaptive quantization strategy. |
bbudge
2015/08/05 17:04:41
nit: s/constants/constant
Or do you want to move m
llandwerlin-old
2015/08/05 17:35:55
Done.
|
+const int kVp9AqModeCyclicRefresh = 3; |
+ |
+namespace { |
+ |
+struct CodecDescription { |
bbudge
2015/08/05 17:04:41
This class just holds parameter values, and some s
llandwerlin-old
2015/08/05 17:35:55
Replaced with a function that does the switch on r
|
+ CodecDescription() |
+ : codec(media::VIDEO_CODEC_PROFILE_UNKNOWN), |
+ vpx_codec(nullptr), |
+ cpu_used(0), |
+ min_quantizer(0), |
+ max_quantizer(0) {} |
+ CodecDescription(media::VideoCodecProfile codec, |
+ vpx_codec_iface_t* vpx_codec, |
+ int32_t cpu_used, |
+ uint32_t min_quantizer, |
+ uint32_t max_quantizer) |
+ : codec(codec), |
+ vpx_codec(vpx_codec), |
+ cpu_used(cpu_used), |
+ min_quantizer(min_quantizer), |
+ max_quantizer(max_quantizer) {} |
+ ~CodecDescription() {} |
+ |
+ bool IsValid() { return vpx_codec != nullptr; } |
+ |
+ media::VideoCodecProfile codec; |
+ |
+ // Libvpx codec interface. |
+ vpx_codec_iface_t* vpx_codec; |
+ |
+ // 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; |
+}; |
+ |
+CodecDescription PP_ToVpxVideoCodecIface(media::VideoCodecProfile codec) { |
+ switch (codec) { |
+ case media::VP8PROFILE_ANY: |
+ // Using same parameters as WebRTC (see media/cast/sender). |
+ return CodecDescription(codec, vpx_codec_vp8_cx(), -6, 2, 52); |
+ case media::VP9PROFILE_ANY: |
+ return CodecDescription(codec, vpx_codec_vp9_cx(), 6, 20, 30); |
+ default: |
+ return CodecDescription(); |
+ } |
+} |
+ |
+} // namespace |
+ |
class VideoEncoderShim::EncoderImpl { |
public: |
explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& shim); |
@@ -51,7 +98,7 @@ class VideoEncoderShim::EncoderImpl { |
void Initialize(media::VideoPixelFormat input_format, |
const gfx::Size& input_visible_size, |
- media::VideoCodecProfile output_profile, |
+ const CodecDescription& codec_descr, |
uint32 initial_bitrate); |
void Encode(const scoped_refptr<media::VideoFrame>& frame, |
bool force_keyframe); |
@@ -113,19 +160,18 @@ VideoEncoderShim::EncoderImpl::~EncoderImpl() { |
void VideoEncoderShim::EncoderImpl::Initialize( |
media::VideoPixelFormat input_format, |
const gfx::Size& input_visible_size, |
- media::VideoCodecProfile output_profile, |
+ const CodecDescription& codec_descr, |
bbudge
2015/08/05 17:04:41
nit: desc is a more common abbreviation for descri
llandwerlin-old
2015/08/05 17:35:55
Done.
|
uint32 initial_bitrate) { |
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) != |
+ if (vpx_codec_enc_config_default(codec_descr.vpx_codec, &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(); |
@@ -135,11 +181,11 @@ void VideoEncoderShim::EncoderImpl::Initialize( |
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; |
+ config_.rc_min_quantizer = codec_descr.min_quantizer; |
+ config_.rc_max_quantizer = codec_descr.max_quantizer; |
vpx_codec_flags_t flags = 0; |
- if (vpx_codec_enc_init(&encoder_, vpx_codec_vp8_cx(), &config_, flags) != |
+ if (vpx_codec_enc_init(&encoder_, codec_descr.vpx_codec, &config_, flags) != |
VPX_CODEC_OK) { |
NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
return; |
@@ -151,12 +197,20 @@ void VideoEncoderShim::EncoderImpl::Initialize( |
return; |
} |
- if (vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, kDefaultCpuUsed) != |
+ if (vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, codec_descr.cpu_used) != |
VPX_CODEC_OK) { |
NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
return; |
} |
+ if (codec_descr.codec == media::VP9PROFILE_ANY) { |
+ if (vpx_codec_control(&encoder_, VP9E_SET_AQ_MODE, |
+ kVp9AqModeCyclicRefresh) != VPX_CODEC_OK) { |
+ NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
+ return; |
+ } |
+ } |
+ |
renderer_task_runner_->PostTask( |
FROM_HERE, |
base::Bind(&VideoEncoderShim::OnRequireBitstreamBuffers, shim_, |
@@ -312,6 +366,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 +391,14 @@ bool VideoEncoderShim::Initialize( |
if (input_format != media::PIXEL_FORMAT_I420) |
return false; |
+ CodecDescription codec_desc = PP_ToVpxVideoCodecIface(output_profile); |
+ if (!codec_desc.IsValid()) |
+ 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)); |
+ FROM_HERE, base::Bind(&VideoEncoderShim::EncoderImpl::Initialize, |
+ base::Unretained(encoder_impl_.get()), input_format, |
+ input_visible_size, codec_desc, initial_bitrate)); |
return true; |
} |