// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/proxy/video_decoder_resource.h"

#include <utility>

#include "base/bind.h"
#include "gpu/command_buffer/client/gles2_cmd_helper.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "ipc/ipc_message.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_opengles2.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_graphics_3d_proxy.h"
#include "ppapi/proxy/serialized_handle.h"
#include "ppapi/proxy/video_decoder_constants.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/thunk/enter.h"

using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_Graphics3D_API;
using ppapi::thunk::PPB_VideoDecoder_API;

namespace ppapi {
namespace proxy {

VideoDecoderResource::ShmBuffer::ShmBuffer(
    std::unique_ptr<base::SharedMemory> shm_ptr,
    uint32_t size,
    uint32_t shm_id)
    : shm(std::move(shm_ptr)), addr(NULL), shm_id(shm_id) {
  if (shm->Map(size))
    addr = shm->memory();
}

VideoDecoderResource::ShmBuffer::~ShmBuffer() {
}

VideoDecoderResource::Texture::Texture(uint32_t texture_target,
                                       const PP_Size& size)
    : texture_target(texture_target), size(size) {
}

VideoDecoderResource::Texture::~Texture() {
}

VideoDecoderResource::Picture::Picture(int32_t decode_id,
                                       uint32_t texture_id,
                                       const PP_Rect& visible_rect)
    : decode_id(decode_id), texture_id(texture_id), visible_rect(visible_rect) {
}

VideoDecoderResource::Picture::~Picture() {
}

VideoDecoderResource::VideoDecoderResource(Connection connection,
                                           PP_Instance instance)
    : PluginResource(connection, instance),
      num_decodes_(0),
      min_picture_count_(0),
      get_picture_(NULL),
      get_picture_0_1_(NULL),
      gles2_impl_(NULL),
      initialized_(false),
      testing_(false),
      // Set |decoder_last_error_| to PP_OK after successful initialization.
      // This makes error checking a little more concise, since we can check
      // that the decoder has been initialized and hasn't returned an error by
      // just testing |decoder_last_error_|.
      decoder_last_error_(PP_ERROR_FAILED) {
  // Clear the decode_ids_ array.
  memset(decode_ids_, 0, sizeof(decode_ids_));
  SendCreate(RENDERER, PpapiHostMsg_VideoDecoder_Create());
}

VideoDecoderResource::~VideoDecoderResource() {
  // Destroy any textures which haven't been dismissed.
  TextureMap::iterator it = textures_.begin();
  for (; it != textures_.end(); ++it)
    DeleteGLTexture(it->first);
}

PPB_VideoDecoder_API* VideoDecoderResource::AsPPB_VideoDecoder_API() {
  return this;
}

int32_t VideoDecoderResource::Initialize0_1(
    PP_Resource graphics_context,
    PP_VideoProfile profile,
    PP_Bool allow_software_fallback,
    scoped_refptr<TrackedCallback> callback) {
  return Initialize(graphics_context,
                    profile,
                    allow_software_fallback
                        ? PP_HARDWAREACCELERATION_WITHFALLBACK
                        : PP_HARDWAREACCELERATION_ONLY,
                    0,
                    callback);
}

int32_t VideoDecoderResource::Initialize0_2(
    PP_Resource graphics_context,
    PP_VideoProfile profile,
    PP_HardwareAcceleration acceleration,
    scoped_refptr<TrackedCallback> callback) {
  return Initialize(graphics_context,
                    profile,
                    acceleration,
                    0,
                    callback);
}

int32_t VideoDecoderResource::Initialize(
    PP_Resource graphics_context,
    PP_VideoProfile profile,
    PP_HardwareAcceleration acceleration,
    uint32_t min_picture_count,
    scoped_refptr<TrackedCallback> callback) {
  if (initialized_)
    return PP_ERROR_FAILED;
  if (profile < 0 || profile > PP_VIDEOPROFILE_MAX)
    return PP_ERROR_BADARGUMENT;
  if (min_picture_count > kMaximumPictureCount)
    return PP_ERROR_BADARGUMENT;
  if (initialize_callback_.get())
    return PP_ERROR_INPROGRESS;
  if (!graphics_context)
    return PP_ERROR_BADRESOURCE;

  min_picture_count_ = min_picture_count;

  HostResource host_resource;
  if (!testing_) {
    // Create a new Graphics3D resource that can create texture resources to
    // share with the plugin. We can't use the plugin's Graphics3D, since we
    // create textures on a proxy thread, and would interfere with the plugin.
    thunk::EnterResourceCreationNoLock enter_create(pp_instance());
    if (enter_create.failed())
      return PP_ERROR_FAILED;
    int32_t attrib_list[] = {PP_GRAPHICS3DATTRIB_NONE};
    graphics3d_ =
        ScopedPPResource(ScopedPPResource::PassRef(),
                         enter_create.functions()->CreateGraphics3D(
                             pp_instance(), graphics_context, attrib_list));
    EnterResourceNoLock<PPB_Graphics3D_API> enter_graphics(graphics3d_.get(),
                                                           false);
    if (enter_graphics.failed())
      return PP_ERROR_BADRESOURCE;

    PPB_Graphics3D_Shared* ppb_graphics3d_shared =
        static_cast<PPB_Graphics3D_Shared*>(enter_graphics.object());
    gles2_impl_ = ppb_graphics3d_shared->gles2_impl();
    host_resource = ppb_graphics3d_shared->host_resource();
  }

  initialize_callback_ = callback;

  Call<PpapiPluginMsg_VideoDecoder_InitializeReply>(
      RENDERER,
      PpapiHostMsg_VideoDecoder_Initialize(
          host_resource, profile, acceleration, min_picture_count),
      base::Bind(&VideoDecoderResource::OnPluginMsgInitializeComplete, this));

  return PP_OK_COMPLETIONPENDING;
}

int32_t VideoDecoderResource::Decode(uint32_t decode_id,
                                     uint32_t size,
                                     const void* buffer,
                                     scoped_refptr<TrackedCallback> callback) {
  if (decoder_last_error_)
    return decoder_last_error_;
  if (flush_callback_.get() || reset_callback_.get())
    return PP_ERROR_FAILED;
  if (decode_callback_.get())
    return PP_ERROR_INPROGRESS;
  if (size > kMaximumBitstreamBufferSize)
    return PP_ERROR_NOMEMORY;

  // If we allow the plugin to call Decode again, we must have somewhere to
  // copy their buffer.
  DCHECK(!available_shm_buffers_.empty() ||
         shm_buffers_.size() < kMaximumPendingDecodes);

  // Count up, wrapping back to 0 before overflowing.
  int32_t uid = ++num_decodes_;
  if (uid == std::numeric_limits<int32_t>::max())
    num_decodes_ = 0;

  // Save decode_id in a ring buffer. The ring buffer is sized to store
  // decode_id for the maximum picture delay.
  decode_ids_[uid % kMaximumPictureDelay] = decode_id;

  if (available_shm_buffers_.empty() ||
      available_shm_buffers_.back()->shm->mapped_size() < size) {
    uint32_t shm_id;
    if (shm_buffers_.size() < kMaximumPendingDecodes) {
      // Signal the host to create a new shm buffer by passing an index outside
      // the legal range.
      shm_id = static_cast<uint32_t>(shm_buffers_.size());
    } else {
      // Signal the host to grow a buffer by passing a legal index. Choose the
      // last available shm buffer for simplicity.
      shm_id = available_shm_buffers_.back()->shm_id;
      available_shm_buffers_.pop_back();
    }

    // Synchronously get shared memory. Use GenericSyncCall so we can get the
    // reply params, which contain the handle.
    uint32_t shm_size = 0;
    IPC::Message reply;
    ResourceMessageReplyParams reply_params;
    int32_t result =
        GenericSyncCall(RENDERER,
                        PpapiHostMsg_VideoDecoder_GetShm(shm_id, size),
                        &reply,
                        &reply_params);
    if (result != PP_OK)
      return PP_ERROR_FAILED;
    if (!UnpackMessage<PpapiPluginMsg_VideoDecoder_GetShmReply>(reply,
                                                                &shm_size))
      return PP_ERROR_FAILED;
    base::SharedMemoryHandle shm_handle;
    if (!reply_params.TakeSharedMemoryHandleAtIndex(0, &shm_handle))
      return PP_ERROR_NOMEMORY;
    std::unique_ptr<base::SharedMemory> shm(
        new base::SharedMemory(shm_handle, false /* read_only */));
    std::unique_ptr<ShmBuffer> shm_buffer(
        new ShmBuffer(std::move(shm), shm_size, shm_id));
    if (!shm_buffer->addr)
      return PP_ERROR_NOMEMORY;

    available_shm_buffers_.push_back(shm_buffer.get());
    if (shm_buffers_.size() < kMaximumPendingDecodes) {
      shm_buffers_.push_back(shm_buffer.release());
    } else {
      // Delete manually since ScopedVector won't delete the existing element if
      // we just assign it.
      delete shm_buffers_[shm_id];
      shm_buffers_[shm_id] = shm_buffer.release();
    }
  }

  // At this point we should have shared memory to hold the plugin's buffer.
  DCHECK(!available_shm_buffers_.empty() &&
         available_shm_buffers_.back()->shm->mapped_size() >= size);

  ShmBuffer* shm_buffer = available_shm_buffers_.back();
  available_shm_buffers_.pop_back();
  memcpy(shm_buffer->addr, buffer, size);

  Call<PpapiPluginMsg_VideoDecoder_DecodeReply>(
      RENDERER,
      PpapiHostMsg_VideoDecoder_Decode(shm_buffer->shm_id, size, uid),
      base::Bind(&VideoDecoderResource::OnPluginMsgDecodeComplete, this));

  // If we have another free buffer, or we can still create new buffers, let
  // the plugin call Decode again.
  if (!available_shm_buffers_.empty() ||
      shm_buffers_.size() < kMaximumPendingDecodes)
    return PP_OK;

  // All buffers are busy and we can't create more. Delay completion until a
  // buffer is available.
  decode_callback_ = callback;
  return PP_OK_COMPLETIONPENDING;
}

int32_t VideoDecoderResource::GetPicture0_1(
    PP_VideoPicture_0_1* picture,
    scoped_refptr<TrackedCallback> callback) {
  get_picture_0_1_ = picture;
  return GetPicture(NULL, callback);
}

int32_t VideoDecoderResource::GetPicture(
    PP_VideoPicture* picture,
    scoped_refptr<TrackedCallback> callback) {
  if (decoder_last_error_)
    return decoder_last_error_;
  if (reset_callback_.get())
    return PP_ERROR_FAILED;
  if (get_picture_callback_.get())
    return PP_ERROR_INPROGRESS;

  get_picture_ = picture;

  // If the next picture is ready, return it synchronously.
  if (!received_pictures_.empty()) {
    WriteNextPicture();
    return PP_OK;
  }

  get_picture_callback_ = callback;

  return PP_OK_COMPLETIONPENDING;
}

void VideoDecoderResource::RecyclePicture(const PP_VideoPicture* picture) {
  if (decoder_last_error_)
    return;

  Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture(picture->texture_id));
}

int32_t VideoDecoderResource::Flush(scoped_refptr<TrackedCallback> callback) {
  if (decoder_last_error_)
    return decoder_last_error_;
  if (reset_callback_.get())
    return PP_ERROR_FAILED;
  if (flush_callback_.get())
    return PP_ERROR_INPROGRESS;
  flush_callback_ = callback;

  Call<PpapiPluginMsg_VideoDecoder_FlushReply>(
      RENDERER,
      PpapiHostMsg_VideoDecoder_Flush(),
      base::Bind(&VideoDecoderResource::OnPluginMsgFlushComplete, this));

  return PP_OK_COMPLETIONPENDING;
}

int32_t VideoDecoderResource::Reset(scoped_refptr<TrackedCallback> callback) {
  if (decoder_last_error_)
    return decoder_last_error_;
  if (flush_callback_.get())
    return PP_ERROR_FAILED;
  if (reset_callback_.get())
    return PP_ERROR_INPROGRESS;
  reset_callback_ = callback;

  // Cause any pending Decode or GetPicture callbacks to abort after we return,
  // to avoid reentering the plugin.
  if (TrackedCallback::IsPending(decode_callback_))
    decode_callback_->PostAbort();
  decode_callback_ = NULL;
  if (TrackedCallback::IsPending(get_picture_callback_))
    get_picture_callback_->PostAbort();
  get_picture_callback_ = NULL;
  Call<PpapiPluginMsg_VideoDecoder_ResetReply>(
      RENDERER,
      PpapiHostMsg_VideoDecoder_Reset(),
      base::Bind(&VideoDecoderResource::OnPluginMsgResetComplete, this));

  return PP_OK_COMPLETIONPENDING;
}

void VideoDecoderResource::OnReplyReceived(
    const ResourceMessageReplyParams& params,
    const IPC::Message& msg) {
  PPAPI_BEGIN_MESSAGE_MAP(VideoDecoderResource, msg)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_VideoDecoder_RequestTextures, OnPluginMsgRequestTextures)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_VideoDecoder_PictureReady, OnPluginMsgPictureReady)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_VideoDecoder_DismissPicture, OnPluginMsgDismissPicture)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_VideoDecoder_NotifyError, OnPluginMsgNotifyError)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
        PluginResource::OnReplyReceived(params, msg))
  PPAPI_END_MESSAGE_MAP()
}

void VideoDecoderResource::SetForTest() {
  testing_ = true;
}

void VideoDecoderResource::OnPluginMsgRequestTextures(
    const ResourceMessageReplyParams& params,
    uint32_t num_textures,
    const PP_Size& size,
    uint32_t texture_target,
    const std::vector<gpu::Mailbox>& mailboxes) {
  DCHECK(num_textures);
  DCHECK(num_textures >= min_picture_count_);
  DCHECK(mailboxes.empty() || mailboxes.size() == num_textures);
  std::vector<uint32_t> texture_ids(num_textures);
  if (gles2_impl_) {
    gles2_impl_->GenTextures(num_textures, &texture_ids.front());
    for (uint32_t i = 0; i < num_textures; ++i) {
      gles2_impl_->ActiveTexture(GL_TEXTURE0);
      gles2_impl_->BindTexture(texture_target, texture_ids[i]);
      gles2_impl_->TexParameteri(
          texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      gles2_impl_->TexParameteri(
          texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      gles2_impl_->TexParameterf(
          texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      gles2_impl_->TexParameterf(
          texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

      if (texture_target == GL_TEXTURE_2D) {
        gles2_impl_->TexImage2D(texture_target,
                                0,
                                GL_RGBA,
                                size.width,
                                size.height,
                                0,
                                GL_RGBA,
                                GL_UNSIGNED_BYTE,
                                NULL);
      }
      if (!mailboxes.empty()) {
        gles2_impl_->ProduceTextureCHROMIUM(
            GL_TEXTURE_2D, reinterpret_cast<const GLbyte*>(mailboxes[i].name));
      }

      textures_.insert(
          std::make_pair(texture_ids[i], Texture(texture_target, size)));
    }
    gles2_impl_->Flush();
  } else {
    DCHECK(testing_);
    // Create some fake texture ids so we can test picture handling.
    for (uint32_t i = 0; i < num_textures; ++i) {
      texture_ids[i] = i + 1;
      textures_.insert(
          std::make_pair(texture_ids[i], Texture(texture_target, size)));
    }
  }

  Post(RENDERER, PpapiHostMsg_VideoDecoder_AssignTextures(size, texture_ids));
}

void VideoDecoderResource::OnPluginMsgPictureReady(
    const ResourceMessageReplyParams& params,
    int32_t decode_id,
    uint32_t texture_id,
    const PP_Rect& visible_rect) {
  received_pictures_.push(Picture(decode_id, texture_id, visible_rect));

  if (TrackedCallback::IsPending(get_picture_callback_)) {
    // The plugin may call GetPicture in its callback.
    scoped_refptr<TrackedCallback> callback;
    callback.swap(get_picture_callback_);
    WriteNextPicture();
    callback->Run(PP_OK);
  }
}

void VideoDecoderResource::OnPluginMsgDismissPicture(
    const ResourceMessageReplyParams& params,
    uint32_t texture_id) {
  DeleteGLTexture(texture_id);
  textures_.erase(texture_id);
}

void VideoDecoderResource::OnPluginMsgNotifyError(
    const ResourceMessageReplyParams& params,
    int32_t error) {
  decoder_last_error_ = error;
  // Cause any pending callbacks to run immediately. Reentrancy isn't a problem,
  // since the plugin wasn't calling us.
  RunCallbackWithError(&initialize_callback_);
  RunCallbackWithError(&decode_callback_);
  RunCallbackWithError(&get_picture_callback_);
  RunCallbackWithError(&flush_callback_);
  RunCallbackWithError(&reset_callback_);
}

void VideoDecoderResource::OnPluginMsgInitializeComplete(
    const ResourceMessageReplyParams& params) {
  decoder_last_error_ = params.result();
  if (decoder_last_error_ == PP_OK)
    initialized_ = true;

  // Let the plugin call Initialize again from its callback in case of failure.
  scoped_refptr<TrackedCallback> callback;
  callback.swap(initialize_callback_);
  callback->Run(decoder_last_error_);
}

void VideoDecoderResource::OnPluginMsgDecodeComplete(
    const ResourceMessageReplyParams& params,
    uint32_t shm_id) {
  if (shm_id >= shm_buffers_.size()) {
    NOTREACHED();
    return;
  }
  // Make the shm buffer available.
  available_shm_buffers_.push_back(shm_buffers_[shm_id]);
  // If the plugin is waiting, let it call Decode again.
  if (decode_callback_.get()) {
    scoped_refptr<TrackedCallback> callback;
    callback.swap(decode_callback_);
    callback->Run(PP_OK);
  }
}

void VideoDecoderResource::OnPluginMsgFlushComplete(
    const ResourceMessageReplyParams& params) {
  // All shm buffers should have been made available by now.
  DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size());

  if (get_picture_callback_.get()) {
    scoped_refptr<TrackedCallback> callback;
    callback.swap(get_picture_callback_);
    callback->Abort();
  }

  scoped_refptr<TrackedCallback> callback;
  callback.swap(flush_callback_);
  callback->Run(params.result());
}

void VideoDecoderResource::OnPluginMsgResetComplete(
    const ResourceMessageReplyParams& params) {
  // All shm buffers should have been made available by now.
  DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size());
  // Recycle any pictures which haven't been passed to the plugin.
  while (!received_pictures_.empty()) {
    Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture(
        received_pictures_.front().texture_id));
    received_pictures_.pop();
  }

  scoped_refptr<TrackedCallback> callback;
  callback.swap(reset_callback_);
  callback->Run(params.result());
}

void VideoDecoderResource::RunCallbackWithError(
    scoped_refptr<TrackedCallback>* callback) {
  if (TrackedCallback::IsPending(*callback)) {
    scoped_refptr<TrackedCallback> temp;
    callback->swap(temp);
    temp->Run(decoder_last_error_);
  }
}

void VideoDecoderResource::DeleteGLTexture(uint32_t id) {
  if (gles2_impl_) {
    gles2_impl_->DeleteTextures(1, &id);
    gles2_impl_->Flush();
  }
}

void VideoDecoderResource::WriteNextPicture() {
  DCHECK(!received_pictures_.empty());
  Picture& picture = received_pictures_.front();

  // Internally, we identify decodes by a unique id, which the host returns
  // to us in the picture. Use this to get the plugin's decode_id.
  uint32_t decode_id = decode_ids_[picture.decode_id % kMaximumPictureDelay];
  uint32_t texture_id = picture.texture_id;
  uint32_t texture_target = 0;
  PP_Size texture_size = PP_MakeSize(0, 0);
  TextureMap::iterator it = textures_.find(picture.texture_id);
  if (it != textures_.end()) {
    texture_target = it->second.texture_target;
    texture_size = it->second.size;
  } else {
    NOTREACHED();
  }

  if (get_picture_) {
    DCHECK(!get_picture_0_1_);
    get_picture_->decode_id = decode_id;
    get_picture_->texture_id = texture_id;
    get_picture_->texture_target = texture_target;
    get_picture_->texture_size = texture_size;
    get_picture_->visible_rect = picture.visible_rect;
    get_picture_ = NULL;
  } else {
    DCHECK(get_picture_0_1_);
    get_picture_0_1_->decode_id = decode_id;
    get_picture_0_1_->texture_id = texture_id;
    get_picture_0_1_->texture_target = texture_target;
    get_picture_0_1_->texture_size = texture_size;
    get_picture_0_1_ = NULL;
  }

  received_pictures_.pop();
}

}  // namespace proxy
}  // namespace ppapi
