// Copyright 2018 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 "media_perception/producer_impl.h"

#include <stdlib.h>

#include <algorithm>
#include <cstring>
#include <utility>

#include <base/bind.h>
#include <base/logging.h>
#include <mojo/public/cpp/system/handle.h>
#include <mojo/public/cpp/system/platform_handle.h>

#include "mojom/constants.mojom.h"
#include "mojom/video_capture_types.mojom.h"

namespace mri {

mojo::PendingRemote<video_capture::mojom::Producer>
ProducerImpl::CreateInterfacePendingRemote() {
  mojo::PendingRemote<video_capture::mojom::Producer> producer;
  receiver_.Bind(producer.InitWithNewPipeAndPassReceiver());
  return producer;
}

void ProducerImpl::RegisterVirtualDevice(
    video_capture::mojom::VideoSourceProviderPtr* provider,
    media::mojom::VideoCaptureDeviceInfoPtr info) {
  (*provider)->AddSharedMemoryVirtualDevice(
      std::move(info), CreateInterfacePendingRemote(), true,
      mojo::MakeRequest(&virtual_device_));
}

void ProducerImpl::OnNewBuffer(int32_t buffer_id,
                               media::mojom::VideoBufferHandlePtr buffer_handle,
                               OnNewBufferCallback callback) {
  CHECK(buffer_handle->is_shared_memory_via_raw_file_descriptor());
  base::ScopedPlatformFile platform_file;
  MojoResult mojo_result = mojo::UnwrapPlatformFile(
      std::move(buffer_handle->get_shared_memory_via_raw_file_descriptor()
                    ->file_descriptor_handle),
      &platform_file);
  if (mojo_result != MOJO_RESULT_OK) {
    LOG(ERROR) << "Failed to unwrap handle: " << mojo_result;
    return;
  }
  base::UnsafeSharedMemoryRegion shm_region =
      base::UnsafeSharedMemoryRegion::Deserialize(
          base::subtle::PlatformSharedMemoryRegion::Take(
              base::ScopedFD(std::move(platform_file)),
              base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
              buffer_handle->get_shared_memory_via_raw_file_descriptor()
                  ->shared_memory_size_in_bytes,
              base::UnguessableToken::Create()));
  if (!shm_region.IsValid()) {
    LOG(ERROR) << "Failed to take shared memory region.";
    return;
  }
  base::WritableSharedMemoryMapping shm_mapping = shm_region.Map();
  if (!shm_mapping.IsValid()) {
    LOG(ERROR) << "Failed to map shared memory region.";
    return;
  }
  outgoing_buffer_id_to_buffer_map_.insert(
      std::make_pair(buffer_id, std::move(shm_mapping)));
  std::move(callback).Run();
}

void ProducerImpl::OnBufferRetired(int32_t buffer_id) {
  outgoing_buffer_id_to_buffer_map_.erase(buffer_id);
}

void ProducerImpl::PushNextFrame(
    std::shared_ptr<ProducerImpl> producer_impl,
    base::TimeDelta timestamp,
    std::unique_ptr<const uint8_t[]> data,
    int data_size,
    media::mojom::VideoCapturePixelFormat pixel_format,
    int width,
    int height) {
  gfx::mojom::SizePtr size = gfx::mojom::Size::New();
  size->width = width;
  size->height = height;
  virtual_device_->RequestFrameBuffer(
      std::move(size), pixel_format, nullptr,
      base::Bind(&ProducerImpl::OnFrameBufferReceived, base::Unretained(this),
                 producer_impl, timestamp, base::Passed(&data), data_size,
                 pixel_format, width, height));
}

void ProducerImpl::OnFrameBufferReceived(
    std::shared_ptr<ProducerImpl> producer_impl,
    base::TimeDelta timestamp,
    std::unique_ptr<const uint8_t[]> data,
    int data_size,
    media::mojom::VideoCapturePixelFormat pixel_format,
    int width,
    int height,
    int32_t buffer_id) {
  if (buffer_id == video_capture::mojom::kInvalidBufferId) {
    LOG(ERROR) << "Got invalid buffer id.";
    return;
  }

  media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New();
  info->timestamp = mojo_base::mojom::TimeDelta::New();
  info->timestamp->microseconds = timestamp.InMicroseconds();
  info->pixel_format = pixel_format;
  gfx::mojom::SizePtr size = gfx::mojom::Size::New();
  size->width = width;
  size->height = height;
  info->coded_size = std::move(size);
  gfx::mojom::RectPtr rect = gfx::mojom::Rect::New();
  rect->width = width;
  rect->height = height;
  info->visible_rect = std::move(rect);
  info->metadata = media::mojom::VideoFrameMetadata::New();

  base::WritableSharedMemoryMapping* outgoing_buffer =
      &outgoing_buffer_id_to_buffer_map_.at(buffer_id);
  std::memcpy(
      outgoing_buffer->GetMemoryAs<uint8_t>(), data.get(),
      std::min(outgoing_buffer->mapped_size(), static_cast<size_t>(data_size)));
  virtual_device_->OnFrameReadyInBuffer(buffer_id, std::move(info));
}

}  // namespace mri
