146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// found in the LICENSE file.
446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/proxy/video_decoder_resource.h"
646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/bind.h"
846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "gpu/command_buffer/client/gles2_cmd_helper.h"
946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "gpu/command_buffer/client/gles2_implementation.h"
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "gpu/command_buffer/common/mailbox.h"
1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ipc/ipc_message.h"
1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/c/pp_errors.h"
1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/c/ppb_opengles2.h"
1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/proxy/plugin_dispatcher.h"
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/proxy/ppb_graphics_3d_proxy.h"
1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/proxy/serialized_handle.h"
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/proxy/video_decoder_constants.h"
1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h"
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h"
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/shared_impl/resource_tracker.h"
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ppapi/thunk/enter.h"
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using ppapi::thunk::EnterResourceNoLock;
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using ppapi::thunk::PPB_Graphics3D_API;
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using ppapi::thunk::PPB_VideoDecoder_API;
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace ppapi {
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace proxy {
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)VideoDecoderResource::ShmBuffer::ShmBuffer(
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<base::SharedMemory> shm_ptr,
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    uint32_t size,
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    uint32_t shm_id)
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : shm(shm_ptr.Pass()), addr(NULL), shm_id(shm_id) {
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (shm->Map(size))
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    addr = shm->memory();
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)VideoDecoderResource::ShmBuffer::~ShmBuffer() {
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)VideoDecoderResource::Texture::Texture(uint32_t texture_target,
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                       const PP_Size& size)
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : texture_target(texture_target), size(size) {
4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)VideoDecoderResource::Texture::~Texture() {
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)VideoDecoderResource::Picture::Picture(int32_t decode_id, uint32_t texture_id)
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : decode_id(decode_id), texture_id(texture_id) {
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)VideoDecoderResource::Picture::~Picture() {
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)VideoDecoderResource::VideoDecoderResource(Connection connection,
6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                           PP_Instance instance)
6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : PluginResource(connection, instance),
6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      num_decodes_(0),
6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      get_picture_(NULL),
6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      gles2_impl_(NULL),
6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      initialized_(false),
6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      testing_(false),
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Set |decoder_last_error_| to PP_OK after successful initialization.
6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // This makes error checking a little more concise, since we can check
6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // that the decoder has been initialized and hasn't returned an error by
7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // just testing |decoder_last_error_|.
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      decoder_last_error_(PP_ERROR_FAILED) {
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Clear the decode_ids_ array.
7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  memset(decode_ids_, 0, arraysize(decode_ids_));
7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SendCreate(RENDERER, PpapiHostMsg_VideoDecoder_Create());
7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)VideoDecoderResource::~VideoDecoderResource() {
7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Destroy any textures which haven't been dismissed.
7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  TextureMap::iterator it = textures_.begin();
8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (; it != textures_.end(); ++it)
8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DeleteGLTexture(it->first);
8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)PPB_VideoDecoder_API* VideoDecoderResource::AsPPB_VideoDecoder_API() {
8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return this;
8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint32_t VideoDecoderResource::Initialize0_1(
8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PP_Resource graphics_context,
9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PP_VideoProfile profile,
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PP_Bool allow_software_fallback,
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return Initialize(graphics_context,
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    profile,
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    allow_software_fallback
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        ? PP_HARDWAREACCELERATION_WITHFALLBACK
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        : PP_HARDWAREACCELERATION_ONLY,
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    callback);
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint32_t VideoDecoderResource::Initialize(
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PP_Resource graphics_context,
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PP_VideoProfile profile,
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PP_HardwareAcceleration acceleration,
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_refptr<TrackedCallback> callback) {
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (initialized_)
10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_FAILED;
10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (profile < 0 || profile > PP_VIDEOPROFILE_MAX)
10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_BADARGUMENT;
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (initialize_callback_.get())
11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_INPROGRESS;
11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!graphics_context)
11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_BADRESOURCE;
11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  HostResource host_resource;
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!testing_) {
11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Create a new Graphics3D resource that can create texture resources to
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // share with the plugin. We can't use the plugin's Graphics3D, since we
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // create textures on a proxy thread, and would interfere with the plugin.
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    thunk::EnterResourceCreationNoLock enter_create(pp_instance());
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (enter_create.failed())
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return PP_ERROR_FAILED;
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int32_t attrib_list[] = {PP_GRAPHICS3DATTRIB_NONE};
12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    graphics3d_ =
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        ScopedPPResource(ScopedPPResource::PassRef(),
12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                         enter_create.functions()->CreateGraphics3D(
12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                             pp_instance(), graphics_context, attrib_list));
12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    EnterResourceNoLock<PPB_Graphics3D_API> enter_graphics(graphics3d_.get(),
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                           false);
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (enter_graphics.failed())
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return PP_ERROR_BADRESOURCE;
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PPB_Graphics3D_Shared* ppb_graphics3d_shared =
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        static_cast<PPB_Graphics3D_Shared*>(enter_graphics.object());
13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    gles2_impl_ = ppb_graphics3d_shared->gles2_impl();
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    host_resource = ppb_graphics3d_shared->host_resource();
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  initialize_callback_ = callback;
14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  Call<PpapiPluginMsg_VideoDecoder_InitializeReply>(
14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      RENDERER,
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      PpapiHostMsg_VideoDecoder_Initialize(
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          host_resource, profile, acceleration),
14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&VideoDecoderResource::OnPluginMsgInitializeComplete, this));
14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int32_t VideoDecoderResource::Decode(uint32_t decode_id,
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                     uint32_t size,
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                     const void* buffer,
15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                     scoped_refptr<TrackedCallback> callback) {
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (decoder_last_error_)
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return decoder_last_error_;
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (flush_callback_.get() || reset_callback_.get())
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_FAILED;
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (decode_callback_.get())
15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_INPROGRESS;
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (size > kMaximumBitstreamBufferSize)
16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_NOMEMORY;
16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If we allow the plugin to call Decode again, we must have somewhere to
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // copy their buffer.
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!available_shm_buffers_.empty() ||
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         shm_buffers_.size() < kMaximumPendingDecodes);
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Count up, wrapping back to 0 before overflowing.
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int32_t uid = ++num_decodes_;
17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (uid == std::numeric_limits<int32_t>::max())
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    num_decodes_ = 0;
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Save decode_id in a ring buffer. The ring buffer is sized to store
17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // decode_id for the maximum picture delay.
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  decode_ids_[uid % kMaximumPictureDelay] = decode_id;
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (available_shm_buffers_.empty() ||
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      available_shm_buffers_.back()->shm->mapped_size() < size) {
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    uint32_t shm_id;
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (shm_buffers_.size() < kMaximumPendingDecodes) {
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Signal the host to create a new shm buffer by passing an index outside
18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // the legal range.
18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      shm_id = static_cast<uint32_t>(shm_buffers_.size());
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    } else {
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Signal the host to grow a buffer by passing a legal index. Choose the
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // last available shm buffer for simplicity.
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      shm_id = available_shm_buffers_.back()->shm_id;
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      available_shm_buffers_.pop_back();
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Synchronously get shared memory. Use GenericSyncCall so we can get the
19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // reply params, which contain the handle.
19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    uint32_t shm_size = 0;
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    IPC::Message reply;
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ResourceMessageReplyParams reply_params;
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int32_t result =
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        GenericSyncCall(RENDERER,
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        PpapiHostMsg_VideoDecoder_GetShm(shm_id, size),
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        &reply,
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        &reply_params);
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (result != PP_OK)
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return PP_ERROR_FAILED;
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (!UnpackMessage<PpapiPluginMsg_VideoDecoder_GetShmReply>(reply,
20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                                                &shm_size))
20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return PP_ERROR_FAILED;
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::SharedMemoryHandle shm_handle = base::SharedMemory::NULLHandle();
20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (!reply_params.TakeSharedMemoryHandleAtIndex(0, &shm_handle))
20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return PP_ERROR_NOMEMORY;
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<base::SharedMemory> shm(
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        new base::SharedMemory(shm_handle, false /* read_only */));
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<ShmBuffer> shm_buffer(
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        new ShmBuffer(shm.Pass(), shm_size, shm_id));
21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (!shm_buffer->addr)
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return PP_ERROR_NOMEMORY;
21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    available_shm_buffers_.push_back(shm_buffer.get());
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (shm_buffers_.size() < kMaximumPendingDecodes) {
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      shm_buffers_.push_back(shm_buffer.release());
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    } else {
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Delete manually since ScopedVector won't delete the existing element if
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // we just assign it.
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      delete shm_buffers_[shm_id];
22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      shm_buffers_[shm_id] = shm_buffer.release();
22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // At this point we should have shared memory to hold the plugin's buffer.
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!available_shm_buffers_.empty() &&
22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         available_shm_buffers_.back()->shm->mapped_size() >= size);
23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ShmBuffer* shm_buffer = available_shm_buffers_.back();
23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  available_shm_buffers_.pop_back();
23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  memcpy(shm_buffer->addr, buffer, size);
23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  Call<PpapiPluginMsg_VideoDecoder_DecodeReply>(
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      RENDERER,
23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      PpapiHostMsg_VideoDecoder_Decode(shm_buffer->shm_id, size, uid),
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&VideoDecoderResource::OnPluginMsgDecodeComplete, this));
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If we have another free buffer, or we can still create new buffers, let
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // the plugin call Decode again.
24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!available_shm_buffers_.empty() ||
24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      shm_buffers_.size() < kMaximumPendingDecodes)
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_OK;
24546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // All buffers are busy and we can't create more. Delay completion until a
24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // buffer is available.
24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  decode_callback_ = callback;
24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int32_t VideoDecoderResource::GetPicture(
25346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PP_VideoPicture* picture,
25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (decoder_last_error_)
25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return decoder_last_error_;
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (reset_callback_.get())
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_FAILED;
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (get_picture_callback_.get())
26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_INPROGRESS;
26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
26246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If the next picture is ready, return it synchronously.
26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!received_pictures_.empty()) {
26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    WriteNextPicture(picture);
26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_OK;
26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  get_picture_callback_ = callback;
26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  get_picture_ = picture;
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::RecyclePicture(const PP_VideoPicture* picture) {
27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (decoder_last_error_)
27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture(picture->texture_id));
27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int32_t VideoDecoderResource::Flush(scoped_refptr<TrackedCallback> callback) {
28146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (decoder_last_error_)
28246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return decoder_last_error_;
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (reset_callback_.get())
28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_FAILED;
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (flush_callback_.get())
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_INPROGRESS;
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  flush_callback_ = callback;
28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  Call<PpapiPluginMsg_VideoDecoder_FlushReply>(
29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      RENDERER,
29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      PpapiHostMsg_VideoDecoder_Flush(),
29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&VideoDecoderResource::OnPluginMsgFlushComplete, this));
29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int32_t VideoDecoderResource::Reset(scoped_refptr<TrackedCallback> callback) {
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (decoder_last_error_)
29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return decoder_last_error_;
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (flush_callback_.get())
30146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_FAILED;
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (reset_callback_.get())
30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return PP_ERROR_INPROGRESS;
30446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  reset_callback_ = callback;
30546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
30646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Cause any pending Decode or GetPicture callbacks to abort after we return,
30746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // to avoid reentering the plugin.
30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (TrackedCallback::IsPending(decode_callback_))
30946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    decode_callback_->PostAbort();
31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  decode_callback_ = NULL;
31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (TrackedCallback::IsPending(get_picture_callback_))
31246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    get_picture_callback_->PostAbort();
31346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  get_picture_callback_ = NULL;
31446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  Call<PpapiPluginMsg_VideoDecoder_ResetReply>(
31546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      RENDERER,
31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      PpapiHostMsg_VideoDecoder_Reset(),
31746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&VideoDecoderResource::OnPluginMsgResetComplete, this));
31846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
31946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
32046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
32146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
32246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::OnReplyReceived(
32346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ResourceMessageReplyParams& params,
32446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const IPC::Message& msg) {
32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  PPAPI_BEGIN_MESSAGE_MAP(VideoDecoderResource, msg)
32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        PpapiPluginMsg_VideoDecoder_RequestTextures, OnPluginMsgRequestTextures)
32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        PpapiPluginMsg_VideoDecoder_PictureReady, OnPluginMsgPictureReady)
33046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
33146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        PpapiPluginMsg_VideoDecoder_DismissPicture, OnPluginMsgDismissPicture)
33246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
33346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        PpapiPluginMsg_VideoDecoder_NotifyError, OnPluginMsgNotifyError)
33446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
33546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        PluginResource::OnReplyReceived(params, msg))
33646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  PPAPI_END_MESSAGE_MAP()
33746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
33846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::SetForTest() {
34046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  testing_ = true;
34146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
34246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
34346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::OnPluginMsgRequestTextures(
34446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ResourceMessageReplyParams& params,
34546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    uint32_t num_textures,
34646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const PP_Size& size,
347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    uint32_t texture_target,
348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::vector<gpu::Mailbox>& mailboxes) {
34946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(num_textures);
350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(mailboxes.empty() || mailboxes.size() == num_textures);
35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::vector<uint32_t> texture_ids(num_textures);
35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (gles2_impl_) {
35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    gles2_impl_->GenTextures(num_textures, &texture_ids.front());
35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (uint32_t i = 0; i < num_textures; ++i) {
35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      gles2_impl_->ActiveTexture(GL_TEXTURE0);
35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      gles2_impl_->BindTexture(texture_target, texture_ids[i]);
35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      gles2_impl_->TexParameteri(
35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      gles2_impl_->TexParameteri(
36046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
36146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      gles2_impl_->TexParameterf(
36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      gles2_impl_->TexParameterf(
36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
36546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
36646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (texture_target == GL_TEXTURE_2D) {
36746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        gles2_impl_->TexImage2D(texture_target,
36846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                0,
36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                GL_RGBA,
37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                size.width,
37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                size.height,
37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                0,
37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                GL_RGBA,
37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                GL_UNSIGNED_BYTE,
37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                NULL);
37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (!mailboxes.empty()) {
378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        gles2_impl_->ProduceTextureCHROMIUM(
379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            GL_TEXTURE_2D, reinterpret_cast<const GLbyte*>(mailboxes[i].name));
380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
38246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      textures_.insert(
38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          std::make_pair(texture_ids[i], Texture(texture_target, size)));
38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    gles2_impl_->Flush();
38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else {
38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK(testing_);
38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Create some fake texture ids so we can test picture handling.
38946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (uint32_t i = 0; i < num_textures; ++i) {
39046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      texture_ids[i] = i + 1;
39146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      textures_.insert(
39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          std::make_pair(texture_ids[i], Texture(texture_target, size)));
39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
39546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  Post(RENDERER, PpapiHostMsg_VideoDecoder_AssignTextures(size, texture_ids));
39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
39846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::OnPluginMsgPictureReady(
40046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ResourceMessageReplyParams& params,
40146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int32_t decode_id,
40246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    uint32_t texture_id) {
40346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  received_pictures_.push(Picture(decode_id, texture_id));
40446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (TrackedCallback::IsPending(get_picture_callback_)) {
40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // The plugin may call GetPicture in its callback.
40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback;
40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    callback.swap(get_picture_callback_);
40946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    PP_VideoPicture* picture = get_picture_;
41046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    get_picture_ = NULL;
41146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    WriteNextPicture(picture);
41246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    callback->Run(PP_OK);
41346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
41446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
41546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::OnPluginMsgDismissPicture(
41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ResourceMessageReplyParams& params,
41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    uint32_t texture_id) {
41946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DeleteGLTexture(texture_id);
42046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  textures_.erase(texture_id);
42146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
42246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
42346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::OnPluginMsgNotifyError(
42446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ResourceMessageReplyParams& params,
42546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int32_t error) {
42646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  decoder_last_error_ = error;
42746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Cause any pending callbacks to run immediately. Reentrancy isn't a problem,
42846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // since the plugin wasn't calling us.
42946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  RunCallbackWithError(&initialize_callback_);
43046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  RunCallbackWithError(&decode_callback_);
43146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  RunCallbackWithError(&get_picture_callback_);
43246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  RunCallbackWithError(&flush_callback_);
43346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  RunCallbackWithError(&reset_callback_);
43446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
43546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
43646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::OnPluginMsgInitializeComplete(
43746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ResourceMessageReplyParams& params) {
43846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  decoder_last_error_ = params.result();
43946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (decoder_last_error_ == PP_OK)
44046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    initialized_ = true;
44146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
44246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Let the plugin call Initialize again from its callback in case of failure.
44346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_refptr<TrackedCallback> callback;
44446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callback.swap(initialize_callback_);
44546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callback->Run(decoder_last_error_);
44646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
44746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
44846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::OnPluginMsgDecodeComplete(
44946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ResourceMessageReplyParams& params,
45046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    uint32_t shm_id) {
45146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (shm_id >= shm_buffers_.size()) {
45246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    NOTREACHED();
45346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
45446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
45546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Make the shm buffer available.
45646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  available_shm_buffers_.push_back(shm_buffers_[shm_id]);
45746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If the plugin is waiting, let it call Decode again.
4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (decode_callback_.get()) {
45946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback;
46046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    callback.swap(decode_callback_);
46146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    callback->Run(PP_OK);
46246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
46346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
46446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
46546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::OnPluginMsgFlushComplete(
46646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ResourceMessageReplyParams& params) {
46746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // All shm buffers should have been made available by now.
46846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size());
46946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (get_picture_callback_.get()) {
47146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback;
47246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    callback.swap(get_picture_callback_);
47346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    callback->Abort();
47446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
47546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
47646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_refptr<TrackedCallback> callback;
47746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callback.swap(flush_callback_);
47846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callback->Run(params.result());
47946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
48046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
48146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::OnPluginMsgResetComplete(
48246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ResourceMessageReplyParams& params) {
48346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // All shm buffers should have been made available by now.
48446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size());
485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Recycle any pictures which haven't been passed to the plugin.
486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  while (!received_pictures_.empty()) {
487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture(
488116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        received_pictures_.front().texture_id));
489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    received_pictures_.pop();
490116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
49246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_refptr<TrackedCallback> callback;
49346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callback.swap(reset_callback_);
49446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callback->Run(params.result());
49546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
49646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
49746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::RunCallbackWithError(
49846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<TrackedCallback>* callback) {
49946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (TrackedCallback::IsPending(*callback)) {
50046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<TrackedCallback> temp;
50146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    callback->swap(temp);
50246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    temp->Run(decoder_last_error_);
50346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
50446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
50546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
50646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::DeleteGLTexture(uint32_t id) {
50746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (gles2_impl_) {
50846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    gles2_impl_->DeleteTextures(1, &id);
50946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    gles2_impl_->Flush();
51046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
51146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
51246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
51346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoDecoderResource::WriteNextPicture(PP_VideoPicture* pp_picture) {
51446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!received_pictures_.empty());
51546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  Picture& picture = received_pictures_.front();
51646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Internally, we identify decodes by a unique id, which the host returns
51746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // to us in the picture. Use this to get the plugin's decode_id.
51846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pp_picture->decode_id = decode_ids_[picture.decode_id % kMaximumPictureDelay];
51946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pp_picture->texture_id = picture.texture_id;
52046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  TextureMap::iterator it = textures_.find(picture.texture_id);
52146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (it != textures_.end()) {
52246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    pp_picture->texture_target = it->second.texture_target;
52346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    pp_picture->texture_size = it->second.size;
52446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else {
52546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    NOTREACHED();
52646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
52746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  received_pictures_.pop();
52846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
52946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
53046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace proxy
53146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace ppapi
532