// 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/ppb_video_decoder_proxy.h"

#include "base/check.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "ppapi/proxy/enter_proxy.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_buffer_proxy.h"
#include "ppapi/proxy/ppb_graphics_3d_proxy.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/resource_creation_api.h"
#include "ppapi/thunk/thunk.h"

using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_Buffer_API;
using ppapi::thunk::PPB_Graphics3D_API;
using ppapi::thunk::PPB_VideoDecoder_Dev_API;

namespace ppapi {
namespace proxy {

class VideoDecoder : public PPB_VideoDecoder_Shared {
 public:
  // You must call Init() before using this class.
  explicit VideoDecoder(const HostResource& resource);
  ~VideoDecoder() override;

  static VideoDecoder* Create(const HostResource& resource,
                              PP_Resource graphics_context,
                              PP_VideoDecoder_Profile profile);

  // PPB_VideoDecoder_Dev_API implementation.
  int32_t Decode(const PP_VideoBitstreamBuffer_Dev* bitstream_buffer,
                 scoped_refptr<TrackedCallback> callback) override;
  void AssignPictureBuffers(uint32_t no_of_buffers,
                            const PP_PictureBuffer_Dev* buffers) override;
  void ReusePictureBuffer(int32_t picture_buffer_id) override;
  int32_t Flush(scoped_refptr<TrackedCallback> callback) override;
  int32_t Reset(scoped_refptr<TrackedCallback> callback) override;
  void Destroy() override;

 private:
  friend class PPB_VideoDecoder_Proxy;

  PluginDispatcher* GetDispatcher() const;

  // Run the callbacks that were passed into the plugin interface.
  void FlushACK(int32_t result);
  void ResetACK(int32_t result);
  void EndOfBitstreamACK(int32_t buffer_id, int32_t result);

  DISALLOW_COPY_AND_ASSIGN(VideoDecoder);
};

VideoDecoder::VideoDecoder(const HostResource& decoder)
    : PPB_VideoDecoder_Shared(decoder) {
}

VideoDecoder::~VideoDecoder() {
  FlushCommandBuffer();
  PPB_VideoDecoder_Shared::Destroy();
}

int32_t VideoDecoder::Decode(
    const PP_VideoBitstreamBuffer_Dev* bitstream_buffer,
    scoped_refptr<TrackedCallback> callback) {
  EnterResourceNoLock<PPB_Buffer_API>
      enter_buffer(bitstream_buffer->data, true);
  if (enter_buffer.failed())
    return PP_ERROR_BADRESOURCE;

  if (!SetBitstreamBufferCallback(bitstream_buffer->id, callback))
    return PP_ERROR_BADARGUMENT;

  Buffer* ppb_buffer =
      static_cast<Buffer*>(enter_buffer.object());
  HostResource host_buffer = ppb_buffer->host_resource();

  FlushCommandBuffer();
  GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Decode(
      API_ID_PPB_VIDEO_DECODER_DEV, host_resource(),
      host_buffer, bitstream_buffer->id,
      bitstream_buffer->size));
  return PP_OK_COMPLETIONPENDING;
}

void VideoDecoder::AssignPictureBuffers(uint32_t no_of_buffers,
                                        const PP_PictureBuffer_Dev* buffers) {
  std::vector<PP_PictureBuffer_Dev> buffer_list(
      buffers, buffers + no_of_buffers);
  FlushCommandBuffer();
  GetDispatcher()->Send(
      new PpapiHostMsg_PPBVideoDecoder_AssignPictureBuffers(
          API_ID_PPB_VIDEO_DECODER_DEV, host_resource(), buffer_list));
}

void VideoDecoder::ReusePictureBuffer(int32_t picture_buffer_id) {
  FlushCommandBuffer();
  GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_ReusePictureBuffer(
      API_ID_PPB_VIDEO_DECODER_DEV, host_resource(), picture_buffer_id));
}

int32_t VideoDecoder::Flush(scoped_refptr<TrackedCallback> callback) {
  if (!SetFlushCallback(callback))
    return PP_ERROR_INPROGRESS;

  FlushCommandBuffer();
  GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Flush(
      API_ID_PPB_VIDEO_DECODER_DEV, host_resource()));
  return PP_OK_COMPLETIONPENDING;
}

int32_t VideoDecoder::Reset(scoped_refptr<TrackedCallback> callback) {
  if (!SetResetCallback(callback))
    return PP_ERROR_INPROGRESS;

  FlushCommandBuffer();
  GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Reset(
      API_ID_PPB_VIDEO_DECODER_DEV, host_resource()));
  return PP_OK_COMPLETIONPENDING;
}

void VideoDecoder::Destroy() {
  FlushCommandBuffer();
  GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Destroy(
      API_ID_PPB_VIDEO_DECODER_DEV, host_resource()));
  PPB_VideoDecoder_Shared::Destroy();
}

PluginDispatcher* VideoDecoder::GetDispatcher() const {
  return PluginDispatcher::GetForResource(this);
}

void VideoDecoder::ResetACK(int32_t result) {
  RunResetCallback(result);
}

void VideoDecoder::FlushACK(int32_t result) {
  RunFlushCallback(result);
}

void VideoDecoder::EndOfBitstreamACK(
    int32_t bitstream_buffer_id, int32_t result) {
  RunBitstreamBufferCallback(bitstream_buffer_id, result);
}

PPB_VideoDecoder_Proxy::PPB_VideoDecoder_Proxy(Dispatcher* dispatcher)
    : InterfaceProxy(dispatcher),
      callback_factory_(this) {
}

PPB_VideoDecoder_Proxy::~PPB_VideoDecoder_Proxy() {
}

bool PPB_VideoDecoder_Proxy::OnMessageReceived(const IPC::Message& msg) {
  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
    return false;

  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(PPB_VideoDecoder_Proxy, msg)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Create,
                        OnMsgCreate)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Decode, OnMsgDecode)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_AssignPictureBuffers,
                        OnMsgAssignPictureBuffers)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_ReusePictureBuffer,
                        OnMsgReusePictureBuffer)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Flush, OnMsgFlush)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Reset, OnMsgReset)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Destroy, OnMsgDestroy)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_ResetACK, OnMsgResetACK)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK,
                        OnMsgEndOfBitstreamACK)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_FlushACK, OnMsgFlushACK)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  DCHECK(handled);
  return handled;
}

PP_Resource PPB_VideoDecoder_Proxy::CreateProxyResource(
    PP_Instance instance,
    PP_Resource graphics_context,
    PP_VideoDecoder_Profile profile) {
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
  // Dispatcher is null if it cannot find the instance passed to it (i.e. if the
  // client passes in an invalid instance).
  if (!dispatcher)
    return 0;

  if (!dispatcher->preferences().is_accelerated_video_decode_enabled)
    return 0;

  EnterResourceNoLock<PPB_Graphics3D_API> enter_context(graphics_context,
                                                        true);
  if (enter_context.failed())
    return 0;

  Graphics3D* context = static_cast<Graphics3D*>(enter_context.object());

  HostResource result;
  dispatcher->Send(new PpapiHostMsg_PPBVideoDecoder_Create(
      API_ID_PPB_VIDEO_DECODER_DEV, instance,
      context->host_resource(), profile, &result));
  if (result.is_null())
    return 0;

  // Need a scoped_refptr to keep the object alive during the Init call.
  scoped_refptr<VideoDecoder> decoder(new VideoDecoder(result));
  decoder->InitCommon(graphics_context, context->gles2_impl());
  return decoder->GetReference();
}

void PPB_VideoDecoder_Proxy::OnMsgCreate(
    PP_Instance instance, const HostResource& graphics_context,
    PP_VideoDecoder_Profile profile,
    HostResource* result) {
  thunk::EnterResourceCreation resource_creation(instance);
  if (resource_creation.failed())
    return;

  // Make the resource and get the API pointer to its interface.
  result->SetHostResource(
      instance, resource_creation.functions()->CreateVideoDecoderDev(
          instance, graphics_context.host_resource(), profile));
}

void PPB_VideoDecoder_Proxy::OnMsgDecode(const HostResource& decoder,
                                         const HostResource& buffer,
                                         int32_t id,
                                         uint32_t size) {
  EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_Dev_API> enter(
      decoder, callback_factory_,
      &PPB_VideoDecoder_Proxy::SendMsgEndOfBitstreamACKToPlugin, decoder, id);
  if (enter.failed())
    return;
  PP_VideoBitstreamBuffer_Dev bitstream = { id, buffer.host_resource(), size };
  enter.SetResult(enter.object()->Decode(&bitstream, enter.callback()));
}

void PPB_VideoDecoder_Proxy::OnMsgAssignPictureBuffers(
    const HostResource& decoder,
    const std::vector<PP_PictureBuffer_Dev>& buffers) {
  EnterHostFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder);
  if (enter.succeeded() && !buffers.empty()) {
    const PP_PictureBuffer_Dev* buffer_array = &buffers.front();
    enter.object()->AssignPictureBuffers(
        base::checked_cast<uint32_t>(buffers.size()), buffer_array);
  }
}

void PPB_VideoDecoder_Proxy::OnMsgReusePictureBuffer(
    const HostResource& decoder,
    int32_t picture_buffer_id) {
  EnterHostFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder);
  if (enter.succeeded())
    enter.object()->ReusePictureBuffer(picture_buffer_id);
}

void PPB_VideoDecoder_Proxy::OnMsgFlush(const HostResource& decoder) {
  EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_Dev_API> enter(
      decoder, callback_factory_,
      &PPB_VideoDecoder_Proxy::SendMsgFlushACKToPlugin, decoder);
  if (enter.succeeded())
    enter.SetResult(enter.object()->Flush(enter.callback()));
}

void PPB_VideoDecoder_Proxy::OnMsgReset(const HostResource& decoder) {
  EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_Dev_API> enter(
      decoder, callback_factory_,
      &PPB_VideoDecoder_Proxy::SendMsgResetACKToPlugin, decoder);
  if (enter.succeeded())
    enter.SetResult(enter.object()->Reset(enter.callback()));
}

void PPB_VideoDecoder_Proxy::OnMsgDestroy(const HostResource& decoder) {
  EnterHostFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder);
  if (enter.succeeded())
    enter.object()->Destroy();
}

void PPB_VideoDecoder_Proxy::SendMsgEndOfBitstreamACKToPlugin(
    int32_t result,
    const HostResource& decoder,
    int32_t id) {
  dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK(
      API_ID_PPB_VIDEO_DECODER_DEV, decoder, id, result));
}

void PPB_VideoDecoder_Proxy::SendMsgFlushACKToPlugin(
    int32_t result, const HostResource& decoder) {
  dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_FlushACK(
      API_ID_PPB_VIDEO_DECODER_DEV, decoder, result));
}

void PPB_VideoDecoder_Proxy::SendMsgResetACKToPlugin(
    int32_t result, const HostResource& decoder) {
  dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_ResetACK(
      API_ID_PPB_VIDEO_DECODER_DEV, decoder, result));
}

void PPB_VideoDecoder_Proxy::OnMsgEndOfBitstreamACK(
    const HostResource& decoder, int32_t id, int32_t result) {
  EnterPluginFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder);
  if (enter.succeeded())
    static_cast<VideoDecoder*>(enter.object())->EndOfBitstreamACK(id, result);
}

void PPB_VideoDecoder_Proxy::OnMsgFlushACK(
    const HostResource& decoder, int32_t result) {
  EnterPluginFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder);
  if (enter.succeeded())
    static_cast<VideoDecoder*>(enter.object())->FlushACK(result);
}

void PPB_VideoDecoder_Proxy::OnMsgResetACK(
    const HostResource& decoder, int32_t result) {
  EnterPluginFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder);
  if (enter.succeeded())
    static_cast<VideoDecoder*>(enter.object())->ResetACK(result);
}

}  // namespace proxy
}  // namespace ppapi
