// 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/files/file_path.h>
#include <base/files/scoped_file.h>
#include <base/logging.h>
#include <base/posix/eintr_wrapper.h>
#include <base/stl_util.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;
}
