// Copyright (c) 2013 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/android/video_capture_device_android.h"

#include <stdint.h>
#include <utility>

#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "media/capture/mojom/image_capture_types.h"
#include "media/capture/video/android/capture_jni_headers/VideoCapture_jni.h"
#include "media/capture/video/android/photo_capabilities.h"
#include "media/capture/video/android/video_capture_device_factory_android.h"
#include "third_party/libyuv/include/libyuv.h"
#include "ui/gfx/geometry/point_f.h"

using base::android::AttachCurrentThread;
using base::android::CheckException;
using base::android::GetClass;
using base::android::JavaParamRef;
using base::android::MethodID;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;

namespace media {

namespace {

mojom::MeteringMode ToMojomMeteringMode(
    PhotoCapabilities::AndroidMeteringMode android_mode) {
  switch (android_mode) {
    case PhotoCapabilities::AndroidMeteringMode::FIXED:
      return mojom::MeteringMode::MANUAL;
    case PhotoCapabilities::AndroidMeteringMode::SINGLE_SHOT:
      return mojom::MeteringMode::SINGLE_SHOT;
    case PhotoCapabilities::AndroidMeteringMode::CONTINUOUS:
      return mojom::MeteringMode::CONTINUOUS;
    case PhotoCapabilities::AndroidMeteringMode::NONE:
      return mojom::MeteringMode::NONE;
    case PhotoCapabilities::AndroidMeteringMode::NOT_SET:
    case PhotoCapabilities::AndroidMeteringMode::NUM_ENTRIES:
      NOTREACHED();
  }
  return mojom::MeteringMode::NONE;
}

PhotoCapabilities::AndroidMeteringMode ToAndroidMeteringMode(
    mojom::MeteringMode mojom_mode) {
  switch (mojom_mode) {
    case mojom::MeteringMode::MANUAL:
      return PhotoCapabilities::AndroidMeteringMode::FIXED;
    case mojom::MeteringMode::SINGLE_SHOT:
      return PhotoCapabilities::AndroidMeteringMode::SINGLE_SHOT;
    case mojom::MeteringMode::CONTINUOUS:
      return PhotoCapabilities::AndroidMeteringMode::CONTINUOUS;
    case mojom::MeteringMode::NONE:
      return PhotoCapabilities::AndroidMeteringMode::NONE;
  }
  NOTREACHED();
  return PhotoCapabilities::AndroidMeteringMode::NOT_SET;
}

mojom::FillLightMode ToMojomFillLightMode(
    PhotoCapabilities::AndroidFillLightMode android_mode) {
  switch (android_mode) {
    case PhotoCapabilities::AndroidFillLightMode::FLASH:
      return mojom::FillLightMode::FLASH;
    case PhotoCapabilities::AndroidFillLightMode::AUTO:
      return mojom::FillLightMode::AUTO;
    case PhotoCapabilities::AndroidFillLightMode::OFF:
      return mojom::FillLightMode::OFF;
    case PhotoCapabilities::AndroidFillLightMode::NOT_SET:
    case PhotoCapabilities::AndroidFillLightMode::NUM_ENTRIES:
      NOTREACHED();
  }
  NOTREACHED();
  return mojom::FillLightMode::OFF;
}

PhotoCapabilities::AndroidFillLightMode ToAndroidFillLightMode(
    mojom::FillLightMode mojom_mode) {
  switch (mojom_mode) {
    case mojom::FillLightMode::FLASH:
      return PhotoCapabilities::AndroidFillLightMode::FLASH;
    case mojom::FillLightMode::AUTO:
      return PhotoCapabilities::AndroidFillLightMode::AUTO;
    case mojom::FillLightMode::OFF:
      return PhotoCapabilities::AndroidFillLightMode::OFF;
  }
  NOTREACHED();
  return PhotoCapabilities::AndroidFillLightMode::NOT_SET;
}

}  // anonymous namespace

VideoCaptureDeviceAndroid::VideoCaptureDeviceAndroid(
    const VideoCaptureDeviceDescriptor& device_descriptor)
    : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
      device_descriptor_(device_descriptor) {}

VideoCaptureDeviceAndroid::~VideoCaptureDeviceAndroid() {
  DCHECK(main_task_runner_->BelongsToCurrentThread());
  StopAndDeAllocate();
}

bool VideoCaptureDeviceAndroid::Init() {
  int id;
  if (!base::StringToInt(device_descriptor_.device_id, &id))
    return false;

  j_capture_.Reset(VideoCaptureDeviceFactoryAndroid::createVideoCaptureAndroid(
      id, reinterpret_cast<intptr_t>(this)));
  return true;
}

void VideoCaptureDeviceAndroid::AllocateAndStart(
    const VideoCaptureParams& params,
    std::unique_ptr<Client> client) {
  DCHECK(main_task_runner_->BelongsToCurrentThread());
  {
    base::AutoLock lock(lock_);
    if (state_ != kIdle)
      return;
    client_ = std::move(client);
    got_first_frame_ = false;
  }

  JNIEnv* env = AttachCurrentThread();

  jboolean ret = Java_VideoCapture_allocate(
      env, j_capture_, params.requested_format.frame_size.width(),
      params.requested_format.frame_size.height(),
      params.requested_format.frame_rate, params.enable_face_detection);
  if (!ret) {
    SetErrorState(media::VideoCaptureError::kAndroidFailedToAllocate, FROM_HERE,
                  "failed to allocate");
    return;
  }

  // TODO(julien.isorce): Use Camera.SENSOR_COLOR_TRANSFORM2 to build a
  // gfx::ColorSpace, and rename VideoCaptureDeviceAndroid::GetColorspace()
  // to GetPixelFormat, see http://crbug.com/959901.
  capture_color_space_ = gfx::ColorSpace();

  capture_format_.frame_size.SetSize(
      Java_VideoCapture_queryWidth(env, j_capture_),
      Java_VideoCapture_queryHeight(env, j_capture_));
  capture_format_.frame_rate =
      Java_VideoCapture_queryFrameRate(env, j_capture_);
  capture_format_.pixel_format = GetColorspace();
  DCHECK_NE(capture_format_.pixel_format, PIXEL_FORMAT_UNKNOWN);
  CHECK(capture_format_.frame_size.GetArea() > 0);
  CHECK(!(capture_format_.frame_size.width() % 2));
  CHECK(!(capture_format_.frame_size.height() % 2));

  if (capture_format_.frame_rate > 0) {
    frame_interval_ = base::Microseconds(
        (base::Time::kMicrosecondsPerSecond + capture_format_.frame_rate - 1) /
        capture_format_.frame_rate);
  }

  DVLOG(1) << __func__ << " requested ("
           << capture_format_.frame_size.ToString() << ")@ "
           << capture_format_.frame_rate << "fps";

  ret = Java_VideoCapture_startCaptureMaybeAsync(env, j_capture_);
  if (!ret) {
    SetErrorState(media::VideoCaptureError::kAndroidFailedToStartCapture,
                  FROM_HERE, "failed to start capture");
    return;
  }

  {
    base::AutoLock lock(lock_);
    state_ = kConfigured;
  }
}

void VideoCaptureDeviceAndroid::StopAndDeAllocate() {
  DCHECK(main_task_runner_->BelongsToCurrentThread());
  {
    base::AutoLock lock(lock_);
    if (state_ != kConfigured && state_ != kError)
      return;
  }

  JNIEnv* env = AttachCurrentThread();

  const jboolean ret =
      Java_VideoCapture_stopCaptureAndBlockUntilStopped(env, j_capture_);
  if (!ret) {
    SetErrorState(media::VideoCaptureError::kAndroidFailedToStopCapture,
                  FROM_HERE, "failed to stop capture");
    return;
  }

  {
    base::AutoLock lock(lock_);
    state_ = kIdle;
    client_.reset();
  }

  Java_VideoCapture_deallocate(env, j_capture_);
}

void VideoCaptureDeviceAndroid::TakePhoto(TakePhotoCallback callback) {
  DCHECK(main_task_runner_->BelongsToCurrentThread());
  TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
                       "VideoCaptureDeviceAndroid::TakePhoto",
                       TRACE_EVENT_SCOPE_PROCESS);
  {
    base::AutoLock lock(lock_);
    if (state_ != kConfigured)
      return;
    if (!got_first_frame_) {  // We have to wait until we get the first frame.
      TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
                           "VideoCaptureDeviceAndroid::TakePhoto enqueuing to "
                           "wait for first frame",
                           TRACE_EVENT_SCOPE_PROCESS);
      photo_requests_queue_.push_back(
          base::BindOnce(&VideoCaptureDeviceAndroid::DoTakePhoto,
                         weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
      return;
    }
  }
  DoTakePhoto(std::move(callback));
}

void VideoCaptureDeviceAndroid::GetPhotoState(GetPhotoStateCallback callback) {
  DCHECK(main_task_runner_->BelongsToCurrentThread());
  {
    base::AutoLock lock(lock_);
    if (state_ != kConfigured)
      return;
    if (!got_first_frame_) {  // We have to wait until we get the first frame.
      photo_requests_queue_.push_back(
          base::BindOnce(&VideoCaptureDeviceAndroid::DoGetPhotoState,
                         weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
      return;
    }
  }
  DoGetPhotoState(std::move(callback));
}

void VideoCaptureDeviceAndroid::SetPhotoOptions(
    mojom::PhotoSettingsPtr settings,
    SetPhotoOptionsCallback callback) {
  DCHECK(main_task_runner_->BelongsToCurrentThread());
  {
    base::AutoLock lock(lock_);
    if (state_ != kConfigured)
      return;
    if (!got_first_frame_) {  // We have to wait until we get the first frame.
      photo_requests_queue_.push_back(
          base::BindOnce(&VideoCaptureDeviceAndroid::DoSetPhotoOptions,
                         weak_ptr_factory_.GetWeakPtr(), std::move(settings),
                         std::move(callback)));
      return;
    }
  }
  DoSetPhotoOptions(std::move(settings), std::move(callback));
}

void VideoCaptureDeviceAndroid::OnFrameAvailable(
    JNIEnv* env,
    const JavaParamRef<jobject>& obj,
    const JavaParamRef<jbyteArray>& data,
    jint length,
    jint rotation) {
  if (!IsClientConfigured())
    return;

  const base::TimeTicks current_time = base::TimeTicks::Now();
  ProcessFirstFrameAvailable(current_time);
  // Using |expected_next_frame_time_| to estimate a proper capture timestamp
  // since android.hardware.Camera API doesn't expose a better timestamp.
  const base::TimeDelta capture_time =
      expected_next_frame_time_ - base::TimeTicks();

  // Deliver the frame when it doesn't arrive too early.
  if (ThrottleFrame(current_time)) {
    client_->OnFrameDropped(VideoCaptureFrameDropReason::kAndroidThrottling);
    return;
  }

  jbyte* buffer = env->GetByteArrayElements(data, NULL);
  if (!buffer) {
    LOG(ERROR) << "VideoCaptureDeviceAndroid::OnFrameAvailable: "
                  "failed to GetByteArrayElements";
    // In case of error, restore back the throttle control value.
    expected_next_frame_time_ -= frame_interval_;
    client_->OnFrameDropped(
        VideoCaptureFrameDropReason::kAndroidGetByteArrayElementsFailed);
    return;
  }

  // TODO(qiangchen): Investigate how to get raw timestamp for Android,
  // rather than using reference time to calculate timestamp.
  SendIncomingDataToClient(reinterpret_cast<uint8_t*>(buffer), length, rotation,
                           current_time, capture_time);

  env->ReleaseByteArrayElements(data, buffer, JNI_ABORT);
}

void VideoCaptureDeviceAndroid::OnI420FrameAvailable(JNIEnv* env,
                                                     jobject obj,
                                                     jobject y_buffer,
                                                     jint y_stride,
                                                     jobject u_buffer,
                                                     jobject v_buffer,
                                                     jint uv_row_stride,
                                                     jint uv_pixel_stride,
                                                     jint width,
                                                     jint height,
                                                     jint rotation,
                                                     jlong timestamp) {
  if (!IsClientConfigured())
    return;
  const int64_t absolute_micro =
      timestamp / base::Time::kNanosecondsPerMicrosecond;
  const base::TimeDelta capture_time = base::Microseconds(absolute_micro);

  const base::TimeTicks current_time = base::TimeTicks::Now();
  ProcessFirstFrameAvailable(current_time);

  // Deliver the frame when it doesn't arrive too early.
  if (ThrottleFrame(current_time)) {
    client_->OnFrameDropped(VideoCaptureFrameDropReason::kAndroidThrottling);
    return;
  }

  uint8_t* const y_src =
      reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer));
  CHECK(y_src);
  uint8_t* const u_src =
      reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(u_buffer));
  CHECK(u_src);
  uint8_t* const v_src =
      reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer));
  CHECK(v_src);

  const int y_plane_length = width * height;
  const int uv_plane_length = y_plane_length / 4;
  const int buffer_length = y_plane_length + uv_plane_length * 2;
  std::unique_ptr<uint8_t[]> buffer(new uint8_t[buffer_length]);

  libyuv::Android420ToI420(y_src, y_stride, u_src, uv_row_stride, v_src,
                           uv_row_stride, uv_pixel_stride, buffer.get(), width,
                           buffer.get() + y_plane_length, width / 2,
                           buffer.get() + y_plane_length + uv_plane_length,
                           width / 2, width, height);

  SendIncomingDataToClient(buffer.get(), buffer_length, rotation, current_time,
                           capture_time);
}

void VideoCaptureDeviceAndroid::OnError(JNIEnv* env,
                                        const JavaParamRef<jobject>& obj,
                                        int android_video_capture_error,
                                        const JavaParamRef<jstring>& message) {
  SetErrorState(
      static_cast<media::VideoCaptureError>(android_video_capture_error),
      FROM_HERE, base::android::ConvertJavaStringToUTF8(env, message));
}

void VideoCaptureDeviceAndroid::OnFrameDropped(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& obj,
    int android_video_capture_frame_drop_reason) {
  base::AutoLock lock(lock_);
  if (!client_)
    return;
  client_->OnFrameDropped(static_cast<media::VideoCaptureFrameDropReason>(
      android_video_capture_frame_drop_reason));
}

void VideoCaptureDeviceAndroid::OnGetPhotoCapabilitiesReply(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& obj,
    jlong callback_id,
    jobject result) {
  base::AutoLock lock(photo_callbacks_lock_);
  GetPhotoStateCallback* const cb =
      reinterpret_cast<GetPhotoStateCallback*>(callback_id);
  // Search for the pointer |cb| in the list of |take_photo_callbacks_|.
  const auto reference_it = std::find_if(
      get_photo_state_callbacks_.begin(), get_photo_state_callbacks_.end(),
      [cb](const std::unique_ptr<GetPhotoStateCallback>& callback) {
        return callback.get() == cb;
      });
  if (reference_it == get_photo_state_callbacks_.end()) {
    NOTREACHED() << "|callback_id| not found.";
    return;
  }
  if (result == nullptr) {
    get_photo_state_callbacks_.erase(reference_it);
    return;
  }

  base::android::ScopedJavaLocalRef<jobject> scoped_photo_capabilities(env,
                                                                       result);
  PhotoCapabilities caps(scoped_photo_capabilities);

  // TODO(mcasas): Manual member copying sucks, consider adding typemapping from
  // PhotoCapabilities to mojom::PhotoStatePtr, https://crbug.com/622002.
  mojom::PhotoStatePtr photo_capabilities = mojo::CreateEmptyPhotoState();

  const auto jni_white_balance_modes = caps.getMeteringModeArray(
      PhotoCapabilities::MeteringModeType::WHITE_BALANCE);
  std::vector<mojom::MeteringMode> white_balance_modes;
  for (const auto& white_balance_mode : jni_white_balance_modes)
    white_balance_modes.push_back(ToMojomMeteringMode(white_balance_mode));
  photo_capabilities->supported_white_balance_modes = white_balance_modes;
  photo_capabilities->current_white_balance_mode = ToMojomMeteringMode(
      caps.getMeteringMode(PhotoCapabilities::MeteringModeType::WHITE_BALANCE));

  const auto jni_exposure_modes =
      caps.getMeteringModeArray(PhotoCapabilities::MeteringModeType::EXPOSURE);
  std::vector<mojom::MeteringMode> exposure_modes;
  for (const auto& exposure_mode : jni_exposure_modes)
    exposure_modes.push_back(ToMojomMeteringMode(exposure_mode));
  photo_capabilities->supported_exposure_modes = exposure_modes;
  photo_capabilities->current_exposure_mode = ToMojomMeteringMode(
      caps.getMeteringMode(PhotoCapabilities::MeteringModeType::EXPOSURE));

  const auto jni_focus_modes =
      caps.getMeteringModeArray(PhotoCapabilities::MeteringModeType::FOCUS);
  std::vector<mojom::MeteringMode> focus_modes;
  for (const auto& focus_mode : jni_focus_modes)
    focus_modes.push_back(ToMojomMeteringMode(focus_mode));
  photo_capabilities->supported_focus_modes = focus_modes;
  photo_capabilities->current_focus_mode = ToMojomMeteringMode(
      caps.getMeteringMode(PhotoCapabilities::MeteringModeType::FOCUS));

  photo_capabilities->focus_distance = mojom::Range::New();
  photo_capabilities->focus_distance->current = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::CURRENT_FOCUS_DISTANCE);
  photo_capabilities->focus_distance->max = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::MAX_FOCUS_DISTANCE);
  photo_capabilities->focus_distance->min = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::MIN_FOCUS_DISTANCE);
  photo_capabilities->focus_distance->step = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::STEP_FOCUS_DISTANCE);

  photo_capabilities->exposure_compensation = mojom::Range::New();
  photo_capabilities->exposure_compensation->current = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::CURRENT_EXPOSURE_COMPENSATION);
  photo_capabilities->exposure_compensation->max = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::MAX_EXPOSURE_COMPENSATION);
  photo_capabilities->exposure_compensation->min = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::MIN_EXPOSURE_COMPENSATION);
  photo_capabilities->exposure_compensation->step = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::STEP_EXPOSURE_COMPENSATION);

  photo_capabilities->exposure_time = mojom::Range::New();
  photo_capabilities->exposure_time->current = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::CURRENT_EXPOSURE_TIME);
  photo_capabilities->exposure_time->max = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::MAX_EXPOSURE_TIME);
  photo_capabilities->exposure_time->min = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::MIN_EXPOSURE_TIME);
  photo_capabilities->exposure_time->step = caps.getDouble(
      PhotoCapabilities::PhotoCapabilityDouble::STEP_EXPOSURE_TIME);

  photo_capabilities->color_temperature = mojom::Range::New();
  photo_capabilities->color_temperature->current = caps.getInt(
      PhotoCapabilities::PhotoCapabilityInt::CURRENT_COLOR_TEMPERATURE);
  photo_capabilities->color_temperature->max =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::MAX_COLOR_TEMPERATURE);
  photo_capabilities->color_temperature->min =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::MIN_COLOR_TEMPERATURE);
  photo_capabilities->color_temperature->step = caps.getInt(
      PhotoCapabilities::PhotoCapabilityInt::STEP_COLOR_TEMPERATURE);

  photo_capabilities->iso = mojom::Range::New();
  photo_capabilities->iso->current =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::CURRENT_ISO);
  photo_capabilities->iso->max =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::MAX_ISO);
  photo_capabilities->iso->min =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::MIN_ISO);
  photo_capabilities->iso->step =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::STEP_ISO);

  photo_capabilities->brightness = mojom::Range::New();
  photo_capabilities->contrast = mojom::Range::New();
  photo_capabilities->saturation = mojom::Range::New();
  photo_capabilities->sharpness = mojom::Range::New();

  photo_capabilities->zoom = mojom::Range::New();
  photo_capabilities->zoom->current =
      caps.getDouble(PhotoCapabilities::PhotoCapabilityDouble::CURRENT_ZOOM);
  photo_capabilities->zoom->max =
      caps.getDouble(PhotoCapabilities::PhotoCapabilityDouble::MAX_ZOOM);
  photo_capabilities->zoom->min =
      caps.getDouble(PhotoCapabilities::PhotoCapabilityDouble::MIN_ZOOM);
  photo_capabilities->zoom->step =
      caps.getDouble(PhotoCapabilities::PhotoCapabilityDouble::STEP_ZOOM);

  photo_capabilities->supports_torch =
      caps.getBool(PhotoCapabilities::PhotoCapabilityBool::SUPPORTS_TORCH);
  photo_capabilities->torch =
      caps.getBool(PhotoCapabilities::PhotoCapabilityBool::TORCH);

  photo_capabilities->red_eye_reduction =
      caps.getBool(PhotoCapabilities::PhotoCapabilityBool::RED_EYE_REDUCTION)
          ? mojom::RedEyeReduction::CONTROLLABLE
          : mojom::RedEyeReduction::NEVER;
  photo_capabilities->height = mojom::Range::New();
  photo_capabilities->height->current =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::CURRENT_HEIGHT);
  photo_capabilities->height->max =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::MAX_HEIGHT);
  photo_capabilities->height->min =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::MIN_HEIGHT);
  photo_capabilities->height->step =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::STEP_HEIGHT);
  photo_capabilities->width = mojom::Range::New();
  photo_capabilities->width->current =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::CURRENT_WIDTH);
  photo_capabilities->width->max =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::MAX_WIDTH);
  photo_capabilities->width->min =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::MIN_WIDTH);
  photo_capabilities->width->step =
      caps.getInt(PhotoCapabilities::PhotoCapabilityInt::STEP_WIDTH);
  const auto fill_light_modes = caps.getFillLightModeArray();
  std::vector<mojom::FillLightMode> modes;
  for (const auto& fill_light_mode : fill_light_modes)
    modes.push_back(ToMojomFillLightMode(fill_light_mode));
  photo_capabilities->fill_light_mode = modes;

  std::move(*cb).Run(std::move(photo_capabilities));
  get_photo_state_callbacks_.erase(reference_it);
}

void VideoCaptureDeviceAndroid::OnPhotoTaken(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& obj,
    jlong callback_id,
    const base::android::JavaParamRef<jbyteArray>& data) {
  DCHECK(callback_id);
  TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
                       "VideoCaptureDeviceAndroid::OnPhotoTaken",
                       TRACE_EVENT_SCOPE_PROCESS);

  base::AutoLock lock(photo_callbacks_lock_);

  TakePhotoCallback* const cb =
      reinterpret_cast<TakePhotoCallback*>(callback_id);
  // Search for the pointer |cb| in the list of |take_photo_callbacks_|.
  const auto reference_it =
      std::find_if(take_photo_callbacks_.begin(), take_photo_callbacks_.end(),
                   [cb](const std::unique_ptr<TakePhotoCallback>& callback) {
                     return callback.get() == cb;
                   });
  if (reference_it == take_photo_callbacks_.end()) {
    NOTREACHED() << "|callback_id| not found.";
    return;
  }

  if (data != nullptr) {
    mojom::BlobPtr blob = mojom::Blob::New();
    base::android::JavaByteArrayToByteVector(env, data, &blob->data);
    blob->mime_type = blob->data.empty() ? "" : "image/jpeg";
    std::move(*cb).Run(std::move(blob));
  }

  take_photo_callbacks_.erase(reference_it);
}

void VideoCaptureDeviceAndroid::OnStarted(JNIEnv* env,
                                          const JavaParamRef<jobject>& obj) {
  if (client_)
    client_->OnStarted();
}

void VideoCaptureDeviceAndroid::DCheckCurrentlyOnIncomingTaskRunner(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& obj) {
  DCHECK(main_task_runner_->BelongsToCurrentThread());
}

void VideoCaptureDeviceAndroid::ConfigureForTesting() {
  Java_VideoCapture_setTestMode(AttachCurrentThread(), j_capture_);
}

void VideoCaptureDeviceAndroid::ProcessFirstFrameAvailable(
    base::TimeTicks current_time) {
  base::AutoLock lock(lock_);
  if (got_first_frame_)
    return;
  got_first_frame_ = true;

  // Set aside one frame allowance for fluctuation.
  expected_next_frame_time_ = current_time - frame_interval_;
  for (auto& request : photo_requests_queue_)
    main_task_runner_->PostTask(FROM_HERE, std::move(request));
  photo_requests_queue_.clear();
}

bool VideoCaptureDeviceAndroid::IsClientConfigured() {
  base::AutoLock lock(lock_);
  return (state_ == kConfigured && client_);
}

bool VideoCaptureDeviceAndroid::ThrottleFrame(base::TimeTicks current_time) {
  if (expected_next_frame_time_ > current_time)
    return true;
  expected_next_frame_time_ += frame_interval_;
  return false;
}

void VideoCaptureDeviceAndroid::SendIncomingDataToClient(
    const uint8_t* data,
    int length,
    int rotation,
    base::TimeTicks reference_time,
    base::TimeDelta timestamp) {
  base::AutoLock lock(lock_);
  if (!client_)
    return;
  client_->OnIncomingCapturedData(
      data, length, capture_format_, capture_color_space_, rotation,
      false /* flip_y */, reference_time, timestamp);
}

VideoPixelFormat VideoCaptureDeviceAndroid::GetColorspace() {
  JNIEnv* env = AttachCurrentThread();
  const int current_capture_colorspace =
      Java_VideoCapture_getColorspace(env, j_capture_);
  switch (current_capture_colorspace) {
    case ANDROID_IMAGE_FORMAT_YV12:
      return PIXEL_FORMAT_YV12;
    case ANDROID_IMAGE_FORMAT_YUV_420_888:
      return PIXEL_FORMAT_I420;
    case ANDROID_IMAGE_FORMAT_NV21:
      return PIXEL_FORMAT_NV21;
    case ANDROID_IMAGE_FORMAT_UNKNOWN:
    default:
      return PIXEL_FORMAT_UNKNOWN;
  }
}

void VideoCaptureDeviceAndroid::SetErrorState(media::VideoCaptureError error,
                                              const base::Location& from_here,
                                              const std::string& reason) {
  {
    base::AutoLock lock(lock_);
    state_ = kError;
    if (!client_)
      return;
    client_->OnError(error, from_here, reason);
  }
}

void VideoCaptureDeviceAndroid::DoTakePhoto(TakePhotoCallback callback) {
  DCHECK(main_task_runner_->BelongsToCurrentThread());
  TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
                       "VideoCaptureDeviceAndroid::DoTakePhoto",
                       TRACE_EVENT_SCOPE_PROCESS);
#if DCHECK_IS_ON()
  {
    base::AutoLock lock(lock_);
    DCHECK_EQ(kConfigured, state_);
    DCHECK(got_first_frame_);
  }
#endif
  JNIEnv* env = AttachCurrentThread();

  // Make copy on the heap so we can pass the pointer through JNI.
  std::unique_ptr<TakePhotoCallback> heap_callback(
      new TakePhotoCallback(std::move(callback)));
  const intptr_t callback_id = reinterpret_cast<intptr_t>(heap_callback.get());
  {
    base::AutoLock lock(photo_callbacks_lock_);
    take_photo_callbacks_.push_back(std::move(heap_callback));
  }
  Java_VideoCapture_takePhotoAsync(env, j_capture_, callback_id);
}

void VideoCaptureDeviceAndroid::DoGetPhotoState(
    GetPhotoStateCallback callback) {
  DCHECK(main_task_runner_->BelongsToCurrentThread());
#if DCHECK_IS_ON()
  {
    base::AutoLock lock(lock_);
    DCHECK_EQ(kConfigured, state_);
    DCHECK(got_first_frame_);
  }
#endif
  JNIEnv* env = AttachCurrentThread();

  // Make copy on the heap so we can pass the pointer through JNI.
  std::unique_ptr<GetPhotoStateCallback> heap_callback(
      new GetPhotoStateCallback(std::move(callback)));
  const intptr_t callback_id = reinterpret_cast<intptr_t>(heap_callback.get());
  {
    base::AutoLock lock(photo_callbacks_lock_);
    get_photo_state_callbacks_.push_back(std::move(heap_callback));
  }
  Java_VideoCapture_getPhotoCapabilitiesAsync(env, j_capture_, callback_id);
}

void VideoCaptureDeviceAndroid::DoSetPhotoOptions(
    mojom::PhotoSettingsPtr settings,
    SetPhotoOptionsCallback callback) {
  DCHECK(main_task_runner_->BelongsToCurrentThread());
#if DCHECK_IS_ON()
  {
    base::AutoLock lock(lock_);
    DCHECK_EQ(kConfigured, state_);
    DCHECK(got_first_frame_);
  }
#endif
  JNIEnv* env = AttachCurrentThread();

  const double zoom = settings->has_zoom ? settings->zoom : 0.0;

  const double focusDistance =
      settings->has_focus_distance ? settings->focus_distance : 0.0;

  const PhotoCapabilities::AndroidMeteringMode focus_mode =
      settings->has_focus_mode
          ? ToAndroidMeteringMode(settings->focus_mode)
          : PhotoCapabilities::AndroidMeteringMode::NOT_SET;

  const PhotoCapabilities::AndroidMeteringMode exposure_mode =
      settings->has_exposure_mode
          ? ToAndroidMeteringMode(settings->exposure_mode)
          : PhotoCapabilities::AndroidMeteringMode::NOT_SET;

  const double width = settings->has_width ? settings->width : 0.0;
  const double height = settings->has_height ? settings->height : 0.0;

  std::vector<double> points_of_interest_marshalled;
  for (const auto& point : settings->points_of_interest) {
    points_of_interest_marshalled.push_back(point->x);
    points_of_interest_marshalled.push_back(point->y);
  }
  ScopedJavaLocalRef<jdoubleArray> points_of_interest =
      base::android::ToJavaDoubleArray(env, points_of_interest_marshalled);

  const double exposure_compensation = settings->has_exposure_compensation
                                           ? settings->exposure_compensation
                                           : 0.0;
  const double exposure_time =
      settings->has_exposure_time ? settings->exposure_time : 0.0;

  const PhotoCapabilities::AndroidMeteringMode white_balance_mode =
      settings->has_white_balance_mode
          ? ToAndroidMeteringMode(settings->white_balance_mode)
          : PhotoCapabilities::AndroidMeteringMode::NOT_SET;

  const double iso = settings->has_iso ? settings->iso : 0.0;

  const PhotoCapabilities::AndroidFillLightMode fill_light_mode =
      settings->has_fill_light_mode
          ? ToAndroidFillLightMode(settings->fill_light_mode)
          : PhotoCapabilities::AndroidFillLightMode::NOT_SET;

  const double color_temperature =
      settings->has_color_temperature ? settings->color_temperature : 0.0;

  Java_VideoCapture_setPhotoOptions(
      env, j_capture_, zoom, static_cast<int>(focus_mode), focusDistance,
      static_cast<int>(exposure_mode), width, height, points_of_interest,
      settings->has_exposure_compensation, exposure_compensation, exposure_time,
      static_cast<int>(white_balance_mode), iso,
      settings->has_red_eye_reduction, settings->red_eye_reduction,
      static_cast<int>(fill_light_mode), settings->has_torch, settings->torch,
      color_temperature);

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

}  // namespace media
