/* Copyright 2016 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 "hal/usb/stream_format.h"

#include <algorithm>
#include <cmath>
#include <tuple>

#include <linux/videodev2.h>
#include <system/graphics.h>

#include "cros-camera/common.h"
#include "hal/usb/quirks.h"

namespace cros {

namespace {

constexpr int kSupportedHalFormats[] = {
    HAL_PIXEL_FORMAT_BLOB, HAL_PIXEL_FORMAT_YCbCr_420_888,
    HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED};

std::vector<uint32_t> GetSupportedFourCCs(bool prefer_mjpeg) {
  // The preference of supported fourccs in the list is from high to low.
  if (prefer_mjpeg) {
    return {
        V4L2_PIX_FMT_MJPEG,
        V4L2_PIX_FMT_YUYV,
    };
  }
  return {
      V4L2_PIX_FMT_YUYV,
      V4L2_PIX_FMT_MJPEG,
  };
}

}  // namespace

// Return corresponding format by matching resolution |width|x|height| in
// |formats|.
const SupportedFormat* FindFormatByResolution(const SupportedFormats& formats,
                                              uint32_t width,
                                              uint32_t height) {
  for (const auto& format : formats) {
    if (format.width == width && format.height == height) {
      return &format;
    }
  }
  return NULL;
}

SupportedFormat GetMaximumFormat(const SupportedFormats& supported_formats) {
  SupportedFormat max_format;
  memset(&max_format, 0, sizeof(max_format));
  for (const auto& supported_format : supported_formats) {
    if (supported_format.width >= max_format.width &&
        supported_format.height >= max_format.height) {
      max_format = supported_format;
    }
  }
  return max_format;
}

std::vector<int32_t> GetJpegAvailableThumbnailSizes(
    const SupportedFormats& supported_formats) {
  // This list will include at least one non-zero resolution, plus (0,0) for
  // indicating no thumbnail should be generated.
  std::vector<Size> sizes = {{0, 0}};

  // Each output JPEG size in android.scaler.availableStreamConfigurations will
  // have at least one corresponding size that has the same aspect ratio in
  // availableThumbnailSizes, and vice versa.
  for (auto& supported_format : supported_formats) {
    double aspect_ratio =
        static_cast<double>(supported_format.width) / supported_format.height;

    if (supported_format.width < 192) {
      // Use the same resolution as the thumbnail size.
      sizes.push_back({supported_format.width, supported_format.height});
      continue;
    }
    // Note that we only support to generate thumbnails with (width % 8 == 0)
    // and (height % 2 == 0) for now, so set width as multiple of 48 is good for
    // the common ratios 4:3, 16:9, and 3:2. When width is 192, the thumbnail
    // sizes would be 192x144, 192x108, and 192x128 respectively.
    uint32_t thumbnail_width = 192;
    uint32_t thumbnail_height = round(thumbnail_width / aspect_ratio);

    // It's still possible that some resolutions that make thumbnail_height odd,
    // such as 11:9 (352x288). Ensure it's even by masking out LSB.
    thumbnail_height &= ~1;

    sizes.push_back({thumbnail_width, thumbnail_height});
  }

  // The sizes will be sorted by increasing pixel area (width x height). If
  // several resolutions have the same area, they will be sorted by increasing
  // width.
  std::sort(sizes.begin(), sizes.end());
  sizes.erase(std::unique(sizes.begin(), sizes.end()), sizes.end());

  // The aspect ratio of the largest thumbnail size will be same as the aspect
  // ratio of largest JPEG output size in
  // android.scaler.availableStreamConfigurations. The largest size is defined
  // as the size that has the largest pixel area in a given size list.
  auto max_format = GetMaximumFormat(supported_formats);
  double aspect_ratio =
      static_cast<double>(max_format.width) / max_format.height;
  for (uint32_t thumbnail_width = 240; true; thumbnail_width += 48) {
    uint32_t thumbnail_height = round(thumbnail_width / aspect_ratio);
    thumbnail_height &= ~1;
    Size size(thumbnail_width, thumbnail_height);
    if (sizes.back() < size) {
      sizes.push_back(size);
      break;
    }
  }

  std::vector<int32_t> ret;
  for (auto& size : sizes) {
    ret.push_back(size.width);
    ret.push_back(size.height);
  }
  return ret;
}

SupportedFormats GetQualifiedFormats(const SupportedFormats& supported_formats,
                                     uint32_t quirks) {
  // The preference of supported fourccs in the list is from high to low.
  bool prefer_mjpeg = quirks & kQuirkPreferMjpeg;
  const std::vector<uint32_t> supported_fourccs =
      GetSupportedFourCCs(prefer_mjpeg);
  SupportedFormats qualified_formats;
  for (const auto& supported_fourcc : supported_fourccs) {
    for (const auto& supported_format : supported_formats) {
      if (supported_format.fourcc != supported_fourcc) {
        continue;
      }

      // For the same resolution, prefer the format which has larger frame rate.
      // For the same frame rate, choose preferred fourcc first.
      auto it = qualified_formats.cbegin();
      for (; it != qualified_formats.cend(); it++) {
        if (it->width == supported_format.width &&
            it->height == supported_format.height) {
          break;
        }
      }
      if (it != qualified_formats.cend()) {
        float max_fps_existed_format = GetMaximumFrameRate(*it);
        float max_fps_current_format = GetMaximumFrameRate(supported_format);
        if (max_fps_existed_format < max_fps_current_format) {
          qualified_formats.erase(it);
        } else {
          continue;
        }
      }
      qualified_formats.push_back(supported_format);
    }
  }

  // Sort the resolution from high to low for easier reading and consistent of
  // different camera modules.
  // CTS uses the first 2 resolutions to create streams. It also let CTS choose
  // high resolutions.
  std::sort(qualified_formats.begin(), qualified_formats.end());
  std::reverse(qualified_formats.begin(), qualified_formats.end());
  return qualified_formats;
}

bool IsFormatSupported(const SupportedFormats& supported_formats,
                       const camera3_stream_t& stream) {
  if (std::find(std::begin(kSupportedHalFormats),
                std::end(kSupportedHalFormats),
                stream.format) == std::end(kSupportedHalFormats)) {
    return false;
  }
  for (const auto& supported_format : supported_formats) {
    if (stream.width == supported_format.width &&
        stream.height == supported_format.height) {
      return true;
    }
  }
  return false;
}

float GetMaximumFrameRate(const SupportedFormat& format) {
  float max_fps = 0;
  for (const auto& frame_rate : format.frame_rates) {
    if (frame_rate > max_fps) {
      max_fps = frame_rate;
    }
  }

  return max_fps;
}

}  // namespace cros
