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

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: Additional comments 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), using the same value as WebRTC.
44 const int32_t kVp8DefaultCpuUsed = -6;
45
46 // Default quantizer min/max values (same values as WebRTC).
47 const int32_t kVp8DefaultMinQuantizer = 2;
48 const int32_t kVp8DefaultMaxQuantizer = 52;
49
50 // For VP9, the following 3 values are the same values as remoting.
51 const int32_t kVp9DefaultCpuUsed = 6;
52
53 const int32_t kVp9DefaultMinQuantizer = 20;
54 const int32_t kVp9DefaultMaxQuantizer = 30;
55
56 // VP9 adaptive quantization strategy (same as remoting (live video
57 // conferencing)).
58 const int kVp9AqModeCyclicRefresh = 3;
59
60 void GetVpxCodecParameters(media::VideoCodecProfile codec,
61 vpx_codec_iface_t** vpx_codec,
62 int32_t* min_quantizer,
63 int32_t* max_quantizer,
64 int32_t* cpu_used) {
65 switch (codec) {
66 case media::VP8PROFILE_ANY:
67 *vpx_codec = vpx_codec_vp8_cx();
68 *min_quantizer = kVp8DefaultMinQuantizer;
69 *max_quantizer = kVp8DefaultMaxQuantizer;
70 *cpu_used = kVp8DefaultCpuUsed;
71 break;
72 case media::VP9PROFILE_ANY:
73 *vpx_codec = vpx_codec_vp9_cx();
74 *min_quantizer = kVp9DefaultMinQuantizer;
75 *max_quantizer = kVp9DefaultMaxQuantizer;
76 *cpu_used = kVp9DefaultCpuUsed;
77 break;
78 default:
79 *vpx_codec = nullptr;
80 NOTREACHED();
81 }
82 }
83
84 } // namespace
85
47 class VideoEncoderShim::EncoderImpl { 86 class VideoEncoderShim::EncoderImpl {
48 public: 87 public:
49 explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& shim); 88 explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& shim);
50 ~EncoderImpl(); 89 ~EncoderImpl();
51 90
52 void Initialize(media::VideoPixelFormat input_format, 91 void Initialize(media::VideoPixelFormat input_format,
53 const gfx::Size& input_visible_size, 92 const gfx::Size& input_visible_size,
54 media::VideoCodecProfile output_profile, 93 media::VideoCodecProfile output_profile,
55 uint32 initial_bitrate); 94 uint32 initial_bitrate);
56 void Encode(const scoped_refptr<media::VideoFrame>& frame, 95 void Encode(const scoped_refptr<media::VideoFrame>& frame,
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 } 150 }
112 151
113 void VideoEncoderShim::EncoderImpl::Initialize( 152 void VideoEncoderShim::EncoderImpl::Initialize(
114 media::VideoPixelFormat input_format, 153 media::VideoPixelFormat input_format,
115 const gfx::Size& input_visible_size, 154 const gfx::Size& input_visible_size,
116 media::VideoCodecProfile output_profile, 155 media::VideoCodecProfile output_profile,
117 uint32 initial_bitrate) { 156 uint32 initial_bitrate) {
118 gfx::Size coded_size = 157 gfx::Size coded_size =
119 media::VideoFrame::PlaneSize(input_format, 0, input_visible_size); 158 media::VideoFrame::PlaneSize(input_format, 0, input_visible_size);
120 159
160 vpx_codec_iface_t* vpx_codec;
161 int32_t min_quantizer, max_quantizer, cpu_used;
162 GetVpxCodecParameters(output_profile, &vpx_codec, &min_quantizer,
163 &max_quantizer, &cpu_used);
164
121 // Populate encoder configuration with default values. 165 // Populate encoder configuration with default values.
122 if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config_, 0) != 166 if (vpx_codec_enc_config_default(vpx_codec, &config_, 0) != VPX_CODEC_OK) {
123 VPX_CODEC_OK) {
124 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 167 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
125 return; 168 return;
126 } 169 }
127 170
128 config_.g_threads = 1;
129 config_.g_w = input_visible_size.width(); 171 config_.g_w = input_visible_size.width();
130 config_.g_h = input_visible_size.height(); 172 config_.g_h = input_visible_size.height();
131 173
132 framerate_ = config_.g_timebase.den; 174 framerate_ = config_.g_timebase.den;
133 175
134 config_.g_lag_in_frames = 0; 176 config_.g_lag_in_frames = 0;
135 config_.g_timebase.num = 1; 177 config_.g_timebase.num = 1;
136 config_.g_timebase.den = base::Time::kMicrosecondsPerSecond; 178 config_.g_timebase.den = base::Time::kMicrosecondsPerSecond;
137 config_.rc_target_bitrate = initial_bitrate / 1000; 179 config_.rc_target_bitrate = initial_bitrate / 1000;
138 config_.rc_min_quantizer = kDefaultMinQuantizer; 180 config_.rc_min_quantizer = min_quantizer;
139 config_.rc_max_quantizer = kDefaultMaxQuantizer; 181 config_.rc_max_quantizer = max_quantizer;
140 182
141 vpx_codec_flags_t flags = 0; 183 vpx_codec_flags_t flags = 0;
142 if (vpx_codec_enc_init(&encoder_, vpx_codec_vp8_cx(), &config_, flags) != 184 if (vpx_codec_enc_init(&encoder_, vpx_codec, &config_, flags) !=
143 VPX_CODEC_OK) { 185 VPX_CODEC_OK) {
144 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 186 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
145 return; 187 return;
146 } 188 }
147 initialized_ = true; 189 initialized_ = true;
148 190
149 if (vpx_codec_enc_config_set(&encoder_, &config_) != VPX_CODEC_OK) { 191 if (vpx_codec_enc_config_set(&encoder_, &config_) != VPX_CODEC_OK) {
150 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 192 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
151 return; 193 return;
152 } 194 }
153 195
154 if (vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, kDefaultCpuUsed) != 196 if (vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, cpu_used) !=
155 VPX_CODEC_OK) { 197 VPX_CODEC_OK) {
156 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); 198 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
157 return; 199 return;
158 } 200 }
159 201
202 if (output_profile == media::VP9PROFILE_ANY) {
203 if (vpx_codec_control(&encoder_, VP9E_SET_AQ_MODE,
204 kVp9AqModeCyclicRefresh) != VPX_CODEC_OK) {
205 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
206 return;
207 }
208 }
209
160 renderer_task_runner_->PostTask( 210 renderer_task_runner_->PostTask(
161 FROM_HERE, 211 FROM_HERE,
162 base::Bind(&VideoEncoderShim::OnRequireBitstreamBuffers, shim_, 212 base::Bind(&VideoEncoderShim::OnRequireBitstreamBuffers, shim_,
163 kInputFrameCount, coded_size, kBitstreamBufferSize)); 213 kInputFrameCount, coded_size, kBitstreamBufferSize));
164 } 214 }
165 215
166 void VideoEncoderShim::EncoderImpl::Encode( 216 void VideoEncoderShim::EncoderImpl::Encode(
167 const scoped_refptr<media::VideoFrame>& frame, 217 const scoped_refptr<media::VideoFrame>& frame,
168 bool force_keyframe) { 218 bool force_keyframe) {
169 frames_.push_back(PendingEncode(frame, force_keyframe)); 219 frames_.push_back(PendingEncode(frame, force_keyframe));
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 media::VideoEncodeAccelerator::SupportedProfile profile; 355 media::VideoEncodeAccelerator::SupportedProfile profile;
306 profile.profile = media::VP8PROFILE_ANY; 356 profile.profile = media::VP8PROFILE_ANY;
307 profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight); 357 profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight);
308 // Libvpx and media::VideoEncodeAccelerator are using opposite 358 // Libvpx and media::VideoEncodeAccelerator are using opposite
309 // notions of denominator/numerator. 359 // notions of denominator/numerator.
310 profile.max_framerate_numerator = config.g_timebase.den; 360 profile.max_framerate_numerator = config.g_timebase.den;
311 profile.max_framerate_denominator = config.g_timebase.num; 361 profile.max_framerate_denominator = config.g_timebase.num;
312 profiles.push_back(profile); 362 profiles.push_back(profile);
313 } 363 }
314 364
365 ret = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), &config, 0);
366 if (ret == VPX_CODEC_OK) {
367 media::VideoEncodeAccelerator::SupportedProfile profile;
368 profile.profile = media::VP9PROFILE_ANY;
369 profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight);
370 profile.max_framerate_numerator = config.g_timebase.den;
371 profile.max_framerate_denominator = config.g_timebase.num;
372 profiles.push_back(profile);
373 }
374
315 return profiles; 375 return profiles;
316 } 376 }
317 377
318 bool VideoEncoderShim::Initialize( 378 bool VideoEncoderShim::Initialize(
319 media::VideoPixelFormat input_format, 379 media::VideoPixelFormat input_format,
320 const gfx::Size& input_visible_size, 380 const gfx::Size& input_visible_size,
321 media::VideoCodecProfile output_profile, 381 media::VideoCodecProfile output_profile,
322 uint32 initial_bitrate, 382 uint32 initial_bitrate,
323 media::VideoEncodeAccelerator::Client* client) { 383 media::VideoEncodeAccelerator::Client* client) {
324 DCHECK(RenderThreadImpl::current()); 384 DCHECK(RenderThreadImpl::current());
325 DCHECK_EQ(client, host_); 385 DCHECK_EQ(client, host_);
326 386
327 if (input_format != media::PIXEL_FORMAT_I420) 387 if (input_format != media::PIXEL_FORMAT_I420)
328 return false; 388 return false;
329 389
390 if (output_profile != media::VP8PROFILE_ANY &&
391 output_profile != media::VP9PROFILE_ANY)
392 return false;
393
330 media_task_runner_->PostTask( 394 media_task_runner_->PostTask(
331 FROM_HERE, 395 FROM_HERE,
332 base::Bind(&VideoEncoderShim::EncoderImpl::Initialize, 396 base::Bind(&VideoEncoderShim::EncoderImpl::Initialize,
333 base::Unretained(encoder_impl_.get()), input_format, 397 base::Unretained(encoder_impl_.get()), input_format,
334 input_visible_size, output_profile, initial_bitrate)); 398 input_visible_size, output_profile, initial_bitrate));
335 399
336 return true; 400 return true;
337 } 401 }
338 402
339 void VideoEncoderShim::Encode(const scoped_refptr<media::VideoFrame>& frame, 403 void VideoEncoderShim::Encode(const scoped_refptr<media::VideoFrame>& frame,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 } 459 }
396 460
397 void VideoEncoderShim::OnNotifyError( 461 void VideoEncoderShim::OnNotifyError(
398 media::VideoEncodeAccelerator::Error error) { 462 media::VideoEncodeAccelerator::Error error) {
399 DCHECK(RenderThreadImpl::current()); 463 DCHECK(RenderThreadImpl::current());
400 464
401 host_->NotifyError(error); 465 host_->NotifyError(error);
402 } 466 }
403 467
404 } // namespace content 468 } // 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