// Copyright 2014 The Chromium 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/capture/video/linux/video_capture_device_factory_linux.h"

#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/ioctl.h>

#include <algorithm>
#include <utility>

#include "base/containers/contains.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "media/capture/video/linux/scoped_v4l2_device_fd.h"
#include "media/capture/video/linux/video_capture_device_linux.h"

#if defined(OS_OPENBSD)
#include <sys/videoio.h>
#else
#include <linux/videodev2.h>
#endif

namespace media {

namespace {

bool CompareCaptureDevices(const VideoCaptureDeviceInfo& a,
                           const VideoCaptureDeviceInfo& b) {
  return a.descriptor < b.descriptor;
}

// USB VID and PID are both 4 bytes long.
const size_t kVidPidSize = 4;
const size_t kMaxInterfaceNameSize = 256;

// /sys/class/video4linux/video{N}/device is a symlink to the corresponding
// USB device info directory.
const char kVidPathTemplate[] = "/sys/class/video4linux/%s/device/../idVendor";
const char kPidPathTemplate[] = "/sys/class/video4linux/%s/device/../idProduct";
const char kInterfacePathTemplate[] =
    "/sys/class/video4linux/%s/device/interface";

bool ReadIdFile(const std::string& path, std::string* id) {
  char id_buf[kVidPidSize];
  FILE* file = fopen(path.c_str(), "rb");
  if (!file)
    return false;
  const bool success = fread(id_buf, kVidPidSize, 1, file) == 1;
  fclose(file);
  if (!success)
    return false;
  id->append(id_buf, kVidPidSize);
  return true;
}

std::string ExtractFileNameFromDeviceId(const std::string& device_id) {
  // |unique_id| is of the form "/dev/video2".  |file_name| is "video2".
  const char kDevDir[] = "/dev/";
  DCHECK(base::StartsWith(device_id, kDevDir, base::CompareCase::SENSITIVE));
  return device_id.substr(strlen(kDevDir), device_id.length());
}

class DevVideoFilePathsDeviceProvider
    : public VideoCaptureDeviceFactoryLinux::DeviceProvider {
 public:
  void GetDeviceIds(std::vector<std::string>* target_container) override {
    const base::FilePath path("/dev/");
    base::FileEnumerator enumerator(path, false, base::FileEnumerator::FILES,
                                    "video*");
    while (!enumerator.Next().empty()) {
      const base::FileEnumerator::FileInfo info = enumerator.GetInfo();
      target_container->emplace_back(path.value() + info.GetName().value());
    }
  }

  std::string GetDeviceModelId(const std::string& device_id) override {
    const std::string file_name = ExtractFileNameFromDeviceId(device_id);
    std::string usb_id;
    const std::string vid_path =
        base::StringPrintf(kVidPathTemplate, file_name.c_str());
    if (!ReadIdFile(vid_path, &usb_id))
      return usb_id;

    usb_id.append(":");
    const std::string pid_path =
        base::StringPrintf(kPidPathTemplate, file_name.c_str());
    if (!ReadIdFile(pid_path, &usb_id))
      usb_id.clear();

    return usb_id;
  }

  std::string GetDeviceDisplayName(const std::string& device_id) override {
    const std::string file_name = ExtractFileNameFromDeviceId(device_id);
    const std::string interface_path =
        base::StringPrintf(kInterfacePathTemplate, file_name.c_str());
    std::string display_name;
    if (!base::ReadFileToStringWithMaxSize(base::FilePath(interface_path),
                                           &display_name,
                                           kMaxInterfaceNameSize)) {
      return std::string();
    }
    return display_name;
  }
};

}  // namespace

VideoCaptureDeviceFactoryLinux::VideoCaptureDeviceFactoryLinux(
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
    : v4l2_(base::MakeRefCounted<V4L2CaptureDeviceImpl>()),
      device_provider_(std::make_unique<DevVideoFilePathsDeviceProvider>()),
      ui_task_runner_(ui_task_runner) {}

VideoCaptureDeviceFactoryLinux::~VideoCaptureDeviceFactoryLinux() = default;

void VideoCaptureDeviceFactoryLinux::SetV4L2EnvironmentForTesting(
    scoped_refptr<V4L2CaptureDevice> v4l2,
    std::unique_ptr<VideoCaptureDeviceFactoryLinux::DeviceProvider>
        device_provider) {
  v4l2_ = std::move(v4l2);
  device_provider_ = std::move(device_provider);
}

std::unique_ptr<VideoCaptureDevice>
VideoCaptureDeviceFactoryLinux::CreateDevice(
    const VideoCaptureDeviceDescriptor& device_descriptor) {
  DCHECK(thread_checker_.CalledOnValidThread());
  auto self =
      std::make_unique<VideoCaptureDeviceLinux>(v4l2_.get(), device_descriptor);

  // Test opening the device driver. This is to make sure it is available.
  // We will reopen it again in our worker thread when someone
  // allocates the camera.
  ScopedV4L2DeviceFD fd(
      v4l2_.get(),
      HANDLE_EINTR(v4l2_->open(device_descriptor.device_id.c_str(), O_RDONLY)));
  if (!fd.is_valid()) {
    DLOG(ERROR) << "Cannot open device";
    return nullptr;
  }

  return self;
}

void VideoCaptureDeviceFactoryLinux::GetDevicesInfo(
    GetDevicesInfoCallback callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  std::vector<VideoCaptureDeviceInfo> devices_info;
  std::vector<std::string> filepaths;
  device_provider_->GetDeviceIds(&filepaths);
  for (auto& unique_id : filepaths) {
    const ScopedV4L2DeviceFD fd(
        v4l2_.get(), HANDLE_EINTR(v4l2_->open(unique_id.c_str(), O_RDONLY)));
    if (!fd.is_valid()) {
      DLOG(ERROR) << "Couldn't open " << unique_id;
      continue;
    }
    // Test if this is a V4L2CaptureDevice capture device and if it has at least
    // one supported capture format. Devices that have capture and output
    // capabilities at the same time are memory-to-memory and are skipped, see
    // http://crbug.com/139356.
    // In theory, checking for CAPTURE/OUTPUT in caps.capabilities should only
    // be done if V4L2_CAP_DEVICE_CAPS is not set. However, this was not done
    // in the past and it is unclear if it breaks with existing devices. And if
    // a device is accepted incorrectly then it will not have any usable
    // formats and is skipped anyways.
    v4l2_capability cap;
    if ((DoIoctl(fd.get(), VIDIOC_QUERYCAP, &cap) == 0) &&
        ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE &&
          !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) ||
         (cap.capabilities & V4L2_CAP_DEVICE_CAPS &&
          cap.device_caps & V4L2_CAP_VIDEO_CAPTURE &&
          !(cap.device_caps & V4L2_CAP_VIDEO_OUTPUT))) &&
        HasUsableFormats(fd.get(), cap.capabilities)) {
      const std::string model_id =
          device_provider_->GetDeviceModelId(unique_id);
      std::string display_name =
          device_provider_->GetDeviceDisplayName(unique_id);
      if (display_name.empty())
        display_name = reinterpret_cast<char*>(cap.card);

      VideoFacingMode facing_mode = VideoFacingMode::MEDIA_VIDEO_FACING_NONE;

      VideoCaptureFormats supported_formats;
      GetSupportedFormatsForV4L2BufferType(fd.get(), &supported_formats);
      if (supported_formats.empty()) {
        DVLOG(1) << "No supported formats: " << unique_id;
        continue;
      }

      devices_info.emplace_back(VideoCaptureDeviceDescriptor(
          display_name, unique_id, model_id,
          VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE, GetControlSupport(fd.get()),
          VideoCaptureTransportType::OTHER_TRANSPORT, facing_mode));

      devices_info.back().supported_formats = std::move(supported_formats);
    }
  }

  // This is required for some applications that rely on the stable ordering of
  // devices.
  std::sort(devices_info.begin(), devices_info.end(), CompareCaptureDevices);

  std::move(callback).Run(std::move(devices_info));
}

int VideoCaptureDeviceFactoryLinux::DoIoctl(int fd, int request, void* argp) {
  return HANDLE_EINTR(v4l2_->ioctl(fd, request, argp));
}

// Check if the video capture device supports pan, tilt and zoom controls.
VideoCaptureControlSupport VideoCaptureDeviceFactoryLinux::GetControlSupport(
    int fd) {
  VideoCaptureControlSupport control_support;
  control_support.pan = GetControlSupport(fd, V4L2_CID_PAN_ABSOLUTE);
  control_support.tilt = GetControlSupport(fd, V4L2_CID_TILT_ABSOLUTE);
  control_support.zoom = GetControlSupport(fd, V4L2_CID_ZOOM_ABSOLUTE);
  return control_support;
}

bool VideoCaptureDeviceFactoryLinux::GetControlSupport(int fd, int control_id) {
  v4l2_queryctrl range = {};
  range.id = control_id;
  range.type = V4L2_CTRL_TYPE_INTEGER;
  return DoIoctl(fd, VIDIOC_QUERYCTRL, &range) == 0 &&
         range.minimum < range.maximum;
}

bool VideoCaptureDeviceFactoryLinux::HasUsableFormats(int fd,
                                                      uint32_t capabilities) {
  if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
    return false;

  const std::vector<uint32_t>& usable_fourccs =
      VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false);
  v4l2_fmtdesc fmtdesc = {};
  fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  for (; DoIoctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) {
    if (base::Contains(usable_fourccs, fmtdesc.pixelformat))
      return true;
  }

  DVLOG(1) << "No usable formats found";
  return false;
}

std::vector<float> VideoCaptureDeviceFactoryLinux::GetFrameRateList(
    int fd,
    uint32_t fourcc,
    uint32_t width,
    uint32_t height) {
  std::vector<float> frame_rates;

  v4l2_frmivalenum frame_interval = {};
  frame_interval.pixel_format = fourcc;
  frame_interval.width = width;
  frame_interval.height = height;
  for (; DoIoctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval) == 0;
       ++frame_interval.index) {
    if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
      if (frame_interval.discrete.numerator != 0) {
        frame_rates.push_back(
            frame_interval.discrete.denominator /
            static_cast<float>(frame_interval.discrete.numerator));
      }
    } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
               frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
      // TODO(mcasas): see http://crbug.com/249953, support these devices.
      NOTIMPLEMENTED_LOG_ONCE();
      break;
    }
  }
  // Some devices, e.g. Kinect, do not enumerate any frame rates, see
  // http://crbug.com/412284. Set their frame_rate to zero.
  if (frame_rates.empty())
    frame_rates.push_back(0);
  return frame_rates;
}

void VideoCaptureDeviceFactoryLinux::GetSupportedFormatsForV4L2BufferType(
    int fd,
    VideoCaptureFormats* supported_formats) {
  v4l2_fmtdesc v4l2_format = {};
  v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  for (; DoIoctl(fd, VIDIOC_ENUM_FMT, &v4l2_format) == 0; ++v4l2_format.index) {
    VideoCaptureFormat supported_format;
    supported_format.pixel_format =
        VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat(
            v4l2_format.pixelformat);

    if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN)
      continue;

    v4l2_frmsizeenum frame_size = {};
    frame_size.pixel_format = v4l2_format.pixelformat;
    for (; DoIoctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size) == 0;
         ++frame_size.index) {
      if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
        supported_format.frame_size.SetSize(frame_size.discrete.width,
                                            frame_size.discrete.height);
      } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE ||
                 frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
        // TODO(mcasas): see http://crbug.com/249953, support these devices.
        NOTIMPLEMENTED_LOG_ONCE();
        continue;
      }

      const std::vector<float> frame_rates = GetFrameRateList(
          fd, v4l2_format.pixelformat, frame_size.discrete.width,
          frame_size.discrete.height);
      for (const auto& frame_rate : frame_rates) {
        supported_format.frame_rate = frame_rate;
        supported_formats->push_back(supported_format);
        DVLOG(1) << VideoCaptureFormat::ToString(supported_format);
      }
    }
  }
}

}  // namespace media
