blob: 60020b5a692d05dfd50f0fcbe0629d5039c72a1e [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,
167 PpapiHostMsg_VideoDecoder_Initialize(
lpique9dd55e542015-08-20 01:06:53168 host_resource, profile, acceleration, min_picture_count),
[email protected]dfb0d06f32014-05-30 22:45:56169 base::Bind(&VideoDecoderResource::OnPluginMsgInitializeComplete, this));
170
171 return PP_OK_COMPLETIONPENDING;
172}
173
174int32_t VideoDecoderResource::Decode(uint32_t decode_id,
175 uint32_t size,
176 const void* buffer,
177 scoped_refptr<TrackedCallback> callback) {
178 if (decoder_last_error_)
179 return decoder_last_error_;
Daniel Cheng6d3ae972014-08-26 00:27:38180 if (flush_callback_.get() || reset_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56181 return PP_ERROR_FAILED;
Daniel Cheng6d3ae972014-08-26 00:27:38182 if (decode_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56183 return PP_ERROR_INPROGRESS;
184 if (size > kMaximumBitstreamBufferSize)
185 return PP_ERROR_NOMEMORY;
186
187 // If we allow the plugin to call Decode again, we must have somewhere to
188 // copy their buffer.
189 DCHECK(!available_shm_buffers_.empty() ||
190 shm_buffers_.size() < kMaximumPendingDecodes);
191
192 // Count up, wrapping back to 0 before overflowing.
193 int32_t uid = ++num_decodes_;
194 if (uid == std::numeric_limits<int32_t>::max())
195 num_decodes_ = 0;
196
197 // Save decode_id in a ring buffer. The ring buffer is sized to store
198 // decode_id for the maximum picture delay.
199 decode_ids_[uid % kMaximumPictureDelay] = decode_id;
200
201 if (available_shm_buffers_.empty() ||
Matthew Cary66e4f702019-06-05 08:47:52202 available_shm_buffers_.back()->mapping.size() < size) {
[email protected]dfb0d06f32014-05-30 22:45:56203 uint32_t shm_id;
204 if (shm_buffers_.size() < kMaximumPendingDecodes) {
205 // Signal the host to create a new shm buffer by passing an index outside
206 // the legal range.
207 shm_id = static_cast<uint32_t>(shm_buffers_.size());
208 } else {
209 // Signal the host to grow a buffer by passing a legal index. Choose the
210 // last available shm buffer for simplicity.
211 shm_id = available_shm_buffers_.back()->shm_id;
212 available_shm_buffers_.pop_back();
213 }
214
215 // Synchronously get shared memory. Use GenericSyncCall so we can get the
216 // reply params, which contain the handle.
217 uint32_t shm_size = 0;
218 IPC::Message reply;
219 ResourceMessageReplyParams reply_params;
220 int32_t result =
221 GenericSyncCall(RENDERER,
222 PpapiHostMsg_VideoDecoder_GetShm(shm_id, size),
223 &reply,
224 &reply_params);
225 if (result != PP_OK)
226 return PP_ERROR_FAILED;
227 if (!UnpackMessage<PpapiPluginMsg_VideoDecoder_GetShmReply>(reply,
228 &shm_size))
229 return PP_ERROR_FAILED;
Matthew Cary66e4f702019-06-05 08:47:52230 base::UnsafeSharedMemoryRegion shm_region;
231 if (!reply_params.TakeUnsafeSharedMemoryRegionAtIndex(0, &shm_region) ||
232 !shm_region.IsValid() || shm_region.GetSize() != shm_size)
[email protected]dfb0d06f32014-05-30 22:45:56233 return PP_ERROR_NOMEMORY;
dchengced92242016-04-07 00:00:12234 std::unique_ptr<ShmBuffer> shm_buffer(
Matthew Cary66e4f702019-06-05 08:47:52235 new ShmBuffer(std::move(shm_region), shm_id));
[email protected]dfb0d06f32014-05-30 22:45:56236 if (!shm_buffer->addr)
237 return PP_ERROR_NOMEMORY;
238
239 available_shm_buffers_.push_back(shm_buffer.get());
avi9bf17492017-07-10 02:19:38240 if (shm_buffers_.size() < kMaximumPendingDecodes)
241 shm_buffers_.push_back(std::move(shm_buffer));
242 else
243 shm_buffers_[shm_id] = std::move(shm_buffer);
[email protected]dfb0d06f32014-05-30 22:45:56244 }
245
246 // At this point we should have shared memory to hold the plugin's buffer.
247 DCHECK(!available_shm_buffers_.empty() &&
Matthew Cary66e4f702019-06-05 08:47:52248 available_shm_buffers_.back()->mapping.size() >= size);
[email protected]dfb0d06f32014-05-30 22:45:56249
250 ShmBuffer* shm_buffer = available_shm_buffers_.back();
251 available_shm_buffers_.pop_back();
252 memcpy(shm_buffer->addr, buffer, size);
253
254 Call<PpapiPluginMsg_VideoDecoder_DecodeReply>(
255 RENDERER,
256 PpapiHostMsg_VideoDecoder_Decode(shm_buffer->shm_id, size, uid),
257 base::Bind(&VideoDecoderResource::OnPluginMsgDecodeComplete, this));
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 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>(
318 RENDERER,
319 PpapiHostMsg_VideoDecoder_Flush(),
320 base::Bind(&VideoDecoderResource::OnPluginMsgFlushComplete, this));
321
322 return PP_OK_COMPLETIONPENDING;
323}
324
325int32_t VideoDecoderResource::Reset(scoped_refptr<TrackedCallback> callback) {
326 if (decoder_last_error_)
327 return decoder_last_error_;
Daniel Cheng6d3ae972014-08-26 00:27:38328 if (flush_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56329 return PP_ERROR_FAILED;
Daniel Cheng6d3ae972014-08-26 00:27:38330 if (reset_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56331 return PP_ERROR_INPROGRESS;
332 reset_callback_ = callback;
333
334 // Cause any pending Decode or GetPicture callbacks to abort after we return,
335 // to avoid reentering the plugin.
336 if (TrackedCallback::IsPending(decode_callback_))
337 decode_callback_->PostAbort();
kylechar37594cb2019-11-15 16:41:17338 decode_callback_.reset();
[email protected]dfb0d06f32014-05-30 22:45:56339 if (TrackedCallback::IsPending(get_picture_callback_))
340 get_picture_callback_->PostAbort();
kylechar37594cb2019-11-15 16:41:17341 get_picture_callback_.reset();
[email protected]dfb0d06f32014-05-30 22:45:56342 Call<PpapiPluginMsg_VideoDecoder_ResetReply>(
343 RENDERER,
344 PpapiHostMsg_VideoDecoder_Reset(),
345 base::Bind(&VideoDecoderResource::OnPluginMsgResetComplete, this));
346
347 return PP_OK_COMPLETIONPENDING;
348}
349
350void VideoDecoderResource::OnReplyReceived(
351 const ResourceMessageReplyParams& params,
352 const IPC::Message& msg) {
353 PPAPI_BEGIN_MESSAGE_MAP(VideoDecoderResource, msg)
354 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
355 PpapiPluginMsg_VideoDecoder_RequestTextures, OnPluginMsgRequestTextures)
356 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
357 PpapiPluginMsg_VideoDecoder_PictureReady, OnPluginMsgPictureReady)
358 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
359 PpapiPluginMsg_VideoDecoder_DismissPicture, OnPluginMsgDismissPicture)
360 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
361 PpapiPluginMsg_VideoDecoder_NotifyError, OnPluginMsgNotifyError)
362 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
363 PluginResource::OnReplyReceived(params, msg))
364 PPAPI_END_MESSAGE_MAP()
365}
366
367void VideoDecoderResource::SetForTest() {
368 testing_ = true;
369}
370
371void VideoDecoderResource::OnPluginMsgRequestTextures(
372 const ResourceMessageReplyParams& params,
373 uint32_t num_textures,
374 const PP_Size& size,
Antoine Labour04cb3b22018-06-01 23:25:10375 uint32_t texture_target) {
[email protected]dfb0d06f32014-05-30 22:45:56376 DCHECK(num_textures);
lpique9dd55e542015-08-20 01:06:53377 DCHECK(num_textures >= min_picture_count_);
[email protected]dfb0d06f32014-05-30 22:45:56378 std::vector<uint32_t> texture_ids(num_textures);
Antoine Labour04cb3b22018-06-01 23:25:10379 std::vector<gpu::Mailbox> mailboxes(num_textures);
[email protected]dfb0d06f32014-05-30 22:45:56380 if (gles2_impl_) {
Antoine Labour04cb3b22018-06-01 23:25:10381 gles2_impl_->GenTextures(num_textures, texture_ids.data());
[email protected]dfb0d06f32014-05-30 22:45:56382 for (uint32_t i = 0; i < num_textures; ++i) {
383 gles2_impl_->ActiveTexture(GL_TEXTURE0);
384 gles2_impl_->BindTexture(texture_target, texture_ids[i]);
385 gles2_impl_->TexParameteri(
CodeByThePoundde2d83972015-04-30 20:41:47386 texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
[email protected]dfb0d06f32014-05-30 22:45:56387 gles2_impl_->TexParameteri(
CodeByThePoundde2d83972015-04-30 20:41:47388 texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
[email protected]dfb0d06f32014-05-30 22:45:56389 gles2_impl_->TexParameterf(
390 texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
391 gles2_impl_->TexParameterf(
392 texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
393
394 if (texture_target == GL_TEXTURE_2D) {
395 gles2_impl_->TexImage2D(texture_target,
396 0,
397 GL_RGBA,
398 size.width,
399 size.height,
400 0,
401 GL_RGBA,
402 GL_UNSIGNED_BYTE,
403 NULL);
404 }
Antoine Labour04cb3b22018-06-01 23:25:10405 gles2_impl_->ProduceTextureDirectCHROMIUM(texture_ids[i],
406 mailboxes[i].name);
[email protected]dfb0d06f32014-05-30 22:45:56407
408 textures_.insert(
409 std::make_pair(texture_ids[i], Texture(texture_target, size)));
410 }
411 gles2_impl_->Flush();
412 } else {
413 DCHECK(testing_);
414 // Create some fake texture ids so we can test picture handling.
415 for (uint32_t i = 0; i < num_textures; ++i) {
416 texture_ids[i] = i + 1;
417 textures_.insert(
418 std::make_pair(texture_ids[i], Texture(texture_target, size)));
419 }
420 }
421
Antoine Labour04cb3b22018-06-01 23:25:10422 Post(RENDERER, PpapiHostMsg_VideoDecoder_AssignTextures(
423 size, std::move(texture_ids), std::move(mailboxes)));
[email protected]dfb0d06f32014-05-30 22:45:56424}
425
426void VideoDecoderResource::OnPluginMsgPictureReady(
427 const ResourceMessageReplyParams& params,
428 int32_t decode_id,
Bill Budge2d4bf3a2014-11-06 22:31:21429 uint32_t texture_id,
430 const PP_Rect& visible_rect) {
431 received_pictures_.push(Picture(decode_id, texture_id, visible_rect));
[email protected]dfb0d06f32014-05-30 22:45:56432
433 if (TrackedCallback::IsPending(get_picture_callback_)) {
434 // The plugin may call GetPicture in its callback.
435 scoped_refptr<TrackedCallback> callback;
436 callback.swap(get_picture_callback_);
Bill Budge2d4bf3a2014-11-06 22:31:21437 WriteNextPicture();
[email protected]dfb0d06f32014-05-30 22:45:56438 callback->Run(PP_OK);
439 }
440}
441
442void VideoDecoderResource::OnPluginMsgDismissPicture(
443 const ResourceMessageReplyParams& params,
444 uint32_t texture_id) {
445 DeleteGLTexture(texture_id);
446 textures_.erase(texture_id);
447}
448
449void VideoDecoderResource::OnPluginMsgNotifyError(
450 const ResourceMessageReplyParams& params,
451 int32_t error) {
452 decoder_last_error_ = error;
453 // Cause any pending callbacks to run immediately. Reentrancy isn't a problem,
454 // since the plugin wasn't calling us.
455 RunCallbackWithError(&initialize_callback_);
456 RunCallbackWithError(&decode_callback_);
457 RunCallbackWithError(&get_picture_callback_);
458 RunCallbackWithError(&flush_callback_);
459 RunCallbackWithError(&reset_callback_);
460}
461
462void VideoDecoderResource::OnPluginMsgInitializeComplete(
463 const ResourceMessageReplyParams& params) {
464 decoder_last_error_ = params.result();
465 if (decoder_last_error_ == PP_OK)
466 initialized_ = true;
467
468 // Let the plugin call Initialize again from its callback in case of failure.
469 scoped_refptr<TrackedCallback> callback;
470 callback.swap(initialize_callback_);
471 callback->Run(decoder_last_error_);
472}
473
474void VideoDecoderResource::OnPluginMsgDecodeComplete(
475 const ResourceMessageReplyParams& params,
476 uint32_t shm_id) {
477 if (shm_id >= shm_buffers_.size()) {
478 NOTREACHED();
479 return;
480 }
481 // Make the shm buffer available.
avi9bf17492017-07-10 02:19:38482 available_shm_buffers_.push_back(shm_buffers_[shm_id].get());
[email protected]dfb0d06f32014-05-30 22:45:56483 // If the plugin is waiting, let it call Decode again.
Daniel Cheng6d3ae972014-08-26 00:27:38484 if (decode_callback_.get()) {
[email protected]dfb0d06f32014-05-30 22:45:56485 scoped_refptr<TrackedCallback> callback;
486 callback.swap(decode_callback_);
487 callback->Run(PP_OK);
488 }
489}
490
491void VideoDecoderResource::OnPluginMsgFlushComplete(
492 const ResourceMessageReplyParams& params) {
493 // All shm buffers should have been made available by now.
494 DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size());
495
Daniel Cheng6d3ae972014-08-26 00:27:38496 if (get_picture_callback_.get()) {
[email protected]dfb0d06f32014-05-30 22:45:56497 scoped_refptr<TrackedCallback> callback;
498 callback.swap(get_picture_callback_);
499 callback->Abort();
500 }
501
502 scoped_refptr<TrackedCallback> callback;
503 callback.swap(flush_callback_);
504 callback->Run(params.result());
505}
506
507void VideoDecoderResource::OnPluginMsgResetComplete(
508 const ResourceMessageReplyParams& params) {
509 // All shm buffers should have been made available by now.
510 DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size());
[email protected]7ee85d62014-07-16 20:24:01511 // Recycle any pictures which haven't been passed to the plugin.
512 while (!received_pictures_.empty()) {
513 Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture(
514 received_pictures_.front().texture_id));
[email protected]e9fc71c12014-06-16 22:01:20515 received_pictures_.pop();
[email protected]7ee85d62014-07-16 20:24:01516 }
[email protected]e9fc71c12014-06-16 22:01:20517
[email protected]dfb0d06f32014-05-30 22:45:56518 scoped_refptr<TrackedCallback> callback;
519 callback.swap(reset_callback_);
520 callback->Run(params.result());
521}
522
523void VideoDecoderResource::RunCallbackWithError(
524 scoped_refptr<TrackedCallback>* callback) {
Daniel Bratelleb5dcde2018-10-25 08:39:50525 SafeRunCallback(callback, decoder_last_error_);
[email protected]dfb0d06f32014-05-30 22:45:56526}
527
528void VideoDecoderResource::DeleteGLTexture(uint32_t id) {
529 if (gles2_impl_) {
530 gles2_impl_->DeleteTextures(1, &id);
531 gles2_impl_->Flush();
532 }
533}
534
Bill Budge2d4bf3a2014-11-06 22:31:21535void VideoDecoderResource::WriteNextPicture() {
[email protected]dfb0d06f32014-05-30 22:45:56536 DCHECK(!received_pictures_.empty());
537 Picture& picture = received_pictures_.front();
Bill Budge2d4bf3a2014-11-06 22:31:21538
[email protected]dfb0d06f32014-05-30 22:45:56539 // Internally, we identify decodes by a unique id, which the host returns
540 // to us in the picture. Use this to get the plugin's decode_id.
Bill Budge2d4bf3a2014-11-06 22:31:21541 uint32_t decode_id = decode_ids_[picture.decode_id % kMaximumPictureDelay];
542 uint32_t texture_id = picture.texture_id;
543 uint32_t texture_target = 0;
544 PP_Size texture_size = PP_MakeSize(0, 0);
[email protected]dfb0d06f32014-05-30 22:45:56545 TextureMap::iterator it = textures_.find(picture.texture_id);
546 if (it != textures_.end()) {
Bill Budge2d4bf3a2014-11-06 22:31:21547 texture_target = it->second.texture_target;
548 texture_size = it->second.size;
[email protected]dfb0d06f32014-05-30 22:45:56549 } else {
550 NOTREACHED();
551 }
Bill Budge2d4bf3a2014-11-06 22:31:21552
553 if (get_picture_) {
554 DCHECK(!get_picture_0_1_);
555 get_picture_->decode_id = decode_id;
556 get_picture_->texture_id = texture_id;
557 get_picture_->texture_target = texture_target;
558 get_picture_->texture_size = texture_size;
559 get_picture_->visible_rect = picture.visible_rect;
560 get_picture_ = NULL;
561 } else {
562 DCHECK(get_picture_0_1_);
563 get_picture_0_1_->decode_id = decode_id;
564 get_picture_0_1_->texture_id = texture_id;
565 get_picture_0_1_->texture_target = texture_target;
566 get_picture_0_1_->texture_size = texture_size;
567 get_picture_0_1_ = NULL;
568 }
569
[email protected]dfb0d06f32014-05-30 22:45:56570 received_pictures_.pop();
571}
572
573} // namespace proxy
574} // namespace ppapi