// Copyright 2019 The Fuchsia 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 "stream_constraints.h"

#include <fuchsia/camera2/cpp/fidl.h>
#include <fuchsia/camera2/hal/cpp/fidl.h>
#include <fuchsia/sysmem/c/fidl.h>
#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/image-format/image_format.h>

#include <algorithm>
#include <vector>

#include <fbl/algorithm.h>

namespace camera {

static fuchsia_sysmem_PixelFormat ConvertPixelFormatToC(fuchsia::sysmem::PixelFormat format) {
  fuchsia_sysmem_PixelFormat ret;
  ret.has_format_modifier = format.has_format_modifier;
  switch (format.type) {
    case fuchsia::sysmem::PixelFormatType::INVALID:
      ret.type = fuchsia_sysmem_PixelFormatType_INVALID;
      break;
    case fuchsia::sysmem::PixelFormatType::R8G8B8A8:
      ret.type = fuchsia_sysmem_PixelFormatType_R8G8B8A8;
      break;
    case fuchsia::sysmem::PixelFormatType::BGRA32:
      ret.type = fuchsia_sysmem_PixelFormatType_BGRA32;
      break;
    case fuchsia::sysmem::PixelFormatType::I420:
      ret.type = fuchsia_sysmem_PixelFormatType_I420;
      break;
    case fuchsia::sysmem::PixelFormatType::M420:
      ret.type = fuchsia_sysmem_PixelFormatType_M420;
      break;
    case fuchsia::sysmem::PixelFormatType::NV12:
      ret.type = fuchsia_sysmem_PixelFormatType_NV12;
      break;
    case fuchsia::sysmem::PixelFormatType::YUY2:
      ret.type = fuchsia_sysmem_PixelFormatType_YUY2;
      break;
    case fuchsia::sysmem::PixelFormatType::MJPEG:
      ret.type = fuchsia_sysmem_PixelFormatType_MJPEG;
      break;
    case fuchsia::sysmem::PixelFormatType::YV12:
      ret.type = fuchsia_sysmem_PixelFormatType_YV12;
      break;
    case fuchsia::sysmem::PixelFormatType::BGR24:
      ret.type = fuchsia_sysmem_PixelFormatType_BGR24;
      break;
    case fuchsia::sysmem::PixelFormatType::RGB565:
      ret.type = fuchsia_sysmem_PixelFormatType_RGB565;
      break;
    case fuchsia::sysmem::PixelFormatType::RGB332:
      ret.type = fuchsia_sysmem_PixelFormatType_RGB332;
      break;
    case fuchsia::sysmem::PixelFormatType::RGB2220:
      ret.type = fuchsia_sysmem_PixelFormatType_RGB2220;
      break;
    case fuchsia::sysmem::PixelFormatType::L8:
      ret.type = fuchsia_sysmem_PixelFormatType_L8;
      break;
  }
  return ret;
}

// Make an ImageFormat_2 struct with default values except for width, height and format.
fuchsia::sysmem::ImageFormat_2 StreamConstraints::MakeImageFormat(
    uint32_t width, uint32_t height, fuchsia::sysmem::PixelFormatType format) {
  fuchsia::sysmem::PixelFormat pixel_format = {.type = format, .has_format_modifier = false};
  fuchsia_sysmem_PixelFormat pixel_format_c = ConvertPixelFormatToC(pixel_format);
  uint32_t bytes_per_row = ImageFormatStrideBytesPerWidthPixel(&pixel_format_c) * width;

  return {
      .pixel_format = {.type = format, .has_format_modifier = false},
      .coded_width = width,
      .coded_height = height,
      .bytes_per_row = bytes_per_row,
      .display_width = width,
      .display_height = height,
      .layers = 1,
      .color_space = {.type = fuchsia::sysmem::ColorSpaceType::REC601_PAL},
  };
}

void StreamConstraints::AddImageFormat(uint32_t width, uint32_t height,
                                       fuchsia::sysmem::PixelFormatType format) {
  formats_.push_back(MakeImageFormat(width, height, format));
}

fuchsia::sysmem::BufferCollectionConstraints StreamConstraints::MakeBufferCollectionConstraints()
    const {
  // Don't make a stream config if AddImageFormats has not been called.
  ZX_ASSERT(!formats_.empty());
  fuchsia::sysmem::BufferCollectionConstraints constraints;
  constraints.min_buffer_count_for_camping = buffer_count_for_camping_;
  constraints.has_buffer_memory_constraints = true;
  constraints.buffer_memory_constraints.ram_domain_supported = true;
  if (contiguous_) {
    constraints.buffer_memory_constraints.physically_contiguous_required = true;
  }
  if (cpu_access_) {
    constraints.usage.cpu = fuchsia::sysmem::cpuUsageWrite | fuchsia::sysmem::cpuUsageRead;
  } else {
    constraints.usage.video = fuchsia::sysmem::videoUsageCapture;
  }
  // Just make one constraint that has the biggest width/height for each format type:
  // TODO(41321): Map these out. Right now we just use NV12 for everything.
  uint32_t max_width = 0, max_height = 0;
  for (auto& format : formats_) {
    max_width = std::max(max_width, format.coded_width);
    max_height = std::max(max_height, format.coded_height);
  }
  constraints.image_format_constraints_count = 1;
  constraints.image_format_constraints[0] = {
      .pixel_format = {.type = fuchsia::sysmem::PixelFormatType::NV12},
      .color_spaces_count = 1,
      .color_space =
          {
              {{fuchsia::sysmem::ColorSpaceType::REC601_PAL}},
          },
      .bytes_per_row_divisor = bytes_per_row_divisor_,
      .required_max_coded_width = max_width,
      .required_max_coded_height = max_height,
  };
  return constraints;
}

fuchsia::camera2::hal::StreamConfig StreamConstraints::ConvertToStreamConfig() {
  // Don't make a stream config if AddImageFormats has not been called.
  ZX_ASSERT(!formats_.empty());
  fuchsia::camera2::StreamProperties stream_properties{};
  stream_properties.set_stream_type(stream_type_);

  for (auto& format : formats_) {
    format.bytes_per_row = fbl::round_up(format.coded_width, bytes_per_row_divisor_);
  }

  return {
      .frame_rate = {.frames_per_sec_numerator = frames_per_second_,
                     .frames_per_sec_denominator = 1},
      .constraints = MakeBufferCollectionConstraints(),
      .properties = std::move(stream_properties),
      .image_formats = fidl::Clone(formats_),
  };
}

}  // namespace camera
