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

Unified Diff: content/renderer/pepper/pepper_video_decoder_host.cc

Issue 270213004: Implement Pepper PPB_VideoDecoder interface. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: content/renderer/pepper/pepper_video_decoder_host.cc
diff --git a/content/renderer/pepper/pepper_video_decoder_host.cc b/content/renderer/pepper/pepper_video_decoder_host.cc
new file mode 100644
index 0000000000000000000000000000000000000000..297d50cbf3efe69013f0829372ba0741a9d3c603
--- /dev/null
+++ b/content/renderer/pepper/pepper_video_decoder_host.cc
@@ -0,0 +1,345 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/pepper/pepper_video_decoder_host.h"
+
+#include "base/bind.h"
+#include "base/memory/shared_memory.h"
+#include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "content/renderer/pepper/ppb_graphics_3d_impl.h"
+#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/render_view_impl.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "media/video/picture.h"
+#include "media/video/video_decode_accelerator.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_graphics_3d_api.h"
+
+using ppapi::proxy::SerializedHandle;
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_Graphics3D_API;
+
+namespace content {
+
+namespace {
+
+#define COMPILE_ASSERT_MATCHING_ENUM(media_name, np_name) \
+ COMPILE_ASSERT( \
+ static_cast<int>(media::media_name) == static_cast<int>(np_name), \
+ mismatching_enums)
+
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_BASELINE,
+ PP_VIDEOPROFILE_H264BASELINE);
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_MAIN, PP_VIDEOPROFILE_H264MAIN);
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_EXTENDED,
+ PP_VIDEOPROFILE_H264EXTENDED);
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_HIGH, PP_VIDEOPROFILE_H264HIGH);
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_HIGH10PROFILE,
+ PP_VIDEOPROFILE_H264HIGH10PROFILE);
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_HIGH422PROFILE,
+ PP_VIDEOPROFILE_H264HIGH422PROFILE);
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_HIGH444PREDICTIVEPROFILE,
+ PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE);
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_SCALABLEBASELINE,
+ PP_VIDEOPROFILE_H264SCALABLEBASELINE);
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_SCALABLEHIGH,
+ PP_VIDEOPROFILE_H264SCALABLEHIGH);
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_STEREOHIGH,
+ PP_VIDEOPROFILE_H264STEREOHIGH);
+COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_MULTIVIEWHIGH,
+ PP_VIDEOPROFILE_H264MULTIVIEWHIGH);
+COMPILE_ASSERT_MATCHING_ENUM(VP8PROFILE_MAIN, PP_VIDEOPROFILE_VP8MAIN);
+
+} // namespace
+
+PepperVideoDecoderHost::PepperVideoDecoderHost(RendererPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource)
+ : ResourceHost(host->GetPpapiHost(), instance, resource),
+ renderer_ppapi_host_(host),
+ initialized_(false),
+ weak_factory_(this) {
+}
+
+PepperVideoDecoderHost::~PepperVideoDecoderHost() {
+ if (decoder_) {
+ decoder_->Destroy();
+ decoder_.reset();
+ }
+}
+
+int32_t PepperVideoDecoderHost::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) {
+ IPC_BEGIN_MESSAGE_MAP(PepperVideoDecoderHost, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Initialize,
Tom Sepez 2014/05/08 20:35:07 nit: it's common to indent these two spaces betwee
bbudge 2014/05/14 16:40:41 We're trying to use clang-format on Pepper code. I
+ OnHostMsgInitialize)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_GetShm,
+ OnHostMsgGetShm)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_AssignTextures,
+ OnHostMsgAssignTextures)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Decode,
+ OnHostMsgDecode)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_RecyclePicture,
+ OnHostMsgRecyclePicture)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Flush,
+ OnHostMsgFlush)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Reset,
+ OnHostMsgReset)
+ IPC_END_MESSAGE_MAP()
+ return PP_ERROR_FAILED;
+}
+
+int32_t PepperVideoDecoderHost::OnHostMsgInitialize(
+ ppapi::host::HostMessageContext* context,
+ ppapi::HostResource graphics_context,
+ PP_VideoProfile profile,
+ bool allow_software_fallback) {
+ if (initialized_)
+ return PP_ERROR_FAILED;
+ if (profile < 0 || profile > PP_VIDEOPROFILE_MAX)
dmichael (off chromium) 2014/05/08 20:27:00 Should that be >= PP_VIDEOPROFILE_MAX? It looks l
bbudge 2014/05/14 16:40:41 There should be no more VP9 in the API. It isn't s
+ return PP_ERROR_BADARGUMENT;
+
+ EnterResourceNoLock<PPB_Graphics3D_API> enter(
+ graphics_context.host_resource(), true);
+ if (enter.failed())
+ return PP_ERROR_BADRESOURCE;
+ PPB_Graphics3D_Impl* graphics3d_impl =
+ static_cast<PPB_Graphics3D_Impl*>(enter.object());
+ int command_buffer_route_id = graphics3d_impl->GetCommandBufferRouteId();
+ if (!command_buffer_route_id)
+ return PP_ERROR_FAILED;
+
+ media::VideoCodecProfile media_profile =
+ static_cast<media::VideoCodecProfile>(profile);
+
+ // This is not synchronous, but subsequent IPC messages will be buffered, so
+ // it is okay to immediately send IPC messages through the returned channel.
+ GpuChannelHost* channel = graphics3d_impl->channel();
+ DCHECK(channel);
+
+ if (channel) {
+ decoder_ = channel->CreateVideoDecoder(command_buffer_route_id);
+ if (decoder_ && decoder_->Initialize(media_profile, this)) {
+ initialized_ = true;
+ return PP_OK;
+ }
+ decoder_.reset();
+ }
+
+ // TODO(bbudge) Implement software fallback.
+ return PP_ERROR_NOTSUPPORTED;
+}
+
+int32_t PepperVideoDecoderHost::OnHostMsgGetShm(
+ ppapi::host::HostMessageContext* context,
+ uint32_t size) {
+ if (!initialized_)
+ return PP_ERROR_FAILED;
+
+ content::RenderThread* render_thread = content::RenderThread::Get();
+ scoped_ptr<base::SharedMemory> shm(
+ render_thread->HostAllocateSharedMemoryBuffer(size).Pass());
+ if (!shm)
+ return PP_ERROR_FAILED;
+ if (!shm->Map(size))
+ return PP_ERROR_FAILED;
+
+ base::SharedMemoryHandle shm_handle = shm->handle();
+ shm_buffers_.push_back(shm.release());
+
+ base::PlatformFile platform_file =
+#if defined(OS_WIN)
+ shm_handle;
+#elif defined(OS_POSIX)
+ shm_handle.fd;
+#else
+#error Not implemented.
+#endif
+ SerializedHandle handle(
+ renderer_ppapi_host_->ShareHandleWithRemote(platform_file, false), size);
+ ppapi::host::ReplyMessageContext reply_context =
+ context->MakeReplyMessageContext();
+ reply_context.params.AppendHandle(handle);
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_VideoDecoder_GetShmReply(size));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperVideoDecoderHost::OnHostMsgAssignTextures(
+ ppapi::host::HostMessageContext* context,
+ PP_Size size,
+ const std::vector<uint32_t>& texture_ids) {
+ if (!initialized_)
+ return PP_ERROR_FAILED;
+
+ DCHECK(decoder_);
+ if (decoder_) {
dmichael (off chromium) 2014/05/08 20:27:00 nit: What's inside the if block is actually the co
bbudge 2014/05/14 16:40:41 Much better. Done.
+ std::vector<media::PictureBuffer> picture_buffers;
+ for (uint32 i = 0; i < texture_ids.size(); i++) {
+ media::PictureBuffer buffer(
+ texture_ids[i], // Use the texture_id to identify the buffer.
+ gfx::Size(size.width, size.height),
+ texture_ids[i]);
+ picture_buffers.push_back(buffer);
+ }
+ decoder_->AssignPictureBuffers(picture_buffers);
+ }
+ return PP_OK;
+}
+
+int32_t PepperVideoDecoderHost::OnHostMsgDecode(
+ ppapi::host::HostMessageContext* context,
+ uint32_t shm_id,
+ uint32_t size) {
+ if (!initialized_)
+ return PP_ERROR_FAILED;
+ // |shm_id| is just an index into shm_buffers_. Make sure it's in range.
+ if (static_cast<size_t>(shm_id) >= shm_buffers_.size())
+ return PP_ERROR_FAILED;
+
+ pending_decodes_.insert(
+ std::make_pair(shm_id, context->MakeReplyMessageContext()));
+
+ base::SharedMemory* shm = shm_buffers_[shm_id];
+ DCHECK(decoder_);
+ if (decoder_)
+ decoder_->Decode(media::BitstreamBuffer(shm_id, shm->handle(), size));
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperVideoDecoderHost::OnHostMsgRecyclePicture(
+ ppapi::host::HostMessageContext* context,
+ uint32_t texture_id) {
+ if (!initialized_)
+ return PP_ERROR_FAILED;
+ DCHECK(decoder_);
+ if (decoder_)
+ decoder_->ReusePictureBuffer(texture_id);
+
+ return PP_OK;
+}
+
+int32_t PepperVideoDecoderHost::OnHostMsgFlush(
+ ppapi::host::HostMessageContext* context) {
+ if (!initialized_)
+ return PP_ERROR_FAILED;
+
+ flush_reply_context_ = context->MakeReplyMessageContext();
+ DCHECK(decoder_);
+ if (decoder_)
+ decoder_->Flush();
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperVideoDecoderHost::OnHostMsgReset(
+ ppapi::host::HostMessageContext* context) {
+ if (!initialized_)
+ return PP_ERROR_FAILED;
+
+ reset_reply_context_ = context->MakeReplyMessageContext();
+ DCHECK(decoder_);
+ if (decoder_)
+ decoder_->Reset();
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperVideoDecoderHost::ProvidePictureBuffers(
+ uint32 requested_num_of_buffers,
+ const gfx::Size& dimensions,
+ uint32 texture_target) {
+ RequestTextures(requested_num_of_buffers,
+ dimensions,
+ texture_target,
+ std::vector<gpu::Mailbox>());
+}
+
+void PepperVideoDecoderHost::RequestTextures(
+ uint32 requested_num_of_buffers,
+ const gfx::Size& dimensions,
+ uint32 texture_target,
+ const std::vector<gpu::Mailbox>& mailboxes) {
dmichael (off chromium) 2014/05/08 20:27:00 I don't see any case where mailboxes will be anyth
bbudge 2014/05/14 16:40:41 Removed these for now.
+ DCHECK(RenderThreadImpl::current());
+ host()->SendUnsolicitedReply(
+ pp_resource(),
+ PpapiPluginMsg_VideoDecoder_RequestTextures(
+ requested_num_of_buffers,
+ PP_MakeSize(dimensions.width(), dimensions.height()),
+ texture_target,
+ mailboxes));
+}
+
+void PepperVideoDecoderHost::PictureReady(const media::Picture& picture) {
+ DCHECK(RenderThreadImpl::current());
+ host()->SendUnsolicitedReply(
+ pp_resource(),
+ PpapiPluginMsg_VideoDecoder_PictureReady(picture.bitstream_buffer_id(),
+ picture.picture_buffer_id()));
+}
+
+void PepperVideoDecoderHost::DismissPictureBuffer(int32 picture_buffer_id) {
+ DCHECK(RenderThreadImpl::current());
+ host()->SendUnsolicitedReply(
+ pp_resource(),
+ PpapiPluginMsg_VideoDecoder_DismissPicture(picture_buffer_id));
+}
+
+void PepperVideoDecoderHost::NotifyError(
+ media::VideoDecodeAccelerator::Error error) {
+ DCHECK(RenderThreadImpl::current());
+ int32_t pp_error = PP_ERROR_FAILED;
+ switch (error) {
+ case media::VideoDecodeAccelerator::UNREADABLE_INPUT:
+ pp_error = PP_ERROR_UNREADABLE_INPUT;
+ break;
+ case media::VideoDecodeAccelerator::ILLEGAL_STATE:
+ case media::VideoDecodeAccelerator::INVALID_ARGUMENT:
+ case media::VideoDecodeAccelerator::PLATFORM_FAILURE:
+ pp_error = PP_ERROR_PLATFORM_FAILED;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ host()->SendUnsolicitedReply(
+ pp_resource(), PpapiPluginMsg_VideoDecoder_NotifyError(pp_error));
+}
+
+void PepperVideoDecoderHost::NotifyResetDone() {
+ DCHECK(RenderThreadImpl::current());
+ host()->SendReply(reset_reply_context_,
+ PpapiPluginMsg_VideoDecoder_ResetReply());
+ reset_reply_context_ = ppapi::host::ReplyMessageContext();
+}
+
+void PepperVideoDecoderHost::NotifyEndOfBitstreamBuffer(
+ int32 bitstream_buffer_id) {
+ DCHECK(RenderThreadImpl::current());
+ uint32_t shm_id = static_cast<uint32_t>(bitstream_buffer_id);
+ ReplyMap::iterator it = pending_decodes_.find(shm_id);
+ DCHECK(it != pending_decodes_.end());
Tom Sepez 2014/05/08 20:35:07 Can this happen for real? Does bitstream_buffer_i
bbudge 2014/05/14 16:40:41 This is from the decoder which is trusted. A futur
+ host()->SendReply(it->second,
+ PpapiPluginMsg_VideoDecoder_DecodeReply(shm_id));
+
+ pending_decodes_.erase(it);
+}
+
+void PepperVideoDecoderHost::NotifyFlushDone() {
+ DCHECK(RenderThreadImpl::current());
+ host()->SendReply(flush_reply_context_,
+ PpapiPluginMsg_VideoDecoder_FlushReply());
+ flush_reply_context_ = ppapi::host::ReplyMessageContext();
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698