blob: 495d257a6958a8a5ec2c7c65902a89c5e5cade37 [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(
dchengced92242016-04-07 00:00:1235 std::unique_ptr<base::SharedMemory> shm_ptr,
[email protected]dfb0d06f32014-05-30 22:45:5636 uint32_t size,
37 uint32_t shm_id)
dchengd2b9f612015-12-18 19:08:5138 : shm(std::move(shm_ptr)), addr(NULL), shm_id(shm_id) {
[email protected]dfb0d06f32014-05-30 22:45:5639 if (shm->Map(size))
40 addr = shm->memory();
41}
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() ||
202 available_shm_buffers_.back()->shm->mapped_size() < size) {
203 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;
erikchena40775d02017-04-29 07:15:49230 base::SharedMemoryHandle shm_handle;
[email protected]dfb0d06f32014-05-30 22:45:56231 if (!reply_params.TakeSharedMemoryHandleAtIndex(0, &shm_handle))
232 return PP_ERROR_NOMEMORY;
dchengced92242016-04-07 00:00:12233 std::unique_ptr<base::SharedMemory> shm(
[email protected]dfb0d06f32014-05-30 22:45:56234 new base::SharedMemory(shm_handle, false /* read_only */));
dchengced92242016-04-07 00:00:12235 std::unique_ptr<ShmBuffer> shm_buffer(
dchengd2b9f612015-12-18 19:08:51236 new ShmBuffer(std::move(shm), shm_size, 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() &&
249 available_shm_buffers_.back()->shm->mapped_size() >= size);
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>(
256 RENDERER,
257 PpapiHostMsg_VideoDecoder_Decode(shm_buffer->shm_id, size, uid),
258 base::Bind(&VideoDecoderResource::OnPluginMsgDecodeComplete, this));
259
260 // If we have another free buffer, or we can still create new buffers, let
261 // the plugin call Decode again.
262 if (!available_shm_buffers_.empty() ||
263 shm_buffers_.size() < kMaximumPendingDecodes)
264 return PP_OK;
265
266 // All buffers are busy and we can't create more. Delay completion until a
267 // buffer is available.
268 decode_callback_ = callback;
269 return PP_OK_COMPLETIONPENDING;
270}
271
Bill Budge2d4bf3a2014-11-06 22:31:21272int32_t VideoDecoderResource::GetPicture0_1(
273 PP_VideoPicture_0_1* picture,
274 scoped_refptr<TrackedCallback> callback) {
275 get_picture_0_1_ = picture;
276 return GetPicture(NULL, callback);
277}
278
[email protected]dfb0d06f32014-05-30 22:45:56279int32_t VideoDecoderResource::GetPicture(
280 PP_VideoPicture* picture,
281 scoped_refptr<TrackedCallback> callback) {
282 if (decoder_last_error_)
283 return decoder_last_error_;
Daniel Cheng6d3ae972014-08-26 00:27:38284 if (reset_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56285 return PP_ERROR_FAILED;
Daniel Cheng6d3ae972014-08-26 00:27:38286 if (get_picture_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56287 return PP_ERROR_INPROGRESS;
288
Bill Budge2d4bf3a2014-11-06 22:31:21289 get_picture_ = picture;
290
[email protected]dfb0d06f32014-05-30 22:45:56291 // If the next picture is ready, return it synchronously.
292 if (!received_pictures_.empty()) {
Bill Budge2d4bf3a2014-11-06 22:31:21293 WriteNextPicture();
[email protected]dfb0d06f32014-05-30 22:45:56294 return PP_OK;
295 }
296
297 get_picture_callback_ = callback;
Bill Budge2d4bf3a2014-11-06 22:31:21298
[email protected]dfb0d06f32014-05-30 22:45:56299 return PP_OK_COMPLETIONPENDING;
300}
301
302void VideoDecoderResource::RecyclePicture(const PP_VideoPicture* picture) {
303 if (decoder_last_error_)
304 return;
[email protected]dfb0d06f32014-05-30 22:45:56305
306 Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture(picture->texture_id));
307}
308
309int32_t VideoDecoderResource::Flush(scoped_refptr<TrackedCallback> callback) {
310 if (decoder_last_error_)
311 return decoder_last_error_;
Daniel Cheng6d3ae972014-08-26 00:27:38312 if (reset_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56313 return PP_ERROR_FAILED;
Daniel Cheng6d3ae972014-08-26 00:27:38314 if (flush_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56315 return PP_ERROR_INPROGRESS;
316 flush_callback_ = callback;
317
318 Call<PpapiPluginMsg_VideoDecoder_FlushReply>(
319 RENDERER,
320 PpapiHostMsg_VideoDecoder_Flush(),
321 base::Bind(&VideoDecoderResource::OnPluginMsgFlushComplete, this));
322
323 return PP_OK_COMPLETIONPENDING;
324}
325
326int32_t VideoDecoderResource::Reset(scoped_refptr<TrackedCallback> callback) {
327 if (decoder_last_error_)
328 return decoder_last_error_;
Daniel Cheng6d3ae972014-08-26 00:27:38329 if (flush_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56330 return PP_ERROR_FAILED;
Daniel Cheng6d3ae972014-08-26 00:27:38331 if (reset_callback_.get())
[email protected]dfb0d06f32014-05-30 22:45:56332 return PP_ERROR_INPROGRESS;
333 reset_callback_ = callback;
334
335 // Cause any pending Decode or GetPicture callbacks to abort after we return,
336 // to avoid reentering the plugin.
337 if (TrackedCallback::IsPending(decode_callback_))
338 decode_callback_->PostAbort();
339 decode_callback_ = NULL;
340 if (TrackedCallback::IsPending(get_picture_callback_))
341 get_picture_callback_->PostAbort();
342 get_picture_callback_ = NULL;
343 Call<PpapiPluginMsg_VideoDecoder_ResetReply>(
344 RENDERER,
345 PpapiHostMsg_VideoDecoder_Reset(),
346 base::Bind(&VideoDecoderResource::OnPluginMsgResetComplete, this));
347
348 return PP_OK_COMPLETIONPENDING;
349}
350
351void VideoDecoderResource::OnReplyReceived(
352 const ResourceMessageReplyParams& params,
353 const IPC::Message& msg) {
354 PPAPI_BEGIN_MESSAGE_MAP(VideoDecoderResource, msg)
355 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
356 PpapiPluginMsg_VideoDecoder_RequestTextures, OnPluginMsgRequestTextures)
357 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
358 PpapiPluginMsg_VideoDecoder_PictureReady, OnPluginMsgPictureReady)
359 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
360 PpapiPluginMsg_VideoDecoder_DismissPicture, OnPluginMsgDismissPicture)
361 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
362 PpapiPluginMsg_VideoDecoder_NotifyError, OnPluginMsgNotifyError)
363 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
364 PluginResource::OnReplyReceived(params, msg))
365 PPAPI_END_MESSAGE_MAP()
366}
367
368void VideoDecoderResource::SetForTest() {
369 testing_ = true;
370}
371
372void VideoDecoderResource::OnPluginMsgRequestTextures(
373 const ResourceMessageReplyParams& params,
374 uint32_t num_textures,
375 const PP_Size& size,
[email protected]0ff052d2014-06-13 15:00:14376 uint32_t texture_target,
377 const std::vector<gpu::Mailbox>& mailboxes) {
[email protected]dfb0d06f32014-05-30 22:45:56378 DCHECK(num_textures);
lpique9dd55e542015-08-20 01:06:53379 DCHECK(num_textures >= min_picture_count_);
[email protected]0ff052d2014-06-13 15:00:14380 DCHECK(mailboxes.empty() || mailboxes.size() == num_textures);
[email protected]dfb0d06f32014-05-30 22:45:56381 std::vector<uint32_t> texture_ids(num_textures);
382 if (gles2_impl_) {
383 gles2_impl_->GenTextures(num_textures, &texture_ids.front());
384 for (uint32_t i = 0; i < num_textures; ++i) {
385 gles2_impl_->ActiveTexture(GL_TEXTURE0);
386 gles2_impl_->BindTexture(texture_target, texture_ids[i]);
387 gles2_impl_->TexParameteri(
CodeByThePoundde2d83972015-04-30 20:41:47388 texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
[email protected]dfb0d06f32014-05-30 22:45:56389 gles2_impl_->TexParameteri(
CodeByThePoundde2d83972015-04-30 20:41:47390 texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
[email protected]dfb0d06f32014-05-30 22:45:56391 gles2_impl_->TexParameterf(
392 texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
393 gles2_impl_->TexParameterf(
394 texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
395
396 if (texture_target == GL_TEXTURE_2D) {
397 gles2_impl_->TexImage2D(texture_target,
398 0,
399 GL_RGBA,
400 size.width,
401 size.height,
402 0,
403 GL_RGBA,
404 GL_UNSIGNED_BYTE,
405 NULL);
406 }
[email protected]0ff052d2014-06-13 15:00:14407 if (!mailboxes.empty()) {
408 gles2_impl_->ProduceTextureCHROMIUM(
409 GL_TEXTURE_2D, reinterpret_cast<const GLbyte*>(mailboxes[i].name));
410 }
[email protected]dfb0d06f32014-05-30 22:45:56411
412 textures_.insert(
413 std::make_pair(texture_ids[i], Texture(texture_target, size)));
414 }
415 gles2_impl_->Flush();
416 } else {
417 DCHECK(testing_);
418 // Create some fake texture ids so we can test picture handling.
419 for (uint32_t i = 0; i < num_textures; ++i) {
420 texture_ids[i] = i + 1;
421 textures_.insert(
422 std::make_pair(texture_ids[i], Texture(texture_target, size)));
423 }
424 }
425
426 Post(RENDERER, PpapiHostMsg_VideoDecoder_AssignTextures(size, texture_ids));
427}
428
429void VideoDecoderResource::OnPluginMsgPictureReady(
430 const ResourceMessageReplyParams& params,
431 int32_t decode_id,
Bill Budge2d4bf3a2014-11-06 22:31:21432 uint32_t texture_id,
433 const PP_Rect& visible_rect) {
434 received_pictures_.push(Picture(decode_id, texture_id, visible_rect));
[email protected]dfb0d06f32014-05-30 22:45:56435
436 if (TrackedCallback::IsPending(get_picture_callback_)) {
437 // The plugin may call GetPicture in its callback.
438 scoped_refptr<TrackedCallback> callback;
439 callback.swap(get_picture_callback_);
Bill Budge2d4bf3a2014-11-06 22:31:21440 WriteNextPicture();
[email protected]dfb0d06f32014-05-30 22:45:56441 callback->Run(PP_OK);
442 }
443}
444
445void VideoDecoderResource::OnPluginMsgDismissPicture(
446 const ResourceMessageReplyParams& params,
447 uint32_t texture_id) {
448 DeleteGLTexture(texture_id);
449 textures_.erase(texture_id);
450}
451
452void VideoDecoderResource::OnPluginMsgNotifyError(
453 const ResourceMessageReplyParams& params,
454 int32_t error) {
455 decoder_last_error_ = error;
456 // Cause any pending callbacks to run immediately. Reentrancy isn't a problem,
457 // since the plugin wasn't calling us.
458 RunCallbackWithError(&initialize_callback_);
459 RunCallbackWithError(&decode_callback_);
460 RunCallbackWithError(&get_picture_callback_);
461 RunCallbackWithError(&flush_callback_);
462 RunCallbackWithError(&reset_callback_);
463}
464
465void VideoDecoderResource::OnPluginMsgInitializeComplete(
466 const ResourceMessageReplyParams& params) {
467 decoder_last_error_ = params.result();
468 if (decoder_last_error_ == PP_OK)
469 initialized_ = true;
470
471 // Let the plugin call Initialize again from its callback in case of failure.
472 scoped_refptr<TrackedCallback> callback;
473 callback.swap(initialize_callback_);
474 callback->Run(decoder_last_error_);
475}
476
477void VideoDecoderResource::OnPluginMsgDecodeComplete(
478 const ResourceMessageReplyParams& params,
479 uint32_t shm_id) {
480 if (shm_id >= shm_buffers_.size()) {
481 NOTREACHED();
482 return;
483 }
484 // Make the shm buffer available.
avi9bf17492017-07-10 02:19:38485 available_shm_buffers_.push_back(shm_buffers_[shm_id].get());
[email protected]dfb0d06f32014-05-30 22:45:56486 // If the plugin is waiting, let it call Decode again.
Daniel Cheng6d3ae972014-08-26 00:27:38487 if (decode_callback_.get()) {
[email protected]dfb0d06f32014-05-30 22:45:56488 scoped_refptr<TrackedCallback> callback;
489 callback.swap(decode_callback_);
490 callback->Run(PP_OK);
491 }
492}
493
494void VideoDecoderResource::OnPluginMsgFlushComplete(
495 const ResourceMessageReplyParams& params) {
496 // All shm buffers should have been made available by now.
497 DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size());
498
Daniel Cheng6d3ae972014-08-26 00:27:38499 if (get_picture_callback_.get()) {
[email protected]dfb0d06f32014-05-30 22:45:56500 scoped_refptr<TrackedCallback> callback;
501 callback.swap(get_picture_callback_);
502 callback->Abort();
503 }
504
505 scoped_refptr<TrackedCallback> callback;
506 callback.swap(flush_callback_);
507 callback->Run(params.result());
508}
509
510void VideoDecoderResource::OnPluginMsgResetComplete(
511 const ResourceMessageReplyParams& params) {
512 // All shm buffers should have been made available by now.
513 DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size());
[email protected]7ee85d62014-07-16 20:24:01514 // Recycle any pictures which haven't been passed to the plugin.
515 while (!received_pictures_.empty()) {
516 Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture(
517 received_pictures_.front().texture_id));
[email protected]e9fc71c12014-06-16 22:01:20518 received_pictures_.pop();
[email protected]7ee85d62014-07-16 20:24:01519 }
[email protected]e9fc71c12014-06-16 22:01:20520
[email protected]dfb0d06f32014-05-30 22:45:56521 scoped_refptr<TrackedCallback> callback;
522 callback.swap(reset_callback_);
523 callback->Run(params.result());
524}
525
526void VideoDecoderResource::RunCallbackWithError(
527 scoped_refptr<TrackedCallback>* callback) {
528 if (TrackedCallback::IsPending(*callback)) {
529 scoped_refptr<TrackedCallback> temp;
530 callback->swap(temp);
531 temp->Run(decoder_last_error_);
532 }
533}
534
535void VideoDecoderResource::DeleteGLTexture(uint32_t id) {
536 if (gles2_impl_) {
537 gles2_impl_->DeleteTextures(1, &id);
538 gles2_impl_->Flush();
539 }
540}
541
Bill Budge2d4bf3a2014-11-06 22:31:21542void VideoDecoderResource::WriteNextPicture() {
[email protected]dfb0d06f32014-05-30 22:45:56543 DCHECK(!received_pictures_.empty());
544 Picture& picture = received_pictures_.front();
Bill Budge2d4bf3a2014-11-06 22:31:21545
[email protected]dfb0d06f32014-05-30 22:45:56546 // Internally, we identify decodes by a unique id, which the host returns
547 // to us in the picture. Use this to get the plugin's decode_id.
Bill Budge2d4bf3a2014-11-06 22:31:21548 uint32_t decode_id = decode_ids_[picture.decode_id % kMaximumPictureDelay];
549 uint32_t texture_id = picture.texture_id;
550 uint32_t texture_target = 0;
551 PP_Size texture_size = PP_MakeSize(0, 0);
[email protected]dfb0d06f32014-05-30 22:45:56552 TextureMap::iterator it = textures_.find(picture.texture_id);
553 if (it != textures_.end()) {
Bill Budge2d4bf3a2014-11-06 22:31:21554 texture_target = it->second.texture_target;
555 texture_size = it->second.size;
[email protected]dfb0d06f32014-05-30 22:45:56556 } else {
557 NOTREACHED();
558 }
Bill Budge2d4bf3a2014-11-06 22:31:21559
560 if (get_picture_) {
561 DCHECK(!get_picture_0_1_);
562 get_picture_->decode_id = decode_id;
563 get_picture_->texture_id = texture_id;
564 get_picture_->texture_target = texture_target;
565 get_picture_->texture_size = texture_size;
566 get_picture_->visible_rect = picture.visible_rect;
567 get_picture_ = NULL;
568 } else {
569 DCHECK(get_picture_0_1_);
570 get_picture_0_1_->decode_id = decode_id;
571 get_picture_0_1_->texture_id = texture_id;
572 get_picture_0_1_->texture_target = texture_target;
573 get_picture_0_1_->texture_size = texture_size;
574 get_picture_0_1_ = NULL;
575 }
576
[email protected]dfb0d06f32014-05-30 22:45:56577 received_pictures_.pop();
578}
579
580} // namespace proxy
581} // namespace ppapi