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

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

Issue 213313003: Experimental patch for MediaCodec APIs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update. Requires chromium @r273920 Created 6 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 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 <GLES2/gl2.h>
6 #include <GLES2/gl2ext.h>
7 #include <GLES2/gl2extchromium.h>
8
5 #include "content/renderer/pepper/pepper_video_decoder_host.h" 9 #include "content/renderer/pepper/pepper_video_decoder_host.h"
6 10
7 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/memory/ref_counted.h"
8 #include "base/memory/shared_memory.h" 13 #include "base/memory/shared_memory.h"
9 #include "content/common/gpu/client/gpu_channel_host.h" 14 #include "content/common/gpu/client/gpu_channel_host.h"
10 #include "content/public/renderer/render_thread.h" 15 #include "content/public/renderer/render_thread.h"
11 #include "content/public/renderer/renderer_ppapi_host.h" 16 #include "content/public/renderer/renderer_ppapi_host.h"
12 #include "content/renderer/pepper/ppb_graphics_3d_impl.h" 17 #include "content/renderer/pepper/ppb_graphics_3d_impl.h"
13 #include "content/renderer/render_thread_impl.h" 18 #include "content/renderer/render_thread_impl.h"
14 #include "content/renderer/render_view_impl.h" 19 #include "content/renderer/render_view_impl.h"
20 #include "gpu/command_buffer/client/gles2_implementation.h"
21 #include "media/base/decoder_buffer.h"
22 #include "media/filters/ffmpeg_video_decoder.h"
15 #include "media/video/picture.h" 23 #include "media/video/picture.h"
16 #include "media/video/video_decode_accelerator.h" 24 #include "media/video/video_decode_accelerator.h"
17 #include "ppapi/c/pp_completion_callback.h" 25 #include "ppapi/c/pp_completion_callback.h"
18 #include "ppapi/c/pp_errors.h" 26 #include "ppapi/c/pp_errors.h"
19 #include "ppapi/host/dispatch_host_message.h" 27 #include "ppapi/host/dispatch_host_message.h"
20 #include "ppapi/host/ppapi_host.h" 28 #include "ppapi/host/ppapi_host.h"
21 #include "ppapi/proxy/ppapi_messages.h" 29 #include "ppapi/proxy/ppapi_messages.h"
22 #include "ppapi/proxy/video_decoder_constants.h" 30 #include "ppapi/proxy/video_decoder_constants.h"
23 #include "ppapi/thunk/enter.h" 31 #include "ppapi/thunk/enter.h"
24 #include "ppapi/thunk/ppb_graphics_3d_api.h" 32 #include "ppapi/thunk/ppb_graphics_3d_api.h"
33 #include "third_party/libyuv/include/libyuv.h"
34 #include "webkit/common/gpu/context_provider_web_context.h"
25 35
26 using ppapi::proxy::SerializedHandle; 36 using ppapi::proxy::SerializedHandle;
27 using ppapi::thunk::EnterResourceNoLock; 37 using ppapi::thunk::EnterResourceNoLock;
28 using ppapi::thunk::PPB_Graphics3D_API; 38 using ppapi::thunk::PPB_Graphics3D_API;
29 39
30 namespace content { 40 namespace content {
31 41
32 namespace { 42 namespace {
33 43
34 media::VideoCodecProfile PepperToMediaVideoProfile(PP_VideoProfile profile) { 44 media::VideoCodecProfile PepperToMediaVideoProfile(PP_VideoProfile profile) {
(...skipping 15 matching lines...) Expand all
50 case PP_VIDEOPROFILE_H264SCALABLEBASELINE: 60 case PP_VIDEOPROFILE_H264SCALABLEBASELINE:
51 return media::H264PROFILE_SCALABLEBASELINE; 61 return media::H264PROFILE_SCALABLEBASELINE;
52 case PP_VIDEOPROFILE_H264SCALABLEHIGH: 62 case PP_VIDEOPROFILE_H264SCALABLEHIGH:
53 return media::H264PROFILE_SCALABLEHIGH; 63 return media::H264PROFILE_SCALABLEHIGH;
54 case PP_VIDEOPROFILE_H264STEREOHIGH: 64 case PP_VIDEOPROFILE_H264STEREOHIGH:
55 return media::H264PROFILE_STEREOHIGH; 65 return media::H264PROFILE_STEREOHIGH;
56 case PP_VIDEOPROFILE_H264MULTIVIEWHIGH: 66 case PP_VIDEOPROFILE_H264MULTIVIEWHIGH:
57 return media::H264PROFILE_MULTIVIEWHIGH; 67 return media::H264PROFILE_MULTIVIEWHIGH;
58 case PP_VIDEOPROFILE_VP8MAIN: 68 case PP_VIDEOPROFILE_VP8MAIN:
59 return media::VP8PROFILE_MAIN; 69 return media::VP8PROFILE_MAIN;
60 // No default case, to catch unhandled PP_VideoProfile values. 70 // No default case, to catch unhandled PP_VideoProfile values.
61 } 71 }
62 72
63 return media::VIDEO_CODEC_PROFILE_UNKNOWN; 73 return media::VIDEO_CODEC_PROFILE_UNKNOWN;
64 } 74 }
65 75
76 int32_t MediaPipelineStatusToPepper(media::PipelineStatus status) {
77 switch (status) {
78 case media::PIPELINE_OK:
79 return PP_OK;
80 case media::DECODER_ERROR_NOT_SUPPORTED:
81 return PP_ERROR_NOTSUPPORTED;
82 default:
83 return PP_ERROR_FAILED;
84 }
85 }
86
66 } // namespace 87 } // namespace
67 88
89 // TODO
90 // - variable # of shm buffers, depending on software or hardware.
91
92 // This wrapper class calls methods on a media::VideoDecoder on the media thread
93 // and relays results back to the host on the main thread. It should be created,
94 // used, and destroyed on the main (render) thread.
95 class SoftwareDecoder {
96 public:
97 explicit SoftwareDecoder(PepperVideoDecoderHost* host);
98 ~SoftwareDecoder();
99
100 void Initialize(media::VideoCodecProfile profile);
101 void Decode(uint32_t decode_id,
102 const scoped_refptr<media::DecoderBuffer>& buffer);
103 void AssignTextures(const std::vector<uint32_t>& plugin_texture_ids);
104 void RecycleTexture(uint32_t plugin_texture_id);
105 void Flush();
106 void Reset();
107 void Destroy();
108
109 private:
110 struct PendingDecode {
111 PendingDecode(uint32_t decode_id,
112 const scoped_refptr<media::DecoderBuffer>& buffer);
113 ~PendingDecode();
114
115 uint32_t decode_id;
116 scoped_refptr<media::DecoderBuffer> buffer;
117 };
118
119 struct PendingFrame {
120 PendingFrame(uint32_t decode_id, const gfx::Size& size);
121 ~PendingFrame();
122
123 uint32_t decode_id;
124 gfx::Size size;
125 std::vector<uint8_t> pixels;
126 };
127
128 void InitializeOnMediaThread(media::VideoDecoderConfig config);
129 void PipelineStatusOnMediaThread(media::PipelineStatus status);
130 void PipelineStatusOnMainThread(media::PipelineStatus status);
131
132 void ReceiveBufferOnMediaThread(uint32_t decode_id,
133 scoped_refptr<media::DecoderBuffer> buffer);
134 void DecodeOnMediaThread();
135 void ConvertFrameOnMediaThread(uint32_t decode_id,
136 media::VideoDecoder::Status status,
137 const scoped_refptr<media::VideoFrame>& frame);
138 void ReceiveFrameOnMainThread(media::VideoDecoder::Status status,
139 scoped_ptr<PendingFrame> frame);
140 void SendPicturesOnMainThread();
141
142 void DoResetOnMediaThread();
143 void ResetCompleteOnMediaThread();
144 void ResetCompleteOnMainThread();
145
146 void DestroyOnMediaThread();
147 void DestroyOnMainThread();
148
149 void DeleteTextures();
150 void FlushCommandBuffer();
151
152 // These members are accessed only on the main thread.
153
154 PepperVideoDecoderHost* host_;
155 scoped_refptr<base::MessageLoopProxy> media_message_loop_;
156 scoped_refptr<webkit::gpu::ContextProviderWebContext> context_provider_;
157 // The current decoded frame size.
158 gfx::Size texture_size_;
159 // Map that takes the plugin's GL texture id to the renderer's GL texture id.
160 typedef std::map<uint32_t, uint32_t> SharedTextureMap;
161 SharedTextureMap shared_textures_;
162 // Track available textures using the plugin's ids.
163 std::vector<uint32_t> plugin_texture_ids_;
164 // Mailboxes for pending texture requests, to write to plugin's textures.
165 std::vector<gpu::Mailbox> pending_texture_mailboxes_;
166 // Queue of pending decoded frames. These have been converted to RGB, and
167 // await upload to a GL texture.
168 typedef std::queue<PendingFrame*> PendingFrameQueue;
169 PendingFrameQueue pending_frames_;
170 uint32_t num_pending_decodes_;
171 bool flushing_;
172 bool resetting_;
173
174 // These members are accessed only on the media thread.
175
176 scoped_ptr<media::VideoDecoder> decoder_;
177 scoped_refptr<base::MessageLoopProxy> main_message_loop_;
178 // Queue of pending decodes. The front element is the buffer currently in
179 // use by the software decoder.
180 typedef std::queue<PendingDecode> PendingDecodeQueue;
181 PendingDecodeQueue pending_decodes_;
182 };
183
184 SoftwareDecoder::PendingDecode::PendingDecode(
185 uint32_t decode_id,
186 const scoped_refptr<media::DecoderBuffer>& buffer)
187 : decode_id(decode_id), buffer(buffer) {
188 }
189
190 SoftwareDecoder::PendingDecode::~PendingDecode() {
191 }
192
193 SoftwareDecoder::PendingFrame::PendingFrame(uint32_t decode_id,
194 const gfx::Size& size)
195 : decode_id(decode_id),
196 size(size),
197 pixels(size.width() * size.height() * 4) {
198 }
199
200 SoftwareDecoder::PendingFrame::~PendingFrame() {
201 }
202
203 SoftwareDecoder::SoftwareDecoder(PepperVideoDecoderHost* host)
204 : host_(host),
205 media_message_loop_(
206 RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy()),
207 context_provider_(
208 RenderThreadImpl::current()->SharedMainThreadContextProvider()),
209 num_pending_decodes_(0),
210 flushing_(false),
211 resetting_(false),
212 main_message_loop_(base::MessageLoopProxy::current()) {
213 DCHECK(host_);
214 DCHECK(main_message_loop_);
215 DCHECK(media_message_loop_);
216 DCHECK(context_provider_);
217 }
218
219 SoftwareDecoder::~SoftwareDecoder() {
220 DCHECK(RenderThreadImpl::current());
221 while (!pending_frames_.empty()) {
222 delete pending_frames_.front();
223 pending_frames_.pop();
224 }
225 DeleteTextures();
226 FlushCommandBuffer();
227 }
228
229 void SoftwareDecoder::Initialize(media::VideoCodecProfile profile) {
230 DCHECK(RenderThreadImpl::current());
231 DCHECK(!decoder_);
232 media::VideoCodec codec = media::kUnknownVideoCodec;
233 if (profile <= media::H264PROFILE_MAX)
234 codec = media::kCodecH264;
235 else if (profile <= media::VP8PROFILE_MAX)
236 codec = media::kCodecVP8;
237 DCHECK_NE(codec, media::kUnknownVideoCodec);
238
239 media::VideoDecoderConfig config(
240 codec,
241 profile,
242 media::VideoFrame::YV12,
243 gfx::Size(32, 24), // Small sizes that won't fail.
244 gfx::Rect(32, 24),
245 gfx::Size(32, 24),
246 NULL /* extra_data */,
247 0 /* extra_data_size */,
248 false /* decryption */);
249
250 decoder_.reset(new media::FFmpegVideoDecoder(media_message_loop_));
251
252 media_message_loop_->PostTask(
253 FROM_HERE,
254 base::Bind(&SoftwareDecoder::InitializeOnMediaThread,
255 base::Unretained(this),
256 config));
257 }
258
259 void SoftwareDecoder::Decode(
260 uint32_t decode_id,
261 const scoped_refptr<media::DecoderBuffer>& buffer) {
262 DCHECK(RenderThreadImpl::current());
263 DCHECK(decoder_);
264 DCHECK(!resetting_ && !flushing_);
265
266 num_pending_decodes_++;
267
268 media_message_loop_->PostTask(
269 FROM_HERE,
270 base::Bind(&SoftwareDecoder::ReceiveBufferOnMediaThread,
271 base::Unretained(this),
272 decode_id,
273 buffer));
274 }
275
276 void SoftwareDecoder::AssignTextures(
277 const std::vector<uint32_t>& plugin_texture_ids) {
278 DCHECK(RenderThreadImpl::current());
279 DCHECK(decoder_);
280 DCHECK(plugin_texture_ids.size());
281 DCHECK_EQ(plugin_texture_ids.size(), pending_texture_mailboxes_.size());
282 uint32_t num_textures = static_cast<GLuint>(plugin_texture_ids.size());
283 std::vector<uint32_t> local_ids(num_textures);
284 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
285 gles2->GenTextures(num_textures, &local_ids.front());
286 for (uint32_t i = 0; i < num_textures; i++) {
287 gles2->ActiveTexture(GL_TEXTURE0);
288 gles2->BindTexture(GL_TEXTURE_2D, local_ids[i]);
289 gles2->ConsumeTextureCHROMIUM(GL_TEXTURE_2D,
290 pending_texture_mailboxes_[i].name);
291 // Map the plugin texture id to the local texture id.
292 shared_textures_.insert(
293 std::make_pair(plugin_texture_ids[i], local_ids[i]));
294 }
295 pending_texture_mailboxes_.clear();
296 plugin_texture_ids_ = plugin_texture_ids;
297 SendPicturesOnMainThread();
298 }
299
300 void SoftwareDecoder::RecycleTexture(uint32_t plugin_texture_id) {
301 DCHECK(RenderThreadImpl::current());
302 DCHECK(decoder_);
303 // Make sure it is still a valid texture.
304 SharedTextureMap::iterator it = shared_textures_.find(plugin_texture_id);
305 if (it != shared_textures_.end()) {
306 plugin_texture_ids_.push_back(plugin_texture_id);
307 }
308 SendPicturesOnMainThread();
309 }
310
311 void SoftwareDecoder::Flush() {
312 DCHECK(RenderThreadImpl::current());
313 DCHECK(decoder_);
314 DCHECK(!resetting_ && !flushing_);
315 flushing_ = true;
316 }
317
318 void SoftwareDecoder::Reset() {
319 DCHECK(RenderThreadImpl::current());
320 DCHECK(decoder_);
321 DCHECK(!resetting_ && !flushing_);
322 printf("SoftwareDecoder::Reset\n");
323 resetting_ = true;
324 media_message_loop_->PostTask(
325 FROM_HERE,
326 base::Bind(&SoftwareDecoder::DoResetOnMediaThread,
327 base::Unretained(this)));
328 }
329
330 void SoftwareDecoder::Destroy() {
331 DCHECK(RenderThreadImpl::current());
332 DCHECK(decoder_);
333 DCHECK(host_);
334 host_ = NULL;
335 media_message_loop_->PostTask(
336 FROM_HERE,
337 base::Bind(&SoftwareDecoder::DestroyOnMediaThread,
338 base::Unretained(this)));
339 }
340
341 void SoftwareDecoder::InitializeOnMediaThread(
342 media::VideoDecoderConfig config) {
343 DCHECK(decoder_);
344 decoder_->Initialize(config,
345 true /* low_delay */,
346 base::Bind(&SoftwareDecoder::PipelineStatusOnMediaThread,
347 base::Unretained(this)));
348 }
349
350 void SoftwareDecoder::PipelineStatusOnMediaThread(
351 media::PipelineStatus status) {
352 if (!host_)
353 return;
354 main_message_loop_->PostTask(
355 FROM_HERE,
356 base::Bind(&SoftwareDecoder::PipelineStatusOnMainThread,
357 base::Unretained(this),
358 status));
359 }
360
361 void SoftwareDecoder::PipelineStatusOnMainThread(media::PipelineStatus status) {
362 if (!host_)
363 return;
364 host_->OnInitializeComplete(status);
365 }
366
367 void SoftwareDecoder::ReceiveBufferOnMediaThread(
368 uint32_t decode_id,
369 scoped_refptr<media::DecoderBuffer> buffer) {
370 bool decoder_busy = !pending_decodes_.empty();
371 pending_decodes_.push(PendingDecode(decode_id, buffer));
372 if (!decoder_busy)
373 DecodeOnMediaThread();
374 }
375
376 void SoftwareDecoder::DecodeOnMediaThread() {
377 DCHECK(!pending_decodes_.empty());
378 PendingDecode& next_decode = pending_decodes_.front();
379 decoder_->Decode(next_decode.buffer,
380 base::Bind(&SoftwareDecoder::ConvertFrameOnMediaThread,
381 base::Unretained(this),
382 next_decode.decode_id));
383 pending_decodes_.pop();
384 }
385
386 void SoftwareDecoder::ConvertFrameOnMediaThread(
387 uint32_t decode_id,
388 media::VideoDecoder::Status status,
389 const scoped_refptr<media::VideoFrame>& frame) {
390 if (!host_)
391 return;
392 scoped_ptr<PendingFrame> pending_frame(
393 new PendingFrame(decode_id, gfx::Size()));
394 if (frame) {
395 pending_frame->size = frame->coded_size();
396 pending_frame->pixels.resize(frame->coded_size().width() *
397 frame->coded_size().height() * 4);
398 // Convert the decoded frame to ARGB pixels.
399 libyuv::I420ToARGB(frame->data(media::VideoFrame::kYPlane),
400 frame->stride(media::VideoFrame::kYPlane),
401 frame->data(media::VideoFrame::kUPlane),
402 frame->stride(media::VideoFrame::kUPlane),
403 frame->data(media::VideoFrame::kVPlane),
404 frame->stride(media::VideoFrame::kVPlane),
405 &pending_frame->pixels.front(),
406 frame->coded_size().width() * 4,
407 frame->coded_size().width(),
408 frame->coded_size().height());
409 }
410
411 main_message_loop_->PostTask(
412 FROM_HERE,
413 base::Bind(&SoftwareDecoder::ReceiveFrameOnMainThread,
414 base::Unretained(this),
415 status,
416 base::Passed(&pending_frame)));
417
418 if (!pending_decodes_.empty())
419 DecodeOnMediaThread();
420 }
421
422 void SoftwareDecoder::ReceiveFrameOnMainThread(
423 media::VideoDecoder::Status status,
424 scoped_ptr<PendingFrame> frame) {
425 DCHECK(RenderThreadImpl::current());
426 if (!host_)
427 return;
428
429 num_pending_decodes_--;
430
431 if (frame->pixels.size()) {
432 if (texture_size_ != frame->size) {
433 // If the size has changed, dismiss all textures. TODO what if some are
434 // in use? Dismiss free ones, mark busy ones, and wait for recycle?
435 for (size_t i = 0; i < plugin_texture_ids_.size(); i++)
436 host_->DismissPictureBuffer(plugin_texture_ids_[i]);
437 plugin_texture_ids_.clear();
438
439 DeleteTextures();
440
441 DCHECK(pending_texture_mailboxes_.empty());
442 const uint32_t num_textures = 8;
443 for (uint32_t i = 0; i < num_textures; i++)
444 pending_texture_mailboxes_.push_back(gpu::Mailbox::Generate());
445
446 host_->RequestTextures(
447 num_textures, frame->size, GL_TEXTURE_2D, pending_texture_mailboxes_);
448 texture_size_ = frame->size;
449 }
450
451 pending_frames_.push(frame.release());
452 SendPicturesOnMainThread();
453 } else {
454 host_->NotifyEndOfBitstreamBuffer(frame->decode_id);
455 }
456 }
457
458 void SoftwareDecoder::SendPicturesOnMainThread() {
459 DCHECK(RenderThreadImpl::current());
460 if (!host_)
461 return;
462 while (!pending_frames_.empty() && !plugin_texture_ids_.empty()) {
463 scoped_ptr<PendingFrame> frame(pending_frames_.front());
464 pending_frames_.pop();
465
466 uint32_t plugin_texture_id = plugin_texture_ids_.back();
467 plugin_texture_ids_.pop_back();
468
469 uint32_t local_id = shared_textures_[plugin_texture_id];
470 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
471 gles2->ActiveTexture(GL_TEXTURE0);
472 gles2->BindTexture(GL_TEXTURE_2D, local_id);
473 gles2->TexImage2D(GL_TEXTURE_2D,
474 0,
475 GL_RGBA,
476 texture_size_.width(),
477 texture_size_.height(),
478 0,
479 GL_RGBA,
480 GL_UNSIGNED_BYTE,
481 &frame->pixels.front());
482
483 host_->NotifyEndOfBitstreamBuffer(frame->decode_id);
484 host_->PictureReady(media::Picture(plugin_texture_id, frame->decode_id));
485 }
486
487 FlushCommandBuffer();
488
489 if (flushing_ && !num_pending_decodes_ && pending_frames_.empty()) {
490 flushing_ = false;
491 host_->NotifyFlushDone();
492 }
493 }
494
495 void SoftwareDecoder::DoResetOnMediaThread() {
496 printf("SoftwareDecoder::DoResetOnMediaThread\n");
497 decoder_->Reset(base::Bind(&SoftwareDecoder::ResetCompleteOnMediaThread,
498 base::Unretained(this)));
499 }
500
501 void SoftwareDecoder::ResetCompleteOnMediaThread() {
502 printf("SoftwareDecoder::ResetCompleteOnMediaThread\n");
503 // Cancel all remaining decodes, and notify the host so it can free the shm
504 // buffers. We'll clear pending frames on the main thread.
505 while (!pending_decodes_.empty()) {
506 PendingDecode& next_decode = pending_decodes_.front();
507 scoped_ptr<PendingFrame> pending_frame(
508 new PendingFrame(next_decode.decode_id, gfx::Size()));
509 main_message_loop_->PostTask(
510 FROM_HERE,
511 base::Bind(&SoftwareDecoder::ReceiveFrameOnMainThread,
512 base::Unretained(this),
513 media::VideoDecoder::kAborted,
514 base::Passed(&pending_frame)));
515 pending_decodes_.pop();
516 }
517 main_message_loop_->PostTask(
518 FROM_HERE,
519 base::Bind(&SoftwareDecoder::ResetCompleteOnMainThread,
520 base::Unretained(this)));
521 }
522
523 void SoftwareDecoder::ResetCompleteOnMainThread() {
524 if (!host_)
525 return;
526 printf("SoftwareDecoder::ResetCompleteOnMainThread\n");
527
528 while (!pending_frames_.empty()) {
529 scoped_ptr<PendingFrame> frame(pending_frames_.front());
530 host_->NotifyEndOfBitstreamBuffer(frame->decode_id);
531 pending_frames_.pop();
532 }
533
534 resetting_ = false;
535 host_->NotifyResetDone();
536 }
537
538 void SoftwareDecoder::DestroyOnMediaThread() {
539 DCHECK(decoder_);
540 decoder_->Stop();
541 // All callbacks have been called on the media thread, and thus all tasks
542 // posted for the main thread. This is our last task for the main thread.
543 main_message_loop_->PostTask(FROM_HERE,
544 base::Bind(&SoftwareDecoder::DestroyOnMainThread,
545 base::Unretained(this)));
546 }
547
548 void SoftwareDecoder::DestroyOnMainThread() {
549 DCHECK(RenderThreadImpl::current());
550 DCHECK(!host_);
551 delete this;
552 }
553
554 void SoftwareDecoder::DeleteTextures() {
555 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
556 SharedTextureMap::iterator it = shared_textures_.begin();
557 for (; it != shared_textures_.end(); ++it)
558 gles2->DeleteTextures(1, &it->second);
559 shared_textures_.clear();
560 }
561
562 void SoftwareDecoder::FlushCommandBuffer() {
563 DCHECK(RenderThreadImpl::current());
564 context_provider_->ContextGL()->Flush();
565 }
566
68 PepperVideoDecoderHost::PendingDecode::PendingDecode( 567 PepperVideoDecoderHost::PendingDecode::PendingDecode(
69 uint32_t shm_id, 568 uint32_t shm_id,
70 const ppapi::host::ReplyMessageContext& reply_context) 569 const ppapi::host::ReplyMessageContext& reply_context)
71 : shm_id(shm_id), reply_context(reply_context) { 570 : shm_id(shm_id), reply_context(reply_context) {
72 } 571 }
73 572
74 PepperVideoDecoderHost::PendingDecode::~PendingDecode() { 573 PepperVideoDecoderHost::PendingDecode::~PendingDecode() {
75 } 574 }
76 575
77 PepperVideoDecoderHost::PepperVideoDecoderHost(RendererPpapiHost* host, 576 PepperVideoDecoderHost::PepperVideoDecoderHost(RendererPpapiHost* host,
78 PP_Instance instance, 577 PP_Instance instance,
79 PP_Resource resource) 578 PP_Resource resource)
80 : ResourceHost(host->GetPpapiHost(), instance, resource), 579 : ResourceHost(host->GetPpapiHost(), instance, resource),
81 renderer_ppapi_host_(host), 580 renderer_ppapi_host_(host),
82 initialized_(false) { 581 initialized_(false) {
83 } 582 }
84 583
85 PepperVideoDecoderHost::~PepperVideoDecoderHost() { 584 PepperVideoDecoderHost::~PepperVideoDecoderHost() {
585 // TODO DefaultDeleter.
586 if (software_decoder_)
587 software_decoder_.release()->Destroy();
86 } 588 }
87 589
88 int32_t PepperVideoDecoderHost::OnResourceMessageReceived( 590 int32_t PepperVideoDecoderHost::OnResourceMessageReceived(
89 const IPC::Message& msg, 591 const IPC::Message& msg,
90 ppapi::host::HostMessageContext* context) { 592 ppapi::host::HostMessageContext* context) {
91 PPAPI_BEGIN_MESSAGE_MAP(PepperVideoDecoderHost, msg) 593 PPAPI_BEGIN_MESSAGE_MAP(PepperVideoDecoderHost, msg)
92 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Initialize, 594 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Initialize,
93 OnHostMsgInitialize) 595 OnHostMsgInitialize)
94 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_GetShm, 596 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_GetShm,
95 OnHostMsgGetShm) 597 OnHostMsgGetShm)
96 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Decode, 598 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Decode,
97 OnHostMsgDecode) 599 OnHostMsgDecode)
98 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_AssignTextures, 600 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_AssignTextures,
99 OnHostMsgAssignTextures) 601 OnHostMsgAssignTextures)
100 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_RecyclePicture, 602 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_RecyclePicture,
101 OnHostMsgRecyclePicture) 603 OnHostMsgRecyclePicture)
102 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Flush, 604 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Flush,
103 OnHostMsgFlush) 605 OnHostMsgFlush)
104 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Reset, 606 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Reset,
105 OnHostMsgReset) 607 OnHostMsgReset)
106 PPAPI_END_MESSAGE_MAP() 608 PPAPI_END_MESSAGE_MAP()
107 return PP_ERROR_FAILED; 609 return PP_ERROR_FAILED;
108 } 610 }
109 611
110 int32_t PepperVideoDecoderHost::OnHostMsgInitialize( 612 int32_t PepperVideoDecoderHost::OnHostMsgInitialize(
111 ppapi::host::HostMessageContext* context, 613 ppapi::host::HostMessageContext* context,
112 const ppapi::HostResource& graphics_context, 614 const ppapi::HostResource& graphics_context,
113 PP_VideoProfile profile, 615 PP_VideoProfile profile,
114 bool allow_software_fallback) { 616 bool allow_software_fallback) {
115 if (initialized_) 617 if (initialized_)
116 return PP_ERROR_FAILED; 618 return PP_ERROR_FAILED;
117 619
118 EnterResourceNoLock<PPB_Graphics3D_API> enter_graphics( 620 EnterResourceNoLock<PPB_Graphics3D_API> enter_graphics(
119 graphics_context.host_resource(), true); 621 graphics_context.host_resource(), true);
120 if (enter_graphics.failed()) 622 if (enter_graphics.failed())
121 return PP_ERROR_FAILED; 623 return PP_ERROR_FAILED;
122 graphics3d_ = static_cast<PPB_Graphics3D_Impl*>(enter_graphics.object()); 624 PPB_Graphics3D_Impl* graphics3d =
625 static_cast<PPB_Graphics3D_Impl*>(enter_graphics.object());
123 626
124 int command_buffer_route_id = graphics3d_->GetCommandBufferRouteId(); 627 int command_buffer_route_id = graphics3d->GetCommandBufferRouteId();
125 if (!command_buffer_route_id) 628 if (!command_buffer_route_id)
126 return PP_ERROR_FAILED; 629 return PP_ERROR_FAILED;
127 630
128 media::VideoCodecProfile media_profile = PepperToMediaVideoProfile(profile); 631 media::VideoCodecProfile media_profile = PepperToMediaVideoProfile(profile);
129 632
130 // This is not synchronous, but subsequent IPC messages will be buffered, so 633 // This is not synchronous, but subsequent IPC messages will be buffered, so
131 // it is okay to immediately send IPC messages through the returned channel. 634 // it is okay to immediately send IPC messages through the returned channel.
132 GpuChannelHost* channel = graphics3d_->channel(); 635 GpuChannelHost* channel = graphics3d->channel();
133 DCHECK(channel); 636 DCHECK(channel);
134 decoder_ = channel->CreateVideoDecoder(command_buffer_route_id); 637 decoder_ = channel->CreateVideoDecoder(command_buffer_route_id);
135 if (decoder_ && decoder_->Initialize(media_profile, this)) { 638 if (decoder_ && decoder_->Initialize(media_profile, this)) {
136 initialized_ = true; 639 initialized_ = true;
137 return PP_OK; 640 return PP_OK;
138 } 641 }
139 decoder_.reset(); 642 decoder_.reset();
140 643
141 // TODO(bbudge) Implement software fallback. 644 if (!allow_software_fallback)
142 return PP_ERROR_NOTSUPPORTED; 645 return PP_ERROR_NOTSUPPORTED;
646
647 software_decoder_.reset(new SoftwareDecoder(this));
648 initialize_reply_context_ = context->MakeReplyMessageContext();
649 software_decoder_->Initialize(media_profile);
650
651 return PP_OK_COMPLETIONPENDING;
143 } 652 }
144 653
145 int32_t PepperVideoDecoderHost::OnHostMsgGetShm( 654 int32_t PepperVideoDecoderHost::OnHostMsgGetShm(
146 ppapi::host::HostMessageContext* context, 655 ppapi::host::HostMessageContext* context,
147 uint32_t shm_id, 656 uint32_t shm_id,
148 uint32_t shm_size) { 657 uint32_t shm_size) {
149 if (!initialized_) 658 if (!initialized_)
150 return PP_ERROR_FAILED; 659 return PP_ERROR_FAILED;
151 660
152 // Make the buffers larger since we hope to reuse them. 661 // Make the buffers larger since we hope to reuse them.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 return PP_OK_COMPLETIONPENDING; 710 return PP_OK_COMPLETIONPENDING;
202 } 711 }
203 712
204 int32_t PepperVideoDecoderHost::OnHostMsgDecode( 713 int32_t PepperVideoDecoderHost::OnHostMsgDecode(
205 ppapi::host::HostMessageContext* context, 714 ppapi::host::HostMessageContext* context,
206 uint32_t shm_id, 715 uint32_t shm_id,
207 uint32_t size, 716 uint32_t size,
208 int32_t decode_id) { 717 int32_t decode_id) {
209 if (!initialized_) 718 if (!initialized_)
210 return PP_ERROR_FAILED; 719 return PP_ERROR_FAILED;
211 DCHECK(decoder_); 720 DCHECK(decoder_ || software_decoder_);
212 // |shm_id| is just an index into shm_buffers_. Make sure it's in range. 721 // |shm_id| is just an index into shm_buffers_. Make sure it's in range.
213 if (static_cast<size_t>(shm_id) >= shm_buffers_.size()) 722 if (static_cast<size_t>(shm_id) >= shm_buffers_.size())
214 return PP_ERROR_FAILED; 723 return PP_ERROR_FAILED;
215 // Reject an attempt to pass a busy buffer to the decoder again. 724 // Reject an attempt to pass a busy buffer to the decoder again.
216 if (shm_buffer_busy_[shm_id]) 725 if (shm_buffer_busy_[shm_id])
217 return PP_ERROR_FAILED; 726 return PP_ERROR_FAILED;
218 // Reject non-unique decode_id values. 727 // Reject non-unique decode_id values.
219 if (pending_decodes_.find(decode_id) != pending_decodes_.end()) 728 if (pending_decodes_.find(decode_id) != pending_decodes_.end())
220 return PP_ERROR_FAILED; 729 return PP_ERROR_FAILED;
221 730
222 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid()) 731 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid())
223 return PP_ERROR_FAILED; 732 return PP_ERROR_FAILED;
224 733
225 pending_decodes_.insert(std::make_pair( 734 pending_decodes_.insert(std::make_pair(
226 decode_id, PendingDecode(shm_id, context->MakeReplyMessageContext()))); 735 decode_id, PendingDecode(shm_id, context->MakeReplyMessageContext())));
227 736
228 shm_buffer_busy_[shm_id] = true; 737 shm_buffer_busy_[shm_id] = true;
229 decoder_->Decode( 738 base::SharedMemory* shm = shm_buffers_[shm_id];
230 media::BitstreamBuffer(decode_id, shm_buffers_[shm_id]->handle(), size)); 739 if (decoder_) {
740 decoder_->Decode(media::BitstreamBuffer(decode_id, shm->handle(), size));
741 } else {
742 software_decoder_->Decode(decode_id,
743 media::DecoderBuffer::CopyFrom(
744 static_cast<uint8_t*>(shm->memory()), size));
745 }
231 746
232 return PP_OK_COMPLETIONPENDING; 747 return PP_OK_COMPLETIONPENDING;
233 } 748 }
234 749
235 int32_t PepperVideoDecoderHost::OnHostMsgAssignTextures( 750 int32_t PepperVideoDecoderHost::OnHostMsgAssignTextures(
236 ppapi::host::HostMessageContext* context, 751 ppapi::host::HostMessageContext* context,
237 const PP_Size& size, 752 const PP_Size& size,
238 const std::vector<uint32_t>& texture_ids) { 753 const std::vector<uint32_t>& texture_ids) {
239 if (!initialized_) 754 if (!initialized_)
240 return PP_ERROR_FAILED; 755 return PP_ERROR_FAILED;
241 DCHECK(decoder_); 756 DCHECK(decoder_ || software_decoder_);
242 757
243 std::vector<media::PictureBuffer> picture_buffers; 758 if (decoder_) {
244 for (uint32 i = 0; i < texture_ids.size(); i++) { 759 std::vector<media::PictureBuffer> picture_buffers;
245 media::PictureBuffer buffer( 760 for (uint32 i = 0; i < texture_ids.size(); i++) {
246 texture_ids[i], // Use the texture_id to identify the buffer. 761 media::PictureBuffer buffer(
247 gfx::Size(size.width, size.height), 762 texture_ids[i], // Use the texture_id to identify the buffer.
248 texture_ids[i]); 763 gfx::Size(size.width, size.height),
249 picture_buffers.push_back(buffer); 764 texture_ids[i]);
765 picture_buffers.push_back(buffer);
766 }
767 decoder_->AssignPictureBuffers(picture_buffers);
768 } else {
769 software_decoder_->AssignTextures(texture_ids);
250 } 770 }
251 decoder_->AssignPictureBuffers(picture_buffers);
252 return PP_OK; 771 return PP_OK;
253 } 772 }
254 773
255 int32_t PepperVideoDecoderHost::OnHostMsgRecyclePicture( 774 int32_t PepperVideoDecoderHost::OnHostMsgRecyclePicture(
256 ppapi::host::HostMessageContext* context, 775 ppapi::host::HostMessageContext* context,
257 uint32_t texture_id) { 776 uint32_t texture_id) {
258 if (!initialized_) 777 if (!initialized_)
259 return PP_ERROR_FAILED; 778 return PP_ERROR_FAILED;
260 DCHECK(decoder_); 779 DCHECK(decoder_ || software_decoder_);
261 if (reset_reply_context_.is_valid()) 780 if (reset_reply_context_.is_valid())
262 return PP_ERROR_FAILED; 781 return PP_ERROR_FAILED;
263 782 if (decoder_) {
264 decoder_->ReusePictureBuffer(texture_id); 783 decoder_->ReusePictureBuffer(texture_id);
784 } else {
785 software_decoder_->RecycleTexture(texture_id);
786 }
265 787
266 return PP_OK; 788 return PP_OK;
267 } 789 }
268 790
269 int32_t PepperVideoDecoderHost::OnHostMsgFlush( 791 int32_t PepperVideoDecoderHost::OnHostMsgFlush(
270 ppapi::host::HostMessageContext* context) { 792 ppapi::host::HostMessageContext* context) {
271 if (!initialized_) 793 if (!initialized_)
272 return PP_ERROR_FAILED; 794 return PP_ERROR_FAILED;
273 DCHECK(decoder_); 795 DCHECK(decoder_ || software_decoder_);
274 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid()) 796 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid())
275 return PP_ERROR_FAILED; 797 return PP_ERROR_FAILED;
276 798
277 flush_reply_context_ = context->MakeReplyMessageContext(); 799 flush_reply_context_ = context->MakeReplyMessageContext();
278 decoder_->Flush(); 800 if (decoder_)
801 decoder_->Flush();
802 else
803 software_decoder_->Flush();
279 804
280 return PP_OK_COMPLETIONPENDING; 805 return PP_OK_COMPLETIONPENDING;
281 } 806 }
282 807
283 int32_t PepperVideoDecoderHost::OnHostMsgReset( 808 int32_t PepperVideoDecoderHost::OnHostMsgReset(
284 ppapi::host::HostMessageContext* context) { 809 ppapi::host::HostMessageContext* context) {
285 if (!initialized_) 810 if (!initialized_)
286 return PP_ERROR_FAILED; 811 return PP_ERROR_FAILED;
287 DCHECK(decoder_); 812 DCHECK(decoder_ || software_decoder_);
288 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid()) 813 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid())
289 return PP_ERROR_FAILED; 814 return PP_ERROR_FAILED;
815 printf("PepperVideoDecoderHost::OnHostMsgReset\n");
290 816
291 reset_reply_context_ = context->MakeReplyMessageContext(); 817 reset_reply_context_ = context->MakeReplyMessageContext();
292 decoder_->Reset(); 818 if (decoder_)
819 decoder_->Reset();
820 else
821 software_decoder_->Reset();
293 822
294 return PP_OK_COMPLETIONPENDING; 823 return PP_OK_COMPLETIONPENDING;
295 } 824 }
296 825
297 void PepperVideoDecoderHost::ProvidePictureBuffers( 826 void PepperVideoDecoderHost::ProvidePictureBuffers(
298 uint32 requested_num_of_buffers, 827 uint32 requested_num_of_buffers,
299 const gfx::Size& dimensions, 828 const gfx::Size& dimensions,
300 uint32 texture_target) { 829 uint32 texture_target) {
301 DCHECK(RenderThreadImpl::current()); 830 RequestTextures(requested_num_of_buffers,
302 host()->SendUnsolicitedReply( 831 dimensions,
303 pp_resource(), 832 texture_target,
304 PpapiPluginMsg_VideoDecoder_RequestTextures( 833 std::vector<gpu::Mailbox>());
305 requested_num_of_buffers,
306 PP_MakeSize(dimensions.width(), dimensions.height()),
307 texture_target));
308 } 834 }
309 835
310 void PepperVideoDecoderHost::PictureReady(const media::Picture& picture) { 836 void PepperVideoDecoderHost::PictureReady(const media::Picture& picture) {
311 DCHECK(RenderThreadImpl::current()); 837 DCHECK(RenderThreadImpl::current());
312 host()->SendUnsolicitedReply( 838 host()->SendUnsolicitedReply(
313 pp_resource(), 839 pp_resource(),
314 PpapiPluginMsg_VideoDecoder_PictureReady(picture.bitstream_buffer_id(), 840 PpapiPluginMsg_VideoDecoder_PictureReady(picture.bitstream_buffer_id(),
315 picture.picture_buffer_id())); 841 picture.picture_buffer_id()));
316 } 842 }
317 843
(...skipping 18 matching lines...) Expand all
336 case media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM: 862 case media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM:
337 pp_error = PP_ERROR_RESOURCE_FAILED; 863 pp_error = PP_ERROR_RESOURCE_FAILED;
338 break; 864 break;
339 // No default case, to catch unhandled enum values. 865 // No default case, to catch unhandled enum values.
340 } 866 }
341 host()->SendUnsolicitedReply( 867 host()->SendUnsolicitedReply(
342 pp_resource(), PpapiPluginMsg_VideoDecoder_NotifyError(pp_error)); 868 pp_resource(), PpapiPluginMsg_VideoDecoder_NotifyError(pp_error));
343 } 869 }
344 870
345 void PepperVideoDecoderHost::NotifyResetDone() { 871 void PepperVideoDecoderHost::NotifyResetDone() {
872 printf("PepperVideoDecoderHost::NotifyResetDone:pending=%i\n", (int)pending_de codes_.size());
346 DCHECK(RenderThreadImpl::current()); 873 DCHECK(RenderThreadImpl::current());
347 host()->SendReply(reset_reply_context_, 874 host()->SendReply(reset_reply_context_,
348 PpapiPluginMsg_VideoDecoder_ResetReply()); 875 PpapiPluginMsg_VideoDecoder_ResetReply());
349 reset_reply_context_ = ppapi::host::ReplyMessageContext(); 876 reset_reply_context_ = ppapi::host::ReplyMessageContext();
350 } 877 }
351 878
352 void PepperVideoDecoderHost::NotifyEndOfBitstreamBuffer( 879 void PepperVideoDecoderHost::NotifyEndOfBitstreamBuffer(
353 int32 bitstream_buffer_id) { 880 int32 bitstream_buffer_id) {
354 DCHECK(RenderThreadImpl::current()); 881 DCHECK(RenderThreadImpl::current());
355 PendingDecodeMap::iterator it = pending_decodes_.find(bitstream_buffer_id); 882 PendingDecodeMap::iterator it = pending_decodes_.find(bitstream_buffer_id);
356 if (it == pending_decodes_.end()) { 883 if (it == pending_decodes_.end()) {
357 NOTREACHED(); 884 NOTREACHED();
358 return; 885 return;
359 } 886 }
360 const PendingDecode& pending_decode = it->second; 887 const PendingDecode& pending_decode = it->second;
361 host()->SendReply( 888 host()->SendReply(
362 pending_decode.reply_context, 889 pending_decode.reply_context,
363 PpapiPluginMsg_VideoDecoder_DecodeReply(pending_decode.shm_id)); 890 PpapiPluginMsg_VideoDecoder_DecodeReply(pending_decode.shm_id));
364 shm_buffer_busy_[pending_decode.shm_id] = false; 891 shm_buffer_busy_[pending_decode.shm_id] = false;
365 pending_decodes_.erase(it); 892 pending_decodes_.erase(it);
366 } 893 }
367 894
368 void PepperVideoDecoderHost::NotifyFlushDone() { 895 void PepperVideoDecoderHost::NotifyFlushDone() {
369 DCHECK(RenderThreadImpl::current()); 896 DCHECK(RenderThreadImpl::current());
370 host()->SendReply(flush_reply_context_, 897 host()->SendReply(flush_reply_context_,
371 PpapiPluginMsg_VideoDecoder_FlushReply()); 898 PpapiPluginMsg_VideoDecoder_FlushReply());
372 flush_reply_context_ = ppapi::host::ReplyMessageContext(); 899 flush_reply_context_ = ppapi::host::ReplyMessageContext();
373 } 900 }
374 901
902 void PepperVideoDecoderHost::OnInitializeComplete(
903 media::PipelineStatus status) {
904 if (!initialized_) {
905 initialized_ = true;
906 int32_t result = MediaPipelineStatusToPepper(status);
907 initialize_reply_context_.params.set_result(result);
908 host()->SendReply(initialize_reply_context_,
909 PpapiPluginMsg_VideoDecoder_InitializeReply());
910 }
911 }
912
913 void PepperVideoDecoderHost::RequestTextures(
914 uint32 requested_num_of_buffers,
915 const gfx::Size& dimensions,
916 uint32 texture_target,
917 const std::vector<gpu::Mailbox>& mailboxes) {
918 DCHECK(RenderThreadImpl::current());
919 host()->SendUnsolicitedReply(
920 pp_resource(),
921 PpapiPluginMsg_VideoDecoder_RequestTextures(
922 requested_num_of_buffers,
923 PP_MakeSize(dimensions.width(), dimensions.height()),
924 texture_target,
925 mailboxes));
926 }
927
375 } // namespace content 928 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/pepper/pepper_video_decoder_host.h ('k') | content/test/ppapi/ppapi_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698