// Copyright (c) 2010 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 <iostream>
#include <limits>
#include <memory>
#include <string>
#include <vector>

#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/system/sys_info.h>
#include <base/time/time.h>
#include <brillo/flag_helper.h>
#include <chromeos-config/libcros_config/cros_config.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <libyuv.h>

#include "cros-camera/common.h"
#include "hal/usb/camera_characteristics.h"
#include "hal/usb/common_types.h"
#include "hal/usb/v4l2_test/media_v4l2_device.h"

namespace cros {
namespace tests {

class V4L2TestEnvironment;

namespace {

using ::testing::AnyOf;
using ::testing::StrEq;
using ::testing::GTEST_FLAG(filter);
using ::testing::MatchesRegex;

V4L2TestEnvironment* g_env;

// Test lists:
// default: for devices without ARC++, and devices with ARC++ which use
//          camera HAL v1.
// halv3: for devices with ARC++ which use camera HAL v3.
// certification: for third-party labs to verify new camera modules.

constexpr char kDefaultTestList[] = "default";
constexpr char kHalv3TestList[] = "halv3";
constexpr char kCertificationTestList[] = "certification";

const float kDefaultFrameRate = 30.0;

std::string GetUsbVidPid(const base::FilePath& path) {
  auto read_id = [&](const char* name) -> std::string {
    base::FilePath id_path(
        base::StringPrintf("/sys/class/video4linux/%s/device/../%s",
                           path.BaseName().value().c_str(), name));
    base::FilePath normalized;
    if (!base::NormalizeFilePath(id_path, &normalized)) {
      return "";
    }
    std::string id;
    if (!base::ReadFileToString(normalized, &id)) {
      return "";
    }
    return base::TrimWhitespaceASCII(id, base::TRIM_ALL).as_string();
  };
  std::string vid = read_id("idVendor");
  std::string pid = read_id("idProduct");
  if (vid.empty() || pid.empty()) {
    return "";
  }
  return vid + ":" + pid;
}

bool IsCaptureDevice(const base::FilePath& path) {
  const uint32_t kCaptureMask =
      V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
  // Old drivers use (CAPTURE | OUTPUT) for memory-to-memory video devices.
  const uint32_t kOutputMask =
      V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
  const uint32_t kM2mMask = V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE;

  V4L2Device dev(path.value().c_str(), 1);
  if (!dev.OpenDevice(/*show_err=*/false)) {
    return false;
  }
  v4l2_capability caps;
  if (!dev.ProbeCaps(&caps, false)) {
    return false;
  }
  uint32_t mask = (caps.capabilities & V4L2_CAP_DEVICE_CAPS)
                      ? caps.device_caps
                      : caps.capabilities;
  return (mask & kCaptureMask) && !(mask & kOutputMask) && !(mask & kM2mMask);
}

bool IsUsbCamera(const base::FilePath& path) {
  return IsCaptureDevice(path) && !GetUsbVidPid(path).empty();
}

std::vector<base::FilePath> GetUsbCameras() {
  std::vector<base::FilePath> usb_cameras;
  base::FilePath pattern("/dev/video*");
  base::FileEnumerator enumerator(pattern.DirName(), false,
                                  base::FileEnumerator::FILES,
                                  pattern.BaseName().value());
  for (auto path = enumerator.Next(); !path.empty(); path = enumerator.Next()) {
    if (IsUsbCamera(path)) {
      usb_cameras.push_back(path);
    }
  }
  std::sort(usb_cameras.begin(), usb_cameras.end());
  return usb_cameras;
}

void AddNegativeGtestFilter(const std::string& pattern) {
  if (GTEST_FLAG(filter).find(pattern) == std::string::npos) {
    LOG(INFO) << "Disable test " << pattern;
    char has_dash = GTEST_FLAG(filter).find('-') != std::string::npos;
    GTEST_FLAG(filter).append(has_dash ? ":" : "-").append(pattern);
  }
}

// This is for Android SurfaceViewPreviewTest CTS test cases.
bool CheckTimestampsInOrder(const std::vector<int64_t>& timestamps) {
  for (size_t i = 1; i < timestamps.size(); i++) {
    if (timestamps[i - 1] >= timestamps[i])
      return false;
  }
  return true;
}

// This is for Android testCameraToSurfaceTextureMetadata CTS test case.
bool CheckConstantFramerate(const std::vector<int64_t>& timestamps,
                            float require_fps) {
  // Timestamps are from driver. We only allow 1.5% error buffer for the frame
  // duration. The margin is aligned to CTS tests.
  float slop_margin = 0.015;
  float slop_max_frame_duration_ms = (1e3 / require_fps) * (1 + slop_margin);
  float slop_min_frame_duration_ms = (1e3 / require_fps) * (1 - slop_margin);

  for (size_t i = 1; i < timestamps.size(); i++) {
    float frame_duration_ms = (timestamps[i] - timestamps[i - 1]) / 1e6;
    if (frame_duration_ms > slop_max_frame_duration_ms ||
        frame_duration_ms < slop_min_frame_duration_ms) {
      LOG(WARNING) << base::StringPrintf(
          "Frame duration %f out of frame rate bounds [%f, %f]",
          frame_duration_ms, slop_min_frame_duration_ms,
          slop_max_frame_duration_ms);
      return false;
    }
  }
  return true;
}

bool HasFrameRate(const SupportedFormat& format, float target) {
  return std::any_of(
      format.frame_rates.begin(), format.frame_rates.end(), [&](float fps) {
        return abs(fps - target) <= std::numeric_limits<float>::epsilon();
      });
}

bool CompareFormat(const SupportedFormat& fmt1, const SupportedFormat& fmt2) {
  auto get_key = [](const SupportedFormat& fmt)
      -> std::tuple<uint32_t, uint32_t, bool, int> {
    uint32_t area = fmt.width * fmt.height;
    bool has_default_fps = HasFrameRate(fmt, kDefaultFrameRate);
    int fourcc = [&] {
      switch (fmt.fourcc) {
        case V4L2_PIX_FMT_YUYV:
          return 2;
        case V4L2_PIX_FMT_MJPEG:
          return 1;
        default:
          return 0;
      }
    }();
    return {area, fmt.width, has_default_fps, fourcc};
  };
  return get_key(fmt1) > get_key(fmt2);
}

}  // namespace

class V4L2TestEnvironment : public ::testing::Environment {
 public:
  V4L2TestEnvironment(const std::string& test_list,
                      const std::string& device_path)
      : test_list_(test_list),
        device_path_(device_path),
        usb_info_(GetUsbVidPid(base::FilePath(device_path))) {
    std::string model = []() {
      std::string res;
      brillo::CrosConfig cros_config;
      if (!cros_config.Init()) {
        LOGF(WARNING) << "Failed to initialize CrOS config";
        return res;
      }
      if (!cros_config.GetString("/", "name", &res)) {
        LOGF(WARNING) << "Failed to get model name of CrOS device";
      }
      return res;
    }();
    // The WFC maximum supported resoltuion requirement is waived on some
    // models (b/158564147).
    if ((model == "blacktip360" && usb_info_ == "0408:5192") ||
        (model == "garg360" && usb_info_ == "0408:5194")) {
      AddNegativeGtestFilter("V4L2Test.MaximumSupportedResolution");
    }

    // The gtest filter need to be modified before RUN_ALL_TESTS().
    if (test_list == kDefaultTestList) {
      // Disable new requirements added in HALv3.
      AddNegativeGtestFilter("V4L2Test.FirstFrameAfterStreamOn");
      AddNegativeGtestFilter("V4L2Test.CroppingResolution");

      // Some snappy old SKU cannot meet the requirement. Skip the test to
      // avoid alarm. Please see http://crbug.com/737874 for detail.
      if (base::SysInfo::GetLsbReleaseBoard() == "snappy") {
        AddNegativeGtestFilter("V4L2Test.MaximumSupportedResolution");
      }
      // The camera module sometimes generate out-of-order buffer timestamps.
      // See b/158957477 for detail.
      if (usb_info_ == "0c45:6a05") {
        check_timestamps_in_order_ = false;
      }
    } else if (test_list == kCertificationTestList) {
      // There is no facing information when running certification test.
      AddNegativeGtestFilter("V4L2Test.MaximumSupportedResolution");
    } else if (test_list == kHalv3TestList) {
      // The camera modules do not support 1080p 30fps and got waived.
      // Please see http://b/142289821 and http://b/115453284 for the detail.
      if (usb_info_ == "04f2:b6b5" || usb_info_ == "0bda:5647") {
        AddNegativeGtestFilter(
            "V4L2Test/V4L2TestWithResolution.Resolutions/1920x1080");
        AddNegativeGtestFilter("V4L2Test.CroppingResolution");
      }
    }
  }

  void SetUp() {
    ASSERT_THAT(usb_info_, MatchesRegex("[0-9a-f]{4}:[0-9a-f]{4}"));

    LOG(INFO) << "Test list: " << test_list_;
    LOG(INFO) << "Device path: " << device_path_;
    LOG(INFO) << "USB Info: " << usb_info_;

    ASSERT_THAT(test_list_,
                AnyOf(StrEq(kDefaultTestList), StrEq(kHalv3TestList),
                      StrEq(kCertificationTestList)));
    ASSERT_TRUE(base::PathExists(base::FilePath(device_path_)));

    CameraCharacteristics characteristics;
    const DeviceInfo* device_info =
        characteristics.Find(usb_info_.substr(0, 4), usb_info_.substr(5, 9));

    if (test_list_ != kDefaultTestList) {
      ASSERT_TRUE(characteristics.ConfigFileExists())
          << test_list_ << " test list needs camera config file";
      ASSERT_NE(device_info, nullptr)
          << usb_info_ << " is not described in camera config file\n";
    } else {
      if (!characteristics.ConfigFileExists()) {
        LOG(INFO) << "Camera config file doesn't exist";
      } else if (device_info == nullptr && !usb_info_.empty()) {
        LOG(INFO) << usb_info_ << " is not described in camera config file";
      }
    }

    // Get parameter from config file.
    if (device_info) {
      support_constant_framerate_ =
          !device_info->constant_framerate_unsupported;
      skip_frames_ = device_info->frames_to_skip_after_streamon;
      lens_facing_ = device_info->lens_facing;

      // If there is a camera config and test list is not HAL v1, then we can
      // check cropping requirement according to the sensor physical size.
      if (test_list_ != kDefaultTestList) {
        if (device_info->sensor_info_active_array_size.is_valid()) {
          sensor_array_size_width_ =
              device_info->sensor_info_active_array_size.width();
          sensor_array_size_height_ =
              device_info->sensor_info_active_array_size.height();
        } else {
          LOGF(WARNING) << "Sensor active array size is not available in camera"
                           " config file, using full pixel array size";
          sensor_array_size_width_ =
              device_info->sensor_info_pixel_array_size_width;
          sensor_array_size_height_ =
              device_info->sensor_info_pixel_array_size_height;
        }
      }
    }

    if (test_list_ == kDefaultTestList) {
      check_1280x960_ = false;
      check_1600x1200_ = false;
      check_constant_framerate_ = false;
    } else {
      check_1280x960_ = true;
      check_1600x1200_ = true;
      check_constant_framerate_ = true;
      if (skip_frames_ != 0) {
        // Some existing HALv3 boards are using this field to workaround issues
        // that are not caught in this test, such as:
        // * corrupted YUYV frames, and
        // * broken JPEG image when setting power frequency to 60Hz.
        // Although it's infeasible to test every possible parameter
        // combinations, we might want to add tests for the failing cases above
        // in the future and qualify the existing devices.
        LOG(WARNING) << "Ignore non-zero skip frames for v3 devices";
        skip_frames_ = 0;
      }
      ASSERT_TRUE(support_constant_framerate_)
          << "HALv3 devices should support constant framerate";
    }

    LOG(INFO) << "Check 1280x960: " << std::boolalpha << check_1280x960_;
    LOG(INFO) << "Check 1600x1200: " << std::boolalpha << check_1600x1200_;
    LOG(INFO) << "Check constant framerate: " << std::boolalpha
              << check_constant_framerate_;
    LOG(INFO) << "Number of skip frames after stream on: " << skip_frames_;
  }

  std::string test_list_;
  std::string device_path_;
  std::string usb_info_;

  bool check_1280x960_ = false;
  bool check_1600x1200_ = false;
  bool check_constant_framerate_ = false;
  bool check_timestamps_in_order_ = true;

  bool support_constant_framerate_ = false;
  uint32_t skip_frames_ = 0;
  LensFacing lens_facing_ = LensFacing::kFront;
  uint32_t sensor_array_size_width_ = 0;
  uint32_t sensor_array_size_height_ = 0;
};

class V4L2Test : public ::testing::Test {
 protected:
  V4L2Test() : dev_(g_env->device_path_.c_str(), 4) {}

  void SetUp() override { ASSERT_TRUE(dev_.OpenDevice()); }

  void TearDown() override { dev_.CloseDevice(); }

  void ProbeSupportedFormats() {
    uint32_t num_format = 0;
    dev_.EnumFormat(&num_format, false);
    for (uint32_t i = 0; i < num_format; ++i) {
      SupportedFormat format;
      ASSERT_TRUE(dev_.GetPixelFormat(i, &format.fourcc));

      uint32_t num_frame_size;
      ASSERT_TRUE(dev_.EnumFrameSize(format.fourcc, &num_frame_size, false));

      for (uint32_t j = 0; j < num_frame_size; ++j) {
        ASSERT_TRUE(
            dev_.GetFrameSize(j, format.fourcc, &format.width, &format.height));
        uint32_t num_frame_rate;
        ASSERT_TRUE(dev_.EnumFrameInterval(format.fourcc, format.width,
                                           format.height, &num_frame_rate,
                                           false));

        format.frame_rates.clear();
        for (uint32_t k = 0; k < num_frame_rate; ++k) {
          float frame_rate;
          ASSERT_TRUE(dev_.GetFrameInterval(k, format.fourcc, format.width,
                                            format.height, &frame_rate));
          // All supported resolution should have at least 1 fps.
          ASSERT_GE(frame_rate, 1.0);
          format.frame_rates.push_back(frame_rate);
        }
        supported_formats_.push_back(format);
      }
    }

    std::sort(supported_formats_.begin(), supported_formats_.end(),
              CompareFormat);
  }

  const SupportedFormats& GetSupportedFormats() {
    if (supported_formats_.empty()) {
      ProbeSupportedFormats();
    }
    return supported_formats_;
  }

  // Find format according to width and height. If multiple formats support the
  // same resolution, choose the first one.
  const SupportedFormat* FindFormatByResolution(uint32_t width,
                                                uint32_t height) {
    for (const auto& format : GetSupportedFormats()) {
      if (format.width == width && format.height == height) {
        return &format;
      }
    }
    return nullptr;
  }

  // Find format according to V4L2 fourcc. If multiple resolution support the
  // same fourcc, choose the first one.
  const SupportedFormat* FindFormatByFourcc(uint32_t fourcc) {
    for (const auto& format : supported_formats_) {
      if (format.fourcc == fourcc) {
        return &format;
      }
    }
    return nullptr;
  }

  SupportedFormat GetMaximumResolution() {
    SupportedFormat max_format;
    for (const auto& format : GetSupportedFormats()) {
      if (format.width >= max_format.width) {
        max_format.width = format.width;
      }
      if (format.height >= max_format.height) {
        max_format.height = format.height;
      }
    }
    return max_format;
  }

  const SupportedFormat* GetResolutionForCropping() {
    // FOV requirement cannot allow cropping twice. If two streams resolution
    // are 1920x1080 and 1600x1200, we need a larger resolution which aspect
    // ratio is the same as sensor aspect ratio.
    float sensor_aspect_ratio =
        static_cast<float>(g_env->sensor_array_size_width_) /
        g_env->sensor_array_size_height_;

    // We need to compare the aspect ratio from sensor resolution.
    // The sensor resolution may not be just the size. It may be a little
    // larger. Add a margin to check if the sensor aspect ratio fall in the
    // specific aspect ratio. 16:9=1.778, 16:10=1.6, 3:2=1.5, 4:3=1.333
    const float kAspectRatioMargin = 0.04;

    for (const auto& format : GetSupportedFormats()) {
      if (format.width >= 1920 && format.height >= 1200) {
        float aspect_ratio = static_cast<float>(format.width) / format.height;
        if (abs(sensor_aspect_ratio - aspect_ratio) < kAspectRatioMargin &&
            HasFrameRate(format, kDefaultFrameRate)) {
          return &format;
        }
      }
    }
    return nullptr;
  }

  bool ExerciseControl(uint32_t id, const char* control) {
    v4l2_queryctrl query_ctrl;
    if (!dev_.QueryControl(id, &query_ctrl)) {
      LOG(WARNING) << "Cannot query control name: " << control;
      return false;
    }
    if (!dev_.SetControl(id, query_ctrl.maximum)) {
      LOG(WARNING) << "Cannot set " << control << " to maximum value";
    }
    if (!dev_.SetControl(id, query_ctrl.minimum)) {
      LOG(WARNING) << "Cannot set " << control << " to minimum value";
    }
    if (!dev_.SetControl(id, query_ctrl.default_value)) {
      LOG(WARNING) << "Cannot set " << control << " to default value";
    }
    return true;
  }

  void RunCapture(V4L2Device::IOMethod io,
                  uint32_t width,
                  uint32_t height,
                  uint32_t pixfmt,
                  float fps,
                  V4L2Device::ConstantFramerate constant_framerate,
                  uint32_t skip_frames,
                  base::TimeDelta duration) {
    ASSERT_TRUE(dev_.InitDevice(io, width, height, pixfmt, fps,
                                constant_framerate, skip_frames));
    ASSERT_TRUE(dev_.StartCapture());
    ASSERT_TRUE(dev_.Run(duration.InSeconds()));
    ASSERT_TRUE(dev_.StopCapture());
    ASSERT_TRUE(dev_.UninitDevice());

    // Make sure the driver didn't adjust the format.
    v4l2_format fmt = {};
    ASSERT_TRUE(dev_.GetV4L2Format(&fmt));
    ASSERT_EQ(width, fmt.fmt.pix.width);
    ASSERT_EQ(height, fmt.fmt.pix.height);
    ASSERT_EQ(pixfmt, fmt.fmt.pix.pixelformat);
    ASSERT_FLOAT_EQ(fps, dev_.GetFrameRate());
  }

  void ExerciseResolution(uint32_t width, uint32_t height) {
    const int kMaxRetryTimes = 5;
    const auto duration = base::TimeDelta::FromSeconds(3);

    std::vector<V4L2Device::ConstantFramerate> constant_framerates;
    if (g_env->check_constant_framerate_) {
      constant_framerates = {V4L2Device::ENABLE_CONSTANT_FRAMERATE,
                             V4L2Device::DISABLE_CONSTANT_FRAMERATE};
    } else {
      constant_framerates = {V4L2Device::DEFAULT_FRAMERATE_SETTING};
    }

    const SupportedFormat* test_format = FindFormatByResolution(width, height);
    ASSERT_NE(test_format, nullptr)
        << "Cannot find resolution " << width << "x" << height;

    bool default_framerate_supported =
        HasFrameRate(*test_format, kDefaultFrameRate);
    EXPECT_TRUE(default_framerate_supported) << base::StringPrintf(
        "Cannot test %g fps for %dx%d (%08X)", kDefaultFrameRate,
        test_format->width, test_format->height, test_format->fourcc);

    for (const auto& constant_framerate : constant_framerates) {
      if (!default_framerate_supported &&
          constant_framerate == V4L2Device::ENABLE_CONSTANT_FRAMERATE) {
        continue;
      }

      bool success = false;
      for (int retry_count = 0; retry_count < kMaxRetryTimes; retry_count++) {
        ASSERT_TRUE(dev_.InitDevice(V4L2Device::IO_METHOD_MMAP, width, height,
                                    test_format->fourcc, kDefaultFrameRate,
                                    constant_framerate, 0));
        ASSERT_TRUE(dev_.StartCapture());
        ASSERT_TRUE(dev_.Run(3));
        ASSERT_TRUE(dev_.StopCapture());
        ASSERT_TRUE(dev_.UninitDevice());

        // Make sure the driver didn't adjust the format.
        v4l2_format fmt = {};
        ASSERT_TRUE(dev_.GetV4L2Format(&fmt));
        ASSERT_EQ(width, fmt.fmt.pix.width);
        ASSERT_EQ(height, fmt.fmt.pix.height);
        ASSERT_EQ(test_format->fourcc, fmt.fmt.pix.pixelformat);
        ASSERT_FLOAT_EQ(kDefaultFrameRate, dev_.GetFrameRate());

        if (g_env->check_timestamps_in_order_) {
          ASSERT_TRUE(CheckTimestampsInOrder(dev_.GetFrameTimestamps()))
              << base::StringPrintf(
                     "Capture test %dx%d (%08X) failed because frame "
                     "timestamps are out of order",
                     test_format->width, test_format->height,
                     test_format->fourcc);
        }

        if (constant_framerate == V4L2Device::ENABLE_CONSTANT_FRAMERATE) {
          float actual_fps = (dev_.GetNumFrames() - 1) / duration.InSecondsF();
          // 1 fps buffer is because |time_to_capture| may be too short.
          // EX: 30 fps and capture 3 secs. We may get 89 frames or 91 frames.
          // The actual fps will be 29.66 or 30.33.
          if (abs(actual_fps - kDefaultFrameRate) > 1) {
            LOG(WARNING) << base::StringPrintf(
                "Capture test %dx%d (%08X) failed with fps %.2f",
                test_format->width, test_format->height, test_format->fourcc,
                actual_fps);
            continue;
          }

          if (!CheckConstantFramerate(dev_.GetFrameTimestamps(),
                                      kDefaultFrameRate)) {
            LOG(WARNING) << base::StringPrintf(
                "Capture test %dx%d (%08X) failed and didn't meet "
                "constant framerate",
                test_format->width, test_format->height, test_format->fourcc);
            continue;
          }
        }

        success = true;
        break;
      }
      EXPECT_TRUE(success) << "Cannot meet constant framerate requirement for "
                           << kMaxRetryTimes << " times";
    }
  }

  V4L2Device dev_;
  SupportedFormats supported_formats_;
};

class V4L2TestWithIO
    : public V4L2Test,
      public ::testing::WithParamInterface<V4L2Device::IOMethod> {};

class V4L2TestWithResolution
    : public V4L2Test,
      public ::testing::WithParamInterface<std::pair<uint32_t, uint32_t>> {};

TEST_F(V4L2Test, MultipleOpen) {
  V4L2Device dev2(g_env->device_path_.c_str(), 4);
  ASSERT_TRUE(dev2.OpenDevice()) << "Cannot open device for the second time";
  dev2.CloseDevice();
}

TEST_P(V4L2TestWithIO, MultipleInit) {
  V4L2Device::IOMethod io = GetParam();
  V4L2Device::ConstantFramerate constant_framerate =
      V4L2Device::DEFAULT_FRAMERATE_SETTING;
  V4L2Device& dev1 = dev_;
  V4L2Device dev2(g_env->device_path_.c_str(), 4);
  ASSERT_TRUE(dev2.OpenDevice()) << "Cannot open device for the second time";

  ASSERT_TRUE(dev1.InitDevice(io, 640, 480, V4L2_PIX_FMT_YUYV, 30,
                              constant_framerate, 0))
      << "Cannot init device for the first time";

  ASSERT_FALSE(dev2.InitDevice(io, 640, 480, V4L2_PIX_FMT_YUYV, 30,
                               constant_framerate, 0))
      << "Multiple init device should fail";

  dev1.UninitDevice();
  dev2.UninitDevice();
  dev2.CloseDevice();
}

INSTANTIATE_TEST_SUITE_P(V4L2Test,
                         V4L2TestWithIO,
                         ::testing::Values(V4L2Device::IO_METHOD_MMAP,
                                           V4L2Device::IO_METHOD_USERPTR));

// EnumInput and EnumStandard are optional.
TEST_F(V4L2Test, EnumInputAndStandard) {
  dev_.EnumInput();
  dev_.EnumStandard();
}

// EnumControl is optional, but the output is useful. For example, we could
// know whether constant framerate is supported or not.
TEST_F(V4L2Test, EnumControl) {
  dev_.EnumControl();
}

TEST_F(V4L2Test, SetControl) {
  // Test mandatory controls.
  if (g_env->check_constant_framerate_) {
    ASSERT_TRUE(ExerciseControl(V4L2_CID_EXPOSURE_AUTO_PRIORITY,
                                "exposure_auto_priority"));
  }

  // Test optional controls.
  ExerciseControl(V4L2_CID_BRIGHTNESS, "brightness");
  ExerciseControl(V4L2_CID_CONTRAST, "contrast");
  ExerciseControl(V4L2_CID_SATURATION, "saturation");
  ExerciseControl(V4L2_CID_GAMMA, "gamma");
  ExerciseControl(V4L2_CID_HUE, "hue");
  ExerciseControl(V4L2_CID_GAIN, "gain");
  ExerciseControl(V4L2_CID_SHARPNESS, "sharpness");
}

// SetCrop is optional.
TEST_F(V4L2Test, SetCrop) {
  v4l2_cropcap cropcap = {};
  if (dev_.GetCropCap(&cropcap)) {
    v4l2_crop crop = {};
    crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    crop.c = cropcap.defrect;
    dev_.SetCrop(&crop);
  }
}

// GetCrop is optional.
TEST_F(V4L2Test, GetCrop) {
  v4l2_crop crop = {};
  crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  dev_.GetCrop(&crop);
}

TEST_F(V4L2Test, ProbeCaps) {
  v4l2_capability caps;
  ASSERT_TRUE(dev_.ProbeCaps(&caps, true));
  uint32_t dev_caps = (caps.capabilities & V4L2_CAP_DEVICE_CAPS)
                          ? caps.device_caps
                          : caps.capabilities;
  ASSERT_TRUE(dev_caps & V4L2_CAP_VIDEO_CAPTURE)
      << "Should support video capture interface";
}

TEST_F(V4L2Test, EnumFormats) {
  ASSERT_TRUE(dev_.EnumFormat(NULL));
}

TEST_F(V4L2Test, EnumFrameSize) {
  uint32_t format_count = 0;
  ASSERT_TRUE(dev_.EnumFormat(&format_count));
  for (uint32_t i = 0; i < format_count; i++) {
    uint32_t pixfmt;
    ASSERT_TRUE(dev_.GetPixelFormat(i, &pixfmt));
    ASSERT_TRUE(dev_.EnumFrameSize(pixfmt, NULL));
  }
}

TEST_F(V4L2Test, EnumFrameInterval) {
  uint32_t format_count = 0;
  ASSERT_TRUE(dev_.EnumFormat(&format_count));
  for (uint32_t i = 0; i < format_count; i++) {
    uint32_t pixfmt;
    ASSERT_TRUE(dev_.GetPixelFormat(i, &pixfmt));
    uint32_t size_count;
    ASSERT_TRUE(dev_.EnumFrameSize(pixfmt, &size_count));

    for (uint32_t j = 0; j < size_count; j++) {
      uint32_t width, height;
      ASSERT_TRUE(dev_.GetFrameSize(j, pixfmt, &width, &height));
      ASSERT_TRUE(dev_.EnumFrameInterval(pixfmt, width, height, NULL));
    }
  }
}

TEST_F(V4L2Test, FrameRate) {
  v4l2_streamparm param;
  ASSERT_TRUE(dev_.GetParam(&param));
  // we only try to adjust frame rate when it claims can.
  if (param.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
    ASSERT_TRUE(dev_.SetParam(&param));
  } else {
    LOG(INFO) << "Does not support TIMEPERFRAME";
  }
}

TEST_F(V4L2Test, CroppingResolution) {
  const SupportedFormat* cropping_resolution = GetResolutionForCropping();
  if (cropping_resolution == nullptr) {
    SupportedFormat max_resolution = GetMaximumResolution();
    ASSERT_TRUE(max_resolution.width < 1920 || max_resolution.height < 1200)
        << "Cannot find cropping resolution";
    return;
  }
  ExerciseResolution(cropping_resolution->width, cropping_resolution->height);
}

// Test all required resolutions with 30 fps.
// If device supports constant framerate, the test will toggle the setting
// and check actual fps. Otherwise, use the default setting of
// V4L2_CID_EXPOSURE_AUTO_PRIORITY.
TEST_P(V4L2TestWithResolution, Resolutions) {
  uint32_t width = GetParam().first;
  uint32_t height = GetParam().second;

  // TODO(shik): Use GTEST_SKIP() after we upgrade to gtest 1.9.
  if (width == 1280 && height == 960 && !g_env->check_1280x960_) {
    LOG(INFO) << "Skipped because check_1280x960_ is not set";
    return;
  }
  if (width == 1600 && height == 1200 && !g_env->check_1600x1200_) {
    LOG(INFO) << "Skipped because check_1600x1200_ is not set";
    return;
  }

  SupportedFormat max_resolution = GetMaximumResolution();
  if (width > max_resolution.width || height > max_resolution.height) {
    LOG(INFO) << "Skipped because it's larger than maximum resolution";
    return;
  }

  ExerciseResolution(width, height);
}

const std::pair<uint32_t, uint32_t> kTestResolutions[] = {
    {320, 240},  {640, 480},   {1280, 720},
    {1280, 960}, {1600, 1200}, {1920, 1080},
};
INSTANTIATE_TEST_SUITE_P(V4L2Test,
                         V4L2TestWithResolution,
                         ::testing::ValuesIn(kTestResolutions),
                         [](const auto& info) {
                           uint32_t width = std::get<0>(info.param);
                           uint32_t height = std::get<1>(info.param);
                           return base::StringPrintf("%ux%u", width, height);
                         });

// ChromeOS spec requires world-facing camera should be at least 1920x1080 and
// user-facing camera should be at least 1280x720.
TEST_F(V4L2Test, MaximumSupportedResolution) {
  SupportedFormat max_resolution = GetMaximumResolution();

  uint32_t required_width;
  uint32_t required_height;
  std::string facing_str;
  if (g_env->lens_facing_ == LensFacing::kFront) {
    required_width = 1280;
    required_height = 720;
    facing_str = "user";
  } else if (g_env->lens_facing_ == LensFacing::kBack) {
    required_width = 1920;
    required_height = 1080;
    facing_str = "world";
  } else {
    FAIL() << "Invalid facing: " << static_cast<int>(g_env->lens_facing_);
  }

  EXPECT_GE(max_resolution.width, required_width);
  EXPECT_GE(max_resolution.height, required_height);

  if (HasFailure()) {
    LOG(ERROR) << base::StringPrintf(
        "The maximum resolution %dx%d does not meet the requirement %dx%d for "
        "%s-facing camera",
        max_resolution.width, max_resolution.height, required_width,
        required_height, facing_str.c_str());
  }
}

TEST_F(V4L2Test, FirstFrameAfterStreamOn) {
  const SupportedFormat* test_format = FindFormatByFourcc(V4L2_PIX_FMT_MJPEG);
  if (test_format == nullptr) {
    // TODO(shik): Use GTEST_SKIP() after we upgrade to gtest 1.9.
    LOG(INFO) << "Skipped because the camera doesn't support MJPEG format";
    return;
  }

  uint32_t width = test_format->width;
  uint32_t height = test_format->height;

  for (int i = 0; i < 20; i++) {
    ASSERT_TRUE(dev_.InitDevice(V4L2Device::IO_METHOD_MMAP, width, height,
                                V4L2_PIX_FMT_MJPEG, kDefaultFrameRate,
                                V4L2Device::DEFAULT_FRAMERATE_SETTING,
                                g_env->skip_frames_));
    ASSERT_TRUE(dev_.StartCapture());

    uint32_t buf_index, data_size;
    int ret;
    do {
      ret = dev_.ReadOneFrame(&buf_index, &data_size);
    } while (ret == 0);
    ASSERT_GT(ret, 0);

    const V4L2Device::Buffer& buffer = dev_.GetBufferInfo(buf_index);
    std::vector<uint8_t> yuv_buffer(width * height * 2);

    int res = libyuv::MJPGToI420(static_cast<uint8_t*>(buffer.start), data_size,
                                 yuv_buffer.data(), width,
                                 yuv_buffer.data() + width * height, width / 2,
                                 yuv_buffer.data() + width * height * 5 / 4,
                                 width / 2, width, height, width, height);
    if (res != 0) {
      base::WriteFile(base::FilePath("FirstFrame.jpg"),
                      static_cast<char*>(buffer.start), data_size);
      FAIL() << "First frame is not a valid mjpeg image.";
    }

    ASSERT_TRUE(dev_.EnqueueBuffer(buf_index));
    ASSERT_TRUE(dev_.StopCapture());
    ASSERT_TRUE(dev_.UninitDevice());
  }
}

}  // namespace tests
}  // namespace cros

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);

  DEFINE_bool(list_usbcam, false, "List available USB cameras");
  DEFINE_string(test_list, "default", "Select different test list");
  DEFINE_string(device_path, "/dev/video0", "Path to the video device");

  // Add a newline at the beginning of the usage text to separate the help
  // message from gtest.
  brillo::FlagHelper::Init(argc, argv, "\nTest V4L2 camera functionalities.");

  if (FLAGS_list_usbcam) {
    std::vector<base::FilePath> usb_cameras = cros::tests::GetUsbCameras();
    for (const auto& path : usb_cameras) {
      std::cout << path.value() << std::endl;
    }
    return 0;
  }

  cros::tests::g_env =
      new cros::tests::V4L2TestEnvironment(FLAGS_test_list, FLAGS_device_path);
  ::testing::AddGlobalTestEnvironment(cros::tests::g_env);
  return RUN_ALL_TESTS();
}
