// Copyright 2019 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 "third_party/blink/renderer/modules/webcodecs/video_frame.h"

#include <utility>

#include "base/memory/scoped_refptr.h"
#include "base/numerics/checked_math.h"
#include "media/base/timestamp_constants.h"
#include "media/base/video_frame.h"
#include "media/base/video_frame_metadata.h"
#include "media/base/video_frame_pool.h"
#include "media/base/video_util.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_plane_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_plane_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
#include "third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/video_frame_image_util.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"

namespace blink {

namespace {

struct YUVReadbackContext {
  gfx::Size coded_size;
  gfx::Rect visible_rect;
  gfx::Size natural_size;
  base::TimeDelta timestamp;
  scoped_refptr<media::VideoFrame> frame;
};

void OnYUVReadbackDone(
    void* raw_ctx,
    std::unique_ptr<const SkImage::AsyncReadResult> async_result) {
  if (!async_result)
    return;
  auto* context = reinterpret_cast<YUVReadbackContext*>(raw_ctx);
  context->frame = media::VideoFrame::WrapExternalYuvData(
      media::PIXEL_FORMAT_I420, context->coded_size, context->visible_rect,
      context->natural_size, static_cast<int>(async_result->rowBytes(0)),
      static_cast<int>(async_result->rowBytes(1)),
      static_cast<int>(async_result->rowBytes(2)),
      // TODO(crbug.com/1161304): We should be able to wrap readonly memory in
      // a VideoFrame without resorting to a const_cast.
      reinterpret_cast<uint8_t*>(const_cast<void*>(async_result->data(0))),
      reinterpret_cast<uint8_t*>(const_cast<void*>(async_result->data(1))),
      reinterpret_cast<uint8_t*>(const_cast<void*>(async_result->data(2))),
      context->timestamp);
  if (!context->frame)
    return;
  context->frame->AddDestructionObserver(
      ConvertToBaseOnceCallback(WTF::CrossThreadBindOnce(
          base::DoNothing::Once<
              std::unique_ptr<const SkImage::AsyncReadResult>>(),
          std::move(async_result))));
}

media::VideoPixelFormat ToMediaPixelFormat(V8VideoPixelFormat::Enum fmt) {
  switch (fmt) {
    case V8VideoPixelFormat::Enum::kI420:
      return media::PIXEL_FORMAT_I420;
    case V8VideoPixelFormat::Enum::kNV12:
      return media::PIXEL_FORMAT_NV12;
    case V8VideoPixelFormat::Enum::kABGR:
      return media::PIXEL_FORMAT_ABGR;
    case V8VideoPixelFormat::Enum::kXBGR:
      return media::PIXEL_FORMAT_XBGR;
    case V8VideoPixelFormat::Enum::kARGB:
      return media::PIXEL_FORMAT_ARGB;
    case V8VideoPixelFormat::Enum::kXRGB:
      return media::PIXEL_FORMAT_XRGB;
  }
}

class CachedVideoFramePool : public GarbageCollected<CachedVideoFramePool>,
                             public Supplement<ExecutionContext> {
 public:
  static const char kSupplementName[];

  static CachedVideoFramePool& From(ExecutionContext& context) {
    CachedVideoFramePool* supplement =
        Supplement<ExecutionContext>::From<CachedVideoFramePool>(context);
    if (!supplement) {
      supplement = MakeGarbageCollected<CachedVideoFramePool>(context);
      Supplement<ExecutionContext>::ProvideTo(context, supplement);
    }
    return *supplement;
  }

  explicit CachedVideoFramePool(ExecutionContext& context)
      : Supplement<ExecutionContext>(context),
        task_runner_(Thread::Current()->GetTaskRunner()) {}
  virtual ~CachedVideoFramePool() = default;

  // Disallow copy and assign.
  CachedVideoFramePool& operator=(const CachedVideoFramePool&) = delete;
  CachedVideoFramePool(const CachedVideoFramePool&) = delete;

  scoped_refptr<media::VideoFrame> CreateFrame(media::VideoPixelFormat format,
                                               const gfx::Size& coded_size,
                                               const gfx::Rect& visible_rect,
                                               const gfx::Size& natural_size,
                                               base::TimeDelta timestamp) {
    if (!frame_pool_)
      CreatePoolAndStartIdleObsever();

    last_frame_creation_ = base::TimeTicks::Now();
    return frame_pool_->CreateFrame(format, coded_size, visible_rect,
                                    natural_size, timestamp);
  }

  void Trace(Visitor* visitor) const override {
    Supplement<ExecutionContext>::Trace(visitor);
  }

 private:
  static const base::TimeDelta kIdleTimeout;

  void PostMonitoringTask() {
    DCHECK(!task_handle_.IsActive());
    task_handle_ = PostDelayedCancellableTask(
        *task_runner_, FROM_HERE,
        WTF::Bind(&CachedVideoFramePool::PurgeIdleFramePool,
                  WrapWeakPersistent(this)),
        kIdleTimeout);
  }

  void CreatePoolAndStartIdleObsever() {
    DCHECK(!frame_pool_);
    frame_pool_ = std::make_unique<media::VideoFramePool>();
    PostMonitoringTask();
  }

  // We don't want a VideoFramePool to stick around forever wasting memory, so
  // once we haven't issued any VideoFrames for a while, turn down the pool.
  void PurgeIdleFramePool() {
    if (base::TimeTicks::Now() - last_frame_creation_ > kIdleTimeout) {
      frame_pool_.reset();
      return;
    }
    PostMonitoringTask();
  }

  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  std::unique_ptr<media::VideoFramePool> frame_pool_;
  base::TimeTicks last_frame_creation_;
  TaskHandle task_handle_;
};

// static -- defined out of line to satisfy link time requirements.
const char CachedVideoFramePool::kSupplementName[] = "CachedVideoFramePool";
const base::TimeDelta CachedVideoFramePool::kIdleTimeout =
    base::TimeDelta::FromSeconds(10);

bool IsSupportedPlanarFormat(const media::VideoFrame& frame) {
  if (!frame.IsMappable() && !frame.HasGpuMemoryBuffer())
    return false;

  const size_t num_planes = frame.layout().num_planes();
  switch (frame.format()) {
    case media::PIXEL_FORMAT_I420:
      return num_planes == 3;
    case media::PIXEL_FORMAT_I420A:
      return num_planes == 4;
    case media::PIXEL_FORMAT_NV12:
      return num_planes == 2;
    case media::PIXEL_FORMAT_XBGR:
    case media::PIXEL_FORMAT_XRGB:
    case media::PIXEL_FORMAT_ABGR:
    case media::PIXEL_FORMAT_ARGB:
      return num_planes == 1;
    default:
      return false;
  }
}

}  // namespace

VideoFrame::VideoFrame(scoped_refptr<media::VideoFrame> frame,
                       ExecutionContext* context) {
  DCHECK(frame);
  handle_ = base::MakeRefCounted<VideoFrameHandle>(std::move(frame), context);
}

VideoFrame::VideoFrame(scoped_refptr<VideoFrameHandle> handle)
    : handle_(std::move(handle)) {
  DCHECK(handle_);

  // Note: The provided |handle| may be invalid if close() has been called while
  // a frame is in transit to another thread.
}

// static
VideoFrame* VideoFrame::Create(ScriptState* script_state,
                               const CanvasImageSourceUnion& source,
                               const VideoFrameInit* init,
                               ExceptionState& exception_state) {
  auto* image_source = ToCanvasImageSource(source, exception_state);
  if (!image_source) {
    // ToCanvasImageSource() will throw a source appropriate exception.
    return nullptr;
  }

  if (image_source->WouldTaintOrigin()) {
    exception_state.ThrowSecurityError(
        "VideoFrames can't be created from tainted sources.");
    return nullptr;
  }

  // Special case <video> and VideoFrame to directly use the underlying frame.
  if (source.IsVideoFrame() || source.IsHTMLVideoElement()) {
    scoped_refptr<media::VideoFrame> source_frame;
    if (source.IsVideoFrame()) {
      if (!init || (!init->hasTimestamp() && !init->hasDuration()))
        return source.GetAsVideoFrame()->clone(script_state, exception_state);
      source_frame = source.GetAsVideoFrame()->frame();
    } else if (source.IsHTMLVideoElement()) {
      if (auto* wmp = source.GetAsHTMLVideoElement()->GetWebMediaPlayer())
        source_frame = wmp->GetCurrentFrame();
    }

    if (!source_frame) {
      exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                        "Invalid source state");
      return nullptr;
    }

    // We can't modify the timestamp or duration directly since there may be
    // other owners accessing these fields concurrently.
    if (init && (init->hasTimestamp() || init->hasDuration())) {
      source_frame = media::VideoFrame::WrapVideoFrame(
          source_frame, source_frame->format(), source_frame->visible_rect(),
          source_frame->natural_size());
      if (init->hasTimestamp()) {
        source_frame->set_timestamp(
            base::TimeDelta::FromMicroseconds(init->timestamp()));
      }
      if (init->hasDuration()) {
        source_frame->metadata().frame_duration =
            base::TimeDelta::FromMicroseconds(init->duration());
      }
    }

    return MakeGarbageCollected<VideoFrame>(
        std::move(source_frame), ExecutionContext::From(script_state));
  }

  SourceImageStatus status = kInvalidSourceImageStatus;
  auto image = image_source->GetSourceImageForCanvas(&status, FloatSize());
  if (!image || status != kNormalSourceImageStatus) {
    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                      "Invalid source state");
    return nullptr;
  }

  const auto timestamp = base::TimeDelta::FromMicroseconds(
      (init && init->hasTimestamp()) ? init->timestamp() : 0);

  const auto sk_image = image->PaintImageForCurrentFrame().GetSkImage();
  const auto sk_image_info = sk_image->imageInfo();

  auto sk_color_space = sk_image_info.refColorSpace();
  if (!sk_color_space)
    sk_color_space = SkColorSpace::MakeSRGB();

  const auto gfx_color_space = gfx::ColorSpace(*sk_color_space);
  if (!gfx_color_space.IsValid()) {
    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                      "Invalid color space");
    return nullptr;
  }

  const gfx::Size coded_size(sk_image_info.width(), sk_image_info.height());
  const gfx::Rect visible_rect(coded_size);
  const gfx::Size natural_size = coded_size;

  scoped_refptr<media::VideoFrame> frame;
  if (sk_image->isTextureBacked()) {
    YUVReadbackContext result;
    result.coded_size = coded_size;
    result.visible_rect = visible_rect;
    result.natural_size = natural_size;
    result.timestamp = timestamp;

    // While this function indicates it's asynchronous, the flushAndSubmit()
    // call below ensures it completes synchronously.
    sk_image->asyncRescaleAndReadPixelsYUV420(
        kRec709_SkYUVColorSpace, sk_color_space, sk_image_info.bounds(),
        sk_image_info.dimensions(), SkImage::RescaleGamma::kSrc,
        SkImage::RescaleMode::kRepeatedCubic, &OnYUVReadbackDone, &result);
    GrDirectContext* gr_context = image->ContextProvider()->GetGrContext();
    DCHECK(gr_context);
    gr_context->flushAndSubmit(/*syncCpu=*/true);

    if (!result.frame) {
      exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
                                        "YUV conversion error during readback");
      return nullptr;
    }

    frame = std::move(result.frame);
    frame->set_color_space(gfx_color_space);
    if (init && init->hasDuration()) {
      frame->metadata().frame_duration =
          base::TimeDelta::FromMicroseconds(init->duration());
    }
    return MakeGarbageCollected<VideoFrame>(
        std::move(frame), ExecutionContext::From(script_state));
  }

  frame =
      media::CreateFromSkImage(sk_image, visible_rect, natural_size, timestamp);
  if (!frame) {
    exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
                                      "Failed to create video frame");
    return nullptr;
  }
  frame->set_color_space(gfx_color_space);
  if (init && init->hasDuration()) {
    frame->metadata().frame_duration =
        base::TimeDelta::FromMicroseconds(init->duration());
  }
  return MakeGarbageCollected<VideoFrame>(
      base::MakeRefCounted<VideoFrameHandle>(
          std::move(frame), std::move(sk_image),
          ExecutionContext::From(script_state)));
}

// static
VideoFrame* VideoFrame::Create(ScriptState* script_state,
                               const String& format,
                               const HeapVector<Member<PlaneInit>>& planes,
                               const VideoFramePlaneInit* init,
                               ExceptionState& exception_state) {
  if (!init->hasCodedWidth() || !init->hasCodedHeight()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kConstraintError,
        "Coded size is required for planar construction");
    return nullptr;
  }

  // Type formats are enforced by V8.
  auto typed_fmt = V8VideoPixelFormat::Create(format);
  DCHECK(typed_fmt);

  auto media_fmt = ToMediaPixelFormat(typed_fmt->AsEnum());

  // There's no I420A pixel format, so treat I420 + 4 planes as I420A.
  if (media_fmt == media::PIXEL_FORMAT_I420 && planes.size() == 4u)
    media_fmt = media::PIXEL_FORMAT_I420A;

  if (media::VideoFrame::NumPlanes(media_fmt) != planes.size()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kConstraintError,
        String::Format("Invalid number of planes for format %s; expected %zu, "
                       "received %u",
                       format.Ascii().c_str(),
                       media::VideoFrame::NumPlanes(media_fmt), planes.size()));
    return nullptr;
  }

  // gfx::Size() takes int.
  if (!base::CheckedNumeric<uint32_t>(init->codedWidth()).IsValid<int>() ||
      !base::CheckedNumeric<uint32_t>(init->codedHeight()).IsValid<int>() ||
      init->codedWidth() == 0 || init->codedHeight() == 0) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kConstraintError,
        String::Format("Invalid coded size (%u, %u) provided",
                       init->codedWidth(), init->codedHeight()));
    return nullptr;
  }
  const gfx::Size coded_size(init->codedWidth(), init->codedHeight());

  for (wtf_size_t i = 0; i < planes.size(); ++i) {
    const auto minimum_size =
        media::VideoFrame::PlaneSize(media_fmt, i, coded_size);
    if (!base::CheckedNumeric<uint32_t>(planes[i]->stride()).IsValid<int>()) {
      exception_state.ThrowDOMException(
          DOMExceptionCode::kConstraintError,
          String::Format("The stride of plane %u is too large", i));
      return nullptr;
    }
    if (planes[i]->stride() < uint32_t{minimum_size.width()}) {
      exception_state.ThrowDOMException(
          DOMExceptionCode::kConstraintError,
          String::Format(
              "The stride of plane %u is too small for the given coded size "
              "(%s); expected at least %d, received %u",
              i, coded_size.ToString().c_str(), minimum_size.width(),
              planes[i]->stride()));
      return nullptr;
    }
    if (planes[i]->rows() != uint32_t{minimum_size.height()}) {
      exception_state.ThrowDOMException(
          DOMExceptionCode::kConstraintError,
          String::Format(
              "The row count for plane %u is incorrect for the given coded "
              "size (%s); expected %d, received %u",
              i, coded_size.ToString().c_str(), minimum_size.height(),
              planes[i]->rows()));
      return nullptr;
    }

    // This requires the full stride to be provided for every row.
    gfx::Size provided_size(planes[i]->stride(), planes[i]->rows());
    const auto required_byte_size = provided_size.GetCheckedArea();
    if (!required_byte_size.IsValid()) {
      exception_state.ThrowDOMException(
          DOMExceptionCode::kConstraintError,
          String::Format("The size of plane %u is too large", i));
      return nullptr;
    }

    DOMArrayPiece buffer(planes[i]->src());
    if (buffer.ByteLength() < required_byte_size.ValueOrDie()) {
      // Note: We use GetArea() below instead of area.ValueOrDie() since the
      // base::StrictNumeric seems to confuse the printf() format checks.
      exception_state.ThrowDOMException(
          DOMExceptionCode::kConstraintError,
          String::Format(
              "The size of plane %u is too small for the given coded "
              "size (%s); expected at least %d, received %zu",
              i, coded_size.ToString().c_str(), provided_size.GetArea(),
              buffer.ByteLength()));
      return nullptr;
    }
  }

  auto visible_rect = gfx::Rect(coded_size);
  if (init->hasCropLeft() || init->hasCropTop() || init->hasCropWidth() ||
      init->hasCropHeight()) {
    const auto crop_left = init->hasCropLeft() ? init->cropLeft() : 0;
    const auto crop_top = init->hasCropTop() ? init->cropTop() : 0;
    const auto crop_w =
        init->hasCropWidth() ? visible_rect.width() - init->cropWidth() : 0;
    const auto crop_h =
        init->hasCropHeight() ? visible_rect.height() - init->cropHeight() : 0;
    if (crop_w < 0 || crop_h < 0 || crop_w > unsigned{visible_rect.width()} ||
        crop_h > unsigned{visible_rect.height()}) {
      visible_rect = gfx::Rect();
    } else {
      visible_rect.Inset(crop_left, crop_top, crop_w, crop_h);
    }

    if (visible_rect.IsEmpty()) {
      exception_state.ThrowDOMException(
          DOMExceptionCode::kConstraintError,
          String::Format(
              "Invalid visble rect (%s) after crop (%d, %d, %d, %d) applied",
              visible_rect.ToString().c_str(), crop_left, crop_top, crop_w,
              crop_h));
      return nullptr;
    }
  }

  auto natural_size = visible_rect.size();
  if (init->hasDisplayWidth())
    natural_size.set_width(init->displayWidth());
  if (init->hasDisplayHeight())
    natural_size.set_height(init->displayHeight());
  if (coded_size.IsEmpty()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kConstraintError,
        String::Format("Invalid display size (%s) provided",
                       natural_size.ToString().c_str()));
    return nullptr;
  }

  const auto timestamp = base::TimeDelta::FromMicroseconds(init->timestamp());
  auto& frame_pool =
      CachedVideoFramePool::From(*ExecutionContext::From(script_state));
  auto frame = frame_pool.CreateFrame(media_fmt, coded_size, visible_rect,
                                      natural_size, timestamp);
  if (!frame) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kConstraintError,
        String::Format(
            "Failed to create a video frame with configuration {format:%s, "
            "coded_size:%s, visible_rect:%s, display_size:%s}",
            VideoPixelFormatToString(media_fmt).c_str(),
            coded_size.ToString().c_str(), visible_rect.ToString().c_str(),
            natural_size.ToString().c_str()));
    return nullptr;
  }

  for (wtf_size_t i = 0; i < planes.size(); ++i) {
    const auto minimum_size =
        media::VideoFrame::PlaneSize(media_fmt, i, coded_size);

    DOMArrayPiece buffer(planes[i]->src());

    uint8_t* dest_ptr = frame->visible_data(i);
    const uint8_t* src_ptr = reinterpret_cast<uint8_t*>(buffer.Data());
    for (size_t r = 0; r < planes[i]->rows(); ++r) {
      DCHECK_LE(
          src_ptr + planes[i]->stride(),
          reinterpret_cast<uint8_t*>(buffer.Data()) + buffer.ByteLength());

      memcpy(dest_ptr, src_ptr, minimum_size.width());
      src_ptr += planes[i]->stride();
      dest_ptr += frame->stride(i);
    }
  }

  return MakeGarbageCollected<VideoFrame>(std::move(frame),
                                          ExecutionContext::From(script_state));
}

String VideoFrame::format() const {
  auto local_frame = handle_->frame();
  if (!local_frame || !IsSupportedPlanarFormat(*local_frame))
    return String();

  switch (local_frame->format()) {
    case media::PIXEL_FORMAT_I420:
    case media::PIXEL_FORMAT_I420A:
      return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kI420);
    case media::PIXEL_FORMAT_NV12:
      return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kNV12);
    case media::PIXEL_FORMAT_ABGR:
      return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kABGR);
    case media::PIXEL_FORMAT_XBGR:
      return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kXBGR);
    case media::PIXEL_FORMAT_ARGB:
      return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kARGB);
    case media::PIXEL_FORMAT_XRGB:
      return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kXRGB);
    default:
      NOTREACHED();
      return String();
  }
}

base::Optional<HeapVector<Member<Plane>>> VideoFrame::planes() {
  // Verify that |this| has not been invalidated, and that the format is
  // supported.
  auto local_frame = handle_->frame();
  if (!local_frame || !IsSupportedPlanarFormat(*local_frame))
    return base::nullopt;

  // Create a Plane for each VideoFrame plane, but only the first time.
  if (planes_.IsEmpty()) {
    for (size_t i = 0; i < local_frame->layout().num_planes(); i++) {
      // Note: |handle_| may have been invalidated since |local_frame| was read.
      planes_.push_back(MakeGarbageCollected<Plane>(handle_, i));
    }
  }

  return planes_;
}

uint32_t VideoFrame::codedWidth() const {
  auto local_frame = handle_->frame();
  if (!local_frame)
    return 0;
  return local_frame->coded_size().width();
}

uint32_t VideoFrame::codedHeight() const {
  auto local_frame = handle_->frame();
  if (!local_frame)
    return 0;
  return local_frame->coded_size().height();
}

uint32_t VideoFrame::cropLeft() const {
  auto local_frame = handle_->frame();
  if (!local_frame)
    return 0;
  return local_frame->visible_rect().x();
}

uint32_t VideoFrame::cropTop() const {
  auto local_frame = handle_->frame();
  if (!local_frame)
    return 0;
  return local_frame->visible_rect().y();
}

uint32_t VideoFrame::cropWidth() const {
  auto local_frame = handle_->frame();
  if (!local_frame)
    return 0;
  return local_frame->visible_rect().width();
}

uint32_t VideoFrame::cropHeight() const {
  auto local_frame = handle_->frame();
  if (!local_frame)
    return 0;
  return local_frame->visible_rect().height();
}

uint32_t VideoFrame::displayWidth() const {
  auto local_frame = handle_->frame();
  if (!local_frame)
    return 0;
  return local_frame->natural_size().width();
}

uint32_t VideoFrame::displayHeight() const {
  auto local_frame = handle_->frame();
  if (!local_frame)
    return 0;
  return local_frame->natural_size().height();
}

base::Optional<uint64_t> VideoFrame::timestamp() const {
  auto local_frame = handle_->frame();
  if (!local_frame || local_frame->timestamp() == media::kNoTimestamp)
    return base::nullopt;
  return local_frame->timestamp().InMicroseconds();
}

base::Optional<uint64_t> VideoFrame::duration() const {
  auto local_frame = handle_->frame();
  // TODO(sandersd): Can a duration be kNoTimestamp?
  if (!local_frame || !local_frame->metadata().frame_duration.has_value())
    return base::nullopt;
  return local_frame->metadata().frame_duration->InMicroseconds();
}

void VideoFrame::close() {
  handle_->Invalidate();
}

void VideoFrame::destroy(ExecutionContext* execution_context) {
  execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
      mojom::blink::ConsoleMessageSource::kDeprecation,
      mojom::blink::ConsoleMessageLevel::kWarning,
      "VideoFrame.destroy() is deprecated; use VideoFrame.close()."));
  close();
}

VideoFrame* VideoFrame::clone(ScriptState* script_state,
                              ExceptionState& exception_state) {
  VideoFrame* frame = CloneFromNative(ExecutionContext::From(script_state));

  if (!frame) {
    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                      "Cannot clone closed VideoFrame.");
    return nullptr;
  }

  return frame;
}

VideoFrame* VideoFrame::CloneFromNative(ExecutionContext* context) {
  // The returned handle will be nullptr if it was already invalidated.
  auto handle = handle_->Clone();
  return handle ? MakeGarbageCollected<VideoFrame>(std::move(handle)) : nullptr;
}

ScriptPromise VideoFrame::createImageBitmap(ScriptState* script_state,
                                            const ImageBitmapOptions* options,
                                            ExceptionState& exception_state) {
  VideoFrameLogger::From(*ExecutionContext::From(script_state))
      .LogCreateImageBitmapDeprecationNotice();

  base::Optional<IntRect> crop_rect;
  if (auto local_frame = handle_->frame())
    crop_rect = IntRect(local_frame->visible_rect());

  return ImageBitmapFactories::CreateImageBitmap(script_state, this, crop_rect,
                                                 options, exception_state);
}

scoped_refptr<Image> VideoFrame::GetSourceImageForCanvas(
    SourceImageStatus* status,
    const FloatSize&) {
  const auto local_handle = handle_->CloneForInternalUse();
  if (!local_handle) {
    DLOG(ERROR) << "GetSourceImageForCanvas() called for closed frame.";
    *status = kInvalidSourceImageStatus;
    return nullptr;
  }

  if (auto sk_img = local_handle->sk_image()) {
    *status = kNormalSourceImageStatus;
    return UnacceleratedStaticBitmapImage::Create(std::move(sk_img));
  }

  const auto image = CreateImageFromVideoFrame(local_handle->frame());
  if (!image) {
    *status = kInvalidSourceImageStatus;
    return nullptr;
  }

  *status = kNormalSourceImageStatus;
  return image;
}

bool VideoFrame::WouldTaintOrigin() const {
  // VideoFrames can't be created from untainted sources currently. If we ever
  // add that ability we will need a tainting signal on the VideoFrame itself.
  // One example would be allowing <video> elements to provide a VideoFrame.
  return false;
}

FloatSize VideoFrame::ElementSize(
    const FloatSize& default_object_size,
    const RespectImageOrientationEnum respect_orientation) const {
  // TODO(crbug.com/1140137): This will need consideration for orientation.
  return FloatSize(BitmapSourceSize());
}

bool VideoFrame::IsVideoFrame() const {
  return true;
}

bool VideoFrame::IsOpaque() const {
  if (auto local_frame = handle_->frame())
    return media::IsOpaque(local_frame->format());
  return false;
}

bool VideoFrame::IsAccelerated() const {
  if (auto local_handle = handle_->CloneForInternalUse()) {
    return handle_->sk_image() ? false
                               : WillCreateAcceleratedImagesFromVideoFrame(
                                     local_handle->frame().get());
  }
  return false;
}

IntSize VideoFrame::BitmapSourceSize() const {
  // TODO(crbug.com/1096724): Should be scaled to display size.
  if (auto local_frame = handle_->frame())
    return IntSize(local_frame->visible_rect().size());
  return IntSize();
}

ScriptPromise VideoFrame::CreateImageBitmap(ScriptState* script_state,
                                            base::Optional<IntRect> crop_rect,
                                            const ImageBitmapOptions* options,
                                            ExceptionState& exception_state) {
  const auto local_handle = handle_->CloneForInternalUse();
  if (!local_handle) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidStateError,
        "Cannot create ImageBitmap from closed VideoFrame.");
    return ScriptPromise();
  }

  if (auto sk_img = local_handle->sk_image()) {
    auto* image_bitmap = MakeGarbageCollected<ImageBitmap>(
        UnacceleratedStaticBitmapImage::Create(std::move(sk_img)), crop_rect,
        options);
    return ImageBitmapSource::FulfillImageBitmap(script_state, image_bitmap,
                                                 exception_state);
  }

  const auto image = CreateImageFromVideoFrame(local_handle->frame());
  if (!image) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kNotSupportedError,
        String(("Unsupported VideoFrame: " +
                local_handle->frame()->AsHumanReadableString())
                   .c_str()));
    return ScriptPromise();
  }

  auto* image_bitmap =
      MakeGarbageCollected<ImageBitmap>(image, crop_rect, options);
  return ImageBitmapSource::FulfillImageBitmap(script_state, image_bitmap,
                                               exception_state);
}

void VideoFrame::Trace(Visitor* visitor) const {
  visitor->Trace(planes_);
  ScriptWrappable::Trace(visitor);
}

}  // namespace blink
