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

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

Powered by Google App Engine
This is Rietveld 408576698