// Copyright 2015 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_encoder_resource.h"

#include <memory>
#include <utility>

#include "base/memory/shared_memory.h"
#include "base/numerics/safe_conversions.h"
#include "ppapi/c/pp_array_output.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/video_frame_resource.h"
#include "ppapi/shared_impl/array_writer.h"
#include "ppapi/shared_impl/media_stream_buffer.h"
#include "ppapi/shared_impl/media_stream_buffer_manager.h"
#include "ppapi/thunk/enter.h"

using ppapi::proxy::SerializedHandle;
using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_VideoEncoder_API;

namespace ppapi {
namespace proxy {

namespace {

std::vector<PP_VideoProfileDescription_0_1> PP_VideoProfileDescriptionTo_0_1(
    std::vector<PP_VideoProfileDescription> profiles) {
  std::vector<PP_VideoProfileDescription_0_1> profiles_0_1;

  for (uint32_t i = 0; i < profiles.size(); ++i) {
    const PP_VideoProfileDescription& profile = profiles[i];
    PP_VideoProfileDescription_0_1 profile_0_1;

    profile_0_1.profile = profile.profile;
    profile_0_1.max_resolution = profile.max_resolution;
    profile_0_1.max_framerate_numerator = profile.max_framerate_numerator;
    profile_0_1.max_framerate_denominator = profile.max_framerate_denominator;
    profile_0_1.acceleration = profile.hardware_accelerated == PP_TRUE
                                   ? PP_HARDWAREACCELERATION_ONLY
                                   : PP_HARDWAREACCELERATION_NONE;

    profiles_0_1.push_back(profile_0_1);
  }

  return profiles_0_1;
}

}  // namespace

VideoEncoderResource::ShmBuffer::ShmBuffer(
    uint32_t id,
    std::unique_ptr<base::SharedMemory> shm)
    : id(id), shm(std::move(shm)) {}

VideoEncoderResource::ShmBuffer::~ShmBuffer() {
}

VideoEncoderResource::BitstreamBuffer::BitstreamBuffer(uint32_t id,
                                                       uint32_t size,
                                                       bool key_frame)
    : id(id), size(size), key_frame(key_frame) {
}

VideoEncoderResource::BitstreamBuffer::~BitstreamBuffer() {
}

VideoEncoderResource::VideoEncoderResource(Connection connection,
                                           PP_Instance instance)
    : PluginResource(connection, instance),
      initialized_(false),
      closed_(false),
      // Set |encoder_last_error_| to PP_OK after successful initialization.
      // This makes error checking a little more concise, since we can check
      // that the encoder has been initialized and hasn't returned an error by
      // just testing |encoder_last_error_|.
      encoder_last_error_(PP_ERROR_FAILED),
      input_frame_count_(0),
      input_coded_size_(PP_MakeSize(0, 0)),
      buffer_manager_(this),
      get_video_frame_data_(nullptr),
      get_bitstream_buffer_data_(nullptr) {
  SendCreate(RENDERER, PpapiHostMsg_VideoEncoder_Create());
}

VideoEncoderResource::~VideoEncoderResource() {
  Close();
}

PPB_VideoEncoder_API* VideoEncoderResource::AsPPB_VideoEncoder_API() {
  return this;
}

int32_t VideoEncoderResource::GetSupportedProfiles(
    const PP_ArrayOutput& output,
    const scoped_refptr<TrackedCallback>& callback) {
  if (TrackedCallback::IsPending(get_supported_profiles_callback_))
    return PP_ERROR_INPROGRESS;

  get_supported_profiles_callback_ = callback;
  Call<PpapiPluginMsg_VideoEncoder_GetSupportedProfilesReply>(
      RENDERER, PpapiHostMsg_VideoEncoder_GetSupportedProfiles(),
      base::Bind(&VideoEncoderResource::OnPluginMsgGetSupportedProfilesReply,
                 this, output, false));
  return PP_OK_COMPLETIONPENDING;
}

int32_t VideoEncoderResource::GetSupportedProfiles0_1(
    const PP_ArrayOutput& output,
    const scoped_refptr<TrackedCallback>& callback) {
  if (TrackedCallback::IsPending(get_supported_profiles_callback_))
    return PP_ERROR_INPROGRESS;

  get_supported_profiles_callback_ = callback;
  Call<PpapiPluginMsg_VideoEncoder_GetSupportedProfilesReply>(
      RENDERER, PpapiHostMsg_VideoEncoder_GetSupportedProfiles(),
      base::Bind(&VideoEncoderResource::OnPluginMsgGetSupportedProfilesReply,
                 this, output, true));
  return PP_OK_COMPLETIONPENDING;
}

int32_t VideoEncoderResource::GetFramesRequired() {
  if (encoder_last_error_)
    return encoder_last_error_;
  return input_frame_count_;
}

int32_t VideoEncoderResource::GetFrameCodedSize(PP_Size* size) {
  if (encoder_last_error_)
    return encoder_last_error_;
  *size = input_coded_size_;
  return PP_OK;
}

int32_t VideoEncoderResource::Initialize(
    PP_VideoFrame_Format input_format,
    const PP_Size* input_visible_size,
    PP_VideoProfile output_profile,
    uint32_t initial_bitrate,
    PP_HardwareAcceleration acceleration,
    const scoped_refptr<TrackedCallback>& callback) {
  if (initialized_)
    return PP_ERROR_FAILED;
  if (TrackedCallback::IsPending(initialize_callback_))
    return PP_ERROR_INPROGRESS;

  initialize_callback_ = callback;
  Call<PpapiPluginMsg_VideoEncoder_InitializeReply>(
      RENDERER, PpapiHostMsg_VideoEncoder_Initialize(
                    input_format, *input_visible_size, output_profile,
                    initial_bitrate, acceleration),
      base::Bind(&VideoEncoderResource::OnPluginMsgInitializeReply, this));
  return PP_OK_COMPLETIONPENDING;
}

int32_t VideoEncoderResource::GetVideoFrame(
    PP_Resource* video_frame,
    const scoped_refptr<TrackedCallback>& callback) {
  if (encoder_last_error_)
    return encoder_last_error_;

  if (TrackedCallback::IsPending(get_video_frame_callback_))
    return PP_ERROR_INPROGRESS;

  get_video_frame_data_ = video_frame;
  get_video_frame_callback_ = callback;

  // Lazily ask for a shared memory buffer in which video frames are allocated.
  if (buffer_manager_.number_of_buffers() == 0) {
    Call<PpapiPluginMsg_VideoEncoder_GetVideoFramesReply>(
        RENDERER, PpapiHostMsg_VideoEncoder_GetVideoFrames(),
        base::Bind(&VideoEncoderResource::OnPluginMsgGetVideoFramesReply,
                   this));
  } else {
    TryWriteVideoFrame();
  }

  return PP_OK_COMPLETIONPENDING;
}

int32_t VideoEncoderResource::Encode(
    PP_Resource video_frame,
    PP_Bool force_keyframe,
    const scoped_refptr<TrackedCallback>& callback) {
  if (encoder_last_error_)
    return encoder_last_error_;

  VideoFrameMap::iterator it = video_frames_.find(video_frame);
  if (it == video_frames_.end())
    // TODO(llandwerlin): accept MediaStreamVideoTrack's video frames.
    return PP_ERROR_BADRESOURCE;

  scoped_refptr<VideoFrameResource> frame_resource = it->second;

  encode_callbacks_.insert(std::make_pair(video_frame, callback));

  Call<PpapiPluginMsg_VideoEncoder_EncodeReply>(
      RENDERER,
      PpapiHostMsg_VideoEncoder_Encode(frame_resource->GetBufferIndex(),
                                       PP_ToBool(force_keyframe)),
      base::Bind(&VideoEncoderResource::OnPluginMsgEncodeReply, this,
                 video_frame));

  // Invalidate the frame to prevent the plugin from modifying it.
  it->second->Invalidate();
  video_frames_.erase(it);

  return PP_OK_COMPLETIONPENDING;
}

int32_t VideoEncoderResource::GetBitstreamBuffer(
    PP_BitstreamBuffer* bitstream_buffer,
    const scoped_refptr<TrackedCallback>& callback) {
  if (encoder_last_error_)
    return encoder_last_error_;
  if (TrackedCallback::IsPending(get_bitstream_buffer_callback_))
    return PP_ERROR_INPROGRESS;

  get_bitstream_buffer_callback_ = callback;
  get_bitstream_buffer_data_ = bitstream_buffer;

  if (!available_bitstream_buffers_.empty()) {
    BitstreamBuffer buffer(available_bitstream_buffers_.front());
    available_bitstream_buffers_.pop_front();
    WriteBitstreamBuffer(buffer);
  }

  return PP_OK_COMPLETIONPENDING;
}

void VideoEncoderResource::RecycleBitstreamBuffer(
    const PP_BitstreamBuffer* bitstream_buffer) {
  if (encoder_last_error_)
    return;
  BitstreamBufferMap::const_iterator iter =
      bitstream_buffer_map_.find(bitstream_buffer->buffer);
  if (iter != bitstream_buffer_map_.end()) {
    Post(RENDERER,
         PpapiHostMsg_VideoEncoder_RecycleBitstreamBuffer(iter->second));
  }
}

void VideoEncoderResource::RequestEncodingParametersChange(uint32_t bitrate,
                                                           uint32_t framerate) {
  if (encoder_last_error_)
    return;
  Post(RENDERER, PpapiHostMsg_VideoEncoder_RequestEncodingParametersChange(
                     bitrate, framerate));
}

void VideoEncoderResource::Close() {
  if (closed_)
    return;
  Post(RENDERER, PpapiHostMsg_VideoEncoder_Close());
  closed_ = true;
  if (!encoder_last_error_ || !initialized_)
    NotifyError(PP_ERROR_ABORTED);
  ReleaseFrames();
}

void VideoEncoderResource::OnReplyReceived(
    const ResourceMessageReplyParams& params,
    const IPC::Message& msg) {
  PPAPI_BEGIN_MESSAGE_MAP(VideoEncoderResource, msg)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_VideoEncoder_BitstreamBuffers,
        OnPluginMsgBitstreamBuffers)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_VideoEncoder_BitstreamBufferReady,
        OnPluginMsgBitstreamBufferReady)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(PpapiPluginMsg_VideoEncoder_NotifyError,
                                        OnPluginMsgNotifyError)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
        PluginResource::OnReplyReceived(params, msg))
  PPAPI_END_MESSAGE_MAP()
}

void VideoEncoderResource::OnPluginMsgGetSupportedProfilesReply(
    const PP_ArrayOutput& output,
    bool version0_1,
    const ResourceMessageReplyParams& params,
    const std::vector<PP_VideoProfileDescription>& profiles) {
  int32_t error = params.result();
  if (error) {
    NotifyError(error);
    return;
  }

  ArrayWriter writer(output);
  if (!writer.is_valid()) {
    SafeRunCallback(&get_supported_profiles_callback_, PP_ERROR_BADARGUMENT);
    return;
  }

  bool write_result;
  if (version0_1)
    write_result =
        writer.StoreVector(PP_VideoProfileDescriptionTo_0_1(profiles));
  else
    write_result = writer.StoreVector(profiles);

  if (!write_result) {
    SafeRunCallback(&get_supported_profiles_callback_, PP_ERROR_FAILED);
    return;
  }

  SafeRunCallback(&get_supported_profiles_callback_,
                  base::checked_cast<int32_t>(profiles.size()));
}

void VideoEncoderResource::OnPluginMsgInitializeReply(
    const ResourceMessageReplyParams& params,
    uint32_t input_frame_count,
    const PP_Size& input_coded_size) {
  DCHECK(!initialized_);

  encoder_last_error_ = params.result();
  if (!encoder_last_error_)
    initialized_ = true;

  input_frame_count_ = input_frame_count;
  input_coded_size_ = input_coded_size;

  SafeRunCallback(&initialize_callback_, encoder_last_error_);
}

void VideoEncoderResource::OnPluginMsgGetVideoFramesReply(
    const ResourceMessageReplyParams& params,
    uint32_t frame_count,
    uint32_t frame_length,
    const PP_Size& frame_size) {
  int32_t error = params.result();
  if (error) {
    NotifyError(error);
    return;
  }

  base::SharedMemoryHandle buffer_handle;
  params.TakeSharedMemoryHandleAtIndex(0, &buffer_handle);

  if (!buffer_manager_.SetBuffers(
          frame_count, frame_length,
          std::make_unique<base::SharedMemory>(buffer_handle, false), true)) {
    NotifyError(PP_ERROR_FAILED);
    return;
  }

  if (TrackedCallback::IsPending(get_video_frame_callback_))
    TryWriteVideoFrame();
}

void VideoEncoderResource::OnPluginMsgEncodeReply(
    PP_Resource video_frame,
    const ResourceMessageReplyParams& params,
    uint32_t frame_id) {
  // We need to ensure there are still callbacks to be called before
  // processing this message. We might receive a EncodeReply message
  // after having sent a Close message to the renderer. In this case,
  // we don't have any callback left to call.
  if (encode_callbacks_.empty())
    return;
  encoder_last_error_ = params.result();

  EncodeMap::iterator it = encode_callbacks_.find(video_frame);
  DCHECK(encode_callbacks_.end() != it);

  scoped_refptr<TrackedCallback> callback = it->second;
  encode_callbacks_.erase(it);
  SafeRunCallback(&callback, encoder_last_error_);

  buffer_manager_.EnqueueBuffer(frame_id);
  // If the plugin is waiting for a video frame, we can give the one
  // that just became available again.
  if (TrackedCallback::IsPending(get_video_frame_callback_))
    TryWriteVideoFrame();
}

void VideoEncoderResource::OnPluginMsgBitstreamBuffers(
    const ResourceMessageReplyParams& params,
    uint32_t buffer_length) {
  std::vector<base::SharedMemoryHandle> shm_handles;
  params.TakeAllSharedMemoryHandles(&shm_handles);
  if (shm_handles.size() == 0) {
    NotifyError(PP_ERROR_FAILED);
    return;
  }

  for (uint32_t i = 0; i < shm_handles.size(); ++i) {
    std::unique_ptr<base::SharedMemory> shm(
        new base::SharedMemory(shm_handles[i], true));
    CHECK(shm->Map(buffer_length));

    auto buffer = std::make_unique<ShmBuffer>(i, std::move(shm));
    bitstream_buffer_map_.insert(
        std::make_pair(buffer->shm->memory(), buffer->id));
    shm_buffers_.push_back(std::move(buffer));
  }
}

void VideoEncoderResource::OnPluginMsgBitstreamBufferReady(
    const ResourceMessageReplyParams& params,
    uint32_t buffer_id,
    uint32_t buffer_size,
    bool key_frame) {
  available_bitstream_buffers_.push_back(
      BitstreamBuffer(buffer_id, buffer_size, key_frame));

  if (TrackedCallback::IsPending(get_bitstream_buffer_callback_)) {
    BitstreamBuffer buffer(available_bitstream_buffers_.front());
    available_bitstream_buffers_.pop_front();
    WriteBitstreamBuffer(buffer);
  }
}

void VideoEncoderResource::OnPluginMsgNotifyError(
    const ResourceMessageReplyParams& params,
    int32_t error) {
  NotifyError(error);
}

void VideoEncoderResource::NotifyError(int32_t error) {
  encoder_last_error_ = error;
  SafeRunCallback(&get_supported_profiles_callback_, error);
  SafeRunCallback(&initialize_callback_, error);
  SafeRunCallback(&get_video_frame_callback_, error);
  get_video_frame_data_ = nullptr;
  SafeRunCallback(&get_bitstream_buffer_callback_, error);
  get_bitstream_buffer_data_ = nullptr;
  for (EncodeMap::iterator it = encode_callbacks_.begin();
       it != encode_callbacks_.end(); ++it) {
    scoped_refptr<TrackedCallback> callback = it->second;
    SafeRunCallback(&callback, error);
  }
  encode_callbacks_.clear();
}

void VideoEncoderResource::TryWriteVideoFrame() {
  DCHECK(TrackedCallback::IsPending(get_video_frame_callback_));

  int32_t frame_id = buffer_manager_.DequeueBuffer();
  if (frame_id < 0)
    return;

  scoped_refptr<VideoFrameResource> resource = new VideoFrameResource(
      pp_instance(), frame_id, buffer_manager_.GetBufferPointer(frame_id));
  video_frames_.insert(
      VideoFrameMap::value_type(resource->pp_resource(), resource));

  *get_video_frame_data_ = resource->GetReference();
  get_video_frame_data_ = nullptr;
  SafeRunCallback(&get_video_frame_callback_, PP_OK);
}

void VideoEncoderResource::WriteBitstreamBuffer(const BitstreamBuffer& buffer) {
  DCHECK_LT(buffer.id, shm_buffers_.size());

  get_bitstream_buffer_data_->size = buffer.size;
  get_bitstream_buffer_data_->buffer = shm_buffers_[buffer.id]->shm->memory();
  get_bitstream_buffer_data_->key_frame = PP_FromBool(buffer.key_frame);
  get_bitstream_buffer_data_ = nullptr;
  SafeRunCallback(&get_bitstream_buffer_callback_, PP_OK);
}

void VideoEncoderResource::ReleaseFrames() {
  for (VideoFrameMap::iterator it = video_frames_.begin();
       it != video_frames_.end(); ++it) {
    it->second->Invalidate();
    it->second = nullptr;
  }
  video_frames_.clear();
}

}  // namespace proxy
}  // namespace ppapi
