// Copyright 2021 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_capabilities/v4l2.h"

#include <fcntl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <algorithm>
#include <map>
#include <string>
#include <utility>
#include <vector>

#include <base/containers/contains.h>
#include <base/files/file_path.h>
#include <base/files/scoped_file.h>
#include <base/logging.h>
#include <base/posix/eintr_wrapper.h>

#include "media_capabilities/common.h"

namespace {

enum class Codec {
  kH264 = 0,
  kVP8,
  kVP9,
  kJPEG,
  kUnknown,
};

const char* CodecToString(Codec codec) {
  switch (codec) {
    case Codec::kH264:
      return "H264";
    case Codec::kVP8:
      return "VP8";
    case Codec::kVP9:
      return "VP9";
    case Codec::kJPEG:
      return "JPEG";
    default:
      LOG(FATAL) << "Unknown codec: " << static_cast<int>(codec);
      return "";
  }
}

Codec GetCodec(uint32_t format) {
  switch (format) {
    case V4L2_PIX_FMT_H264:
    case V4L2_PIX_FMT_H264_SLICE:
      return Codec::kH264;
    case V4L2_PIX_FMT_VP8:
    case V4L2_PIX_FMT_VP8_FRAME:
      return Codec::kVP8;
    case V4L2_PIX_FMT_VP9:
    case V4L2_PIX_FMT_VP9_FRAME:
      return Codec::kVP9;
    case V4L2_PIX_FMT_JPEG:
    case V4L2_PIX_FMT_JPEG_RAW:
      return Codec::kJPEG;
    default:
      return Codec::kUnknown;
  }
}

Profile V4L2ProfileToProfile(Codec codec, uint32_t profile) {
  switch (codec) {
    case Codec::kH264:
      switch (profile) {
        case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
        case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
          return Profile::kH264Baseline;
        case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
          return Profile::kH264Main;
        case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
          return Profile::kH264High;
        case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
        case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
        case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
          break;
      }
      break;
    case Codec::kVP8:
      switch (profile) {
        case V4L2_MPEG_VIDEO_VP8_PROFILE_0:
        case V4L2_MPEG_VIDEO_VP8_PROFILE_1:
        case V4L2_MPEG_VIDEO_VP8_PROFILE_2:
        case V4L2_MPEG_VIDEO_VP8_PROFILE_3:
          return Profile::kVP8;
      }
      break;
    case Codec::kVP9:
      switch (profile) {
        case V4L2_MPEG_VIDEO_VP9_PROFILE_0:
          return Profile::kVP9Profile0;
        case V4L2_MPEG_VIDEO_VP9_PROFILE_2:
          return Profile::kVP9Profile2;
        case V4L2_MPEG_VIDEO_VP9_PROFILE_1:
        case V4L2_MPEG_VIDEO_VP9_PROFILE_3:
          break;
      }
      break;
    default:
      break;
  }
  return Profile::kNone;
}

// Return supported profiles for |codec|. If this function is called, a driver
// must support at least one profile because the codec is enumerated by
// VIDIOC_ENUM_FMT.
std::vector<Profile> GetSupportedProfiles(int device_fd, const Codec codec) {
  // Since there is only one JPEG profile, there is no API to acquire the
  // supported JPEG profile. Returns the only JPEG profile.
  if (codec == Codec::kJPEG)
    return {Profile::kJPEG};
  // TODO(b/189169588): Once drivers support V4L2_CID_MPEG_VIDEO_VP8_PROFILE,
  // call VIDIOC_QUERYMENU with it.
  if (codec == Codec::kVP8)
    return {Profile::kVP8};

  uint32_t query_id = 0;
  switch (codec) {
    case Codec::kH264:
      query_id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
      break;
    case Codec::kVP9:
      query_id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE;
      break;
    case Codec::kVP8:
    case Codec::kJPEG:
    default:
      LOG(FATAL) << "Unknown codec: " << static_cast<uint32_t>(codec);
      return {};
  }

  v4l2_queryctrl query_ctrl;
  memset(&query_ctrl, 0, sizeof(query_ctrl));
  query_ctrl.id = query_id;
  if (Ioctl(device_fd, VIDIOC_QUERYCTRL, &query_ctrl) != 0) {
    PLOG(FATAL) << "VIDIOC_QUERYCTRL failed: ";
    return {};
  }

  std::vector<Profile> profiles;
  v4l2_querymenu query_menu;
  memset(&query_menu, 0, sizeof(query_menu));
  query_menu.id = query_ctrl.id;
  for (query_menu.index = query_ctrl.minimum;
       static_cast<int>(query_menu.index) <= query_ctrl.maximum;
       query_menu.index++) {
    if (Ioctl(device_fd, VIDIOC_QUERYMENU, &query_menu) == 0) {
      const Profile profile = V4L2ProfileToProfile(codec, query_menu.index);
      if (profile != Profile::kNone && !base::Contains(profiles, profile))
        profiles.push_back(profile);
    }
  }

  LOG_IF(FATAL, profiles.empty()) << "No profile is supported even though the "
                                  << "codec is enumerated by VIDIOC_ENUM_FMT";
  return profiles;
}

std::pair<int, int> GetMaxResolution(int device_fd, const uint32_t format) {
  std::pair<int, int> max_resolution(0, 0);
  v4l2_frmsizeenum frame_size;
  memset(&frame_size, 0, sizeof(frame_size));
  frame_size.pixel_format = format;
  for (; Ioctl(device_fd, VIDIOC_ENUM_FRAMESIZES, &frame_size) == 0;
       ++frame_size.index) {
    if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
      if (frame_size.discrete.width >=
              static_cast<uint32_t>(max_resolution.first) &&
          frame_size.discrete.height >=
              static_cast<uint32_t>(max_resolution.second)) {
        max_resolution.first = frame_size.discrete.width;
        max_resolution.second = frame_size.discrete.height;
      }
    } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE ||
               frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
      max_resolution.first = frame_size.stepwise.max_width;
      max_resolution.second = frame_size.stepwise.max_height;
      break;
    }
  }

  return max_resolution;
}

std::vector<Capability> GetCapabilitiesInPath(const base::FilePath& path,
                                              bool decode) {
  base::ScopedFD device_fd(
      HANDLE_EINTR(open(path.value().c_str(), O_RDWR | O_CLOEXEC)));
  if (!device_fd.is_valid())
    return {};

  std::vector<uint32_t> formats;
  v4l2_fmtdesc fmtdesc;
  memset(&fmtdesc, 0, sizeof(fmtdesc));
  fmtdesc.type = decode ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
                        : V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  for (; Ioctl(device_fd.get(), VIDIOC_ENUM_FMT, &fmtdesc) == 0;
       ++fmtdesc.index) {
    formats.push_back(fmtdesc.pixelformat);
  }

  std::vector<Capability> capabilities;
  for (uint32_t format : formats) {
    const Codec codec = GetCodec(format);
    if (codec == Codec::kUnknown)
      continue;

    const std::vector<Profile> profiles =
        GetSupportedProfiles(device_fd.get(), codec);
    LOG_ASSERT(!profiles.empty());
    const std::pair<int, int> max_resolution =
        GetMaxResolution(device_fd.get(), format);
    const std::vector<Resolution> resolutions =
        GetInterestingResolutionsUpTo(max_resolution);
    LOG_IF(FATAL, resolutions.empty())
        << "The maximum supported resolution for " << CodecToString(codec)
        << " is too small: " << max_resolution.first << "x"
        << max_resolution.second;

    // V4L2 API doesn't have a way of querying supported subsamplings and color
    // depth.
    for (const Profile profile : profiles) {
      // TODO(b/172229001, b/188598699): For JPEG profiles, actually, supported
      // subsamplings can be queried by V4L2_CID_JPEG_CHROMA_SUBSAMPLING. But it
      // has never been used in Chrome OS. Call it once we confirm that it works
      // on all V4L2 devices. We temporarily do as if all subsamplings are
      // supported to avoid false negatives.
      // TODO(b/172229001): For other profiles, we should guess them from
      // supported YUV formats of CAPTURE queue for decoding and of OUTPUT queue
      // for encoding.
      std::vector<Subsampling> subsamplings = {Subsampling::kYUV420};
      if (profile == Profile::kJPEG) {
        subsamplings = {Subsampling::kYUV420, Subsampling::kYUV422,
                        Subsampling::kYUV444};
      }

      for (const Subsampling subsampling : subsamplings) {
        const ColorDepth color_depth = profile == Profile::kVP9Profile2
                                           ? ColorDepth::k10bit
                                           : ColorDepth::k8bit;
        for (const Resolution resolution : resolutions) {
          capabilities.push_back(Capability(profile, decode, resolution,
                                            subsampling, color_depth));
        }
      }
    }
  }

  return capabilities;
}

std::vector<Capability> GetCapabilitiesInPaths(
    const std::vector<base::FilePath>& paths, bool decode) {
  std::vector<Capability> capabilities;
  for (const base::FilePath& path : paths) {
    for (auto&& c : GetCapabilitiesInPath(path, decode)) {
      if (!base::Contains(capabilities, c))
        capabilities.push_back(std::move(c));
    }
  }

  return capabilities;
}

std::vector<Capability> GetDecodeCapabilities() {
  const base::FilePath kVideoDecoderDevicePath("/dev/video-dec");
  const base::FilePath kJpegDecoderDevicePath("/dev/jpeg-dec");
  std::vector<base::FilePath> device_paths;
  auto video_decoder_device_paths =
      GetAllFilesWithPrefix(kVideoDecoderDevicePath);
  auto jpeg_decoder_device_paths =
      GetAllFilesWithPrefix(kJpegDecoderDevicePath);
  device_paths.insert(device_paths.end(), video_decoder_device_paths.begin(),
                      video_decoder_device_paths.end());
  device_paths.insert(device_paths.end(), jpeg_decoder_device_paths.begin(),
                      jpeg_decoder_device_paths.end());

  return GetCapabilitiesInPaths(device_paths, /*decode=*/true);
}

std::vector<Capability> GetEncodeCapabilities() {
  const base::FilePath kVideoEncoderDevicePath("/dev/video-enc");
  const base::FilePath kJpegEncoderDevicePath("/dev/jpeg-enc");
  std::vector<base::FilePath> device_paths;
  auto video_encoder_device_paths =
      GetAllFilesWithPrefix(kVideoEncoderDevicePath);
  auto jpeg_encoder_device_paths =
      GetAllFilesWithPrefix(kJpegEncoderDevicePath);
  device_paths.insert(device_paths.end(), video_encoder_device_paths.begin(),
                      video_encoder_device_paths.end());
  device_paths.insert(device_paths.end(), jpeg_encoder_device_paths.begin(),
                      jpeg_encoder_device_paths.end());

  return GetCapabilitiesInPaths(device_paths, /*decode=*/false);
}
}  // namespace

std::vector<Capability> DetectV4L2Capabilities() {
  auto decode_capabilities = GetEncodeCapabilities();
  auto encode_capabilities = GetDecodeCapabilities();

  auto& capabilities = decode_capabilities;
  capabilities.insert(capabilities.end(), encode_capabilities.begin(),
                      encode_capabilities.end());
  return capabilities;
}
