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

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: Remove CodecDescription 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
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/memory/scoped_vector.h" 14 #include "base/memory/scoped_vector.h"
15 #include "base/memory/shared_memory.h" 15 #include "base/memory/shared_memory.h"
16 #include "base/single_thread_task_runner.h" 16 #include "base/single_thread_task_runner.h"
17 #include "base/thread_task_runner_handle.h" 17 #include "base/thread_task_runner_handle.h"
18 #include "content/renderer/pepper/pepper_video_encoder_host.h" 18 #include "content/renderer/pepper/pepper_video_encoder_host.h"
19 #include "content/renderer/render_thread_impl.h" 19 #include "content/renderer/render_thread_impl.h"
20 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" 20 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
21 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h" 21 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h"
22 #include "ui/gfx/geometry/size.h" 22 #include "ui/gfx/geometry/size.h"
23 23
24 namespace content { 24 namespace content {
25 25
26 namespace {
27
26 // TODO(llandwerlin): Libvpx doesn't seem to have a maximum frame size 28 // 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 29 // limitation. We currently limit the size of the frames to encode at
28 // 1080p (%64 pixels blocks), this seems like a reasonable limit for 30 // 1080p (%64 pixels blocks), this seems like a reasonable limit for
29 // software encoding. 31 // software encoding.
30 const int32_t kMaxWidth = 1920; 32 const int32_t kMaxWidth = 1920;
31 const int32_t kMaxHeight = 1088; 33 const int32_t kMaxHeight = 1088;
32 34
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. 35 // Bitstream buffer size.
42 const uint32_t kBitstreamBufferSize = 2 * 1024 * 1024; 36 const uint32_t kBitstreamBufferSize = 2 * 1024 * 1024;
43 37
44 // Number of frames needs at any given time. 38 // Number of frames needs at any given time.
45 const uint32_t kInputFrameCount = 1; 39 const uint32_t kInputFrameCount = 1;
46 40
41 // Default speed for the encoder. Increases the CPU usage as the value
42 // is more negative (VP8 valid range: -16..16, VP9 valid range:
43 // -8..8).
bbudge 2015/08/05 17:42:57 If you can, explain why how these values were chos
llandwerlin-old 2015/08/05 18:20:12 Essentially same a WebRTC.
44 const int32_t kVp8DefaultCpuUsed = -6;
45 const int32_t kVp9DefaultCpuUsed = 6;
46
47 // Default quantizer min/max values.
bbudge 2015/08/05 17:42:57 Ditto. The comment doesn't add anything.
llandwerlin-old 2015/08/05 18:20:12 Done.
48 const int32_t kVp8DefaultMinQuantizer = 2;
49 const int32_t kVp8DefaultMaxQuantizer = 52;
50 const int32_t kVp9DefaultMinQuantizer = 20;
51 const int32_t kVp9DefaultMaxQuantizer = 30;
52
53 // VP9 adaptive quantization strategy (live video conferencing).
bbudge 2015/08/05 17:42:57 This comment is good.
llandwerlin-old 2015/08/05 18:20:12 Done.
54 const int kVp9AqModeCyclicRefresh = 3;
55
56 void GetVpxCodecParameters(media::VideoCodecProfile codec,
57 vpx_codec_iface_t** vpx_codec,
58 int32_t* min_quantizer,
59 int32_t* max_quantizer,
60 int32_t* cpu_used) {
61 switch (codec) {
62 case media::VP8PROFILE_ANY:
63 *vpx_codec = vpx_codec_vp8_cx();
64 *min_quantizer = kVp8DefaultMinQuantizer;
65 *max_quantizer = kVp8DefaultMaxQuantizer;
66 *cpu_used = kVp8DefaultCpuUsed;
67 break;
68 case media::VP9PROFILE_ANY:
69 *vpx_codec = vpx_codec_vp9_cx();
70 *min_quantizer = kVp9DefaultMinQuantizer;
71 *max_quantizer = kVp9DefaultMaxQuantizer;
72 *cpu_used = kVp9DefaultCpuUsed;
73 break;
74 default:
bbudge 2015/08/05 17:44:20 zero vpx_codec for sanity.
llandwerlin-old 2015/08/05 18:20:12 Done.
75 NOTREACHED();
76 }
77 }
78
79 } // namespace
80
47 class VideoEncoderShim::EncoderImpl { 81 class VideoEncoderShim::EncoderImpl {
48 public: 82 public:
49 explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& shim); 83 explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& shim);
50 ~EncoderImpl(); 84 ~EncoderImpl();
51 85
52 void Initialize(media::VideoPixelFormat input_format, 86 void Initialize(media::VideoPixelFormat input_format,
53 const gfx::Size& input_visible_size, 87 const gfx::Size& input_visible_size,
54 media::VideoCodecProfile output_profile, 88 media::VideoCodecProfile output_profile,
55 uint32 initial_bitrate); 89 uint32 initial_bitrate);
56 void Encode(const scoped_refptr<media::VideoFrame>& frame, 90 void Encode(const scoped_refptr<media::VideoFrame>& frame,
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 } 145 }
112 146
113 void VideoEncoderShim::EncoderImpl::Initialize( 147 void VideoEncoderShim::EncoderImpl::Initialize(
114 media::VideoPixelFormat input_format, 148 media::VideoPixelFormat input_format,
115 const gfx::Size& input_visible_size, 149 const gfx::Size& input_visible_size,
116 media::VideoCodecProfile output_profile, 150 media::VideoCodecProfile output_profile,
117 uint32 initial_bitrate) { 151 uint32 initial_bitrate) {
118 gfx::Size coded_size = 152 gfx::Size coded_size =
119 media::VideoFrame::PlaneSize(input_format, 0, input_visible_size); 153 media::VideoFrame::PlaneSize(input_format, 0, input_visible_size);
120 154
155 vpx_codec_iface_t* vpx_codec;
156 int32_t min_quantizer, max_quantizer, cpu_used;
157 GetVpxCodecParameters(output_profile, &vpx_codec, &min_quantizer,
158 &max_quantizer, &cpu_used);
159
121 // Populate encoder configuration with default values. 160 // Populate encoder configuration with default values.
122 if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config_, 0) != 161 if (vpx_codec_enc_config_default(vpx_codec, &config_, 0) != VPX_CODEC_OK) {
123 VPX_CODEC_OK) {
124 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 162 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
125 return; 163 return;
126 } 164 }
127 165
128 config_.g_threads = 1;
129 config_.g_w = input_visible_size.width(); 166 config_.g_w = input_visible_size.width();
130 config_.g_h = input_visible_size.height(); 167 config_.g_h = input_visible_size.height();
131 168
132 framerate_ = config_.g_timebase.den; 169 framerate_ = config_.g_timebase.den;
133 170
134 config_.g_lag_in_frames = 0; 171 config_.g_lag_in_frames = 0;
135 config_.g_timebase.num = 1; 172 config_.g_timebase.num = 1;
136 config_.g_timebase.den = base::Time::kMicrosecondsPerSecond; 173 config_.g_timebase.den = base::Time::kMicrosecondsPerSecond;
137 config_.rc_target_bitrate = initial_bitrate / 1000; 174 config_.rc_target_bitrate = initial_bitrate / 1000;
138 config_.rc_min_quantizer = kDefaultMinQuantizer; 175 config_.rc_min_quantizer = min_quantizer;
139 config_.rc_max_quantizer = kDefaultMaxQuantizer; 176 config_.rc_max_quantizer = max_quantizer;
140 177
141 vpx_codec_flags_t flags = 0; 178 vpx_codec_flags_t flags = 0;
142 if (vpx_codec_enc_init(&encoder_, vpx_codec_vp8_cx(), &config_, flags) != 179 if (vpx_codec_enc_init(&encoder_, vpx_codec, &config_, flags) !=
143 VPX_CODEC_OK) { 180 VPX_CODEC_OK) {
144 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 181 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
145 return; 182 return;
146 } 183 }
147 initialized_ = true; 184 initialized_ = true;
148 185
149 if (vpx_codec_enc_config_set(&encoder_, &config_) != VPX_CODEC_OK) { 186 if (vpx_codec_enc_config_set(&encoder_, &config_) != VPX_CODEC_OK) {
150 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 187 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
151 return; 188 return;
152 } 189 }
153 190
154 if (vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, kDefaultCpuUsed) != 191 if (vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, cpu_used) !=
155 VPX_CODEC_OK) { 192 VPX_CODEC_OK) {
156 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 193 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
157 return; 194 return;
158 } 195 }
159 196
197 if (output_profile == media::VP9PROFILE_ANY) {
198 if (vpx_codec_control(&encoder_, VP9E_SET_AQ_MODE,
199 kVp9AqModeCyclicRefresh) != VPX_CODEC_OK) {
200 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
201 return;
202 }
203 }
204
160 renderer_task_runner_->PostTask( 205 renderer_task_runner_->PostTask(
161 FROM_HERE, 206 FROM_HERE,
162 base::Bind(&VideoEncoderShim::OnRequireBitstreamBuffers, shim_, 207 base::Bind(&VideoEncoderShim::OnRequireBitstreamBuffers, shim_,
163 kInputFrameCount, coded_size, kBitstreamBufferSize)); 208 kInputFrameCount, coded_size, kBitstreamBufferSize));
164 } 209 }
165 210
166 void VideoEncoderShim::EncoderImpl::Encode( 211 void VideoEncoderShim::EncoderImpl::Encode(
167 const scoped_refptr<media::VideoFrame>& frame, 212 const scoped_refptr<media::VideoFrame>& frame,
168 bool force_keyframe) { 213 bool force_keyframe) {
169 frames_.push_back(PendingEncode(frame, force_keyframe)); 214 frames_.push_back(PendingEncode(frame, force_keyframe));
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 media::VideoEncodeAccelerator::SupportedProfile profile; 350 media::VideoEncodeAccelerator::SupportedProfile profile;
306 profile.profile = media::VP8PROFILE_ANY; 351 profile.profile = media::VP8PROFILE_ANY;
307 profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight); 352 profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight);
308 // Libvpx and media::VideoEncodeAccelerator are using opposite 353 // Libvpx and media::VideoEncodeAccelerator are using opposite
309 // notions of denominator/numerator. 354 // notions of denominator/numerator.
310 profile.max_framerate_numerator = config.g_timebase.den; 355 profile.max_framerate_numerator = config.g_timebase.den;
311 profile.max_framerate_denominator = config.g_timebase.num; 356 profile.max_framerate_denominator = config.g_timebase.num;
312 profiles.push_back(profile); 357 profiles.push_back(profile);
313 } 358 }
314 359
360 ret = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), &config, 0);
361 if (ret == VPX_CODEC_OK) {
362 media::VideoEncodeAccelerator::SupportedProfile profile;
363 profile.profile = media::VP9PROFILE_ANY;
364 profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight);
365 profile.max_framerate_numerator = config.g_timebase.den;
366 profile.max_framerate_denominator = config.g_timebase.num;
367 profiles.push_back(profile);
368 }
369
315 return profiles; 370 return profiles;
316 } 371 }
317 372
318 bool VideoEncoderShim::Initialize( 373 bool VideoEncoderShim::Initialize(
319 media::VideoPixelFormat input_format, 374 media::VideoPixelFormat input_format,
320 const gfx::Size& input_visible_size, 375 const gfx::Size& input_visible_size,
321 media::VideoCodecProfile output_profile, 376 media::VideoCodecProfile output_profile,
322 uint32 initial_bitrate, 377 uint32 initial_bitrate,
323 media::VideoEncodeAccelerator::Client* client) { 378 media::VideoEncodeAccelerator::Client* client) {
324 DCHECK(RenderThreadImpl::current()); 379 DCHECK(RenderThreadImpl::current());
325 DCHECK_EQ(client, host_); 380 DCHECK_EQ(client, host_);
326 381
327 if (input_format != media::PIXEL_FORMAT_I420) 382 if (input_format != media::PIXEL_FORMAT_I420)
328 return false; 383 return false;
329 384
385 if (output_profile != media::VP8PROFILE_ANY &&
386 output_profile != media::VP9PROFILE_ANY)
387 return false;
388
330 media_task_runner_->PostTask( 389 media_task_runner_->PostTask(
331 FROM_HERE, 390 FROM_HERE,
332 base::Bind(&VideoEncoderShim::EncoderImpl::Initialize, 391 base::Bind(&VideoEncoderShim::EncoderImpl::Initialize,
333 base::Unretained(encoder_impl_.get()), input_format, 392 base::Unretained(encoder_impl_.get()), input_format,
334 input_visible_size, output_profile, initial_bitrate)); 393 input_visible_size, output_profile, initial_bitrate));
335 394
336 return true; 395 return true;
337 } 396 }
338 397
339 void VideoEncoderShim::Encode(const scoped_refptr<media::VideoFrame>& frame, 398 void VideoEncoderShim::Encode(const scoped_refptr<media::VideoFrame>& frame,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 } 454 }
396 455
397 void VideoEncoderShim::OnNotifyError( 456 void VideoEncoderShim::OnNotifyError(
398 media::VideoEncodeAccelerator::Error error) { 457 media::VideoEncodeAccelerator::Error error) {
399 DCHECK(RenderThreadImpl::current()); 458 DCHECK(RenderThreadImpl::current());
400 459
401 host_->NotifyError(error); 460 host_->NotifyError(error);
402 } 461 }
403 462
404 } // namespace content 463 } // 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