// Copyright 2019 The Chromium OS 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 "arc/vm/libvda/decode_wrapper.h"

#include <utility>

#include <base/logging.h>

#include "arc/vm/libvda/decode/fake/fake_vda_impl.h"
#include "arc/vm/libvda/decode/gpu/gpu_vda_impl.h"
#include "arc/vm/libvda/gpu/vaf_connection.h"

namespace arc {

VdaImpl::VdaImpl() {
  capabilities_.num_input_formats = 0;
  capabilities_.input_formats = nullptr;
  capabilities_.num_output_formats = 0;
  capabilities_.output_formats = nullptr;
}

VdaImpl::~VdaImpl() = default;

const vda_capabilities_t* const VdaImpl::GetCapabilities() {
  return &capabilities_;
}

VdaContext::VdaContext() = default;

VdaContext::~VdaContext() = default;

int VdaContext::GetEventFd() {
  return event_pipe_.GetReadFd();
}

void VdaContext::WriteEvent(const vda_event_t& event) {
  event_pipe_.WriteVdaEvent(event);
}

void VdaContext::DispatchProvidePictureBuffers(uint32_t min_num_buffers,
                                               int32_t width,
                                               int32_t height,
                                               int32_t visible_rect_left,
                                               int32_t visible_rect_top,
                                               int32_t visible_rect_right,
                                               int32_t visible_rect_bottom) {
  vda_event_t event;
  event.event_type = PROVIDE_PICTURE_BUFFERS;
  event.event_data.provide_picture_buffers.min_num_buffers = min_num_buffers;
  event.event_data.provide_picture_buffers.width = width;
  event.event_data.provide_picture_buffers.height = height;
  event.event_data.provide_picture_buffers.visible_rect_left =
      visible_rect_left;
  event.event_data.provide_picture_buffers.visible_rect_top = visible_rect_top;
  event.event_data.provide_picture_buffers.visible_rect_right =
      visible_rect_right;
  event.event_data.provide_picture_buffers.visible_rect_bottom =
      visible_rect_bottom;
  WriteEvent(event);
}

void VdaContext::DispatchPictureReady(int32_t picture_buffer_id,
                                      int32_t bitstream_id,
                                      int crop_left,
                                      int crop_top,
                                      int crop_right,
                                      int crop_bottom) {
  vda_event_t event;
  event.event_type = PICTURE_READY;
  event.event_data.picture_ready.picture_buffer_id = picture_buffer_id;
  event.event_data.picture_ready.bitstream_id = bitstream_id;
  event.event_data.picture_ready.crop_left = crop_left;
  event.event_data.picture_ready.crop_top = crop_top;
  event.event_data.picture_ready.crop_right = crop_right;
  event.event_data.picture_ready.crop_bottom = crop_bottom;
  WriteEvent(event);
}

void VdaContext::DispatchNotifyEndOfBitstreamBuffer(int32_t bitstream_id) {
  vda_event_t event;
  event.event_type = NOTIFY_END_OF_BITSTREAM_BUFFER;
  event.event_data.bitstream_id = bitstream_id;
  WriteEvent(event);
}

void VdaContext::DispatchNotifyError(vda_result_t result) {
  vda_event_t event;
  event.event_type = NOTIFY_ERROR;
  event.event_data.result = result;
  WriteEvent(event);
}

void VdaContext::DispatchResetResponse(vda_result_t result) {
  vda_event_t event;
  event.event_type = RESET_RESPONSE;
  event.event_data.result = result;
  WriteEvent(event);
}

void VdaContext::DispatchFlushResponse(vda_result_t result) {
  vda_event_t event;
  event.event_type = FLUSH_RESPONSE;
  event.event_data.result = result;
  WriteEvent(event);
}

}  // namespace arc

void* initialize(vda_impl_type_t impl_type) {
  switch (impl_type) {
    case FAKE:
      return arc::FakeVdaImpl::Create();
    case GAVDA: {
      arc::VafConnection* conn = arc::VafConnection::Get();
      if (conn == nullptr) {
        LOG(ERROR) << "Failed to retrieve VAF connection.";
        return nullptr;
      }
      return arc::GpuVdaImpl::Create(conn);
    }
    default:
      LOG(ERROR) << "Unknown impl type " << impl_type;
      return nullptr;
  }
}

void deinitialize(void* impl) {
  arc::VdaImpl* cast_impl = static_cast<arc::VdaImpl*>(impl);
  delete cast_impl;
}

const vda_capabilities_t* get_vda_capabilities(void* impl) {
  return static_cast<arc::VdaImpl*>(impl)->GetCapabilities();
}

vda_session_info_t* init_decode_session(void* impl, vda_profile_t profile) {
  arc::VdaContext* context =
      static_cast<arc::VdaImpl*>(impl)->InitDecodeSession(profile);
  if (!context)
    return nullptr;
  vda_session_info_t* session_info = new vda_session_info_t();
  session_info->ctx = context;
  session_info->event_pipe_fd = context->GetEventFd();
  return session_info;
}

void close_decode_session(void* impl, vda_session_info_t* session_info) {
  static_cast<arc::VdaImpl*>(impl)->CloseDecodeSession(
      static_cast<arc::VdaContext*>(session_info->ctx));
  delete session_info;
}

vda_result_t vda_decode(void* ctx,
                        int32_t bitstream_id,
                        int fd,
                        uint32_t offset,
                        uint32_t bytes_used) {
  return static_cast<arc::VdaContext*>(ctx)->Decode(
      bitstream_id, base::ScopedFD(fd), offset, bytes_used);
}

vda_result_t vda_set_output_buffer_count(void* ctx, size_t num_output_buffers) {
  return static_cast<arc::VdaContext*>(ctx)->SetOutputBufferCount(
      num_output_buffers);
}

vda_result_t vda_use_output_buffer(void* ctx,
                                   int32_t picture_buffer_id,
                                   vda_pixel_format_t format,
                                   int fd,
                                   size_t num_planes,
                                   video_frame_plane_t* planes) {
  return static_cast<arc::VdaContext*>(ctx)->UseOutputBuffer(
      picture_buffer_id, format, base::ScopedFD(fd), num_planes, planes);
}

vda_result_t vda_reuse_output_buffer(void* ctx, int32_t picture_buffer_id) {
  return static_cast<arc::VdaContext*>(ctx)->ReuseOutputBuffer(
      picture_buffer_id);
}

vda_result vda_reset(void* ctx) {
  return static_cast<arc::VdaContext*>(ctx)->Reset();
}

vda_result vda_flush(void* ctx) {
  return static_cast<arc::VdaContext*>(ctx)->Flush();
}
