diff options
author | vrk@chromium.org <vrk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-06 03:23:58 +0000 |
---|---|---|
committer | vrk@chromium.org <vrk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-06 03:23:58 +0000 |
commit | 7ace8ad34d1f1d98b62da88ac6aaff1f33d8aaaa (patch) | |
tree | 4beeeef47d3ee8a731dcd56150c6938a99b9df78 /ppapi | |
parent | 10a57d167dd2836ddbd62e8786a12a344707ac73 (diff) | |
download | chromium_src-7ace8ad34d1f1d98b62da88ac6aaff1f33d8aaaa.zip chromium_src-7ace8ad34d1f1d98b62da88ac6aaff1f33d8aaaa.tar.gz chromium_src-7ace8ad34d1f1d98b62da88ac6aaff1f33d8aaaa.tar.bz2 |
Implement PPAPI VideoDecode out-of-process support
This CL implements the proxy necessary for out-of-process video decoding and
introduces a shared base class between the PPB_VideoDecoder_Impl and the proxy.
BUG=NONE
TEST=gles2 plugin runs with or without --ppapi-out-of-process flag, no crashes
Review URL: http://codereview.chromium.org/7545014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95724 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/c/dev/ppb_video_decoder_dev.h | 2 | ||||
-rw-r--r-- | ppapi/examples/gles2/gles2.cc | 17 | ||||
-rw-r--r-- | ppapi/ppapi_proxy.gypi | 4 | ||||
-rw-r--r-- | ppapi/ppapi_shared.gypi | 2 | ||||
-rw-r--r-- | ppapi/proxy/dispatcher.cc | 4 | ||||
-rw-r--r-- | ppapi/proxy/plugin_resource.h | 5 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 66 | ||||
-rw-r--r-- | ppapi/proxy/ppb_buffer_proxy.cc | 31 | ||||
-rw-r--r-- | ppapi/proxy/ppb_buffer_proxy.h | 31 | ||||
-rw-r--r-- | ppapi/proxy/ppb_video_decoder_proxy.cc | 365 | ||||
-rw-r--r-- | ppapi/proxy/ppb_video_decoder_proxy.h | 81 | ||||
-rw-r--r-- | ppapi/proxy/ppp_video_decoder_proxy.cc | 167 | ||||
-rw-r--r-- | ppapi/proxy/ppp_video_decoder_proxy.h | 52 | ||||
-rw-r--r-- | ppapi/proxy/resource_creation_proxy.cc | 5 | ||||
-rw-r--r-- | ppapi/shared_impl/tracker_base.h | 2 | ||||
-rw-r--r-- | ppapi/shared_impl/video_decoder_impl.cc | 109 | ||||
-rw-r--r-- | ppapi/shared_impl/video_decoder_impl.h | 97 |
17 files changed, 999 insertions, 41 deletions
diff --git a/ppapi/c/dev/ppb_video_decoder_dev.h b/ppapi/c/dev/ppb_video_decoder_dev.h index cf188d2..5a3417e 100644 --- a/ppapi/c/dev/ppb_video_decoder_dev.h +++ b/ppapi/c/dev/ppb_video_decoder_dev.h @@ -38,6 +38,8 @@ struct PPB_VideoDecoder_Dev { // |decoder_config| the configuration to use to initialize the decoder. // // The created decoder is returned as PP_Resource. 0 means failure. + // TODO(fischman/vrk): Get rid of silly PP_VideoConfigElement* vector in favor + // of config struct. PP_Resource (*Create)(PP_Instance instance, PP_Resource context, const PP_VideoConfigElement* decoder_config); diff --git a/ppapi/examples/gles2/gles2.cc b/ppapi/examples/gles2/gles2.cc index e917374..aa3a4fb 100644 --- a/ppapi/examples/gles2/gles2.cc +++ b/ppapi/examples/gles2/gles2.cc @@ -298,7 +298,8 @@ void GLES2DemoInstance::DecodeNextNALU() { } void GLES2DemoInstance::ProvidePictureBuffers( - PP_Resource /* decoder */, uint32_t req_num_of_bufs, PP_Size dimensions) { + PP_Resource decoder, uint32_t req_num_of_bufs, PP_Size dimensions) { + assert(decoder == video_decoder_->pp_resource()); std::vector<PP_PictureBuffer_Dev> buffers; for (uint32_t i = 0; i < req_num_of_bufs; i++) { PP_PictureBuffer_Dev buffer; @@ -311,16 +312,18 @@ void GLES2DemoInstance::ProvidePictureBuffers( video_decoder_->AssignPictureBuffers(buffers); } -void GLES2DemoInstance::DismissPictureBuffer(PP_Resource /* decoder */, +void GLES2DemoInstance::DismissPictureBuffer(PP_Resource decoder, int32_t picture_buffer_id) { + assert(decoder == video_decoder_->pp_resource()); PictureBufferMap::iterator it = buffers_by_id_.find(picture_buffer_id); assert(it != buffers_by_id_.end()); DeleteTexture(it->second.texture_id); buffers_by_id_.erase(it); } -void GLES2DemoInstance::PictureReady(PP_Resource /* decoder */, +void GLES2DemoInstance::PictureReady(PP_Resource decoder, const PP_Picture_Dev& picture) { + assert(decoder == video_decoder_->pp_resource()); if (first_frame_delivered_ticks_ == -1) assert((first_frame_delivered_ticks_ = core_if_->GetTimeTicks()) != -1); if (is_painting_) { @@ -333,11 +336,13 @@ void GLES2DemoInstance::PictureReady(PP_Resource /* decoder */, Render(it->second); } -void GLES2DemoInstance::EndOfStream(PP_Resource /* decoder */) { +void GLES2DemoInstance::EndOfStream(PP_Resource decoder) { + assert(decoder == video_decoder_->pp_resource()); } -void GLES2DemoInstance::NotifyError(PP_Resource /* decoder */, +void GLES2DemoInstance::NotifyError(PP_Resource decoder, PP_VideoDecodeError_Dev error) { + assert(decoder == video_decoder_->pp_resource()); LogError(this).s() << "Received error: " << error; assert(!"Unexpected error; see stderr for details"); } @@ -414,7 +419,7 @@ void GLES2DemoInstance::PaintFinished(int32_t result, int picture_buffer_id) { while (!pictures_pending_paint_.empty() && !is_painting_) { PP_Picture_Dev picture = pictures_pending_paint_.front(); pictures_pending_paint_.pop_front(); - PictureReady(0 /* ignored */, picture); + PictureReady(video_decoder_->pp_resource(), picture); } } diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index 68a5364..49e392d 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -126,6 +126,8 @@ 'proxy/ppb_var_deprecated_proxy.h', 'proxy/ppb_var_proxy.cc', 'proxy/ppb_var_proxy.h', + 'proxy/ppb_video_decoder_proxy.cc', + 'proxy/ppb_video_decoder_proxy.h', 'proxy/ppp_class_proxy.cc', 'proxy/ppp_class_proxy.h', 'proxy/ppp_graphics_3d_proxy.cc', @@ -138,6 +140,8 @@ 'proxy/ppp_instance_proxy.h', 'proxy/ppp_messaging_proxy.cc', 'proxy/ppp_messaging_proxy.h', + 'proxy/ppp_video_decoder_proxy.cc', + 'proxy/ppp_video_decoder_proxy.h', 'proxy/proxy_channel.cc', 'proxy/proxy_channel.h', 'proxy/proxy_module.cc', diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi index 7a3b9e3..51865bd 100644 --- a/ppapi/ppapi_shared.gypi +++ b/ppapi/ppapi_shared.gypi @@ -60,6 +60,8 @@ 'shared_impl/url_util_impl.h', 'shared_impl/var.cc', 'shared_impl/var.h', + 'shared_impl/video_decoder_impl.cc', + 'shared_impl/video_decoder_impl.h', 'shared_impl/webkit_forwarding.cc', 'shared_impl/webkit_forwarding.h', diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc index dc61c51..a1c9974 100644 --- a/ppapi/proxy/dispatcher.cc +++ b/ppapi/proxy/dispatcher.cc @@ -80,12 +80,14 @@ #include "ppapi/proxy/ppb_url_util_proxy.h" #include "ppapi/proxy/ppb_var_deprecated_proxy.h" #include "ppapi/proxy/ppb_var_proxy.h" +#include "ppapi/proxy/ppb_video_decoder_proxy.h" #include "ppapi/proxy/ppp_class_proxy.h" #include "ppapi/proxy/ppp_graphics_3d_proxy.h" #include "ppapi/proxy/ppp_input_event_proxy.h" #include "ppapi/proxy/ppp_instance_private_proxy.h" #include "ppapi/proxy/ppp_instance_proxy.h" #include "ppapi/proxy/ppp_messaging_proxy.h" +#include "ppapi/proxy/ppp_video_decoder_proxy.h" #include "ppapi/proxy/var_serialization_rules.h" namespace pp { @@ -162,6 +164,7 @@ InterfaceList::InterfaceList() { AddPPB(PPB_URLUtil_Proxy::GetInfo()); AddPPB(PPB_Var_Deprecated_Proxy::GetInfo()); AddPPB(PPB_Var_Proxy::GetInfo()); + AddPPB(PPB_VideoDecoder_Proxy::GetInfo()); #ifdef ENABLE_FLAPPER_HACKS AddPPB(PPB_Flash_NetConnector_Proxy::GetInfo()); @@ -173,6 +176,7 @@ InterfaceList::InterfaceList() { AddPPP(PPP_Instance_Private_Proxy::GetInfo()); AddPPP(PPP_Instance_Proxy::GetInfo1_0()); AddPPP(PPP_Messaging_Proxy::GetInfo()); + AddPPP(PPP_VideoDecoder_Proxy::GetInfo()); } void InterfaceList::AddPPP(const InterfaceProxy::Info* info) { diff --git a/ppapi/proxy/plugin_resource.h b/ppapi/proxy/plugin_resource.h index 8646189..a0675d3 100644 --- a/ppapi/proxy/plugin_resource.h +++ b/ppapi/proxy/plugin_resource.h @@ -32,8 +32,9 @@ F(PrivateFontFile) \ F(Surface3D) \ F(URLLoader) \ - F(URLRequestInfo)\ - F(URLResponseInfo) + F(URLRequestInfo) \ + F(URLResponseInfo) \ + F(VideoDecoder) namespace pp { namespace proxy { diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 9a1e47b..b039878 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -26,6 +26,7 @@ #include "ppapi/c/pp_rect.h" #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_size.h" +#include "ppapi/c/dev/pp_video_dev.h" #include "ppapi/c/private/ppb_flash_tcp_socket.h" #include "ppapi/proxy/ppapi_param_traits.h" #include "ppapi/proxy/serialized_flash_menu.h" @@ -37,6 +38,7 @@ IPC_ENUM_TRAITS(PP_InputEvent_Type) IPC_ENUM_TRAITS(PP_InputEvent_MouseButton) +IPC_ENUM_TRAITS(PP_VideoDecodeError_Dev) IPC_STRUCT_TRAITS_BEGIN(PP_Point) IPC_STRUCT_TRAITS_MEMBER(x) @@ -58,6 +60,17 @@ IPC_STRUCT_TRAITS_BEGIN(PP_Rect) IPC_STRUCT_TRAITS_MEMBER(size) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(PP_PictureBuffer_Dev) + IPC_STRUCT_TRAITS_MEMBER(id) + IPC_STRUCT_TRAITS_MEMBER(size) + IPC_STRUCT_TRAITS_MEMBER(texture_id) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(PP_Picture_Dev) + IPC_STRUCT_TRAITS_MEMBER(picture_buffer_id) + IPC_STRUCT_TRAITS_MEMBER(bitstream_buffer_id) +IPC_STRUCT_TRAITS_END() + IPC_STRUCT_TRAITS_BEGIN(::ppapi::Preferences) IPC_STRUCT_TRAITS_MEMBER(standard_font_family) IPC_STRUCT_TRAITS_MEMBER(fixed_font_family) @@ -317,6 +330,36 @@ IPC_MESSAGE_ROUTED3(PpapiMsg_PPBURLLoader_ReadResponseBody_Ack, int32 /* result */, std::string /* data */) +// PPB_VideoDecoder_Dev. +// (Messages from renderer to plugin to notify it to run callbacks.) +IPC_MESSAGE_ROUTED3(PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK, + pp::proxy::HostResource /* video_decoder */, + int32_t /* bitstream buffer id */, + int32_t /* PP_CompletionCallback result */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_FlushACK, + pp::proxy::HostResource /* video_decoder */, + int32_t /* PP_CompletionCallback result */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_ResetACK, + pp::proxy::HostResource /* video_decoder */, + int32_t /* PP_CompletionCallback result */) + +// PPP_VideoDecoder_Dev. +IPC_MESSAGE_ROUTED3(PpapiMsg_PPPVideoDecoder_ProvidePictureBuffers, + pp::proxy::HostResource /* video_decoder */, + uint32_t /* requested number of buffers */, + PP_Size /* dimensions of buffers */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_DismissPictureBuffer, + pp::proxy::HostResource /* video_decoder */, + int32_t /* picture buffer id */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_PictureReady, + pp::proxy::HostResource /* video_decoder */, + PP_Picture_Dev /* output picture */) +IPC_MESSAGE_ROUTED1(PpapiMsg_PPPVideoDecoder_NotifyEndOfStream, + pp::proxy::HostResource /* video_decoder */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_NotifyError, + pp::proxy::HostResource /* video_decoder */, + PP_VideoDecodeError_Dev /* error */) + // ----------------------------------------------------------------------------- // These are from the plugin to the renderer. @@ -902,3 +945,26 @@ IPC_SYNC_MESSAGE_ROUTED4_3(PpapiHostMsg_ResourceCreation_ImageData, pp::proxy::HostResource /* result_resource */, std::string /* image_data_desc */, pp::proxy::ImageHandle /* result */) +// PPB_VideoDecoder. +IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVideoDecoder_Create, + PP_Instance /* instance */, + pp::proxy::HostResource /* context */, + std::vector<PP_VideoConfigElement> /* config */, + pp::proxy::HostResource /* result */) +IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBVideoDecoder_Decode, + pp::proxy::HostResource /* video_decoder */, + pp::proxy::HostResource /* bitstream buffer */, + int32 /* bitstream buffer id */, + int32 /* size of buffer */) +IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBVideoDecoder_AssignPictureBuffers, + pp::proxy::HostResource /* video_decoder */, + std::vector<PP_PictureBuffer_Dev> /* picture buffers */) +IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBVideoDecoder_ReusePictureBuffer, + pp::proxy::HostResource /* video_decoder */, + int32_t /* picture buffer id */) +IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBVideoDecoder_Flush, + pp::proxy::HostResource /* video_decoder */) +IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBVideoDecoder_Reset, + pp::proxy::HostResource /* video_decoder */) +IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBVideoDecoder_Destroy, + pp::proxy::HostResource /* video_decoder */) diff --git a/ppapi/proxy/ppb_buffer_proxy.cc b/ppapi/proxy/ppb_buffer_proxy.cc index 2e2ee90..2e782ac 100644 --- a/ppapi/proxy/ppb_buffer_proxy.cc +++ b/ppapi/proxy/ppb_buffer_proxy.cc @@ -14,10 +14,8 @@ #include "ppapi/c/dev/ppb_buffer_dev.h" #include "ppapi/proxy/host_dispatcher.h" #include "ppapi/proxy/plugin_dispatcher.h" -#include "ppapi/proxy/plugin_resource.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/thunk/enter.h" -#include "ppapi/thunk/ppb_buffer_api.h" #include "ppapi/thunk/ppb_buffer_trusted_api.h" #include "ppapi/thunk/thunk.h" @@ -33,35 +31,6 @@ InterfaceProxy* CreateBufferProxy(Dispatcher* dispatcher, } // namespace -class Buffer : public ppapi::thunk::PPB_Buffer_API, - public PluginResource { - public: - Buffer(const HostResource& resource, - const base::SharedMemoryHandle& shm_handle, - uint32_t size); - virtual ~Buffer(); - - // Resource overrides. - virtual Buffer* AsBuffer() OVERRIDE; - - // ResourceObjectBase overrides. - virtual ppapi::thunk::PPB_Buffer_API* AsPPB_Buffer_API() OVERRIDE; - - // PPB_Buffer_API implementation. - virtual PP_Bool Describe(uint32_t* size_in_bytes) OVERRIDE; - virtual PP_Bool IsMapped() OVERRIDE; - virtual void* Map() OVERRIDE; - virtual void Unmap() OVERRIDE; - - private: - base::SharedMemory shm_; - uint32_t size_; - void* mapped_data_; - int map_count_; - - DISALLOW_COPY_AND_ASSIGN(Buffer); -}; - Buffer::Buffer(const HostResource& resource, const base::SharedMemoryHandle& shm_handle, uint32_t size) diff --git a/ppapi/proxy/ppb_buffer_proxy.h b/ppapi/proxy/ppb_buffer_proxy.h index 6002950..e11b94f 100644 --- a/ppapi/proxy/ppb_buffer_proxy.h +++ b/ppapi/proxy/ppb_buffer_proxy.h @@ -8,6 +8,8 @@ #include "base/shared_memory.h" #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/interface_proxy.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/thunk/ppb_buffer_api.h" struct PPB_Buffer_Dev; @@ -16,6 +18,35 @@ namespace proxy { class HostResource; +class Buffer : public ppapi::thunk::PPB_Buffer_API, + public PluginResource { + public: + Buffer(const HostResource& resource, + const base::SharedMemoryHandle& shm_handle, + uint32_t size); + virtual ~Buffer(); + + // Resource overrides. + virtual Buffer* AsBuffer() OVERRIDE; + + // ResourceObjectBase overrides. + virtual ppapi::thunk::PPB_Buffer_API* AsPPB_Buffer_API() OVERRIDE; + + // PPB_Buffer_API implementation. + virtual PP_Bool Describe(uint32_t* size_in_bytes) OVERRIDE; + virtual PP_Bool IsMapped() OVERRIDE; + virtual void* Map() OVERRIDE; + virtual void Unmap() OVERRIDE; + + private: + base::SharedMemory shm_; + uint32_t size_; + void* mapped_data_; + int map_count_; + + DISALLOW_COPY_AND_ASSIGN(Buffer); +}; + class PPB_Buffer_Proxy : public InterfaceProxy { public: PPB_Buffer_Proxy(Dispatcher* dispatcher, const void* target_interface); diff --git a/ppapi/proxy/ppb_video_decoder_proxy.cc b/ppapi/proxy/ppb_video_decoder_proxy.cc new file mode 100644 index 0000000..97c2348 --- /dev/null +++ b/ppapi/proxy/ppb_video_decoder_proxy.cc @@ -0,0 +1,365 @@ +// Copyright (c) 2011 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 "ppapi/proxy/ppb_video_decoder_proxy.h" + +#include "base/logging.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "ppapi/proxy/enter_proxy.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_buffer_proxy.h" +#include "ppapi/proxy/ppb_context_3d_proxy.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/resource_creation_api.h" +#include "ppapi/thunk/thunk.h" + +using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_Buffer_API; +using ppapi::thunk::PPB_Context3D_API; +using ppapi::thunk::PPB_VideoDecoder_API; + +namespace pp { +namespace proxy { + +class VideoDecoder : public PluginResource, + public ::ppapi::VideoDecoderImpl { + public: + virtual ~VideoDecoder(); + + static VideoDecoder* Create(const HostResource& resource, + PP_Resource context3d_id, + const PP_VideoConfigElement* config); + + // ResourceObjectBase overrides. + virtual PPB_VideoDecoder_API* AsPPB_VideoDecoder_API() OVERRIDE; + + // PPB_VideoDecoder_API implementation. + virtual int32_t Decode(const PP_VideoBitstreamBuffer_Dev* bitstream_buffer, + PP_CompletionCallback callback) OVERRIDE; + virtual void AssignPictureBuffers( + uint32_t no_of_buffers, const PP_PictureBuffer_Dev* buffers) OVERRIDE; + virtual void ReusePictureBuffer(int32_t picture_buffer_id) OVERRIDE; + virtual int32_t Flush(PP_CompletionCallback callback) OVERRIDE; + virtual int32_t Reset(PP_CompletionCallback callback) OVERRIDE; + virtual void Destroy() OVERRIDE; + + protected: + virtual void AddRefResource(PP_Resource resource) OVERRIDE; + virtual void UnrefResource(PP_Resource resource) OVERRIDE; + + private: + friend class PPB_VideoDecoder_Proxy; + explicit VideoDecoder(const HostResource& resource); + + // Run the callbacks that were passed into the plugin interface. + void FlushACK(int32_t result); + void ResetACK(int32_t result); + void EndOfBitstreamACK(int32_t buffer_id, int32_t result); + + DISALLOW_COPY_AND_ASSIGN(VideoDecoder); +}; + +VideoDecoder::VideoDecoder(const HostResource& decoder) + : PluginResource(decoder) { +} + +VideoDecoder* VideoDecoder::Create(const HostResource& resource, + PP_Resource context3d_id, + const PP_VideoConfigElement* config) { + if (!context3d_id) + return NULL; + + EnterResourceNoLock<PPB_Context3D_API> enter_context(context3d_id, true); + if (enter_context.failed()) + return NULL; + + scoped_ptr<VideoDecoder> decoder(new VideoDecoder(resource)); + if (decoder->Init(context3d_id, enter_context.object(), config)) + return decoder.release(); + return NULL; +} + +VideoDecoder::~VideoDecoder() { +} + +::ppapi::thunk::PPB_VideoDecoder_API* VideoDecoder::AsPPB_VideoDecoder_API() { + return this; +} + +int32_t VideoDecoder::Decode( + const PP_VideoBitstreamBuffer_Dev* bitstream_buffer, + PP_CompletionCallback callback) { + ppapi::thunk::EnterResourceNoLock<PPB_Buffer_API> + enter_buffer(bitstream_buffer->data, true); + if (enter_buffer.failed()) + return PP_ERROR_BADRESOURCE; + + SetBitstreamBufferCallback(bitstream_buffer->id, callback); + + Buffer* ppb_buffer = + static_cast<Buffer*>(enter_buffer.object()); + HostResource host_buffer = ppb_buffer->host_resource(); + + FlushCommandBuffer(); + GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Decode( + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, host_resource(), + host_buffer, bitstream_buffer->id, + bitstream_buffer->size)); + return PP_OK_COMPLETIONPENDING; +} + +void VideoDecoder::AssignPictureBuffers(uint32_t no_of_buffers, + const PP_PictureBuffer_Dev* buffers) { + std::vector<PP_PictureBuffer_Dev> buffer_list( + buffers, buffers + no_of_buffers); + FlushCommandBuffer(); + GetDispatcher()->Send( + new PpapiHostMsg_PPBVideoDecoder_AssignPictureBuffers( + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, host_resource(), buffer_list)); +} + +void VideoDecoder::ReusePictureBuffer(int32_t picture_buffer_id) { + FlushCommandBuffer(); + GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_ReusePictureBuffer( + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, host_resource(), picture_buffer_id)); +} + +int32_t VideoDecoder::Flush(PP_CompletionCallback callback) { + SetFlushCallback(callback); + + FlushCommandBuffer(); + GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Flush( + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, host_resource())); + return PP_OK_COMPLETIONPENDING; +} + +int32_t VideoDecoder::Reset(PP_CompletionCallback callback) { + SetResetCallback(callback); + + FlushCommandBuffer(); + GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Reset( + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, host_resource())); + return PP_OK_COMPLETIONPENDING; +} + +void VideoDecoder::Destroy() { + FlushCommandBuffer(); + GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Destroy( + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, host_resource())); + ::ppapi::VideoDecoderImpl::Destroy(); +} + +void VideoDecoder::AddRefResource(PP_Resource resource) { + PluginResourceTracker::GetInstance()->AddRefResource(resource); +} + +void VideoDecoder::UnrefResource(PP_Resource resource) { + PluginResourceTracker::GetInstance()->ReleaseResource(resource); +} + +void VideoDecoder::ResetACK(int32_t result) { + RunResetCallback(result); +} + +void VideoDecoder::FlushACK(int32_t result) { + RunFlushCallback(result); +} + +void VideoDecoder::EndOfBitstreamACK( + int32_t bitstream_buffer_id, int32_t result) { + RunBitstreamBufferCallback(bitstream_buffer_id, result); +} + +namespace { + +InterfaceProxy* CreateVideoDecoderProxy(Dispatcher* dispatcher, + const void* target_interface) { + return new PPB_VideoDecoder_Proxy(dispatcher, target_interface); +} + +} // namespace + +PPB_VideoDecoder_Proxy::PPB_VideoDecoder_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface), + callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { +} + +PPB_VideoDecoder_Proxy::~PPB_VideoDecoder_Proxy() { +} + +// static +const InterfaceProxy::Info* PPB_VideoDecoder_Proxy::GetInfo() { + static const Info info = { + ::ppapi::thunk::GetPPB_VideoDecoder_Thunk(), + PPB_VIDEODECODER_DEV_INTERFACE, + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, + false, + &CreateVideoDecoderProxy, + }; + return &info; +} + +bool PPB_VideoDecoder_Proxy::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PPB_VideoDecoder_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Create, + OnMsgCreate) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Decode, OnMsgDecode) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_AssignPictureBuffers, + OnMsgAssignPictureBuffers) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_ReusePictureBuffer, + OnMsgReusePictureBuffer) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Flush, OnMsgFlush) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Reset, OnMsgReset) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Destroy, OnMsgDestroy) + IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_ResetACK, OnMsgResetACK) + IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK, + OnMsgEndOfBitstreamACK) + IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_FlushACK, OnMsgFlushACK) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + DCHECK(handled); + return handled; +} + +PP_Resource PPB_VideoDecoder_Proxy::CreateProxyResource( + PP_Instance instance, PP_Resource context3d_id, + const PP_VideoConfigElement* config) { + PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); + // Dispatcher is null if it cannot find the instance passed to it (i.e. if the + // client passes in an invalid instance). + if (!dispatcher) + return 0; + + std::vector<PP_VideoConfigElement> copied; + if (!ppapi::VideoDecoderImpl::CopyConfigsToVector(config, &copied)) + return 0; + + ppapi::thunk::EnterResourceNoLock<PPB_Context3D_API> + enter_context(context3d_id, true); + if (enter_context.failed()) + return 0; + Context3D* ppb_context = + static_cast<Context3D*>(enter_context.object()); + HostResource host_context = ppb_context->host_resource(); + + HostResource result; + dispatcher->Send(new PpapiHostMsg_PPBVideoDecoder_Create( + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, instance, + host_context, copied, &result)); + if (result.is_null()) + return 0; + + linked_ptr<VideoDecoder> video_decoder( + VideoDecoder::Create(result, context3d_id, config)); + + return PluginResourceTracker::GetInstance()->AddResource(video_decoder); +} + +void PPB_VideoDecoder_Proxy::OnMsgCreate( + PP_Instance instance, const HostResource& context3d_id, + const std::vector<PP_VideoConfigElement>& config, + HostResource* result) { + ::ppapi::thunk::EnterFunction< ::ppapi::thunk::ResourceCreationAPI> + resource_creation(instance, true); + if (resource_creation.failed()) + return; + + std::vector<PP_VideoConfigElement> copied = config; + copied.push_back(PP_VIDEOATTR_DICTIONARY_TERMINATOR); + + // Make the resource and get the API pointer to its interface. + result->SetHostResource( + instance, resource_creation.functions()->CreateVideoDecoder( + instance, context3d_id.host_resource(), &copied.front())); +} + +void PPB_VideoDecoder_Proxy::OnMsgDecode( + const HostResource& decoder, + const HostResource& buffer, int32 id, int32 size) { + CompletionCallback callback = callback_factory_.NewRequiredCallback( + &PPB_VideoDecoder_Proxy::SendMsgEndOfBitstreamACKToPlugin, decoder, id); + + PP_VideoBitstreamBuffer_Dev bitstream = { id, buffer.host_resource(), size }; + ppb_video_decoder_target()->Decode( + decoder.host_resource(), &bitstream, callback.pp_completion_callback()); +} + +void PPB_VideoDecoder_Proxy::OnMsgAssignPictureBuffers( + const HostResource& decoder, + const std::vector<PP_PictureBuffer_Dev>& buffers) { + DCHECK(!buffers.empty()); + const PP_PictureBuffer_Dev* buffer_array = &buffers.front(); + + ppb_video_decoder_target()->AssignPictureBuffers( + decoder.host_resource(), buffers.size(), buffer_array); +} + +void PPB_VideoDecoder_Proxy::OnMsgReusePictureBuffer( + const HostResource& decoder, int32 picture_buffer_id) { + ppb_video_decoder_target()->ReusePictureBuffer( + decoder.host_resource(), picture_buffer_id); +} + +void PPB_VideoDecoder_Proxy::OnMsgFlush(const HostResource& decoder) { + CompletionCallback callback = callback_factory_.NewRequiredCallback( + &PPB_VideoDecoder_Proxy::SendMsgFlushACKToPlugin, decoder); + ppb_video_decoder_target()->Flush( + decoder.host_resource(), callback.pp_completion_callback()); +} + +void PPB_VideoDecoder_Proxy::OnMsgReset(const HostResource& decoder) { + CompletionCallback callback = callback_factory_.NewRequiredCallback( + &PPB_VideoDecoder_Proxy::SendMsgResetACKToPlugin, decoder); + ppb_video_decoder_target()->Reset( + decoder.host_resource(), callback.pp_completion_callback()); +} + +void PPB_VideoDecoder_Proxy::OnMsgDestroy(const HostResource& decoder) { + ppb_video_decoder_target()->Destroy(decoder.host_resource()); +} + +void PPB_VideoDecoder_Proxy::SendMsgEndOfBitstreamACKToPlugin( + int32_t result, const HostResource& decoder, int32 id) { + dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK( + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, decoder, id, result)); +} + +void PPB_VideoDecoder_Proxy::SendMsgFlushACKToPlugin( + int32_t result, const HostResource& decoder) { + dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_FlushACK( + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, decoder, result)); +} + +void PPB_VideoDecoder_Proxy::SendMsgResetACKToPlugin( + int32_t result, const HostResource& decoder) { + dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_ResetACK( + INTERFACE_ID_PPB_VIDEO_DECODER_DEV, decoder, result)); +} + +void PPB_VideoDecoder_Proxy::OnMsgEndOfBitstreamACK( + const HostResource& decoder, int32_t id, int32_t result) { + EnterPluginFromHostResource<PPB_VideoDecoder_API> enter(decoder); + if (enter.succeeded()) + static_cast<VideoDecoder*>(enter.object())->EndOfBitstreamACK(id, result); +} + +void PPB_VideoDecoder_Proxy::OnMsgFlushACK( + const HostResource& decoder, int32_t result) { + EnterPluginFromHostResource<PPB_VideoDecoder_API> enter(decoder); + if (enter.succeeded()) + static_cast<VideoDecoder*>(enter.object())->FlushACK(result); +} + +void PPB_VideoDecoder_Proxy::OnMsgResetACK( + const HostResource& decoder, int32_t result) { + EnterPluginFromHostResource<PPB_VideoDecoder_API> enter(decoder); + if (enter.succeeded()) + static_cast<VideoDecoder*>(enter.object())->ResetACK(result); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppb_video_decoder_proxy.h b/ppapi/proxy/ppb_video_decoder_proxy.h new file mode 100644 index 0000000..134fec7 --- /dev/null +++ b/ppapi/proxy/ppb_video_decoder_proxy.h @@ -0,0 +1,81 @@ +// Copyright (c) 2011 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. + +#ifndef PPAPI_PROXY_PPB_VIDEO_DECODER_PROXY_H_ +#define PPAPI_PROXY_PPB_VIDEO_DECODER_PROXY_H_ + +#include "ppapi/c/pp_instance.h" +#include "ppapi/cpp/completion_callback.h" +#include "ppapi/proxy/interface_proxy.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/shared_impl/video_decoder_impl.h" +#include "ppapi/thunk/ppb_video_decoder_api.h" + +namespace pp { +namespace proxy { + +class PPB_VideoDecoder_Proxy : public InterfaceProxy { + public: + PPB_VideoDecoder_Proxy(Dispatcher* dispatcher, const void* target_interface); + virtual ~PPB_VideoDecoder_Proxy(); + + static const Info* GetInfo(); + + // Creates a VideoDecoder object in the plugin process. + static PP_Resource CreateProxyResource(PP_Instance instance, + PP_Resource context3d_id, const PP_VideoConfigElement* config); + + // InterfaceProxy implementation. + virtual bool OnMessageReceived(const IPC::Message& msg); + + const PPB_VideoDecoder_Dev* ppb_video_decoder_target() const { + return static_cast<const PPB_VideoDecoder_Dev*>(target_interface()); + } + + private: + // Message handlers in the renderer process to receive messages from the + // plugin process. + void OnMsgCreate(PP_Instance instance, const HostResource& context3d_id, + const std::vector<PP_VideoConfigElement>& config, + HostResource* result); + void OnMsgDecode( + const HostResource& decoder, + const HostResource& buffer, int32 id, int32 size); + void OnMsgAssignPictureBuffers( + const HostResource& decoder, + const std::vector<PP_PictureBuffer_Dev>& buffers); + void OnMsgReusePictureBuffer( + const HostResource& decoder, + int32 picture_buffer_id); + void OnMsgFlush(const HostResource& decoder); + void OnMsgReset(const HostResource& decoder); + void OnMsgDestroy(const HostResource& decoder); + + // Send a message from the renderer process to the plugin process to tell it + // to run its callback. + void SendMsgEndOfBitstreamACKToPlugin( + int32_t result, const HostResource& decoder, int32 id); + void SendMsgFlushACKToPlugin( + int32_t result, const HostResource& decoder); + void SendMsgResetACKToPlugin( + int32_t result, const HostResource& decoder); + + // Message handlers in the plugin process to receive messages from the + // renderer process. + void OnMsgEndOfBitstreamACK(const HostResource& decoder, + int32_t id, int32_t result); + void OnMsgFlushACK(const HostResource& decoder, int32_t result); + void OnMsgResetACK(const HostResource& decoder, int32_t result); + + CompletionCallbackFactory<PPB_VideoDecoder_Proxy, + ProxyNonThreadSafeRefCount> callback_factory_; + + DISALLOW_COPY_AND_ASSIGN(PPB_VideoDecoder_Proxy); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_PPB_VIDEO_DECODER_PROXY_H_ diff --git a/ppapi/proxy/ppp_video_decoder_proxy.cc b/ppapi/proxy/ppp_video_decoder_proxy.cc new file mode 100644 index 0000000..cae7c23 --- /dev/null +++ b/ppapi/proxy/ppp_video_decoder_proxy.cc @@ -0,0 +1,167 @@ +// Copyright (c) 2011 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 "ppapi/proxy/ppp_video_decoder_proxy.h" + +#include "ppapi/proxy/host_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_video_decoder_proxy.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_video_decoder_api.h" +#include "ppapi/thunk/thunk.h" + +using ::ppapi::thunk::PPB_VideoDecoder_API; + +namespace pp { +namespace proxy { + +namespace { + +void ProvidePictureBuffers(PP_Instance instance, PP_Resource decoder, + uint32_t req_num_of_bufs, PP_Size dimensions) { + HostResource decoder_resource; + decoder_resource.SetHostResource(instance, decoder); + + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPVideoDecoder_ProvidePictureBuffers( + INTERFACE_ID_PPP_VIDEO_DECODER_DEV, + decoder_resource, req_num_of_bufs, dimensions)); +} + +void DismissPictureBuffer(PP_Instance instance, PP_Resource decoder, + int32_t picture_buffer_id) { + HostResource decoder_resource; + decoder_resource.SetHostResource(instance, decoder); + + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPVideoDecoder_DismissPictureBuffer( + INTERFACE_ID_PPP_VIDEO_DECODER_DEV, + decoder_resource, picture_buffer_id)); +} + +void PictureReady(PP_Instance instance, PP_Resource decoder, + PP_Picture_Dev picture) { + HostResource decoder_resource; + decoder_resource.SetHostResource(instance, decoder); + + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPVideoDecoder_PictureReady( + INTERFACE_ID_PPP_VIDEO_DECODER_DEV, decoder_resource, picture)); +} + +void EndOfStream(PP_Instance instance, PP_Resource decoder) { + HostResource decoder_resource; + decoder_resource.SetHostResource(instance, decoder); + + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPVideoDecoder_NotifyEndOfStream( + INTERFACE_ID_PPP_VIDEO_DECODER_DEV, decoder_resource)); +} + +void NotifyError(PP_Instance instance, PP_Resource decoder, + PP_VideoDecodeError_Dev error) { + HostResource decoder_resource; + decoder_resource.SetHostResource(instance, decoder); + + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPVideoDecoder_NotifyError( + INTERFACE_ID_PPP_VIDEO_DECODER_DEV, decoder_resource, error)); +} + +static const PPP_VideoDecoder_Dev video_decoder_interface = { + &ProvidePictureBuffers, + &DismissPictureBuffer, + &PictureReady, + &EndOfStream, + &NotifyError +}; + +InterfaceProxy* CreateVideoDecoderPPPProxy( + Dispatcher* dispatcher, const void* target_interface) { + return new PPP_VideoDecoder_Proxy(dispatcher, target_interface); +} + +} // namespace + +PPP_VideoDecoder_Proxy::PPP_VideoDecoder_Proxy( + Dispatcher* dispatcher, const void* target_interface) + : InterfaceProxy(dispatcher, target_interface) { +} + +PPP_VideoDecoder_Proxy::~PPP_VideoDecoder_Proxy() { +} + +// static +const InterfaceProxy::Info* PPP_VideoDecoder_Proxy::GetInfo() { + static const Info info = { + &video_decoder_interface, + PPP_VIDEODECODER_DEV_INTERFACE, + INTERFACE_ID_PPP_VIDEO_DECODER_DEV, + false, + &CreateVideoDecoderPPPProxy, + }; + return &info; +} + +bool PPP_VideoDecoder_Proxy::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PPP_VideoDecoder_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPVideoDecoder_ProvidePictureBuffers, + OnMsgProvidePictureBuffers) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPVideoDecoder_DismissPictureBuffer, + OnMsgDismissPictureBuffer) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPVideoDecoder_PictureReady, + OnMsgPictureReady) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPVideoDecoder_NotifyEndOfStream, + OnMsgNotifyEndOfStream) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPVideoDecoder_NotifyError, + OnMsgNotifyError) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + DCHECK(handled); + return handled; +} + +void PPP_VideoDecoder_Proxy::OnMsgProvidePictureBuffers( + const HostResource& decoder, uint32_t req_num_of_bufs, + const PP_Size& dimensions) { + PP_Resource plugin_decoder = PluginResourceTracker::GetInstance()-> + PluginResourceForHostResource(decoder); + ppp_video_decoder_target()->ProvidePictureBuffers( + decoder.instance(), plugin_decoder, req_num_of_bufs, dimensions); +} + +void PPP_VideoDecoder_Proxy::OnMsgDismissPictureBuffer( + const HostResource& decoder, int32_t picture_id) { + PP_Resource plugin_decoder = PluginResourceTracker::GetInstance()-> + PluginResourceForHostResource(decoder); + ppp_video_decoder_target()->DismissPictureBuffer( + decoder.instance(), plugin_decoder, picture_id); +} + +void PPP_VideoDecoder_Proxy::OnMsgPictureReady( + const HostResource& decoder, const PP_Picture_Dev& picture) { + PP_Resource plugin_decoder = PluginResourceTracker::GetInstance()-> + PluginResourceForHostResource(decoder); + ppp_video_decoder_target()->PictureReady( + decoder.instance(), plugin_decoder, picture); +} + +void PPP_VideoDecoder_Proxy::OnMsgNotifyEndOfStream( + const HostResource& decoder) { + PP_Resource plugin_decoder = PluginResourceTracker::GetInstance()-> + PluginResourceForHostResource(decoder); + ppp_video_decoder_target()->EndOfStream(decoder.instance(), plugin_decoder); +} + +void PPP_VideoDecoder_Proxy::OnMsgNotifyError( + const HostResource& decoder, PP_VideoDecodeError_Dev error) { + PP_Resource plugin_decoder = PluginResourceTracker::GetInstance()-> + PluginResourceForHostResource(decoder); + ppp_video_decoder_target()->NotifyError( + decoder.instance(), plugin_decoder, error); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppp_video_decoder_proxy.h b/ppapi/proxy/ppp_video_decoder_proxy.h new file mode 100644 index 0000000..c211a89 --- /dev/null +++ b/ppapi/proxy/ppp_video_decoder_proxy.h @@ -0,0 +1,52 @@ +// Copyright (c) 2011 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. + +#ifndef PPAPI_PROXY_PPP_VIDEO_DECODER_PROXY_H_ +#define PPAPI_PROXY_PPP_VIDEO_DECODER_PROXY_H_ + +#include "ppapi/c/dev/ppp_video_decoder_dev.h" +#include "ppapi/c/pp_instance.h" +#include "ppapi/proxy/host_resource.h" +#include "ppapi/proxy/interface_proxy.h" + +struct PP_Picture_Dev; +struct PP_Size; + +namespace pp { +namespace proxy { + +class PPP_VideoDecoder_Proxy : public InterfaceProxy { + public: + PPP_VideoDecoder_Proxy(Dispatcher* dispatcher, const void* target_interface); + virtual ~PPP_VideoDecoder_Proxy(); + + static const Info* GetInfo(); + + const PPP_VideoDecoder_Dev* ppp_video_decoder_target() const { + return static_cast<const PPP_VideoDecoder_Dev*>(target_interface()); + } + + // InterfaceProxy implementation. + virtual bool OnMessageReceived(const IPC::Message& msg); + + private: + // Message handlers. + void OnMsgProvidePictureBuffers(const HostResource& decoder, + uint32_t req_num_of_buffers, + const PP_Size& dimensions); + void OnMsgDismissPictureBuffer(const HostResource& decoder, + int32_t picture_id); + void OnMsgPictureReady( + const HostResource& decoder, const PP_Picture_Dev& picture_buffer); + void OnMsgNotifyEndOfStream(const HostResource& decoder); + void OnMsgNotifyError(const HostResource& decoder, + PP_VideoDecodeError_Dev error); + + DISALLOW_COPY_AND_ASSIGN(PPP_VideoDecoder_Proxy); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_PPP_VIDEO_DECODER_PROXY_H_ diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc index 57da2e0..dd87a84 100644 --- a/ppapi/proxy/resource_creation_proxy.cc +++ b/ppapi/proxy/resource_creation_proxy.cc @@ -31,6 +31,7 @@ #include "ppapi/proxy/ppb_surface_3d_proxy.h" #include "ppapi/proxy/ppb_url_loader_proxy.h" #include "ppapi/proxy/ppb_url_request_info_proxy.h" +#include "ppapi/proxy/ppb_video_decoder_proxy.h" #include "ppapi/shared_impl/font_impl.h" #include "ppapi/shared_impl/function_group_base.h" #include "ppapi/shared_impl/input_event_impl.h" @@ -300,8 +301,8 @@ PP_Resource ResourceCreationProxy::CreateVideoDecoder( PP_Instance instance, PP_Resource context3d_id, const PP_VideoConfigElement* config) { - NOTIMPLEMENTED(); - return 0; + return PPB_VideoDecoder_Proxy::CreateProxyResource( + instance, context3d_id, config); } PP_Resource ResourceCreationProxy::CreateVideoLayer( diff --git a/ppapi/shared_impl/tracker_base.h b/ppapi/shared_impl/tracker_base.h index 7d4d9e8..7790ea3 100644 --- a/ppapi/shared_impl/tracker_base.h +++ b/ppapi/shared_impl/tracker_base.h @@ -23,6 +23,8 @@ class Var; // called "Tracker", and this would be used in both the plugin side of the // proxy as well as the implementation in the renderer. Currently, all this // does is forward to the process-type-specific tracker to get the information. +// TODO(fischman/vrk): When brettw fixes the TODO above, fix the ugliness in +// VideoDecoderImpl accordingly. class TrackerBase { public: // Must be called before any other function that uses the TrackerBase. diff --git a/ppapi/shared_impl/video_decoder_impl.cc b/ppapi/shared_impl/video_decoder_impl.cc new file mode 100644 index 0000000..ae185c1 --- /dev/null +++ b/ppapi/shared_impl/video_decoder_impl.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2011 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 "ppapi/shared_impl/video_decoder_impl.h" + +#include "base/logging.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/proxy/plugin_resource_tracker.h" +#include "ppapi/thunk/ppb_context_3d_api.h" +#include "ppapi/thunk/enter.h" + +using ppapi::thunk::PPB_Context3D_API; + +namespace ppapi { + +VideoDecoderImpl::VideoDecoderImpl() + : flush_callback_(PP_MakeCompletionCallback(NULL, NULL)), + reset_callback_(PP_MakeCompletionCallback(NULL, NULL)), + context3d_id_(0), + gles2_impl_(NULL) { +} + +thunk::PPB_VideoDecoder_API* VideoDecoderImpl::AsPPB_VideoDecoder_API() { + return this; +} + +VideoDecoderImpl::~VideoDecoderImpl() { +} + +bool VideoDecoderImpl::Init(PP_Resource context3d_id, + PPB_Context3D_API* context3d, + const PP_VideoConfigElement* decoder_config) { + if (!context3d || !decoder_config || !context3d_id) + return false; + + DCHECK(!gles2_impl_ && !context3d_id_); + gles2_impl_ = context3d->GetGLES2Impl(); + AddRefResource(context3d_id); + context3d_id_ = context3d_id; + return true; +} + +void VideoDecoderImpl::Destroy() { + context3d_id_ = 0; + gles2_impl_ = NULL; + UnrefResource(context3d_id_); +} + +void VideoDecoderImpl::SetFlushCallback(PP_CompletionCallback callback) { + CHECK(callback.func); + DCHECK(!flush_callback_.func); + flush_callback_ = callback; +} + +void VideoDecoderImpl::SetResetCallback(PP_CompletionCallback callback) { + CHECK(callback.func); + DCHECK(!reset_callback_.func); + reset_callback_ = callback; +} + +void VideoDecoderImpl::SetBitstreamBufferCallback( + int32 bitstream_buffer_id, PP_CompletionCallback callback) { + CHECK(bitstream_buffer_callbacks_.insert( + std::make_pair(bitstream_buffer_id, callback)).second); +} + +void VideoDecoderImpl::RunFlushCallback(int32 result) { + DCHECK(flush_callback_.func); + PP_RunAndClearCompletionCallback(&flush_callback_, result); +} + +void VideoDecoderImpl::RunResetCallback(int32 result) { + DCHECK(reset_callback_.func); + PP_RunAndClearCompletionCallback(&reset_callback_, result); +} + +void VideoDecoderImpl::RunBitstreamBufferCallback( + int32 bitstream_buffer_id, int32 result) { + CallbackById::iterator it = + bitstream_buffer_callbacks_.find(bitstream_buffer_id); + DCHECK(it != bitstream_buffer_callbacks_.end()); + PP_CompletionCallback cc = it->second; + bitstream_buffer_callbacks_.erase(it); + PP_RunCompletionCallback(&cc, PP_OK); +} + +void VideoDecoderImpl::FlushCommandBuffer() { + if (gles2_impl_) + gles2_impl_->Flush(); +} + +bool VideoDecoderImpl::CopyConfigsToVector( + const PP_VideoConfigElement* configs_to_copy, + std::vector<PP_VideoConfigElement>* out_configs) { + // TODO(fischman/vrk): This is still broken. We need to get rid of the silly + // PP_VideoConfigElement vector in favor of a struct (see TODO in + // ppb_video_decoder_dev.h). + const PP_VideoConfigElement* current = configs_to_copy; + while (current && *current != PP_VIDEOATTR_DICTIONARY_TERMINATOR) { + out_configs->push_back(*current); + out_configs->push_back(*(current + 1)); + current += 2; + } + return true; +} + +} // namespace ppapi diff --git a/ppapi/shared_impl/video_decoder_impl.h b/ppapi/shared_impl/video_decoder_impl.h new file mode 100644 index 0000000..cc0da6d --- /dev/null +++ b/ppapi/shared_impl/video_decoder_impl.h @@ -0,0 +1,97 @@ +// Copyright (c) 2011 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. + +#ifndef PPAPI_SHARED_IMPL_VIDEO_DECODER_IMPL_H_ +#define PPAPI_SHARED_IMPL_VIDEO_DECODER_IMPL_H_ + +#include <map> +#include <vector> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ppapi/c/dev/ppb_video_decoder_dev.h" +#include "ppapi/shared_impl/resource_object_base.h" +#include "ppapi/thunk/ppb_video_decoder_api.h" + +namespace gpu { +namespace gles2 { +class GLES2Implementation; +} // namespace gles2 +} // namespace gpu + +namespace ppapi { +namespace thunk { +class PPB_Context3D_API; +} // namespace thunk +} // namespace ppapi + +namespace ppapi { + +// Implements the logic to set and run callbacks for various video decoder +// events. Both the proxy and the renderer implementation share this code. +class VideoDecoderImpl : public ResourceObjectBase, + public thunk::PPB_VideoDecoder_API { + public: + VideoDecoderImpl(); + virtual ~VideoDecoderImpl(); + + // ResourceObjectBase implementation. + virtual PPB_VideoDecoder_API* AsPPB_VideoDecoder_API() OVERRIDE; + + // PPB_VideoDecoder_API implementation. + virtual void Destroy() OVERRIDE; + + // Copy C-style config list into |out_configs| vector. + static bool CopyConfigsToVector( + const PP_VideoConfigElement* configs_to_copy, + std::vector<PP_VideoConfigElement>* out_configs); + + protected: + void SetFlushCallback(PP_CompletionCallback callback); + void SetResetCallback(PP_CompletionCallback callback); + void SetBitstreamBufferCallback( + int32 bitstream_buffer_id, PP_CompletionCallback callback); + + void RunFlushCallback(int32 result); + void RunResetCallback(int32 result); + void RunBitstreamBufferCallback(int32 bitstream_buffer_id, int32 result); + + // Tell command buffer to process all commands it has received so far. + void FlushCommandBuffer(); + + // Initialize the underlying decoder and return success status. + virtual bool Init(PP_Resource context3d_id, + thunk::PPB_Context3D_API* context, + const PP_VideoConfigElement* dec_config); + + // TODO(fischman/vrk): Remove accordingly when brettw has merged resource + // trackers. + virtual void AddRefResource(PP_Resource resource) = 0; + virtual void UnrefResource(PP_Resource resource) = 0; + + private: + // Key: bitstream_buffer_id, value: callback to run when bitstream decode is + // done. + typedef std::map<int32, PP_CompletionCallback> CallbackById; + + PP_CompletionCallback flush_callback_; + PP_CompletionCallback reset_callback_; + CallbackById bitstream_buffer_callbacks_; + + // The resource ID of the underlying Context3d object being used. Used only + // for reference counting to keep it alive for the lifetime of |*this|. + PP_Resource context3d_id_; + + // Reference to the GLES2Implementation owned by |context3d_id_|. + // Context3D is guaranteed to be alive for the lifetime of this class. + // In the out-of-process case, Context3D's gles2_impl() exists in the plugin + // process only, so gles2_impl_ is NULL in that case. + gpu::gles2::GLES2Implementation* gles2_impl_; + + DISALLOW_COPY_AND_ASSIGN(VideoDecoderImpl); +}; + +} // namespace ppapi + +#endif // PPAPI_SHARED_IMPL_VIDEO_DECODER_IMPL_H_ |