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 18 using ppapi::thunk::EnterResourceNoLock; 19 using ppapi::thunk::PPB_Buffer_API; 20 using ppapi::thunk::PPB_Graphics3D_API; 21 using ppapi::thunk::PPB_VideoDecoder_Dev_API; 22 23 namespace ppapi { 24 namespace proxy { 25 26 class 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 59 VideoDecoder::VideoDecoder(const HostResource& decoder) 60 : PPB_VideoDecoder_Shared(decoder) { 61 } 62 63 VideoDecoder::~VideoDecoder() { 64 FlushCommandBuffer(); 65 PPB_VideoDecoder_Shared::Destroy(); 66 } 67 68 int32_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 91 void 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 101 void 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 107 int32_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 117 int32_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 127 void 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 134 PluginDispatcher* VideoDecoder::GetDispatcher() const { 135 return PluginDispatcher::GetForResource(this); 136 } 137 138 void VideoDecoder::ResetACK(int32_t result) { 139 RunResetCallback(result); 140 } 141 142 void VideoDecoder::FlushACK(int32_t result) { 143 RunFlushCallback(result); 144 } 145 146 void VideoDecoder::EndOfBitstreamACK( 147 int32_t bitstream_buffer_id, int32_t result) { 148 RunBitstreamBufferCallback(bitstream_buffer_id, result); 149 } 150 151 PPB_VideoDecoder_Proxy::PPB_VideoDecoder_Proxy(Dispatcher* dispatcher) 152 : InterfaceProxy(dispatcher), 153 callback_factory_(this) { 154 } 155 156 PPB_VideoDecoder_Proxy::~PPB_VideoDecoder_Proxy() { 157 } 158 159 bool 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 185 PP_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 218 void 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 232 void 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 244 void 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 254 void 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 261 void 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 269 void 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 277 void 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 283 void 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 289 void 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 295 void 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 301 void 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 308 void 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 315 void 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