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

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: Add modifications to the example to expose different profiles 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 // TODO(llandwerlin): Libvpx doesn't seem to have a maximum frame size
23 // limitation. We currently limit the size of the frames to encode at
24 // 1080p (%64 pixels blocks), this seems like a reasonable limit for
25 // software encoding.
26 const int32_t kMaxWidth = 1920;
27 const int32_t kMaxHeight = 1088;
28
29 // Bitstream buffer size : 4Mb.
30 const uint32_t kBitstreamBufferSize = 4000000;
bbudge 2015/03/16 18:27:48 nit: not really megabits (Mbs) or even megabytes (
llandwerlin-old 2015/03/16 19:08:09 Thanks, I think that's a bit too much for the aver
31
32 // Number of frames needs at any given time.
33 const uint32_t kInputFrameCount = 1;
34
35 class VideoEncoderShim::EncoderImpl {
36 public:
37 explicit EncoderImpl(const base::WeakPtr<VideoEncoderShim>& shim);
38 ~EncoderImpl();
39
40 void Initialize(media::VideoFrame::Format input_format,
41 const gfx::Size& input_visible_size,
42 media::VideoCodecProfile output_profile,
43 uint32 initial_bitrate);
44 void Encode(const scoped_refptr<media::VideoFrame>& frame,
45 bool force_keyframe);
46 void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer,
47 uint8_t* mem);
48 void RequestEncodingParametersChange(uint32 bitrate, uint32 framerate);
49 void Stop();
50
51 private:
52 struct PendingEncode {
53 PendingEncode(const scoped_refptr<media::VideoFrame>& frame,
54 bool force_keyframe)
55 : frame(frame), force_keyframe(force_keyframe) {}
56 ~PendingEncode() {}
57
58 scoped_refptr<media::VideoFrame> frame;
59 bool force_keyframe;
60 };
61
62 struct BitstreamBuffer {
63 BitstreamBuffer(const media::BitstreamBuffer buffer, uint8_t* mem)
64 : buffer(buffer), mem(mem) {}
65 ~BitstreamBuffer() {}
66
67 media::BitstreamBuffer buffer;
68 uint8_t* mem;
69 };
70
71 void DoEncode();
72
73 base::WeakPtr<VideoEncoderShim> shim_;
74 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
75
76 scoped_ptr<media::cast::SoftwareVideoEncoder> encoder_;
77 std::deque<PendingEncode> frames_;
78 std::deque<BitstreamBuffer> buffers_;
79 };
80
81 VideoEncoderShim::EncoderImpl::EncoderImpl(
82 const base::WeakPtr<VideoEncoderShim>& shim)
83 : shim_(shim), media_task_runner_(base::MessageLoopProxy::current()) {
84 }
85
86 VideoEncoderShim::EncoderImpl::~EncoderImpl() {
87 }
88
89 void VideoEncoderShim::EncoderImpl::Initialize(
90 media::VideoFrame::Format input_format,
91 const gfx::Size& input_visible_size,
92 media::VideoCodecProfile output_profile,
93 uint32 initial_bitrate) {
94 media::cast::VideoSenderConfig config;
95
96 config.max_number_of_video_buffers_used = kInputFrameCount;
97 config.number_of_encode_threads = 1;
98 encoder_.reset(new media::cast::Vp8Encoder(config));
99
100 encoder_->UpdateRates(initial_bitrate);
101
102 media_task_runner_->PostTask(
103 FROM_HERE, base::Bind(&VideoEncoderShim::OnRequireBitstreamBuffers, shim_,
104 kInputFrameCount, input_visible_size,
105 kBitstreamBufferSize));
106 }
107
108 void VideoEncoderShim::EncoderImpl::Encode(
109 const scoped_refptr<media::VideoFrame>& frame,
110 bool force_keyframe) {
111 frames_.push_back(PendingEncode(frame, force_keyframe));
112 DoEncode();
113 }
114
115 void VideoEncoderShim::EncoderImpl::UseOutputBitstreamBuffer(
116 const media::BitstreamBuffer& buffer,
117 uint8_t* mem) {
118 buffers_.push_back(BitstreamBuffer(buffer, mem));
119 DoEncode();
120 }
121
122 void VideoEncoderShim::EncoderImpl::RequestEncodingParametersChange(
123 uint32 bitrate,
124 uint32 framerate) {
125 encoder_->UpdateRates(bitrate);
126 }
127
128 void VideoEncoderShim::EncoderImpl::Stop() {
129 frames_.clear();
130 buffers_.clear();
131 encoder_.reset();
132 }
133
134 void VideoEncoderShim::EncoderImpl::DoEncode() {
135 while (!frames_.empty() && !buffers_.empty()) {
136 PendingEncode frame = frames_.front();
137 frames_.pop_front();
138
139 if (frame.force_keyframe)
140 encoder_->GenerateKeyFrame();
141
142 scoped_ptr<media::cast::EncodedFrame> encoded_frame(
143 new media::cast::EncodedFrame());
144 encoder_->Encode(frame.frame, base::TimeTicks::Now(), encoded_frame.get());
145
146 BitstreamBuffer buffer = buffers_.front();
147 buffers_.pop_front();
148
149 CHECK(buffer.buffer.size() >= encoded_frame->data.size());
150 memcpy(buffer.mem, encoded_frame->bytes(), encoded_frame->data.size());
151
152 // Pass the media::VideoFrame back to the renderer thread so it's
153 // freed on the right thread.
154 media_task_runner_->PostTask(
155 FROM_HERE,
156 base::Bind(
157 &VideoEncoderShim::OnBitstreamBufferReady, shim_,
158 frame.frame, buffer.buffer.id(), encoded_frame->data.size(),
159 encoded_frame->dependency == media::cast::EncodedFrame::KEY));
160 }
161 }
162
163 VideoEncoderShim::VideoEncoderShim(PepperVideoEncoderHost* host)
164 : host_(host),
165 media_task_runner_(
166 RenderThreadImpl::current()->GetMediaThreadTaskRunner()),
167 weak_ptr_factory_(this) {
168 encoder_impl_.reset(new EncoderImpl(weak_ptr_factory_.GetWeakPtr()));
169 }
170
171 VideoEncoderShim::~VideoEncoderShim() {
172 DCHECK(RenderThreadImpl::current());
173
174 media_task_runner_->PostTask(
175 FROM_HERE, base::Bind(&VideoEncoderShim::EncoderImpl::Stop,
176 base::Owned(encoder_impl_.release())));
177 }
178
179 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
180 VideoEncoderShim::GetSupportedProfiles() {
181 media::VideoEncodeAccelerator::SupportedProfile profile = {
182 media::VP8PROFILE_ANY,
183 gfx::Size(kMaxWidth, kMaxHeight),
184 media::cast::kDefaultMaxFrameRate,
185 1};
186 std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles;
187 profiles.push_back(profile);
188 return profiles;
189 }
190
191 bool VideoEncoderShim::Initialize(
192 media::VideoFrame::Format input_format,
193 const gfx::Size& input_visible_size,
194 media::VideoCodecProfile output_profile,
195 uint32 initial_bitrate,
196 media::VideoEncodeAccelerator::Client* client) {
197 DCHECK(RenderThreadImpl::current());
198 DCHECK_EQ(client, host_);
199
200 if (input_format != media::VideoFrame::I420)
201 return false;
202
203 media_task_runner_->PostTask(
204 FROM_HERE,
205 base::Bind(&VideoEncoderShim::EncoderImpl::Initialize,
206 base::Unretained(encoder_impl_.get()), input_format,
207 input_visible_size, output_profile, initial_bitrate));
208
209 return true;
210 }
211
212 void VideoEncoderShim::Encode(const scoped_refptr<media::VideoFrame>& frame,
213 bool force_keyframe) {
214 DCHECK(RenderThreadImpl::current());
215
216 media_task_runner_->PostTask(
217 FROM_HERE,
218 base::Bind(&VideoEncoderShim::EncoderImpl::Encode,
219 base::Unretained(encoder_impl_.get()), frame, force_keyframe));
220 }
221
222 void VideoEncoderShim::UseOutputBitstreamBuffer(
223 const media::BitstreamBuffer& buffer) {
224 DCHECK(RenderThreadImpl::current());
225
226 media_task_runner_->PostTask(
227 FROM_HERE,
228 base::Bind(&VideoEncoderShim::EncoderImpl::UseOutputBitstreamBuffer,
229 base::Unretained(encoder_impl_.get()), buffer,
230 host_->ShmHandleToAddress(buffer.id())));
231 }
232
233 void VideoEncoderShim::RequestEncodingParametersChange(uint32 bitrate,
234 uint32 framerate) {
235 DCHECK(RenderThreadImpl::current());
236
237 media_task_runner_->PostTask(
238 FROM_HERE,
239 base::Bind(
240 &VideoEncoderShim::EncoderImpl::RequestEncodingParametersChange,
241 base::Unretained(encoder_impl_.get()), bitrate, framerate));
242 }
243
244 void VideoEncoderShim::Destroy() {
245 DCHECK(RenderThreadImpl::current());
246
247 delete this;
248 }
249
250 void VideoEncoderShim::OnRequireBitstreamBuffers(
251 unsigned int input_count,
252 const gfx::Size& input_coded_size,
253 size_t output_buffer_size) {
254 DCHECK(RenderThreadImpl::current());
255
256 host_->RequireBitstreamBuffers(input_count, input_coded_size,
257 output_buffer_size);
258 }
259
260 void VideoEncoderShim::OnBitstreamBufferReady(
261 scoped_refptr<media::VideoFrame> frame,
262 int32 bitstream_buffer_id,
263 size_t payload_size,
264 bool key_frame) {
265 DCHECK(RenderThreadImpl::current());
266
267 host_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame);
268 }
269
270 void VideoEncoderShim::OnNotifyError(
271 media::VideoEncodeAccelerator::Error error) {
272 DCHECK(RenderThreadImpl::current());
273
274 host_->NotifyError(error);
275 }
276
277 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698