// Copyright 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/cdm/library_cdm/clear_key_cdm/cdm_video_decoder.h"

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/containers/queue.h"
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/no_destructor.h"
#include "build/build_config.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
// Necessary to convert async media::VideoDecoder to sync CdmVideoDecoder.
// Typically not recommended for production code, but is ok here since
// ClearKeyCdm is only for testing.
#include "base/run_loop.h"
#include "base/task/single_thread_task_executor.h"
#include "base/threading/thread_task_runner_handle.h"
#include "media/base/decode_status.h"
#include "media/base/media_switches.h"
#include "media/base/media_util.h"
#include "media/cdm/cdm_type_conversion.h"
#include "media/cdm/library_cdm/cdm_host_proxy.h"
#include "media/media_buildflags.h"
#include "third_party/libyuv/include/libyuv/planar_functions.h"

#if BUILDFLAG(ENABLE_LIBVPX)
#include "media/filters/vpx_video_decoder.h"
#endif

#if BUILDFLAG(ENABLE_DAV1D_DECODER)
#include "media/filters/dav1d_video_decoder.h"
#endif

#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
#include "media/filters/ffmpeg_video_decoder.h"
#endif

#if BUILDFLAG(ENABLE_LIBGAV1_DECODER)
#include "media/filters/gav1_video_decoder.h"
#endif

namespace media {

namespace {

media::VideoDecoderConfig ToClearMediaVideoDecoderConfig(
    const cdm::VideoDecoderConfig_3& config) {
  gfx::Size coded_size(config.coded_size.width, config.coded_size.width);

  VideoDecoderConfig media_config(
      ToMediaVideoCodec(config.codec), ToMediaVideoCodecProfile(config.profile),
      VideoDecoderConfig::AlphaMode::kIsOpaque,
      ToMediaColorSpace(config.color_space), kNoTransformation, coded_size,
      gfx::Rect(coded_size), coded_size,
      std::vector<uint8_t>(config.extra_data,
                           config.extra_data + config.extra_data_size),
      EncryptionScheme::kUnencrypted);

  return media_config;
}

bool ToCdmVideoFrame(const VideoFrame& video_frame,
                     CdmHostProxy* cdm_host_proxy,
                     CdmVideoDecoder::CdmVideoFrame* cdm_video_frame) {
  DCHECK(cdm_video_frame);

  if (!video_frame.IsMappable()) {
    DVLOG(1) << "VideoFrame is not mappable";
    return false;
  }

  if (!IsYuvPlanar(video_frame.format())) {
    DVLOG(1) << "Only YUV planar format supported";
    return false;
  }

  if (VideoFrame::NumPlanes(video_frame.format()) != 3u) {
    DVLOG(1) << "Only 3-plane format supported";
    return false;
  }

  auto cdm_video_format = ToCdmVideoFormat(video_frame.format());
  if (cdm_video_format == cdm::kUnknownVideoFormat) {
    DVLOG(1) << "VideoFrame has unsupported format: " << video_frame.format();
    return false;
  }

  // Get required allocation size for a tightly packed frame.
  auto space_required = VideoFrame::AllocationSize(video_frame.format(),
                                                   video_frame.coded_size());
  auto* buffer = cdm_host_proxy->Allocate(space_required);
  if (!buffer) {
    LOG(ERROR) << __func__ << ": Buffer allocation failed.";
    return false;
  }

  buffer->SetSize(base::checked_cast<uint32_t>(space_required));
  cdm_video_frame->SetFrameBuffer(buffer);
  cdm_video_frame->SetFormat(cdm_video_format);
  cdm_video_frame->SetSize(
      {video_frame.coded_size().width(), video_frame.coded_size().height()});
  cdm_video_frame->SetTimestamp(video_frame.timestamp().InMicroseconds());
  // TODO(crbug.com/707127): Set ColorSpace here. It's not trivial to convert
  // a gfx::ColorSpace (from VideoFrame) to another other ColorSpace like
  // cdm::ColorSpace.

  static_assert(VideoFrame::kYPlane == cdm::kYPlane && cdm::kYPlane == 0, "");
  static_assert(VideoFrame::kUPlane == cdm::kUPlane && cdm::kUPlane == 1, "");
  static_assert(VideoFrame::kVPlane == cdm::kVPlane && cdm::kVPlane == 2, "");

  uint8_t* dst = buffer->Data();
  uint32_t offset = 0;
  for (int plane = 0; plane < 3; ++plane) {
    const uint8_t* src = video_frame.data(plane);
    int src_stride = video_frame.stride(plane);
    int row_bytes = video_frame.row_bytes(plane);
    int rows = video_frame.rows(plane);

    auto cdm_plane = static_cast<cdm::VideoPlane>(plane);
    cdm_video_frame->SetPlaneOffset(cdm_plane, offset);
    // Since it's tightly packed, the stride is the same as row bytes.
    cdm_video_frame->SetStride(cdm_plane, row_bytes);

    libyuv::CopyPlane(src, src_stride, dst, row_bytes, row_bytes, rows);
    dst += row_bytes * rows;
    offset += row_bytes * rows;
  }

  DCHECK_GE(space_required, offset) << ": Space mismatch";
  return true;
}

// Media VideoDecoders typically assumes a global environment where a lot of
// things are already setup in the process, e.g. base::ThreadTaskRunnerHandle
// and base::CommandLine. These will be available in the component build because
// the CDM and the host is depending on the same base/ target. In static build,
// they will not be available and we have to setup it by ourselves.
void SetupGlobalEnvironmentIfNeeded() {
  // Creating a base::SingleThreadTaskExecutor to setup
  // base::ThreadTaskRunnerHandle.
  if (!base::ThreadTaskRunnerHandle::IsSet()) {
    static base::NoDestructor<base::SingleThreadTaskExecutor> task_executor;
  }

  // Initialize CommandLine if not already initialized. Since this is a DLL,
  // just use empty arguments.
  if (!base::CommandLine::InitializedForCurrentProcess()) {
#if defined(OS_WIN)
    // Use InitUsingArgvForTesting() instead of Init() to avoid dependency on
    // shell32 API which might not work in the sandbox. See crbug.com/1242710.
    base::CommandLine::InitUsingArgvForTesting(0, nullptr);
#else
    base::CommandLine::Init(0, nullptr);
#endif
  }
}

// Adapts a media::VideoDecoder to a CdmVideoDecoder. Media VideoDecoders
// operations are asynchronous, often posting callbacks to the task runner. The
// CdmVideoDecoder operations are synchronous. Therefore, after calling
// media::VideoDecoder, we need to run a RunLoop manually and wait for the
// asynchronous operation to finish. The RunLoop must be of type
// |kNestableTasksAllowed| because we could be running the RunLoop in a task,
// e.g. in component builds when we share the same task runner as the host. In
// a static build, this is not necessary.
class VideoDecoderAdapter final : public CdmVideoDecoder {
 public:
  VideoDecoderAdapter(CdmHostProxy* cdm_host_proxy,
                      std::unique_ptr<VideoDecoder> video_decoder)
      : cdm_host_proxy_(cdm_host_proxy),
        video_decoder_(std::move(video_decoder)) {
    DCHECK(cdm_host_proxy_);
  }

  VideoDecoderAdapter(const VideoDecoderAdapter&) = delete;
  VideoDecoderAdapter& operator=(const VideoDecoderAdapter&) = delete;

  ~VideoDecoderAdapter() final = default;

  // CdmVideoDecoder implementation.
  Status Initialize(const cdm::VideoDecoderConfig_3& config) final {
    auto clear_config = ToClearMediaVideoDecoderConfig(config);
    DVLOG(1) << __func__ << ": " << clear_config.AsHumanReadableString();
    DCHECK(!last_init_result_.has_value());

    // Initialize |video_decoder_| and wait for completion.
    base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
    video_decoder_->Initialize(
        clear_config,
        /* low_delay = */ false,
        /* cdm_context = */ nullptr,
        base::BindOnce(&VideoDecoderAdapter::OnInitialized,
                       weak_factory_.GetWeakPtr(), run_loop.QuitClosure()),
        base::BindRepeating(&VideoDecoderAdapter::OnVideoFrameReady,
                            weak_factory_.GetWeakPtr()),
        /* waiting_cb = */ base::DoNothing());
    run_loop.Run();

    auto result = std::move(last_init_result_.value());
    last_init_result_.reset();

    return result;
  }

  void Deinitialize() final {
    // Do nothing since |video_decoder_| supports reinitialization without
    // the need to deinitialize first.
  }

  void Reset() final {
    DVLOG(2) << __func__;

    // Reset |video_decoder_| and wait for completion.
    base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
    video_decoder_->Reset(base::BindOnce(&VideoDecoderAdapter::OnReset,
                                         weak_factory_.GetWeakPtr(),
                                         run_loop.QuitClosure()));
    run_loop.Run();
  }

  cdm::Status Decode(scoped_refptr<DecoderBuffer> buffer,
                     CdmVideoFrame* decoded_frame) final {
    DVLOG(3) << __func__;
    DCHECK(!last_decode_status_.has_value());

    // Call |video_decoder_| Decode() and wait for completion.
    base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
    video_decoder_->Decode(
        std::move(buffer),
        base::BindOnce(&VideoDecoderAdapter::OnDecoded,
                       weak_factory_.GetWeakPtr(), run_loop.QuitClosure()));
    run_loop.Run();

    auto decode_status = last_decode_status_.value();
    last_decode_status_.reset();

    // "kAborted" shouldn't happen during a sync decode, so treat it as an
    // error.
    DCHECK_NE(decode_status.code(), StatusCode::kAborted);

    if (!decode_status.is_ok())
      return cdm::kDecodeError;

    if (decoded_video_frames_.empty())
      return cdm::kNeedMoreData;

    auto video_frame = decoded_video_frames_.front();
    decoded_video_frames_.pop();

    return ToCdmVideoFrame(*video_frame, cdm_host_proxy_, decoded_frame)
               ? cdm::kSuccess
               : cdm::kDecodeError;
  }

 private:
  void OnInitialized(base::OnceClosure quit_closure, Status status) {
    DVLOG(1) << __func__ << " success = " << status.is_ok();
    DCHECK(!last_init_result_.has_value());
    last_init_result_ = std::move(status);
    std::move(quit_closure).Run();
  }

  void OnVideoFrameReady(scoped_refptr<VideoFrame> video_frame) {
    // Do not queue EOS frames, which is not needed.
    if (video_frame->metadata().end_of_stream)
      return;

    decoded_video_frames_.push(std::move(video_frame));
  }

  void OnReset(base::OnceClosure quit_closure) {
    VideoFrameQueue empty_queue;
    std::swap(decoded_video_frames_, empty_queue);
    std::move(quit_closure).Run();
  }

  void OnDecoded(base::OnceClosure quit_closure, Status decode_status) {
    DCHECK(!last_decode_status_.has_value());
    last_decode_status_ = std::move(decode_status);
    std::move(quit_closure).Run();
  }

  CdmHostProxy* const cdm_host_proxy_;
  std::unique_ptr<VideoDecoder> video_decoder_;

  // Results of |video_decoder_| operations. Set iff the callback of the
  // operation has been called.
  absl::optional<Status> last_init_result_;
  absl::optional<Status> last_decode_status_;

  // Queue of decoded video frames.
  using VideoFrameQueue = base::queue<scoped_refptr<VideoFrame>>;
  VideoFrameQueue decoded_video_frames_;

  base::WeakPtrFactory<VideoDecoderAdapter> weak_factory_{this};
};

}  // namespace

std::unique_ptr<CdmVideoDecoder> CreateVideoDecoder(
    CdmHostProxy* cdm_host_proxy,
    const cdm::VideoDecoderConfig_3& config) {
  SetupGlobalEnvironmentIfNeeded();

  static base::NoDestructor<media::NullMediaLog> null_media_log;
  std::unique_ptr<VideoDecoder> video_decoder;

#if BUILDFLAG(ENABLE_LIBVPX)
  if (config.codec == cdm::kCodecVp8 || config.codec == cdm::kCodecVp9)
    video_decoder = std::make_unique<VpxVideoDecoder>();
#endif

#if BUILDFLAG(ENABLE_LIBGAV1_DECODER)
  if (base::FeatureList::IsEnabled(kGav1VideoDecoder)) {
    if (config.codec == cdm::kCodecAv1)
      video_decoder.reset(new Gav1VideoDecoder(null_media_log.get()));
  } else
#endif  // BUILDFLAG(ENABLE_LIBGAV1_DECODER)
  {
#if BUILDFLAG(ENABLE_DAV1D_DECODER)
    if (config.codec == cdm::kCodecAv1)
      video_decoder = std::make_unique<Dav1dVideoDecoder>(null_media_log.get());
#endif
  }

#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
  if (!video_decoder)
    video_decoder = std::make_unique<FFmpegVideoDecoder>(null_media_log.get());
#endif

  if (!video_decoder)
    return nullptr;

  return std::make_unique<VideoDecoderAdapter>(cdm_host_proxy,
                                               std::move(video_decoder));
}

}  // namespace media
