blob: 264e15d08f7b48a432c5510c0757964d962e9760 [file] [log] [blame]
[email protected]dfb0d06f32014-05-30 22:45:561// 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
dchengd2b9f612015-12-18 19:08:517#include <utility>
8
[email protected]dfb0d06f32014-05-30 22:45:569#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]0ff052d2014-06-13 15:00:1412#include "gpu/command_buffer/common/mailbox.h"
[email protected]dfb0d06f32014-05-30 22:45:5613#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
27using ppapi::thunk::EnterResourceNoLock;
28using ppapi::thunk::PPB_Graphics3D_API;
29using ppapi::thunk::PPB_VideoDecoder_API;
30
31namespace ppapi {
32namespace proxy {
33
34VideoDecoderResource::ShmBuffer::ShmBuffer(
Matthew Cary66e4f702019-06-05 08:47:5235 base::UnsafeSharedMemoryRegion region,
[email protected]dfb0d06f32014-05-30 22:45:5636 uint32_t shm_id)
Matthew Cary66e4f702019-06-05 08:47:5237 : region(std::move(region)), shm_id(shm_id) {
38 mapping = this->region.Map();
39 if (mapping.IsValid())
40 addr = mapping.memory();
[email protected]dfb0d06f32014-05-30 22:45:5641}
42
43VideoDecoderResource::ShmBuffer::~ShmBuffer() {
44}
45
46VideoDecoderResource::Texture::Texture(uint32_t texture_target,
47 const PP_Size& size)
48 : texture_target(texture_target), size(size) {
49}
50
51VideoDecoderResource::Texture::~Texture() {
52}
53
Bill Budge2d4bf3a2014-11-06 22:31:2154VideoDecoderResource::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]dfb0d06f32014-05-30 22:45:5658}
59
60VideoDecoderResource::Picture::~Picture() {
61}
62
63VideoDecoderResource::VideoDecoderResource(Connection connection,
64 PP_Instance instance)
65 : PluginResource(connection, instance),
66 num_decodes_(0),
lpique9dd55e542015-08-20 01:06:5367 min_picture_count_(0),
[email protected]dfb0d06f32014-05-30 22:45:5668 get_picture_(NULL),
Bill Budge2d4bf3a2014-11-06 22:31:2169 get_picture_0_1_(NULL),
[email protected]dfb0d06f32014-05-30 22:45:5670 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.
tsepeze9faf302015-03-21 07:48:2979 memset(decode_ids_, 0, sizeof(decode_ids_));
[email protected]dfb0d06f32014-05-30 22:45:5680 SendCreate(RENDERER, PpapiHostMsg_VideoDecoder_Create());
81}
82
83VideoDecoderResource::~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
90PPB_VideoDecoder_API* VideoDecoderResource::AsPPB_VideoDecoder_API() {
91 return this;
92}
93
bbudge4d6acaf2014-08-23 22:17:4594int32_t VideoDecoderResource::Initialize0_1(
[email protected]dfb0d06f32014-05-30 22:45:5695 PP_Resource graphics_context,
96 PP_VideoProfile profile,
97 PP_Bool allow_software_fallback,
98 scoped_refptr<TrackedCallback> callback) {
bbudge4d6acaf2014-08-23 22:17:4599 return Initialize(graphics_context,
100 profile,
101 allow_software_fallback
102 ? PP_HARDWAREACCELERATION_WITHFALLBACK
103 : PP_HARDWAREACCELERATION_ONLY,
lpique9dd55e542015-08-20 01:06:53104 0,
105 callback);
106}
107
108int32_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,
bbudge4d6acaf2014-08-23 22:17:45117 callback);
118}
119
120int32_t VideoDecoderResource::Initialize(
121 PP_Resource graphics_context,
122 PP_VideoProfile profile,
123 PP_HardwareAcceleration acceleration,
lpique9dd55e542015-08-20 01:06:53124 uint32_t min_picture_count,
bbudge4d6acaf2014-08-23 22:17:45125 scoped_refptr<TrackedCallback> callback) {
[email protected]dfb0d06f32014-05-30 22:45:56126 if (initialized_)
127 return PP_ERROR_FAILED;
128 if (profile < 0 || profile > PP_VIDEOPROFILE_MAX)
129 return PP_ERROR_BADARGUMENT;
lpique9dd55e542015-08-20 01:06:53130 if (min_picture_count > kMaximumPictureCount)
131 return PP_ERROR_BADARGUMENT;
Daniel Cheng6d3ae972014-08-26 00:27:38132 if (initialize_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56133 return PP_ERROR_INPROGRESS;
134 if (!graphics_context)
135 return PP_ERROR_BADRESOURCE;
136
lpique9dd55e542015-08-20 01:06:53137 min_picture_count_ = min_picture_count;
138
[email protected]dfb0d06f32014-05-30 22:45:56139 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]0ff052d2014-06-13 15:00:14153 false);
[email protected]dfb0d06f32014-05-30 22:45:56154 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 Mistry9182c2a72021-03-17 04:40:08167 PpapiHostMsg_VideoDecoder_Initialize(host_resource, profile, acceleration,
168 min_picture_count),
169 base::BindOnce(&VideoDecoderResource::OnPluginMsgInitializeComplete,
170 this));
[email protected]dfb0d06f32014-05-30 22:45:56171
172 return PP_OK_COMPLETIONPENDING;
173}
174
175int32_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 Cheng6d3ae972014-08-26 00:27:38181 if (flush_callback_.get() || reset_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56182 return PP_ERROR_FAILED;
Daniel Cheng6d3ae972014-08-26 00:27:38183 if (decode_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56184 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 Cary66e4f702019-06-05 08:47:52203 available_shm_buffers_.back()->mapping.size() < size) {
[email protected]dfb0d06f32014-05-30 22:45:56204 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 Cary66e4f702019-06-05 08:47:52231 base::UnsafeSharedMemoryRegion shm_region;
232 if (!reply_params.TakeUnsafeSharedMemoryRegionAtIndex(0, &shm_region) ||
233 !shm_region.IsValid() || shm_region.GetSize() != shm_size)
[email protected]dfb0d06f32014-05-30 22:45:56234 return PP_ERROR_NOMEMORY;
dchengced92242016-04-07 00:00:12235 std::unique_ptr<ShmBuffer> shm_buffer(
Matthew Cary66e4f702019-06-05 08:47:52236 new ShmBuffer(std::move(shm_region), shm_id));
[email protected]dfb0d06f32014-05-30 22:45:56237 if (!shm_buffer->addr)
238 return PP_ERROR_NOMEMORY;
239
240 available_shm_buffers_.push_back(shm_buffer.get());
avi9bf17492017-07-10 02:19:38241 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]dfb0d06f32014-05-30 22:45:56245 }
246
247 // At this point we should have shared memory to hold the plugin's buffer.
248 DCHECK(!available_shm_buffers_.empty() &&
Matthew Cary66e4f702019-06-05 08:47:52249 available_shm_buffers_.back()->mapping.size() >= size);
[email protected]dfb0d06f32014-05-30 22:45:56250
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 Mistry9182c2a72021-03-17 04:40:08256 RENDERER, PpapiHostMsg_VideoDecoder_Decode(shm_buffer->shm_id, size, uid),
257 base::BindOnce(&VideoDecoderResource::OnPluginMsgDecodeComplete, this));
[email protected]dfb0d06f32014-05-30 22:45:56258
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 Budge2d4bf3a2014-11-06 22:31:21271int32_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]dfb0d06f32014-05-30 22:45:56278int32_t VideoDecoderResource::GetPicture(
279 PP_VideoPicture* picture,
280 scoped_refptr<TrackedCallback> callback) {
281 if (decoder_last_error_)
282 return decoder_last_error_;
Daniel Cheng6d3ae972014-08-26 00:27:38283 if (reset_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56284 return PP_ERROR_FAILED;
Daniel Cheng6d3ae972014-08-26 00:27:38285 if (get_picture_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56286 return PP_ERROR_INPROGRESS;
287
Bill Budge2d4bf3a2014-11-06 22:31:21288 get_picture_ = picture;
289
[email protected]dfb0d06f32014-05-30 22:45:56290 // If the next picture is ready, return it synchronously.
291 if (!received_pictures_.empty()) {
Bill Budge2d4bf3a2014-11-06 22:31:21292 WriteNextPicture();
[email protected]dfb0d06f32014-05-30 22:45:56293 return PP_OK;
294 }
295
296 get_picture_callback_ = callback;
Bill Budge2d4bf3a2014-11-06 22:31:21297
[email protected]dfb0d06f32014-05-30 22:45:56298 return PP_OK_COMPLETIONPENDING;
299}
300
301void VideoDecoderResource::RecyclePicture(const PP_VideoPicture* picture) {
302 if (decoder_last_error_)
303 return;
[email protected]dfb0d06f32014-05-30 22:45:56304
305 Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture(picture->texture_id));
306}
307
308int32_t VideoDecoderResource::Flush(scoped_refptr<TrackedCallback> callback) {
309 if (decoder_last_error_)
310 return decoder_last_error_;
Daniel Cheng6d3ae972014-08-26 00:27:38311 if (reset_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56312 return PP_ERROR_FAILED;
Daniel Cheng6d3ae972014-08-26 00:27:38313 if (flush_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56314 return PP_ERROR_INPROGRESS;
315 flush_callback_ = callback;
316
317 Call<PpapiPluginMsg_VideoDecoder_FlushReply>(
Anand K Mistry9182c2a72021-03-17 04:40:08318 RENDERER, PpapiHostMsg_VideoDecoder_Flush(),
319 base::BindOnce(&VideoDecoderResource::OnPluginMsgFlushComplete, this));
[email protected]dfb0d06f32014-05-30 22:45:56320
321 return PP_OK_COMPLETIONPENDING;
322}
323
324int32_t VideoDecoderResource::Reset(scoped_refptr<TrackedCallback> callback) {
325 if (decoder_last_error_)
326 return decoder_last_error_;
Daniel Cheng6d3ae972014-08-26 00:27:38327 if (flush_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56328 return PP_ERROR_FAILED;
Daniel Cheng6d3ae972014-08-26 00:27:38329 if (reset_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56330 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();
kylechar37594cb2019-11-15 16:41:17337 decode_callback_.reset();
[email protected]dfb0d06f32014-05-30 22:45:56338 if (TrackedCallback::IsPending(get_picture_callback_))
339 get_picture_callback_->PostAbort();
kylechar37594cb2019-11-15 16:41:17340 get_picture_callback_.reset();
[email protected]dfb0d06f32014-05-30 22:45:56341 Call<PpapiPluginMsg_VideoDecoder_ResetReply>(
Anand K Mistry9182c2a72021-03-17 04:40:08342 RENDERER, PpapiHostMsg_VideoDecoder_Reset(),
343 base::BindOnce(&VideoDecoderResource::OnPluginMsgResetComplete, this));
[email protected]dfb0d06f32014-05-30 22:45:56344
345 return PP_OK_COMPLETIONPENDING;
346}
347
348void 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
365void VideoDecoderResource::SetForTest() {
366 testing_ = true;
367}
368
369void VideoDecoderResource::OnPluginMsgRequestTextures(
370 const ResourceMessageReplyParams& params,
371 uint32_t num_textures,
372 const PP_Size& size,
Antoine Labour04cb3b22018-06-01 23:25:10373 uint32_t texture_target) {
[email protected]dfb0d06f32014-05-30 22:45:56374 DCHECK(num_textures);
lpique9dd55e542015-08-20 01:06:53375 DCHECK(num_textures >= min_picture_count_);
[email protected]dfb0d06f32014-05-30 22:45:56376 std::vector<uint32_t> texture_ids(num_textures);
Antoine Labour04cb3b22018-06-01 23:25:10377 std::vector<gpu::Mailbox> mailboxes(num_textures);
[email protected]dfb0d06f32014-05-30 22:45:56378 if (gles2_impl_) {
Antoine Labour04cb3b22018-06-01 23:25:10379 gles2_impl_->GenTextures(num_textures, texture_ids.data());
[email protected]dfb0d06f32014-05-30 22:45:56380 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(
CodeByThePoundde2d83972015-04-30 20:41:47384 texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
[email protected]dfb0d06f32014-05-30 22:45:56385 gles2_impl_->TexParameteri(
CodeByThePoundde2d83972015-04-30 20:41:47386 texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
[email protected]dfb0d06f32014-05-30 22:45:56387 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 Labour04cb3b22018-06-01 23:25:10403 gles2_impl_->ProduceTextureDirectCHROMIUM(texture_ids[i],
404 mailboxes[i].name);
[email protected]dfb0d06f32014-05-30 22:45:56405
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 Labour04cb3b22018-06-01 23:25:10420 Post(RENDERER, PpapiHostMsg_VideoDecoder_AssignTextures(
421 size, std::move(texture_ids), std::move(mailboxes)));
[email protected]dfb0d06f32014-05-30 22:45:56422}
423
424void VideoDecoderResource::OnPluginMsgPictureReady(
425 const ResourceMessageReplyParams& params,
426 int32_t decode_id,
Bill Budge2d4bf3a2014-11-06 22:31:21427 uint32_t texture_id,
428 const PP_Rect& visible_rect) {
429 received_pictures_.push(Picture(decode_id, texture_id, visible_rect));
[email protected]dfb0d06f32014-05-30 22:45:56430
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 Budge2d4bf3a2014-11-06 22:31:21435 WriteNextPicture();
[email protected]dfb0d06f32014-05-30 22:45:56436 callback->Run(PP_OK);
437 }
438}
439
440void VideoDecoderResource::OnPluginMsgDismissPicture(
441 const ResourceMessageReplyParams& params,
442 uint32_t texture_id) {
443 DeleteGLTexture(texture_id);
444 textures_.erase(texture_id);
445}
446
447void 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
460void 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
472void 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.
avi9bf17492017-07-10 02:19:38480 available_shm_buffers_.push_back(shm_buffers_[shm_id].get());
[email protected]dfb0d06f32014-05-30 22:45:56481 // If the plugin is waiting, let it call Decode again.
Daniel Cheng6d3ae972014-08-26 00:27:38482 if (decode_callback_.get()) {
[email protected]dfb0d06f32014-05-30 22:45:56483 scoped_refptr<TrackedCallback> callback;
484 callback.swap(decode_callback_);
485 callback->Run(PP_OK);
486 }
487}
488
489void 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 Cheng6d3ae972014-08-26 00:27:38494 if (get_picture_callback_.get()) {
[email protected]dfb0d06f32014-05-30 22:45:56495 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
505void 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]7ee85d62014-07-16 20:24:01509 // 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]e9fc71c12014-06-16 22:01:20513 received_pictures_.pop();
[email protected]7ee85d62014-07-16 20:24:01514 }
[email protected]e9fc71c12014-06-16 22:01:20515
[email protected]dfb0d06f32014-05-30 22:45:56516 scoped_refptr<TrackedCallback> callback;
517 callback.swap(reset_callback_);
518 callback->Run(params.result());
519}
520
521void VideoDecoderResource::RunCallbackWithError(
522 scoped_refptr<TrackedCallback>* callback) {
Daniel Bratelleb5dcde2018-10-25 08:39:50523 SafeRunCallback(callback, decoder_last_error_);
[email protected]dfb0d06f32014-05-30 22:45:56524}
525
526void VideoDecoderResource::DeleteGLTexture(uint32_t id) {
527 if (gles2_impl_) {
528 gles2_impl_->DeleteTextures(1, &id);
529 gles2_impl_->Flush();
530 }
531}
532
Bill Budge2d4bf3a2014-11-06 22:31:21533void VideoDecoderResource::WriteNextPicture() {
[email protected]dfb0d06f32014-05-30 22:45:56534 DCHECK(!received_pictures_.empty());
535 Picture& picture = received_pictures_.front();
Bill Budge2d4bf3a2014-11-06 22:31:21536
[email protected]dfb0d06f32014-05-30 22:45:56537 // 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 Budge2d4bf3a2014-11-06 22:31:21539 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]dfb0d06f32014-05-30 22:45:56543 TextureMap::iterator it = textures_.find(picture.texture_id);
544 if (it != textures_.end()) {
Bill Budge2d4bf3a2014-11-06 22:31:21545 texture_target = it->second.texture_target;
546 texture_size = it->second.size;
[email protected]dfb0d06f32014-05-30 22:45:56547 } else {
548 NOTREACHED();
549 }
Bill Budge2d4bf3a2014-11-06 22:31:21550
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]dfb0d06f32014-05-30 22:45:56568 received_pictures_.pop();
569}
570
571} // namespace proxy
572} // namespace ppapi