[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 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/video_decoder_resource.h" |
| 6 | |
dcheng | d2b9f61 | 2015-12-18 19:08:51 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 9 | #include "base/bind.h" |
| 10 | #include "gpu/command_buffer/client/gles2_cmd_helper.h" |
| 11 | #include "gpu/command_buffer/client/gles2_implementation.h" |
[email protected] | 0ff052d | 2014-06-13 15:00:14 | [diff] [blame] | 12 | #include "gpu/command_buffer/common/mailbox.h" |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 13 | #include "ipc/ipc_message.h" |
| 14 | #include "ppapi/c/pp_errors.h" |
| 15 | #include "ppapi/c/ppb_opengles2.h" |
| 16 | #include "ppapi/proxy/plugin_dispatcher.h" |
| 17 | #include "ppapi/proxy/ppapi_messages.h" |
| 18 | #include "ppapi/proxy/ppb_graphics_3d_proxy.h" |
| 19 | #include "ppapi/proxy/serialized_handle.h" |
| 20 | #include "ppapi/proxy/video_decoder_constants.h" |
| 21 | #include "ppapi/shared_impl/ppapi_globals.h" |
| 22 | #include "ppapi/shared_impl/ppb_graphics_3d_shared.h" |
| 23 | #include "ppapi/shared_impl/proxy_lock.h" |
| 24 | #include "ppapi/shared_impl/resource_tracker.h" |
| 25 | #include "ppapi/thunk/enter.h" |
| 26 | |
| 27 | using ppapi::thunk::EnterResourceNoLock; |
| 28 | using ppapi::thunk::PPB_Graphics3D_API; |
| 29 | using ppapi::thunk::PPB_VideoDecoder_API; |
| 30 | |
| 31 | namespace ppapi { |
| 32 | namespace proxy { |
| 33 | |
| 34 | VideoDecoderResource::ShmBuffer::ShmBuffer( |
Matthew Cary | 66e4f70 | 2019-06-05 08:47:52 | [diff] [blame] | 35 | base::UnsafeSharedMemoryRegion region, |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 36 | uint32_t shm_id) |
Matthew Cary | 66e4f70 | 2019-06-05 08:47:52 | [diff] [blame] | 37 | : region(std::move(region)), shm_id(shm_id) { |
| 38 | mapping = this->region.Map(); |
| 39 | if (mapping.IsValid()) |
| 40 | addr = mapping.memory(); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | VideoDecoderResource::ShmBuffer::~ShmBuffer() { |
| 44 | } |
| 45 | |
| 46 | VideoDecoderResource::Texture::Texture(uint32_t texture_target, |
| 47 | const PP_Size& size) |
| 48 | : texture_target(texture_target), size(size) { |
| 49 | } |
| 50 | |
| 51 | VideoDecoderResource::Texture::~Texture() { |
| 52 | } |
| 53 | |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 54 | VideoDecoderResource::Picture::Picture(int32_t decode_id, |
| 55 | uint32_t texture_id, |
| 56 | const PP_Rect& visible_rect) |
| 57 | : decode_id(decode_id), texture_id(texture_id), visible_rect(visible_rect) { |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 58 | } |
| 59 | |
| 60 | VideoDecoderResource::Picture::~Picture() { |
| 61 | } |
| 62 | |
| 63 | VideoDecoderResource::VideoDecoderResource(Connection connection, |
| 64 | PP_Instance instance) |
| 65 | : PluginResource(connection, instance), |
| 66 | num_decodes_(0), |
lpique | 9dd55e54 | 2015-08-20 01:06:53 | [diff] [blame] | 67 | min_picture_count_(0), |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 68 | get_picture_(NULL), |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 69 | get_picture_0_1_(NULL), |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 70 | gles2_impl_(NULL), |
| 71 | initialized_(false), |
| 72 | testing_(false), |
| 73 | // Set |decoder_last_error_| to PP_OK after successful initialization. |
| 74 | // This makes error checking a little more concise, since we can check |
| 75 | // that the decoder has been initialized and hasn't returned an error by |
| 76 | // just testing |decoder_last_error_|. |
| 77 | decoder_last_error_(PP_ERROR_FAILED) { |
| 78 | // Clear the decode_ids_ array. |
tsepez | e9faf30 | 2015-03-21 07:48:29 | [diff] [blame] | 79 | memset(decode_ids_, 0, sizeof(decode_ids_)); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 80 | SendCreate(RENDERER, PpapiHostMsg_VideoDecoder_Create()); |
| 81 | } |
| 82 | |
| 83 | VideoDecoderResource::~VideoDecoderResource() { |
| 84 | // Destroy any textures which haven't been dismissed. |
| 85 | TextureMap::iterator it = textures_.begin(); |
| 86 | for (; it != textures_.end(); ++it) |
| 87 | DeleteGLTexture(it->first); |
| 88 | } |
| 89 | |
| 90 | PPB_VideoDecoder_API* VideoDecoderResource::AsPPB_VideoDecoder_API() { |
| 91 | return this; |
| 92 | } |
| 93 | |
bbudge | 4d6acaf | 2014-08-23 22:17:45 | [diff] [blame] | 94 | int32_t VideoDecoderResource::Initialize0_1( |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 95 | PP_Resource graphics_context, |
| 96 | PP_VideoProfile profile, |
| 97 | PP_Bool allow_software_fallback, |
| 98 | scoped_refptr<TrackedCallback> callback) { |
bbudge | 4d6acaf | 2014-08-23 22:17:45 | [diff] [blame] | 99 | return Initialize(graphics_context, |
| 100 | profile, |
| 101 | allow_software_fallback |
| 102 | ? PP_HARDWAREACCELERATION_WITHFALLBACK |
| 103 | : PP_HARDWAREACCELERATION_ONLY, |
lpique | 9dd55e54 | 2015-08-20 01:06:53 | [diff] [blame] | 104 | 0, |
| 105 | callback); |
| 106 | } |
| 107 | |
| 108 | int32_t VideoDecoderResource::Initialize0_2( |
| 109 | PP_Resource graphics_context, |
| 110 | PP_VideoProfile profile, |
| 111 | PP_HardwareAcceleration acceleration, |
| 112 | scoped_refptr<TrackedCallback> callback) { |
| 113 | return Initialize(graphics_context, |
| 114 | profile, |
| 115 | acceleration, |
| 116 | 0, |
bbudge | 4d6acaf | 2014-08-23 22:17:45 | [diff] [blame] | 117 | callback); |
| 118 | } |
| 119 | |
| 120 | int32_t VideoDecoderResource::Initialize( |
| 121 | PP_Resource graphics_context, |
| 122 | PP_VideoProfile profile, |
| 123 | PP_HardwareAcceleration acceleration, |
lpique | 9dd55e54 | 2015-08-20 01:06:53 | [diff] [blame] | 124 | uint32_t min_picture_count, |
bbudge | 4d6acaf | 2014-08-23 22:17:45 | [diff] [blame] | 125 | scoped_refptr<TrackedCallback> callback) { |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 126 | if (initialized_) |
| 127 | return PP_ERROR_FAILED; |
| 128 | if (profile < 0 || profile > PP_VIDEOPROFILE_MAX) |
| 129 | return PP_ERROR_BADARGUMENT; |
lpique | 9dd55e54 | 2015-08-20 01:06:53 | [diff] [blame] | 130 | if (min_picture_count > kMaximumPictureCount) |
| 131 | return PP_ERROR_BADARGUMENT; |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 132 | if (initialize_callback_.get()) |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 133 | return PP_ERROR_INPROGRESS; |
| 134 | if (!graphics_context) |
| 135 | return PP_ERROR_BADRESOURCE; |
| 136 | |
lpique | 9dd55e54 | 2015-08-20 01:06:53 | [diff] [blame] | 137 | min_picture_count_ = min_picture_count; |
| 138 | |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 139 | HostResource host_resource; |
| 140 | if (!testing_) { |
| 141 | // Create a new Graphics3D resource that can create texture resources to |
| 142 | // share with the plugin. We can't use the plugin's Graphics3D, since we |
| 143 | // create textures on a proxy thread, and would interfere with the plugin. |
| 144 | thunk::EnterResourceCreationNoLock enter_create(pp_instance()); |
| 145 | if (enter_create.failed()) |
| 146 | return PP_ERROR_FAILED; |
| 147 | int32_t attrib_list[] = {PP_GRAPHICS3DATTRIB_NONE}; |
| 148 | graphics3d_ = |
| 149 | ScopedPPResource(ScopedPPResource::PassRef(), |
| 150 | enter_create.functions()->CreateGraphics3D( |
| 151 | pp_instance(), graphics_context, attrib_list)); |
| 152 | EnterResourceNoLock<PPB_Graphics3D_API> enter_graphics(graphics3d_.get(), |
[email protected] | 0ff052d | 2014-06-13 15:00:14 | [diff] [blame] | 153 | false); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 154 | if (enter_graphics.failed()) |
| 155 | return PP_ERROR_BADRESOURCE; |
| 156 | |
| 157 | PPB_Graphics3D_Shared* ppb_graphics3d_shared = |
| 158 | static_cast<PPB_Graphics3D_Shared*>(enter_graphics.object()); |
| 159 | gles2_impl_ = ppb_graphics3d_shared->gles2_impl(); |
| 160 | host_resource = ppb_graphics3d_shared->host_resource(); |
| 161 | } |
| 162 | |
| 163 | initialize_callback_ = callback; |
| 164 | |
| 165 | Call<PpapiPluginMsg_VideoDecoder_InitializeReply>( |
| 166 | RENDERER, |
Anand K Mistry | 9182c2a7 | 2021-03-17 04:40:08 | [diff] [blame] | 167 | PpapiHostMsg_VideoDecoder_Initialize(host_resource, profile, acceleration, |
| 168 | min_picture_count), |
| 169 | base::BindOnce(&VideoDecoderResource::OnPluginMsgInitializeComplete, |
| 170 | this)); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 171 | |
| 172 | return PP_OK_COMPLETIONPENDING; |
| 173 | } |
| 174 | |
| 175 | int32_t VideoDecoderResource::Decode(uint32_t decode_id, |
| 176 | uint32_t size, |
| 177 | const void* buffer, |
| 178 | scoped_refptr<TrackedCallback> callback) { |
| 179 | if (decoder_last_error_) |
| 180 | return decoder_last_error_; |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 181 | if (flush_callback_.get() || reset_callback_.get()) |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 182 | return PP_ERROR_FAILED; |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 183 | if (decode_callback_.get()) |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 184 | return PP_ERROR_INPROGRESS; |
| 185 | if (size > kMaximumBitstreamBufferSize) |
| 186 | return PP_ERROR_NOMEMORY; |
| 187 | |
| 188 | // If we allow the plugin to call Decode again, we must have somewhere to |
| 189 | // copy their buffer. |
| 190 | DCHECK(!available_shm_buffers_.empty() || |
| 191 | shm_buffers_.size() < kMaximumPendingDecodes); |
| 192 | |
| 193 | // Count up, wrapping back to 0 before overflowing. |
| 194 | int32_t uid = ++num_decodes_; |
| 195 | if (uid == std::numeric_limits<int32_t>::max()) |
| 196 | num_decodes_ = 0; |
| 197 | |
| 198 | // Save decode_id in a ring buffer. The ring buffer is sized to store |
| 199 | // decode_id for the maximum picture delay. |
| 200 | decode_ids_[uid % kMaximumPictureDelay] = decode_id; |
| 201 | |
| 202 | if (available_shm_buffers_.empty() || |
Matthew Cary | 66e4f70 | 2019-06-05 08:47:52 | [diff] [blame] | 203 | available_shm_buffers_.back()->mapping.size() < size) { |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 204 | uint32_t shm_id; |
| 205 | if (shm_buffers_.size() < kMaximumPendingDecodes) { |
| 206 | // Signal the host to create a new shm buffer by passing an index outside |
| 207 | // the legal range. |
| 208 | shm_id = static_cast<uint32_t>(shm_buffers_.size()); |
| 209 | } else { |
| 210 | // Signal the host to grow a buffer by passing a legal index. Choose the |
| 211 | // last available shm buffer for simplicity. |
| 212 | shm_id = available_shm_buffers_.back()->shm_id; |
| 213 | available_shm_buffers_.pop_back(); |
| 214 | } |
| 215 | |
| 216 | // Synchronously get shared memory. Use GenericSyncCall so we can get the |
| 217 | // reply params, which contain the handle. |
| 218 | uint32_t shm_size = 0; |
| 219 | IPC::Message reply; |
| 220 | ResourceMessageReplyParams reply_params; |
| 221 | int32_t result = |
| 222 | GenericSyncCall(RENDERER, |
| 223 | PpapiHostMsg_VideoDecoder_GetShm(shm_id, size), |
| 224 | &reply, |
| 225 | &reply_params); |
| 226 | if (result != PP_OK) |
| 227 | return PP_ERROR_FAILED; |
| 228 | if (!UnpackMessage<PpapiPluginMsg_VideoDecoder_GetShmReply>(reply, |
| 229 | &shm_size)) |
| 230 | return PP_ERROR_FAILED; |
Matthew Cary | 66e4f70 | 2019-06-05 08:47:52 | [diff] [blame] | 231 | base::UnsafeSharedMemoryRegion shm_region; |
| 232 | if (!reply_params.TakeUnsafeSharedMemoryRegionAtIndex(0, &shm_region) || |
| 233 | !shm_region.IsValid() || shm_region.GetSize() != shm_size) |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 234 | return PP_ERROR_NOMEMORY; |
dcheng | ced9224 | 2016-04-07 00:00:12 | [diff] [blame] | 235 | std::unique_ptr<ShmBuffer> shm_buffer( |
Matthew Cary | 66e4f70 | 2019-06-05 08:47:52 | [diff] [blame] | 236 | new ShmBuffer(std::move(shm_region), shm_id)); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 237 | if (!shm_buffer->addr) |
| 238 | return PP_ERROR_NOMEMORY; |
| 239 | |
| 240 | available_shm_buffers_.push_back(shm_buffer.get()); |
avi | 9bf1749 | 2017-07-10 02:19:38 | [diff] [blame] | 241 | if (shm_buffers_.size() < kMaximumPendingDecodes) |
| 242 | shm_buffers_.push_back(std::move(shm_buffer)); |
| 243 | else |
| 244 | shm_buffers_[shm_id] = std::move(shm_buffer); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 245 | } |
| 246 | |
| 247 | // At this point we should have shared memory to hold the plugin's buffer. |
| 248 | DCHECK(!available_shm_buffers_.empty() && |
Matthew Cary | 66e4f70 | 2019-06-05 08:47:52 | [diff] [blame] | 249 | available_shm_buffers_.back()->mapping.size() >= size); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 250 | |
| 251 | ShmBuffer* shm_buffer = available_shm_buffers_.back(); |
| 252 | available_shm_buffers_.pop_back(); |
| 253 | memcpy(shm_buffer->addr, buffer, size); |
| 254 | |
| 255 | Call<PpapiPluginMsg_VideoDecoder_DecodeReply>( |
Anand K Mistry | 9182c2a7 | 2021-03-17 04:40:08 | [diff] [blame] | 256 | RENDERER, PpapiHostMsg_VideoDecoder_Decode(shm_buffer->shm_id, size, uid), |
| 257 | base::BindOnce(&VideoDecoderResource::OnPluginMsgDecodeComplete, this)); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 258 | |
| 259 | // If we have another free buffer, or we can still create new buffers, let |
| 260 | // the plugin call Decode again. |
| 261 | if (!available_shm_buffers_.empty() || |
| 262 | shm_buffers_.size() < kMaximumPendingDecodes) |
| 263 | return PP_OK; |
| 264 | |
| 265 | // All buffers are busy and we can't create more. Delay completion until a |
| 266 | // buffer is available. |
| 267 | decode_callback_ = callback; |
| 268 | return PP_OK_COMPLETIONPENDING; |
| 269 | } |
| 270 | |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 271 | int32_t VideoDecoderResource::GetPicture0_1( |
| 272 | PP_VideoPicture_0_1* picture, |
| 273 | scoped_refptr<TrackedCallback> callback) { |
| 274 | get_picture_0_1_ = picture; |
| 275 | return GetPicture(NULL, callback); |
| 276 | } |
| 277 | |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 278 | int32_t VideoDecoderResource::GetPicture( |
| 279 | PP_VideoPicture* picture, |
| 280 | scoped_refptr<TrackedCallback> callback) { |
| 281 | if (decoder_last_error_) |
| 282 | return decoder_last_error_; |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 283 | if (reset_callback_.get()) |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 284 | return PP_ERROR_FAILED; |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 285 | if (get_picture_callback_.get()) |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 286 | return PP_ERROR_INPROGRESS; |
| 287 | |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 288 | get_picture_ = picture; |
| 289 | |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 290 | // If the next picture is ready, return it synchronously. |
| 291 | if (!received_pictures_.empty()) { |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 292 | WriteNextPicture(); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 293 | return PP_OK; |
| 294 | } |
| 295 | |
| 296 | get_picture_callback_ = callback; |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 297 | |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 298 | return PP_OK_COMPLETIONPENDING; |
| 299 | } |
| 300 | |
| 301 | void VideoDecoderResource::RecyclePicture(const PP_VideoPicture* picture) { |
| 302 | if (decoder_last_error_) |
| 303 | return; |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 304 | |
| 305 | Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture(picture->texture_id)); |
| 306 | } |
| 307 | |
| 308 | int32_t VideoDecoderResource::Flush(scoped_refptr<TrackedCallback> callback) { |
| 309 | if (decoder_last_error_) |
| 310 | return decoder_last_error_; |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 311 | if (reset_callback_.get()) |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 312 | return PP_ERROR_FAILED; |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 313 | if (flush_callback_.get()) |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 314 | return PP_ERROR_INPROGRESS; |
| 315 | flush_callback_ = callback; |
| 316 | |
| 317 | Call<PpapiPluginMsg_VideoDecoder_FlushReply>( |
Anand K Mistry | 9182c2a7 | 2021-03-17 04:40:08 | [diff] [blame] | 318 | RENDERER, PpapiHostMsg_VideoDecoder_Flush(), |
| 319 | base::BindOnce(&VideoDecoderResource::OnPluginMsgFlushComplete, this)); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 320 | |
| 321 | return PP_OK_COMPLETIONPENDING; |
| 322 | } |
| 323 | |
| 324 | int32_t VideoDecoderResource::Reset(scoped_refptr<TrackedCallback> callback) { |
| 325 | if (decoder_last_error_) |
| 326 | return decoder_last_error_; |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 327 | if (flush_callback_.get()) |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 328 | return PP_ERROR_FAILED; |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 329 | if (reset_callback_.get()) |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 330 | return PP_ERROR_INPROGRESS; |
| 331 | reset_callback_ = callback; |
| 332 | |
| 333 | // Cause any pending Decode or GetPicture callbacks to abort after we return, |
| 334 | // to avoid reentering the plugin. |
| 335 | if (TrackedCallback::IsPending(decode_callback_)) |
| 336 | decode_callback_->PostAbort(); |
kylechar | 37594cb | 2019-11-15 16:41:17 | [diff] [blame] | 337 | decode_callback_.reset(); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 338 | if (TrackedCallback::IsPending(get_picture_callback_)) |
| 339 | get_picture_callback_->PostAbort(); |
kylechar | 37594cb | 2019-11-15 16:41:17 | [diff] [blame] | 340 | get_picture_callback_.reset(); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 341 | Call<PpapiPluginMsg_VideoDecoder_ResetReply>( |
Anand K Mistry | 9182c2a7 | 2021-03-17 04:40:08 | [diff] [blame] | 342 | RENDERER, PpapiHostMsg_VideoDecoder_Reset(), |
| 343 | base::BindOnce(&VideoDecoderResource::OnPluginMsgResetComplete, this)); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 344 | |
| 345 | return PP_OK_COMPLETIONPENDING; |
| 346 | } |
| 347 | |
| 348 | void VideoDecoderResource::OnReplyReceived( |
| 349 | const ResourceMessageReplyParams& params, |
| 350 | const IPC::Message& msg) { |
| 351 | PPAPI_BEGIN_MESSAGE_MAP(VideoDecoderResource, msg) |
| 352 | PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( |
| 353 | PpapiPluginMsg_VideoDecoder_RequestTextures, OnPluginMsgRequestTextures) |
| 354 | PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( |
| 355 | PpapiPluginMsg_VideoDecoder_PictureReady, OnPluginMsgPictureReady) |
| 356 | PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( |
| 357 | PpapiPluginMsg_VideoDecoder_DismissPicture, OnPluginMsgDismissPicture) |
| 358 | PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( |
| 359 | PpapiPluginMsg_VideoDecoder_NotifyError, OnPluginMsgNotifyError) |
| 360 | PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED( |
| 361 | PluginResource::OnReplyReceived(params, msg)) |
| 362 | PPAPI_END_MESSAGE_MAP() |
| 363 | } |
| 364 | |
| 365 | void VideoDecoderResource::SetForTest() { |
| 366 | testing_ = true; |
| 367 | } |
| 368 | |
| 369 | void VideoDecoderResource::OnPluginMsgRequestTextures( |
| 370 | const ResourceMessageReplyParams& params, |
| 371 | uint32_t num_textures, |
| 372 | const PP_Size& size, |
Antoine Labour | 04cb3b2 | 2018-06-01 23:25:10 | [diff] [blame] | 373 | uint32_t texture_target) { |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 374 | DCHECK(num_textures); |
lpique | 9dd55e54 | 2015-08-20 01:06:53 | [diff] [blame] | 375 | DCHECK(num_textures >= min_picture_count_); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 376 | std::vector<uint32_t> texture_ids(num_textures); |
Antoine Labour | 04cb3b2 | 2018-06-01 23:25:10 | [diff] [blame] | 377 | std::vector<gpu::Mailbox> mailboxes(num_textures); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 378 | if (gles2_impl_) { |
Antoine Labour | 04cb3b2 | 2018-06-01 23:25:10 | [diff] [blame] | 379 | gles2_impl_->GenTextures(num_textures, texture_ids.data()); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 380 | for (uint32_t i = 0; i < num_textures; ++i) { |
| 381 | gles2_impl_->ActiveTexture(GL_TEXTURE0); |
| 382 | gles2_impl_->BindTexture(texture_target, texture_ids[i]); |
| 383 | gles2_impl_->TexParameteri( |
CodeByThePound | de2d8397 | 2015-04-30 20:41:47 | [diff] [blame] | 384 | texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 385 | gles2_impl_->TexParameteri( |
CodeByThePound | de2d8397 | 2015-04-30 20:41:47 | [diff] [blame] | 386 | texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 387 | gles2_impl_->TexParameterf( |
| 388 | texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 389 | gles2_impl_->TexParameterf( |
| 390 | texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 391 | |
| 392 | if (texture_target == GL_TEXTURE_2D) { |
| 393 | gles2_impl_->TexImage2D(texture_target, |
| 394 | 0, |
| 395 | GL_RGBA, |
| 396 | size.width, |
| 397 | size.height, |
| 398 | 0, |
| 399 | GL_RGBA, |
| 400 | GL_UNSIGNED_BYTE, |
| 401 | NULL); |
| 402 | } |
Antoine Labour | 04cb3b2 | 2018-06-01 23:25:10 | [diff] [blame] | 403 | gles2_impl_->ProduceTextureDirectCHROMIUM(texture_ids[i], |
| 404 | mailboxes[i].name); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 405 | |
| 406 | textures_.insert( |
| 407 | std::make_pair(texture_ids[i], Texture(texture_target, size))); |
| 408 | } |
| 409 | gles2_impl_->Flush(); |
| 410 | } else { |
| 411 | DCHECK(testing_); |
| 412 | // Create some fake texture ids so we can test picture handling. |
| 413 | for (uint32_t i = 0; i < num_textures; ++i) { |
| 414 | texture_ids[i] = i + 1; |
| 415 | textures_.insert( |
| 416 | std::make_pair(texture_ids[i], Texture(texture_target, size))); |
| 417 | } |
| 418 | } |
| 419 | |
Antoine Labour | 04cb3b2 | 2018-06-01 23:25:10 | [diff] [blame] | 420 | Post(RENDERER, PpapiHostMsg_VideoDecoder_AssignTextures( |
| 421 | size, std::move(texture_ids), std::move(mailboxes))); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 422 | } |
| 423 | |
| 424 | void VideoDecoderResource::OnPluginMsgPictureReady( |
| 425 | const ResourceMessageReplyParams& params, |
| 426 | int32_t decode_id, |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 427 | uint32_t texture_id, |
| 428 | const PP_Rect& visible_rect) { |
| 429 | received_pictures_.push(Picture(decode_id, texture_id, visible_rect)); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 430 | |
| 431 | if (TrackedCallback::IsPending(get_picture_callback_)) { |
| 432 | // The plugin may call GetPicture in its callback. |
| 433 | scoped_refptr<TrackedCallback> callback; |
| 434 | callback.swap(get_picture_callback_); |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 435 | WriteNextPicture(); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 436 | callback->Run(PP_OK); |
| 437 | } |
| 438 | } |
| 439 | |
| 440 | void VideoDecoderResource::OnPluginMsgDismissPicture( |
| 441 | const ResourceMessageReplyParams& params, |
| 442 | uint32_t texture_id) { |
| 443 | DeleteGLTexture(texture_id); |
| 444 | textures_.erase(texture_id); |
| 445 | } |
| 446 | |
| 447 | void VideoDecoderResource::OnPluginMsgNotifyError( |
| 448 | const ResourceMessageReplyParams& params, |
| 449 | int32_t error) { |
| 450 | decoder_last_error_ = error; |
| 451 | // Cause any pending callbacks to run immediately. Reentrancy isn't a problem, |
| 452 | // since the plugin wasn't calling us. |
| 453 | RunCallbackWithError(&initialize_callback_); |
| 454 | RunCallbackWithError(&decode_callback_); |
| 455 | RunCallbackWithError(&get_picture_callback_); |
| 456 | RunCallbackWithError(&flush_callback_); |
| 457 | RunCallbackWithError(&reset_callback_); |
| 458 | } |
| 459 | |
| 460 | void VideoDecoderResource::OnPluginMsgInitializeComplete( |
| 461 | const ResourceMessageReplyParams& params) { |
| 462 | decoder_last_error_ = params.result(); |
| 463 | if (decoder_last_error_ == PP_OK) |
| 464 | initialized_ = true; |
| 465 | |
| 466 | // Let the plugin call Initialize again from its callback in case of failure. |
| 467 | scoped_refptr<TrackedCallback> callback; |
| 468 | callback.swap(initialize_callback_); |
| 469 | callback->Run(decoder_last_error_); |
| 470 | } |
| 471 | |
| 472 | void VideoDecoderResource::OnPluginMsgDecodeComplete( |
| 473 | const ResourceMessageReplyParams& params, |
| 474 | uint32_t shm_id) { |
| 475 | if (shm_id >= shm_buffers_.size()) { |
| 476 | NOTREACHED(); |
| 477 | return; |
| 478 | } |
| 479 | // Make the shm buffer available. |
avi | 9bf1749 | 2017-07-10 02:19:38 | [diff] [blame] | 480 | available_shm_buffers_.push_back(shm_buffers_[shm_id].get()); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 481 | // If the plugin is waiting, let it call Decode again. |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 482 | if (decode_callback_.get()) { |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 483 | scoped_refptr<TrackedCallback> callback; |
| 484 | callback.swap(decode_callback_); |
| 485 | callback->Run(PP_OK); |
| 486 | } |
| 487 | } |
| 488 | |
| 489 | void VideoDecoderResource::OnPluginMsgFlushComplete( |
| 490 | const ResourceMessageReplyParams& params) { |
| 491 | // All shm buffers should have been made available by now. |
| 492 | DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size()); |
| 493 | |
Daniel Cheng | 6d3ae97 | 2014-08-26 00:27:38 | [diff] [blame] | 494 | if (get_picture_callback_.get()) { |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 495 | scoped_refptr<TrackedCallback> callback; |
| 496 | callback.swap(get_picture_callback_); |
| 497 | callback->Abort(); |
| 498 | } |
| 499 | |
| 500 | scoped_refptr<TrackedCallback> callback; |
| 501 | callback.swap(flush_callback_); |
| 502 | callback->Run(params.result()); |
| 503 | } |
| 504 | |
| 505 | void VideoDecoderResource::OnPluginMsgResetComplete( |
| 506 | const ResourceMessageReplyParams& params) { |
| 507 | // All shm buffers should have been made available by now. |
| 508 | DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size()); |
[email protected] | 7ee85d6 | 2014-07-16 20:24:01 | [diff] [blame] | 509 | // Recycle any pictures which haven't been passed to the plugin. |
| 510 | while (!received_pictures_.empty()) { |
| 511 | Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture( |
| 512 | received_pictures_.front().texture_id)); |
[email protected] | e9fc71c1 | 2014-06-16 22:01:20 | [diff] [blame] | 513 | received_pictures_.pop(); |
[email protected] | 7ee85d6 | 2014-07-16 20:24:01 | [diff] [blame] | 514 | } |
[email protected] | e9fc71c1 | 2014-06-16 22:01:20 | [diff] [blame] | 515 | |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 516 | scoped_refptr<TrackedCallback> callback; |
| 517 | callback.swap(reset_callback_); |
| 518 | callback->Run(params.result()); |
| 519 | } |
| 520 | |
| 521 | void VideoDecoderResource::RunCallbackWithError( |
| 522 | scoped_refptr<TrackedCallback>* callback) { |
Daniel Bratell | eb5dcde | 2018-10-25 08:39:50 | [diff] [blame] | 523 | SafeRunCallback(callback, decoder_last_error_); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 524 | } |
| 525 | |
| 526 | void VideoDecoderResource::DeleteGLTexture(uint32_t id) { |
| 527 | if (gles2_impl_) { |
| 528 | gles2_impl_->DeleteTextures(1, &id); |
| 529 | gles2_impl_->Flush(); |
| 530 | } |
| 531 | } |
| 532 | |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 533 | void VideoDecoderResource::WriteNextPicture() { |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 534 | DCHECK(!received_pictures_.empty()); |
| 535 | Picture& picture = received_pictures_.front(); |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 536 | |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 537 | // Internally, we identify decodes by a unique id, which the host returns |
| 538 | // to us in the picture. Use this to get the plugin's decode_id. |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 539 | uint32_t decode_id = decode_ids_[picture.decode_id % kMaximumPictureDelay]; |
| 540 | uint32_t texture_id = picture.texture_id; |
| 541 | uint32_t texture_target = 0; |
| 542 | PP_Size texture_size = PP_MakeSize(0, 0); |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 543 | TextureMap::iterator it = textures_.find(picture.texture_id); |
| 544 | if (it != textures_.end()) { |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 545 | texture_target = it->second.texture_target; |
| 546 | texture_size = it->second.size; |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 547 | } else { |
| 548 | NOTREACHED(); |
| 549 | } |
Bill Budge | 2d4bf3a | 2014-11-06 22:31:21 | [diff] [blame] | 550 | |
| 551 | if (get_picture_) { |
| 552 | DCHECK(!get_picture_0_1_); |
| 553 | get_picture_->decode_id = decode_id; |
| 554 | get_picture_->texture_id = texture_id; |
| 555 | get_picture_->texture_target = texture_target; |
| 556 | get_picture_->texture_size = texture_size; |
| 557 | get_picture_->visible_rect = picture.visible_rect; |
| 558 | get_picture_ = NULL; |
| 559 | } else { |
| 560 | DCHECK(get_picture_0_1_); |
| 561 | get_picture_0_1_->decode_id = decode_id; |
| 562 | get_picture_0_1_->texture_id = texture_id; |
| 563 | get_picture_0_1_->texture_target = texture_target; |
| 564 | get_picture_0_1_->texture_size = texture_size; |
| 565 | get_picture_0_1_ = NULL; |
| 566 | } |
| 567 | |
[email protected] | dfb0d06f3 | 2014-05-30 22:45:56 | [diff] [blame] | 568 | received_pictures_.pop(); |
| 569 | } |
| 570 | |
| 571 | } // namespace proxy |
| 572 | } // namespace ppapi |