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

Side by Side Diff: content/renderer/pepper/video_encoder_shim.cc

Issue 956893002: content: pepper: VideoEncoder: add software encoder support (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update after bbudge's review Created 5 years, 9 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/renderer/pepper/video_encoder_shim.h"
6
7 #include <deque>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/memory/shared_memory.h"
13 #include "base/message_loop/message_loop.h"
14 #include "content/renderer/pepper/pepper_video_encoder_host.h"
15 #include "content/renderer/render_thread_impl.h"
16 #include "media/cast/cast_config.h"
17 #include "media/cast/sender/vp8_encoder.h"
18 #include "ui/gfx/geometry/size.h"
19
20 namespace content {
21
22 const int32_t kMaxWidth = 1920;
23 const int32_t kMaxHeight = 1080;
bbudge 2015/03/02 20:01:06 Needs a comment explaining these constants.
llandwerlin-old 2015/03/03 15:23:28 Done.
24
25 class VideoEncoderShim::EncoderImpl {
26 public:
27 explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& proxy);
28 ~EncoderImpl();
29
30 void Initialize(media::VideoFrame::Format input_format,
31 const gfx::Size& input_visible_size,
32 media::VideoCodecProfile output_profile,
33 uint32 initial_bitrate);
34 void Encode(const scoped_refptr<media::VideoFrame>& frame,
35 bool force_keyframe);
36 void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer,
37 uint8_t* mem);
38 void RequestEncodingParametersChange(uint32 bitrate, uint32 framerate);
39 void Stop();
40
41 private:
42 struct Frame {
bbudge 2015/03/02 20:01:06 Suggestion: s/Frame/PendingEncode So you don't hav
llandwerlin-old 2015/03/03 15:23:28 Done.
43 Frame(const scoped_refptr<media::VideoFrame>& frame, bool force_keyframe)
44 : frame(frame), force_keyframe(force_keyframe) {}
45 ~Frame() {}
46
47 scoped_refptr<media::VideoFrame> frame;
48 bool force_keyframe;
49 };
50
51 struct BitstreamBuffer {
52 BitstreamBuffer(const media::BitstreamBuffer buffer, uint8_t* mem)
53 : buffer(buffer), mem(mem) {}
54 ~BitstreamBuffer() {}
55
56 media::BitstreamBuffer buffer;
57 uint8_t* mem;
58 };
59
60 void DoEncode();
61
62 base::WeakPtr<VideoEncoderShim> shim_;
63 scoped_refptr<base::SingleThreadTaskRunner> shim_task_runner_;
bbudge 2015/03/02 20:01:06 Name suggestion: task_runner_ or media_task_runner
llandwerlin-old 2015/03/03 15:23:28 Done.
64
65 scoped_ptr<media::cast::SoftwareVideoEncoder> encoder_;
66 std::deque<Frame> frames_;
67 std::deque<BitstreamBuffer> buffers_;
68 };
69
70 VideoEncoderShim::EncoderImpl::EncoderImpl(
71 const base::WeakPtr<VideoEncoderShim>& proxy)
bbudge 2015/03/02 20:01:06 s/proxy/shim And above in class decl.
llandwerlin-old 2015/03/03 15:23:28 Done.
72 : shim_(proxy), shim_task_runner_(base::MessageLoopProxy::current()) {
73 }
74
75 VideoEncoderShim::EncoderImpl::~EncoderImpl() {
76 }
77
78 void VideoEncoderShim::EncoderImpl::Initialize(
79 media::VideoFrame::Format input_format,
80 const gfx::Size& input_visible_size,
81 media::VideoCodecProfile output_profile,
82 uint32 initial_bitrate) {
83 media::cast::VideoSenderConfig config;
84
85 config.max_number_of_video_buffers_used =
86 3; // media::cast::Vp8Encoder::kNumberOfVp8VideoBuffers;
bbudge 2015/03/02 20:01:06 This comment confused me, since it refers to a pri
llandwerlin-old 2015/03/03 15:23:28 Done.
87 config.number_of_encode_threads = 1;
88 encoder_.reset(new media::cast::Vp8Encoder(config));
89
90 encoder_->UpdateRates(initial_bitrate);
91
92 shim_task_runner_->PostTask(
93 FROM_HERE, base::Bind(&VideoEncoderShim::OnRequireBitstreamBuffers, shim_,
94 3, input_visible_size, 4 * 1000000));
bbudge 2015/03/02 20:01:06 4 * 1000000 should be a constant with a comment.
llandwerlin-old 2015/03/03 15:23:28 Done.
95 }
96
97 void VideoEncoderShim::EncoderImpl::Encode(
98 const scoped_refptr<media::VideoFrame>& frame,
99 bool force_keyframe) {
100 frames_.push_back(Frame(frame, force_keyframe));
101 DoEncode();
102 }
103
104 void VideoEncoderShim::EncoderImpl::UseOutputBitstreamBuffer(
105 const media::BitstreamBuffer& buffer,
106 uint8_t* mem) {
107 buffers_.push_back(BitstreamBuffer(buffer, mem));
108 DoEncode();
109 }
110
111 void VideoEncoderShim::EncoderImpl::RequestEncodingParametersChange(
112 uint32 bitrate,
113 uint32 framerate) {
114 encoder_->UpdateRates(bitrate);
115 }
116
117 void VideoEncoderShim::EncoderImpl::Stop() {
118 frames_.clear();
119 buffers_.clear();
120 encoder_.reset();
121 }
122
123 void VideoEncoderShim::EncoderImpl::DoEncode() {
124 if (frames_.empty() || buffers_.empty())
125 return;
bbudge 2015/03/02 20:01:06 I don't think you need this 'if' - the 'while' han
llandwerlin-old 2015/03/03 15:23:28 Done.
126
127 while (!frames_.empty() && !buffers_.empty()) {
128 Frame frame = frames_.front();
129 frames_.pop_front();
130
131 if (frame.force_keyframe)
132 encoder_->GenerateKeyFrame();
133
134 scoped_ptr<media::cast::EncodedFrame> encoded_frame(
135 new media::cast::EncodedFrame());
136 encoder_->Encode(frame.frame, base::TimeTicks::Now(), encoded_frame.get());
bbudge 2015/03/02 20:01:06 nit: .get() isn't necessary.
llandwerlin-old 2015/03/03 15:23:27 That doesn't compile on GCC : no known conversion
137
138 BitstreamBuffer buffer = buffers_.front();
139 buffers_.pop_front();
140
141 CHECK(buffer.buffer.size() >= encoded_frame->data.size());
142 memcpy(buffer.mem, encoded_frame->bytes(), encoded_frame->data.size());
143
144 shim_task_runner_->PostTask(
145 FROM_HERE,
146 base::Bind(
147 &VideoEncoderShim::OnBitstreamBufferReady, shim_,
148 // Pass the media::VideoFrame back
149 // to the renderer thread so it's
150 // freed on the right thread.
bbudge 2015/03/02 20:01:06 comment formatting is a little weird. Maybe put it
llandwerlin-old 2015/03/03 15:23:27 Done.
151 frame.frame, buffer.buffer.id(), encoded_frame->data.size(),
152 encoded_frame->dependency == media::cast::EncodedFrame::KEY));
153 }
154 }
155
156 // VideoEncoderShim :
bbudge 2015/03/02 20:01:06 nit: remove
llandwerlin-old 2015/03/03 15:23:27 Done.
157
158 VideoEncoderShim::VideoEncoderShim(PepperVideoEncoderHost* host)
159 : host_(host),
160 media_task_runner_(
161 RenderThreadImpl::current()->GetMediaThreadTaskRunner()),
162 weak_ptr_factory_(this) {
163 encoder_impl_.reset(new EncoderImpl(weak_ptr_factory_.GetWeakPtr()));
164 }
165
166 VideoEncoderShim::~VideoEncoderShim() {
167 DCHECK(RenderThreadImpl::current());
168
169 media_task_runner_->PostTask(
170 FROM_HERE, base::Bind(&VideoEncoderShim::EncoderImpl::Stop,
171 base::Owned(encoder_impl_.release())));
172 }
173
174 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
175 VideoEncoderShim::GetSupportedProfiles() {
176 media::VideoEncodeAccelerator::SupportedProfile profile = {
177 media::VP8PROFILE_ANY,
178 // TODO(llandwerlin): find correct values from libvpx.
bbudge 2015/03/02 20:01:06 Move TODO to definitions at top of file.
llandwerlin-old 2015/03/03 15:23:28 Done.
179 gfx::Size(kMaxWidth, kMaxHeight),
180 media::cast::kDefaultMaxFrameRate,
181 1};
182 std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles;
183 profiles.push_back(profile);
184 return profiles;
185 }
186
187 bool VideoEncoderShim::Initialize(
188 media::VideoFrame::Format input_format,
189 const gfx::Size& input_visible_size,
190 media::VideoCodecProfile output_profile,
191 uint32 initial_bitrate,
192 media::VideoEncodeAccelerator::Client* client) {
193 DCHECK(RenderThreadImpl::current());
194 DCHECK_EQ(client, host_);
195
196 if (input_format != media::VideoFrame::I420)
197 return false;
bbudge 2015/03/02 20:01:06 Is it possible that other formats could work? I se
llandwerlin-old 2015/03/03 15:23:28 Looking at the VPX code, it depends on the codec a
bbudge 2015/03/05 01:43:59 It would be nice to have more profiles. I don't kn
198 if (output_profile != media::VP8PROFILE_ANY)
199 return false;
200 if (input_visible_size.width() > kMaxWidth ||
201 input_visible_size.height() > kMaxHeight)
202 return false;
bbudge 2015/03/02 20:01:06 Is this input validation needed? Doesn't the host
llandwerlin-old 2015/03/03 15:23:27 Fair, removing.
203
204 media_task_runner_->PostTask(
205 FROM_HERE,
206 base::Bind(&VideoEncoderShim::EncoderImpl::Initialize,
207 base::Unretained(encoder_impl_.get()), input_format,
208 input_visible_size, output_profile, initial_bitrate));
209
210 return true;
211 }
212
213 void VideoEncoderShim::Encode(const scoped_refptr<media::VideoFrame>& frame,
214 bool force_keyframe) {
215 DCHECK(RenderThreadImpl::current());
216
217 media_task_runner_->PostTask(
218 FROM_HERE,
219 base::Bind(&VideoEncoderShim::EncoderImpl::Encode,
220 base::Unretained(encoder_impl_.get()), frame, force_keyframe));
221 }
222
223 void VideoEncoderShim::UseOutputBitstreamBuffer(
224 const media::BitstreamBuffer& buffer) {
225 DCHECK(RenderThreadImpl::current());
226
227 media_task_runner_->PostTask(
228 FROM_HERE,
229 base::Bind(&VideoEncoderShim::EncoderImpl::UseOutputBitstreamBuffer,
230 base::Unretained(encoder_impl_.get()), buffer,
231 host_->ShmHandleToAddress(buffer.id())));
232 }
233
234 void VideoEncoderShim::RequestEncodingParametersChange(uint32 bitrate,
235 uint32 framerate) {
236 DCHECK(RenderThreadImpl::current());
237
238 media_task_runner_->PostTask(
239 FROM_HERE,
240 base::Bind(
241 &VideoEncoderShim::EncoderImpl::RequestEncodingParametersChange,
242 base::Unretained(encoder_impl_.get()), bitrate, framerate));
243 }
244
245 void VideoEncoderShim::Destroy() {
246 DCHECK(RenderThreadImpl::current());
247
248 delete this;
249 }
250
251 void VideoEncoderShim::OnRequireBitstreamBuffers(
252 unsigned int input_count,
253 const gfx::Size& input_coded_size,
254 size_t output_buffer_size) {
255 DCHECK(RenderThreadImpl::current());
256
257 host_->RequireBitstreamBuffers(input_count, input_coded_size,
258 output_buffer_size);
259 }
260
261 void VideoEncoderShim::OnBitstreamBufferReady(
262 scoped_refptr<media::VideoFrame> frame,
263 int32 bitstream_buffer_id,
264 size_t payload_size,
265 bool key_frame) {
266 DCHECK(RenderThreadImpl::current());
267
268 host_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame);
269 }
270
271 void VideoEncoderShim::OnNotifyError(
272 media::VideoEncodeAccelerator::Error error) {
273 DCHECK(RenderThreadImpl::current());
274
275 host_->NotifyError(error);
276 }
277
278 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698