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

Side by Side 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: Simplify machinery & add vp9 initialization test 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 unified diff | Download patch
« no previous file with comments | « no previous file | native_client_sdk/src/examples/api/video_encode/video_encode.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/pepper/video_encoder_shim.h" 5 #include "content/renderer/pepper/video_encoder_shim.h"
6 6
7 #include <inttypes.h> 7 #include <inttypes.h>
8 8
9 #include <deque> 9 #include <deque>
10 10
(...skipping 12 matching lines...) Expand all
23 23
24 namespace content { 24 namespace content {
25 25
26 // TODO(llandwerlin): Libvpx doesn't seem to have a maximum frame size 26 // TODO(llandwerlin): Libvpx doesn't seem to have a maximum frame size
27 // limitation. We currently limit the size of the frames to encode at 27 // limitation. We currently limit the size of the frames to encode at
28 // 1080p (%64 pixels blocks), this seems like a reasonable limit for 28 // 1080p (%64 pixels blocks), this seems like a reasonable limit for
29 // software encoding. 29 // software encoding.
30 const int32_t kMaxWidth = 1920; 30 const int32_t kMaxWidth = 1920;
31 const int32_t kMaxHeight = 1088; 31 const int32_t kMaxHeight = 1088;
32 32
33 // Default speed for the encoder (same as WebRTC). Increases the CPU
34 // usage as the value is more negative (VP8 valid range: -16..16).
35 const int32_t kDefaultCpuUsed = -6;
36
37 // Default quantizer min/max values.
38 const int32_t kDefaultMinQuantizer = 2;
39 const int32_t kDefaultMaxQuantizer = 52;
40
41 // Bitstream buffer size. 33 // Bitstream buffer size.
42 const uint32_t kBitstreamBufferSize = 2 * 1024 * 1024; 34 const uint32_t kBitstreamBufferSize = 2 * 1024 * 1024;
43 35
44 // Number of frames needs at any given time. 36 // Number of frames needs at any given time.
45 const uint32_t kInputFrameCount = 1; 37 const uint32_t kInputFrameCount = 1;
46 38
39 // 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.
40 const int kVp9AqModeCyclicRefresh = 3;
41
42 namespace {
43
44 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
45 CodecDescription()
46 : codec(media::VIDEO_CODEC_PROFILE_UNKNOWN),
47 vpx_codec(nullptr),
48 cpu_used(0),
49 min_quantizer(0),
50 max_quantizer(0) {}
51 CodecDescription(media::VideoCodecProfile codec,
52 vpx_codec_iface_t* vpx_codec,
53 int32_t cpu_used,
54 uint32_t min_quantizer,
55 uint32_t max_quantizer)
56 : codec(codec),
57 vpx_codec(vpx_codec),
58 cpu_used(cpu_used),
59 min_quantizer(min_quantizer),
60 max_quantizer(max_quantizer) {}
61 ~CodecDescription() {}
62
63 bool IsValid() { return vpx_codec != nullptr; }
64
65 media::VideoCodecProfile codec;
66
67 // Libvpx codec interface.
68 vpx_codec_iface_t* vpx_codec;
69
70 // Default speed for the encoder. Increases the CPU usage as the
71 // value is more negative (VP8 valid range: -16..16, VP9 valid
72 // range: -8..8).
73 int32_t cpu_used;
74
75 // Default quantizer min/max values.
76 uint32_t min_quantizer;
77 uint32_t max_quantizer;
78 };
79
80 CodecDescription PP_ToVpxVideoCodecIface(media::VideoCodecProfile codec) {
81 switch (codec) {
82 case media::VP8PROFILE_ANY:
83 // Using same parameters as WebRTC (see media/cast/sender).
84 return CodecDescription(codec, vpx_codec_vp8_cx(), -6, 2, 52);
85 case media::VP9PROFILE_ANY:
86 return CodecDescription(codec, vpx_codec_vp9_cx(), 6, 20, 30);
87 default:
88 return CodecDescription();
89 }
90 }
91
92 } // namespace
93
47 class VideoEncoderShim::EncoderImpl { 94 class VideoEncoderShim::EncoderImpl {
48 public: 95 public:
49 explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& shim); 96 explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& shim);
50 ~EncoderImpl(); 97 ~EncoderImpl();
51 98
52 void Initialize(media::VideoPixelFormat input_format, 99 void Initialize(media::VideoPixelFormat input_format,
53 const gfx::Size& input_visible_size, 100 const gfx::Size& input_visible_size,
54 media::VideoCodecProfile output_profile, 101 const CodecDescription& codec_descr,
55 uint32 initial_bitrate); 102 uint32 initial_bitrate);
56 void Encode(const scoped_refptr<media::VideoFrame>& frame, 103 void Encode(const scoped_refptr<media::VideoFrame>& frame,
57 bool force_keyframe); 104 bool force_keyframe);
58 void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer, 105 void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer,
59 uint8_t* mem); 106 uint8_t* mem);
60 void RequestEncodingParametersChange(uint32 bitrate, uint32 framerate); 107 void RequestEncodingParametersChange(uint32 bitrate, uint32 framerate);
61 void Stop(); 108 void Stop();
62 109
63 private: 110 private:
64 struct PendingEncode { 111 struct PendingEncode {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 } 153 }
107 154
108 VideoEncoderShim::EncoderImpl::~EncoderImpl() { 155 VideoEncoderShim::EncoderImpl::~EncoderImpl() {
109 if (initialized_) 156 if (initialized_)
110 vpx_codec_destroy(&encoder_); 157 vpx_codec_destroy(&encoder_);
111 } 158 }
112 159
113 void VideoEncoderShim::EncoderImpl::Initialize( 160 void VideoEncoderShim::EncoderImpl::Initialize(
114 media::VideoPixelFormat input_format, 161 media::VideoPixelFormat input_format,
115 const gfx::Size& input_visible_size, 162 const gfx::Size& input_visible_size,
116 media::VideoCodecProfile output_profile, 163 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.
117 uint32 initial_bitrate) { 164 uint32 initial_bitrate) {
118 gfx::Size coded_size = 165 gfx::Size coded_size =
119 media::VideoFrame::PlaneSize(input_format, 0, input_visible_size); 166 media::VideoFrame::PlaneSize(input_format, 0, input_visible_size);
120 167
121 // Populate encoder configuration with default values. 168 // Populate encoder configuration with default values.
122 if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config_, 0) != 169 if (vpx_codec_enc_config_default(codec_descr.vpx_codec, &config_, 0) !=
123 VPX_CODEC_OK) { 170 VPX_CODEC_OK) {
124 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 171 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
125 return; 172 return;
126 } 173 }
127 174
128 config_.g_threads = 1;
129 config_.g_w = input_visible_size.width(); 175 config_.g_w = input_visible_size.width();
130 config_.g_h = input_visible_size.height(); 176 config_.g_h = input_visible_size.height();
131 177
132 framerate_ = config_.g_timebase.den; 178 framerate_ = config_.g_timebase.den;
133 179
134 config_.g_lag_in_frames = 0; 180 config_.g_lag_in_frames = 0;
135 config_.g_timebase.num = 1; 181 config_.g_timebase.num = 1;
136 config_.g_timebase.den = base::Time::kMicrosecondsPerSecond; 182 config_.g_timebase.den = base::Time::kMicrosecondsPerSecond;
137 config_.rc_target_bitrate = initial_bitrate / 1000; 183 config_.rc_target_bitrate = initial_bitrate / 1000;
138 config_.rc_min_quantizer = kDefaultMinQuantizer; 184 config_.rc_min_quantizer = codec_descr.min_quantizer;
139 config_.rc_max_quantizer = kDefaultMaxQuantizer; 185 config_.rc_max_quantizer = codec_descr.max_quantizer;
140 186
141 vpx_codec_flags_t flags = 0; 187 vpx_codec_flags_t flags = 0;
142 if (vpx_codec_enc_init(&encoder_, vpx_codec_vp8_cx(), &config_, flags) != 188 if (vpx_codec_enc_init(&encoder_, codec_descr.vpx_codec, &config_, flags) !=
143 VPX_CODEC_OK) { 189 VPX_CODEC_OK) {
144 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 190 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
145 return; 191 return;
146 } 192 }
147 initialized_ = true; 193 initialized_ = true;
148 194
149 if (vpx_codec_enc_config_set(&encoder_, &config_) != VPX_CODEC_OK) { 195 if (vpx_codec_enc_config_set(&encoder_, &config_) != VPX_CODEC_OK) {
150 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 196 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
151 return; 197 return;
152 } 198 }
153 199
154 if (vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, kDefaultCpuUsed) != 200 if (vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, codec_descr.cpu_used) !=
155 VPX_CODEC_OK) { 201 VPX_CODEC_OK) {
156 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 202 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
157 return; 203 return;
158 } 204 }
159 205
206 if (codec_descr.codec == media::VP9PROFILE_ANY) {
207 if (vpx_codec_control(&encoder_, VP9E_SET_AQ_MODE,
208 kVp9AqModeCyclicRefresh) != VPX_CODEC_OK) {
209 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
210 return;
211 }
212 }
213
160 renderer_task_runner_->PostTask( 214 renderer_task_runner_->PostTask(
161 FROM_HERE, 215 FROM_HERE,
162 base::Bind(&VideoEncoderShim::OnRequireBitstreamBuffers, shim_, 216 base::Bind(&VideoEncoderShim::OnRequireBitstreamBuffers, shim_,
163 kInputFrameCount, coded_size, kBitstreamBufferSize)); 217 kInputFrameCount, coded_size, kBitstreamBufferSize));
164 } 218 }
165 219
166 void VideoEncoderShim::EncoderImpl::Encode( 220 void VideoEncoderShim::EncoderImpl::Encode(
167 const scoped_refptr<media::VideoFrame>& frame, 221 const scoped_refptr<media::VideoFrame>& frame,
168 bool force_keyframe) { 222 bool force_keyframe) {
169 frames_.push_back(PendingEncode(frame, force_keyframe)); 223 frames_.push_back(PendingEncode(frame, force_keyframe));
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 media::VideoEncodeAccelerator::SupportedProfile profile; 359 media::VideoEncodeAccelerator::SupportedProfile profile;
306 profile.profile = media::VP8PROFILE_ANY; 360 profile.profile = media::VP8PROFILE_ANY;
307 profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight); 361 profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight);
308 // Libvpx and media::VideoEncodeAccelerator are using opposite 362 // Libvpx and media::VideoEncodeAccelerator are using opposite
309 // notions of denominator/numerator. 363 // notions of denominator/numerator.
310 profile.max_framerate_numerator = config.g_timebase.den; 364 profile.max_framerate_numerator = config.g_timebase.den;
311 profile.max_framerate_denominator = config.g_timebase.num; 365 profile.max_framerate_denominator = config.g_timebase.num;
312 profiles.push_back(profile); 366 profiles.push_back(profile);
313 } 367 }
314 368
369 ret = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), &config, 0);
370 if (ret == VPX_CODEC_OK) {
371 media::VideoEncodeAccelerator::SupportedProfile profile;
372 profile.profile = media::VP9PROFILE_ANY;
373 profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight);
374 profile.max_framerate_numerator = config.g_timebase.den;
375 profile.max_framerate_denominator = config.g_timebase.num;
376 profiles.push_back(profile);
377 }
378
315 return profiles; 379 return profiles;
316 } 380 }
317 381
318 bool VideoEncoderShim::Initialize( 382 bool VideoEncoderShim::Initialize(
319 media::VideoPixelFormat input_format, 383 media::VideoPixelFormat input_format,
320 const gfx::Size& input_visible_size, 384 const gfx::Size& input_visible_size,
321 media::VideoCodecProfile output_profile, 385 media::VideoCodecProfile output_profile,
322 uint32 initial_bitrate, 386 uint32 initial_bitrate,
323 media::VideoEncodeAccelerator::Client* client) { 387 media::VideoEncodeAccelerator::Client* client) {
324 DCHECK(RenderThreadImpl::current()); 388 DCHECK(RenderThreadImpl::current());
325 DCHECK_EQ(client, host_); 389 DCHECK_EQ(client, host_);
326 390
327 if (input_format != media::PIXEL_FORMAT_I420) 391 if (input_format != media::PIXEL_FORMAT_I420)
328 return false; 392 return false;
329 393
394 CodecDescription codec_desc = PP_ToVpxVideoCodecIface(output_profile);
395 if (!codec_desc.IsValid())
396 return false;
397
330 media_task_runner_->PostTask( 398 media_task_runner_->PostTask(
331 FROM_HERE, 399 FROM_HERE, base::Bind(&VideoEncoderShim::EncoderImpl::Initialize,
332 base::Bind(&VideoEncoderShim::EncoderImpl::Initialize, 400 base::Unretained(encoder_impl_.get()), input_format,
333 base::Unretained(encoder_impl_.get()), input_format, 401 input_visible_size, codec_desc, initial_bitrate));
334 input_visible_size, output_profile, initial_bitrate));
335 402
336 return true; 403 return true;
337 } 404 }
338 405
339 void VideoEncoderShim::Encode(const scoped_refptr<media::VideoFrame>& frame, 406 void VideoEncoderShim::Encode(const scoped_refptr<media::VideoFrame>& frame,
340 bool force_keyframe) { 407 bool force_keyframe) {
341 DCHECK(RenderThreadImpl::current()); 408 DCHECK(RenderThreadImpl::current());
342 409
343 media_task_runner_->PostTask( 410 media_task_runner_->PostTask(
344 FROM_HERE, 411 FROM_HERE,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 } 462 }
396 463
397 void VideoEncoderShim::OnNotifyError( 464 void VideoEncoderShim::OnNotifyError(
398 media::VideoEncodeAccelerator::Error error) { 465 media::VideoEncodeAccelerator::Error error) {
399 DCHECK(RenderThreadImpl::current()); 466 DCHECK(RenderThreadImpl::current());
400 467
401 host_->NotifyError(error); 468 host_->NotifyError(error);
402 } 469 }
403 470
404 } // namespace content 471 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | native_client_sdk/src/examples/api/video_encode/video_encode.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698