// 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(std::move(shm_buffer));
    else
      shm_buffers_[shm_id] = std::move(shm_buffer);
  }

  // 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) {
  DCHECK(num_textures);
  DCHECK(num_textures >= min_picture_count_);
  std::vector<uint32_t> texture_ids(num_textures);
  std::vector<gpu::Mailbox> mailboxes(num_textures);
  if (gles2_impl_) {
    gles2_impl_->GenTextures(num_textures, texture_ids.data());
    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);
      }
      gles2_impl_->ProduceTextureDirectCHROMIUM(texture_ids[i],
                                                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, std::move(texture_ids), std::move(mailboxes)));
}

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].get());
  // 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) {
  SafeRunCallback(callback, 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
