1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ppapi/proxy/ppb_video_decoder_proxy.h" 6 7#include "base/logging.h" 8#include "gpu/command_buffer/client/gles2_implementation.h" 9#include "ppapi/proxy/enter_proxy.h" 10#include "ppapi/proxy/plugin_dispatcher.h" 11#include "ppapi/proxy/ppapi_messages.h" 12#include "ppapi/proxy/ppb_buffer_proxy.h" 13#include "ppapi/proxy/ppb_graphics_3d_proxy.h" 14#include "ppapi/thunk/enter.h" 15#include "ppapi/thunk/resource_creation_api.h" 16#include "ppapi/thunk/thunk.h" 17 18using ppapi::thunk::EnterResourceNoLock; 19using ppapi::thunk::PPB_Buffer_API; 20using ppapi::thunk::PPB_Graphics3D_API; 21using ppapi::thunk::PPB_VideoDecoder_Dev_API; 22 23namespace ppapi { 24namespace proxy { 25 26class VideoDecoder : public PPB_VideoDecoder_Shared { 27 public: 28 // You must call Init() before using this class. 29 explicit VideoDecoder(const HostResource& resource); 30 virtual ~VideoDecoder(); 31 32 static VideoDecoder* Create(const HostResource& resource, 33 PP_Resource graphics_context, 34 PP_VideoDecoder_Profile profile); 35 36 // PPB_VideoDecoder_Dev_API implementation. 37 virtual int32_t Decode(const PP_VideoBitstreamBuffer_Dev* bitstream_buffer, 38 scoped_refptr<TrackedCallback> callback) OVERRIDE; 39 virtual void AssignPictureBuffers( 40 uint32_t no_of_buffers, const PP_PictureBuffer_Dev* buffers) OVERRIDE; 41 virtual void ReusePictureBuffer(int32_t picture_buffer_id) OVERRIDE; 42 virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) OVERRIDE; 43 virtual int32_t Reset(scoped_refptr<TrackedCallback> callback) OVERRIDE; 44 virtual void Destroy() OVERRIDE; 45 46 private: 47 friend class PPB_VideoDecoder_Proxy; 48 49 PluginDispatcher* GetDispatcher() const; 50 51 // Run the callbacks that were passed into the plugin interface. 52 void FlushACK(int32_t result); 53 void ResetACK(int32_t result); 54 void EndOfBitstreamACK(int32_t buffer_id, int32_t result); 55 56 DISALLOW_COPY_AND_ASSIGN(VideoDecoder); 57}; 58 59VideoDecoder::VideoDecoder(const HostResource& decoder) 60 : PPB_VideoDecoder_Shared(decoder) { 61} 62 63VideoDecoder::~VideoDecoder() { 64 FlushCommandBuffer(); 65 PPB_VideoDecoder_Shared::Destroy(); 66} 67 68int32_t VideoDecoder::Decode( 69 const PP_VideoBitstreamBuffer_Dev* bitstream_buffer, 70 scoped_refptr<TrackedCallback> callback) { 71 EnterResourceNoLock<PPB_Buffer_API> 72 enter_buffer(bitstream_buffer->data, true); 73 if (enter_buffer.failed()) 74 return PP_ERROR_BADRESOURCE; 75 76 if (!SetBitstreamBufferCallback(bitstream_buffer->id, callback)) 77 return PP_ERROR_BADARGUMENT; 78 79 Buffer* ppb_buffer = 80 static_cast<Buffer*>(enter_buffer.object()); 81 HostResource host_buffer = ppb_buffer->host_resource(); 82 83 FlushCommandBuffer(); 84 GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Decode( 85 API_ID_PPB_VIDEO_DECODER_DEV, host_resource(), 86 host_buffer, bitstream_buffer->id, 87 bitstream_buffer->size)); 88 return PP_OK_COMPLETIONPENDING; 89} 90 91void VideoDecoder::AssignPictureBuffers(uint32_t no_of_buffers, 92 const PP_PictureBuffer_Dev* buffers) { 93 std::vector<PP_PictureBuffer_Dev> buffer_list( 94 buffers, buffers + no_of_buffers); 95 FlushCommandBuffer(); 96 GetDispatcher()->Send( 97 new PpapiHostMsg_PPBVideoDecoder_AssignPictureBuffers( 98 API_ID_PPB_VIDEO_DECODER_DEV, host_resource(), buffer_list)); 99} 100 101void VideoDecoder::ReusePictureBuffer(int32_t picture_buffer_id) { 102 FlushCommandBuffer(); 103 GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_ReusePictureBuffer( 104 API_ID_PPB_VIDEO_DECODER_DEV, host_resource(), picture_buffer_id)); 105} 106 107int32_t VideoDecoder::Flush(scoped_refptr<TrackedCallback> callback) { 108 if (!SetFlushCallback(callback)) 109 return PP_ERROR_INPROGRESS; 110 111 FlushCommandBuffer(); 112 GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Flush( 113 API_ID_PPB_VIDEO_DECODER_DEV, host_resource())); 114 return PP_OK_COMPLETIONPENDING; 115} 116 117int32_t VideoDecoder::Reset(scoped_refptr<TrackedCallback> callback) { 118 if (!SetResetCallback(callback)) 119 return PP_ERROR_INPROGRESS; 120 121 FlushCommandBuffer(); 122 GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Reset( 123 API_ID_PPB_VIDEO_DECODER_DEV, host_resource())); 124 return PP_OK_COMPLETIONPENDING; 125} 126 127void VideoDecoder::Destroy() { 128 FlushCommandBuffer(); 129 GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Destroy( 130 API_ID_PPB_VIDEO_DECODER_DEV, host_resource())); 131 PPB_VideoDecoder_Shared::Destroy(); 132} 133 134PluginDispatcher* VideoDecoder::GetDispatcher() const { 135 return PluginDispatcher::GetForResource(this); 136} 137 138void VideoDecoder::ResetACK(int32_t result) { 139 RunResetCallback(result); 140} 141 142void VideoDecoder::FlushACK(int32_t result) { 143 RunFlushCallback(result); 144} 145 146void VideoDecoder::EndOfBitstreamACK( 147 int32_t bitstream_buffer_id, int32_t result) { 148 RunBitstreamBufferCallback(bitstream_buffer_id, result); 149} 150 151PPB_VideoDecoder_Proxy::PPB_VideoDecoder_Proxy(Dispatcher* dispatcher) 152 : InterfaceProxy(dispatcher), 153 callback_factory_(this) { 154} 155 156PPB_VideoDecoder_Proxy::~PPB_VideoDecoder_Proxy() { 157} 158 159bool PPB_VideoDecoder_Proxy::OnMessageReceived(const IPC::Message& msg) { 160 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV)) 161 return false; 162 163 bool handled = true; 164 IPC_BEGIN_MESSAGE_MAP(PPB_VideoDecoder_Proxy, msg) 165 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Create, 166 OnMsgCreate) 167 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Decode, OnMsgDecode) 168 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_AssignPictureBuffers, 169 OnMsgAssignPictureBuffers) 170 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_ReusePictureBuffer, 171 OnMsgReusePictureBuffer) 172 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Flush, OnMsgFlush) 173 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Reset, OnMsgReset) 174 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Destroy, OnMsgDestroy) 175 IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_ResetACK, OnMsgResetACK) 176 IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK, 177 OnMsgEndOfBitstreamACK) 178 IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_FlushACK, OnMsgFlushACK) 179 IPC_MESSAGE_UNHANDLED(handled = false) 180 IPC_END_MESSAGE_MAP() 181 DCHECK(handled); 182 return handled; 183} 184 185PP_Resource PPB_VideoDecoder_Proxy::CreateProxyResource( 186 PP_Instance instance, 187 PP_Resource graphics_context, 188 PP_VideoDecoder_Profile profile) { 189 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); 190 // Dispatcher is null if it cannot find the instance passed to it (i.e. if the 191 // client passes in an invalid instance). 192 if (!dispatcher) 193 return 0; 194 195 if (!dispatcher->preferences().is_accelerated_video_decode_enabled) 196 return 0; 197 198 EnterResourceNoLock<PPB_Graphics3D_API> enter_context(graphics_context, 199 true); 200 if (enter_context.failed()) 201 return 0; 202 203 Graphics3D* context = static_cast<Graphics3D*>(enter_context.object()); 204 205 HostResource result; 206 dispatcher->Send(new PpapiHostMsg_PPBVideoDecoder_Create( 207 API_ID_PPB_VIDEO_DECODER_DEV, instance, 208 context->host_resource(), profile, &result)); 209 if (result.is_null()) 210 return 0; 211 212 // Need a scoped_refptr to keep the object alive during the Init call. 213 scoped_refptr<VideoDecoder> decoder(new VideoDecoder(result)); 214 decoder->InitCommon(graphics_context, context->gles2_impl()); 215 return decoder->GetReference(); 216} 217 218void PPB_VideoDecoder_Proxy::OnMsgCreate( 219 PP_Instance instance, const HostResource& graphics_context, 220 PP_VideoDecoder_Profile profile, 221 HostResource* result) { 222 thunk::EnterResourceCreation resource_creation(instance); 223 if (resource_creation.failed()) 224 return; 225 226 // Make the resource and get the API pointer to its interface. 227 result->SetHostResource( 228 instance, resource_creation.functions()->CreateVideoDecoderDev( 229 instance, graphics_context.host_resource(), profile)); 230} 231 232void PPB_VideoDecoder_Proxy::OnMsgDecode( 233 const HostResource& decoder, 234 const HostResource& buffer, int32 id, uint32 size) { 235 EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_Dev_API> enter( 236 decoder, callback_factory_, 237 &PPB_VideoDecoder_Proxy::SendMsgEndOfBitstreamACKToPlugin, decoder, id); 238 if (enter.failed()) 239 return; 240 PP_VideoBitstreamBuffer_Dev bitstream = { id, buffer.host_resource(), size }; 241 enter.SetResult(enter.object()->Decode(&bitstream, enter.callback())); 242} 243 244void PPB_VideoDecoder_Proxy::OnMsgAssignPictureBuffers( 245 const HostResource& decoder, 246 const std::vector<PP_PictureBuffer_Dev>& buffers) { 247 EnterHostFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); 248 if (enter.succeeded() && !buffers.empty()) { 249 const PP_PictureBuffer_Dev* buffer_array = &buffers.front(); 250 enter.object()->AssignPictureBuffers(buffers.size(), buffer_array); 251 } 252} 253 254void PPB_VideoDecoder_Proxy::OnMsgReusePictureBuffer( 255 const HostResource& decoder, int32 picture_buffer_id) { 256 EnterHostFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); 257 if (enter.succeeded()) 258 enter.object()->ReusePictureBuffer(picture_buffer_id); 259} 260 261void PPB_VideoDecoder_Proxy::OnMsgFlush(const HostResource& decoder) { 262 EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_Dev_API> enter( 263 decoder, callback_factory_, 264 &PPB_VideoDecoder_Proxy::SendMsgFlushACKToPlugin, decoder); 265 if (enter.succeeded()) 266 enter.SetResult(enter.object()->Flush(enter.callback())); 267} 268 269void PPB_VideoDecoder_Proxy::OnMsgReset(const HostResource& decoder) { 270 EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_Dev_API> enter( 271 decoder, callback_factory_, 272 &PPB_VideoDecoder_Proxy::SendMsgResetACKToPlugin, decoder); 273 if (enter.succeeded()) 274 enter.SetResult(enter.object()->Reset(enter.callback())); 275} 276 277void PPB_VideoDecoder_Proxy::OnMsgDestroy(const HostResource& decoder) { 278 EnterHostFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); 279 if (enter.succeeded()) 280 enter.object()->Destroy(); 281} 282 283void PPB_VideoDecoder_Proxy::SendMsgEndOfBitstreamACKToPlugin( 284 int32_t result, const HostResource& decoder, int32 id) { 285 dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK( 286 API_ID_PPB_VIDEO_DECODER_DEV, decoder, id, result)); 287} 288 289void PPB_VideoDecoder_Proxy::SendMsgFlushACKToPlugin( 290 int32_t result, const HostResource& decoder) { 291 dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_FlushACK( 292 API_ID_PPB_VIDEO_DECODER_DEV, decoder, result)); 293} 294 295void PPB_VideoDecoder_Proxy::SendMsgResetACKToPlugin( 296 int32_t result, const HostResource& decoder) { 297 dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_ResetACK( 298 API_ID_PPB_VIDEO_DECODER_DEV, decoder, result)); 299} 300 301void PPB_VideoDecoder_Proxy::OnMsgEndOfBitstreamACK( 302 const HostResource& decoder, int32_t id, int32_t result) { 303 EnterPluginFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); 304 if (enter.succeeded()) 305 static_cast<VideoDecoder*>(enter.object())->EndOfBitstreamACK(id, result); 306} 307 308void PPB_VideoDecoder_Proxy::OnMsgFlushACK( 309 const HostResource& decoder, int32_t result) { 310 EnterPluginFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); 311 if (enter.succeeded()) 312 static_cast<VideoDecoder*>(enter.object())->FlushACK(result); 313} 314 315void PPB_VideoDecoder_Proxy::OnMsgResetACK( 316 const HostResource& decoder, int32_t result) { 317 EnterPluginFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); 318 if (enter.succeeded()) 319 static_cast<VideoDecoder*>(enter.object())->ResetACK(result); 320} 321 322} // namespace proxy 323} // namespace ppapi 324