// Copyright 2021 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/xb1/shared/gpu_base_video_decoder.h"

#include <d3d11_1.h>
#include <wrl/client.h>
#include <algorithm>

#include "starboard/once.h"
#include "starboard/shared/uwp/application_uwp.h"
#include "starboard/shared/uwp/async_utils.h"
#include "starboard/shared/uwp/decoder_utils.h"
#include "starboard/shared/uwp/extended_resources_manager.h"
#include "starboard/shared/win32/decode_target_internal.h"
#include "starboard/shared/win32/error_utils.h"
#include "starboard/thread.h"
#include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h"
#include "third_party/angle/include/GLES2/gl2.h"
#include "third_party/angle/include/GLES2/gl2ext.h"
#include "third_party/angle/include/angle_hdr.h"
#if defined(INTERNAL_BUILD)
#include "third_party/internal/libav1_xb1/libav1/d3dx12.h"
#endif  // defined(INTERNAL_BUILD)

namespace starboard {
namespace xb1 {
namespace shared {

namespace {

using Microsoft::WRL::ComPtr;
using starboard::shared::starboard::player::JobThread;
using starboard::shared::starboard::player::filter::VideoFrame;
using starboard::shared::uwp::ApplicationUwp;
using starboard::shared::uwp::ExtendedResourcesManager;
using starboard::shared::uwp::FindByTimestamp;
using starboard::shared::uwp::RemoveByTimestamp;
using starboard::shared::uwp::UpdateHdrColorMetadataToCurrentDisplay;
using Windows::Graphics::Display::Core::HdmiDisplayInformation;

// Limit the number of pending buffers.
constexpr int kMaxNumberOfPendingBuffers = 8;
// Limit the cached presenting images.
constexpr int kNumberOfCachedPresentingImage = 3;
// The number of frame buffers in decoder
constexpr int kNumOutputFrameBuffers = 7;

const char kDecoderThreadName[] = "gpu_video_decoder_thread";
}  // namespace

class GpuFrameBufferPool {
 public:
  HRESULT AllocateFrameBuffers(
      uint16_t width,
      uint16_t height,
      DXGI_FORMAT dxgi_format,
      Microsoft::WRL::ComPtr<ID3D11Device1> d3d11_device,
      Microsoft::WRL::ComPtr<ID3D12Device> d3d12_device) {
    HRESULT hr;
    uint16_t number_of_buffers = kNumOutputFrameBuffers;
    if (!frame_buffers_.empty()) {
      auto& buffer = frame_buffers_.front();
      D3D11_TEXTURE2D_DESC desc;
      buffer->texture(0)->GetDesc(&desc);
      if (desc.Format != dxgi_format || buffer->width() < width ||
          buffer->height() < height ||
          d3d11_device.Get() != buffer->device11().Get() ||
          d3d12_device.Get() != buffer->device12().Get()) {
        frame_buffers_.clear();
      }
    }
    if (frame_buffers_.empty()) {
      frame_buffers_.reserve(number_of_buffers);
      while (number_of_buffers--) {
        GpuVideoDecoderBase::GpuFrameBuffer* gpu_fb =
            new GpuVideoDecoderBase::GpuFrameBuffer(width, height, dxgi_format,
                                                    d3d11_device, d3d12_device);
        hr = gpu_fb->CreateTextures();
        if (FAILED(hr)) {
          frame_buffers_.clear();
          return hr;
        }
        frame_buffers_.emplace_back(gpu_fb);
      }
    }
    return S_OK;
  }

  GpuVideoDecoderBase::GpuFrameBuffer* GetFreeBuffer() {
    SB_DCHECK(!frame_buffers_.empty());
    auto iter = std::find_if(
        frame_buffers_.begin(), frame_buffers_.end(),
        [](const auto& frame_buffer) { return frame_buffer->HasOneRef(); });
    if (iter == frame_buffers_.end())
      return nullptr;
    else
      return iter->get();
  }

  bool CheckIfAllBuffersAreReleased() {
    for (auto&& frame_buffer : frame_buffers_) {
      if (!frame_buffer->HasOneRef())
        return false;
    }
    return true;
  }

  void Clear() { frame_buffers_.clear(); }

 private:
  std::vector<scoped_refptr<GpuVideoDecoderBase::GpuFrameBuffer>>
      frame_buffers_;
};

SB_ONCE_INITIALIZE_FUNCTION(GpuFrameBufferPool, GetGpuFrameBufferPool);

class GpuVideoDecoderBase::GPUDecodeTargetPrivate
    : public SbDecodeTargetPrivate {
 public:
  GPUDecodeTargetPrivate(
      void* egl_display,
      void* egl_config,
      const scoped_refptr<GpuVideoDecoderBase::DecodedImage>& image)
      : egl_display_(egl_display), egl_config_(egl_config), image_(image) {
    SB_DCHECK(egl_display_);
    SB_DCHECK(egl_config);

    if (image->bit_depth() == 8) {
      info.format = kSbDecodeTargetFormat3PlaneYUVI420;
    } else {
      SB_DCHECK(image->bit_depth() == 10);
#if SB_API_VERSION >= 14
      info.format = image->is_compacted()
                        ? kSbDecodeTargetFormat3Plane10BitYUVI420Compact
                        : kSbDecodeTargetFormat3Plane10BitYUVI420;
#else   // SB_API_VERSION >= 14
      SB_DCHECK(!image->is_compacted());
      info.format = kSbDecodeTargetFormat3Plane10BitYUVI420;
#endif  // SB_API_VERSION >= 14
    }
    info.is_opaque = true;
    info.width = image->width();
    info.height = image->height();
    GLuint gl_textures_yuv[kNumberOfPlanes] = {};
    glGenTextures(kNumberOfPlanes, gl_textures_yuv);
    SB_DCHECK(glGetError() == GL_NO_ERROR);

    for (unsigned int i = 0; i < kNumberOfPlanes; ++i) {
      const int stride = image->stride(i);
      const int subsampling = i > 0;
      const int width = info.width >> subsampling;
      const int height = info.height >> subsampling;
      EGLint texture_attributes[] = {EGL_WIDTH,
                                     static_cast<EGLint>(stride),
                                     EGL_HEIGHT,
                                     static_cast<EGLint>(height),
                                     EGL_TEXTURE_TARGET,
                                     EGL_TEXTURE_2D,
                                     EGL_TEXTURE_FORMAT,
                                     EGL_TEXTURE_RGBA,
                                     EGL_NONE};
      surfaces_[i] = eglCreatePbufferFromClientBuffer(
          egl_display_, EGL_D3D_TEXTURE_ANGLE, image->texture(i).Get(),
          egl_config, texture_attributes);
      SB_DCHECK(glGetError() == GL_NO_ERROR && surfaces_[i] != EGL_NO_SURFACE);
      glBindTexture(GL_TEXTURE_2D, gl_textures_yuv[i]);
      SB_DCHECK(glGetError() == GL_NO_ERROR);
      bool result =
          eglBindTexImage(egl_display_, surfaces_[i], EGL_BACK_BUFFER);
      SB_DCHECK(result);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

      D3D11_TEXTURE2D_DESC tex_desc = {};
      image->texture(i)->GetDesc(&tex_desc);

      SbDecodeTargetInfoPlane* plane = &info.planes[i];
      plane->width =
          image->is_compacted() ? tex_desc.Width * 3 : tex_desc.Width;
      plane->height = tex_desc.Height;
      plane->content_region.left = image->texture_corner_left(i);
      plane->content_region.top = plane->height - image->texture_corner_top(i);
      plane->content_region.bottom = plane->content_region.top - height;
      plane->content_region.right = plane->content_region.left + width;
      plane->texture = gl_textures_yuv[i];
      plane->gl_texture_target = GL_TEXTURE_2D;
      plane->gl_texture_format = GL_RED_EXT;
    }
  }

  ~GPUDecodeTargetPrivate() override {
    for (unsigned int i = 0; i < kNumberOfPlanes; ++i) {
      glDeleteTextures(1, &(info.planes[i].texture));
      eglReleaseTexImage(egl_display_, surfaces_[i], EGL_BACK_BUFFER);
      eglDestroySurface(egl_display_, surfaces_[i]);
    }
  }

  SbTime timestamp() { return image_->timestamp(); }

  void ReleaseImage() {
    // Release the codec resource, while the D3D textures are still safe to use.
    SB_DCHECK(image_);
    image_ = nullptr;
  }

 private:
  // Hold the codec resource until it's not needed in render pipeline to prevent
  // it being reused and overwritten.
  scoped_refptr<GpuVideoDecoderBase::DecodedImage> image_;
  // EGLSurface is defined as void* in "third_party/angle/include/EGL/egl.h".
  // Use void* directly here to avoid `egl.h` being included broadly.
  void* surfaces_[kNumberOfPlanes];
  void* egl_display_;
  void* egl_config_;
};

GpuVideoDecoderBase::GpuFrameBuffer::GpuFrameBuffer(
    uint16_t width,
    uint16_t height,
    DXGI_FORMAT dxgi_format,
    Microsoft::WRL::ComPtr<ID3D11Device1> d3d11_device,
    Microsoft::WRL::ComPtr<ID3D12Device> d3d12_device)
    : d3d11_device_(d3d11_device), d3d12_device_(d3d12_device) {
  SB_DCHECK(d3d11_device_);
  SB_DCHECK(d3d12_device_);

  texture_desc_.Format = dxgi_format;
  texture_desc_.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
  texture_desc_.DepthOrArraySize = 1;
  texture_desc_.MipLevels = 1;
  texture_desc_.SampleDesc.Count = 1;
  texture_desc_.SampleDesc.Quality = 0;
  texture_desc_.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
  texture_desc_.Layout = D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE;

  width_ = width;
  height_ = height;
}

HRESULT GpuVideoDecoderBase::GpuFrameBuffer::CreateTextures() {
  const D3D12_HEAP_PROPERTIES kHeapPropertyTypeDefault = {
      D3D12_HEAP_TYPE_DEFAULT, D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
      D3D12_MEMORY_POOL_UNKNOWN, 1, 1};
  HRESULT hr = E_FAIL;
  for (unsigned int i = 0; i < kNumberOfPlanes; i++) {
    const int subsampling = i > 0;
    const int plane_width =
        (texture_desc_.Format == DXGI_FORMAT_R10G10B10A2_UNORM)
            ? (((width_ + subsampling) >> subsampling) + 2) / 3
            : ((width_ + subsampling) >> subsampling);
    const int plane_height = (height_ + subsampling) >> subsampling;

    // Create interop resources.
    texture_desc_.Width = plane_width;
    texture_desc_.Height = plane_height;
    hr = d3d12_device_->CreateCommittedResource(
        &kHeapPropertyTypeDefault, D3D12_HEAP_FLAG_SHARED, &texture_desc_,
        D3D12_RESOURCE_STATE_RENDER_TARGET, 0,
        IID_PPV_ARGS(&d3d12_resources_[i]));
    SB_DCHECK(SUCCEEDED(hr));
    if (FAILED(hr)) {
      return hr;
    }

    // Lowering the priority of texture reduces the amount of texture
    // thrashing when the Xbox attempts to transfer textures to faster
    // memory as it become more reluctant to be moved.
    Microsoft::WRL::ComPtr<ID3D12Device1> d3d12_device1;
    if (SUCCEEDED(d3d12_device_.As(&d3d12_device1)) && d3d12_device1) {
      Microsoft::WRL::ComPtr<ID3D12Pageable> d3d12_pageable;
      if (SUCCEEDED(d3d12_resources_[i].As(&d3d12_pageable)) &&
          d3d12_pageable) {
        D3D12_RESIDENCY_PRIORITY priority = D3D12_RESIDENCY_PRIORITY_LOW;
        hr = d3d12_device1->SetResidencyPriority(
            1, d3d12_pageable.GetAddressOf(), &priority);
        SB_DCHECK(SUCCEEDED(hr));
        if (FAILED(hr)) {
          return hr;
        }
      }
    }

    HANDLE interop_handle = 0;
    hr = d3d12_device_->CreateSharedHandle(d3d12_resources_[i].Get(), 0,
                                           GENERIC_ALL, NULL, &interop_handle);
    SB_DCHECK(SUCCEEDED(hr));
    if (FAILED(hr)) {
      return hr;
    }
    hr = d3d11_device_->OpenSharedResource1(interop_handle,
                                            IID_PPV_ARGS(&d3d11_textures_[i]));
    SB_DCHECK(SUCCEEDED(hr));
    if (FAILED(hr)) {
      return hr;
    }
    CloseHandle(interop_handle);
  }
  return S_OK;
}

GpuVideoDecoderBase::GpuVideoDecoderBase(
    SbDecodeTargetGraphicsContextProvider*
        decode_target_graphics_context_provider,
    const VideoStreamInfo& video_stream_info,
    bool is_hdr_video,
    bool is_10x3_preferred,
    const ComPtr<ID3D12Device>& d3d12_device,
    const ComPtr<ID3D12Heap> d3d12OutputPoolBufferHeap,
    void* d3d12_queue)
    : decode_target_context_runner_(decode_target_graphics_context_provider),
      is_hdr_video_(is_hdr_video),
      is_10x3_preferred_(is_10x3_preferred),
      d3d12_device_(d3d12_device),
      d3d12_queue_(d3d12_queue),
      d3d12FrameBuffersHeap_(d3d12OutputPoolBufferHeap),
      frame_buffers_condition_(frame_buffers_mutex_) {
  SB_DCHECK(d3d12_device_);
  SB_DCHECK(d3d12_queue_);
  SB_DCHECK(d3d12FrameBuffersHeap_);

  egl_display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  EGLint attribute_list[] = {EGL_SURFACE_TYPE,  // this must be first
                             EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
                             EGL_RED_SIZE,
                             8,
                             EGL_GREEN_SIZE,
                             8,
                             EGL_BLUE_SIZE,
                             8,
                             EGL_ALPHA_SIZE,
                             8,
                             EGL_BIND_TO_TEXTURE_RGBA,
                             EGL_TRUE,
                             EGL_RENDERABLE_TYPE,
                             EGL_OPENGL_ES2_BIT,
                             EGL_NONE};
  SB_DCHECK(egl_display_);
  EGLint num_configs;
  int result = eglChooseConfig(egl_display_, attribute_list, &egl_config_, 1,
                               &num_configs);
  SB_DCHECK(result);

  ComPtr<ID3D11Device> d3d11_device =
      starboard::shared::uwp::GetDirectX11Device(egl_display_);
  HRESULT hr = d3d11_device.As(&d3d11_device_);
  SB_DCHECK(SUCCEEDED(hr));

  if (is_hdr_video_) {
    UpdateHdrMetadata(video_stream_info.color_metadata);
  }
  frame_width_ = video_stream_info.frame_width;
  frame_height_ = video_stream_info.frame_height;
}

GpuVideoDecoderBase::~GpuVideoDecoderBase() {
  // Reset() should be already called before ~GpuVideoDecoderBase().
  SB_DCHECK(!decoder_thread_);
  SB_DCHECK(pending_inputs_.empty());
  SB_DCHECK(written_inputs_.empty());
  SB_DCHECK(output_queue_.empty());
  SB_DCHECK(decoder_behavior_.load() == kDecodingStopped);
  SB_DCHECK(GetGpuFrameBufferPool()->CheckIfAllBuffersAreReleased());
  // All presenting decode targets should be released.
  SB_DCHECK(presenting_decode_targets_.empty());

  if (ApplicationUwp::Get()->IsHdrSupported() && IsHdrAngleModeEnabled()) {
    SetHdrAngleModeEnabled(false);
    auto hdmi_display_info = HdmiDisplayInformation::GetForCurrentView();
    starboard::shared::uwp::WaitForComplete(
        hdmi_display_info->SetDefaultDisplayModeAsync());
  }
}

void GpuVideoDecoderBase::Initialize(const DecoderStatusCB& decoder_status_cb,
                                     const ErrorCB& error_cb) {
  SB_DCHECK(decoder_status_cb);
  SB_DCHECK(!decoder_status_cb_);
  SB_DCHECK(error_cb);
  SB_DCHECK(!error_cb_);
  decoder_status_cb_ = decoder_status_cb;
  error_cb_ = error_cb;
}

size_t GpuVideoDecoderBase::GetPrerollFrameCount() const {
  // The underlying decoder has its own output queue. We notify the underlying
  // decoder to preroll frames once we receive first needed frame. Then the
  // underlying decoder will delay outputs until it has enough prerolled frames.
  // When we receive the second output frame, the underlying decoder should
  // already have enough prerolled frames in its own output queue. So, we always
  // return 2 here.
  return 2;
}

size_t GpuVideoDecoderBase::GetMaxNumberOfCachedFrames() const {
  return GetMaxNumberOfCachedFramesInternal() + kNumOutputFrameBuffers;
}

void GpuVideoDecoderBase::WriteInputBuffers(const InputBuffers& input_buffers) {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(decoder_status_cb_);
  SB_DCHECK(input_buffers.size() == 1);
  SB_DCHECK(input_buffers[0]);
  SB_DCHECK(decoder_behavior_.load() != kResettingDecoder);
  SB_DCHECK(decoder_behavior_.load() != kEndingStream);

  if (error_occured_.load()) {
    return;
  }

  const auto& input_buffer = input_buffers[0];

  if (!decoder_thread_) {
    decoder_thread_.reset(new JobThread(kDecoderThreadName));
    decoder_thread_->job_queue()->Schedule(
        std::bind(&GpuVideoDecoderBase::InitializeCodecIfNeededInternal, this));
  }

  bool needs_more_input = false;
  {
    ScopedLock pending_inputs_lock(pending_inputs_mutex_);
    pending_inputs_.push_back(input_buffer);

    needs_more_input = pending_inputs_.size() < kMaxNumberOfPendingBuffers;
  }
  decoder_behavior_.store(kDecodingFrames);
  decoder_thread_->job_queue()->Schedule(
      std::bind(&GpuVideoDecoderBase::DecodeOneBuffer, this));
  if (needs_more_input) {
    decoder_status_cb_(kNeedMoreInput, nullptr);
  }
}

void GpuVideoDecoderBase::WriteEndOfStream() {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(decoder_status_cb_);
  SB_DCHECK(decoder_behavior_.load() != kResettingDecoder);
  SB_DCHECK(decoder_behavior_.load() != kEndingStream);

  if (error_occured_.load()) {
    return;
  }

  if (decoder_thread_) {
    SB_DCHECK(decoder_behavior_.load() == kDecodingFrames);
    decoder_behavior_.store(kEndingStream);
    decoder_thread_->job_queue()->Schedule(
        std::bind(&GpuVideoDecoderBase::DecodeEndOfStream, this));
    return;
  }

  SB_DCHECK(decoder_behavior_.load() == kDecodingStopped);
  decoder_status_cb_(kBufferFull, VideoFrame::CreateEOSFrame());
}

void GpuVideoDecoderBase::Reset() {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(decoder_status_cb_);
  decoder_behavior_.store(kResettingDecoder);
  if (decoder_thread_) {
    // Release stored frames to free frame buffers.
    decoder_status_cb_(kReleaseAllFrames, nullptr);
    decoder_thread_->job_queue()->Schedule(
        std::bind(&GpuVideoDecoderBase::DrainDecoder, this));
    decoder_thread_.reset();
  }
  pending_inputs_.clear();
  {
    ScopedLock input_queue_lock(written_inputs_mutex_);
    written_inputs_.clear();
  }
  // Release all frames after decoder thread is destroyed.
  decoder_status_cb_(kReleaseAllFrames, nullptr);
  {
    ScopedLock output_queue_lock(output_queue_mutex_);
    output_queue_.clear();
  }
  error_occured_.store(false);
  decoder_behavior_.store(kDecodingStopped);
  is_drain_decoder_called_ = false;
}

SbDecodeTarget GpuVideoDecoderBase::GetCurrentDecodeTarget() {
  scoped_refptr<DecodedImage> image = nullptr;
  {
    ScopedLock output_queue_lock(output_queue_mutex_);
    if (!output_queue_.empty()) {
      image = output_queue_.front();
    }
  }

  if (!image && presenting_decode_targets_.empty()) {
    return kSbDecodeTargetInvalid;
  }

  if (presenting_decode_targets_.empty() ||
      (image &&
       image->timestamp() != presenting_decode_targets_.back()->timestamp())) {
    // Create the new decode target and update hdr meta data.
    if (is_hdr_video_) {
      UpdateHdrMetadata(image->color_metadata());
    }
    presenting_decode_targets_.push_back(
        new GPUDecodeTargetPrivate(egl_display_, egl_config_, image));
    number_of_presenting_decode_targets_++;
  }

  // Increment the refcount for the returned decode target.
  presenting_decode_targets_.back()->AddRef();

  // There's a data synchronization issue (b/180532476) between decoder and
  // render pipelines. If we release the decode target immediately after it's
  // released on render pipeline (the underllying resources may be reused by the
  // libvpx/av1 decoder), there's a chance that the rendering frame gets
  // overwritten. The root cause is still unclear and under investigating. So,
  // as a workaround, we retain the decode target for longer time until it's no
  // longer used by the renderer thread.
  while (presenting_decode_targets_.size() > kNumberOfCachedPresentingImage &&
         presenting_decode_targets_.front()->refcount == 1) {
    SbDecodeTargetRelease(presenting_decode_targets_.front());
    presenting_decode_targets_.pop_front();
    number_of_presenting_decode_targets_--;
  }
  return presenting_decode_targets_.back();
}

bool GpuVideoDecoderBase::BelongsToDecoderThread() const {
  return decoder_thread_->job_queue()->BelongsToCurrentThread();
}

int GpuVideoDecoderBase::OnOutputRetrieved(
    const scoped_refptr<DecodedImage>& image) {
  SB_DCHECK(decoder_thread_);
  SB_DCHECK(decoder_status_cb_);
  SB_DCHECK(image);

  if (decoder_behavior_.load() == kResettingDecoder || error_occured_) {
    return 0;
  }

  SbTime timestamp = image->timestamp();
  {
    ScopedLock input_queue_lock(written_inputs_mutex_);
    const auto iter = FindByTimestamp(written_inputs_, timestamp);
    SB_DCHECK(iter != written_inputs_.cend());
    if (is_hdr_video_) {
      image->AttachColorMetadata((*iter)->video_stream_info().color_metadata);
    }
    written_inputs_.erase(iter);
  }
  scoped_refptr<VideoFrameImpl> frame(new VideoFrameImpl(
      timestamp, std::bind(&GpuVideoDecoderBase::DeleteVideoFrame, this,
                           std::placeholders::_1)));
  decoder_status_cb_(
      decoder_behavior_.load() == kEndingStream ? kBufferFull : kNeedMoreInput,
      frame);

  // The underlying decoder relies on the return value of OnOutputRetrieved() to
  // determine stream preroll status. The underlying decoder will start
  // prorolling at the first time it receives 1 from OnOutputRetrieved(). In
  // other words, if OnOutputRetrieved() returns 1, the underlying decoder will
  // delay next output until it has enough prerolled frames inside the
  // underlying decoder.
  if (!frame->HasOneRef()) {
    ScopedLock output_queue_lock(output_queue_mutex_);
    output_queue_.push_back(image);
    if (is_waiting_frame_after_drain_) {
      is_waiting_frame_after_drain_ = false;
      return 1;
    }
  }
  return 0;
}

void GpuVideoDecoderBase::OnDecoderDrained() {
  SB_DCHECK(decoder_thread_);
  SB_DCHECK(decoder_status_cb_);
  SB_DCHECK(decoder_behavior_.load() == kEndingStream ||
            decoder_behavior_.load() == kResettingDecoder);

  is_waiting_frame_after_drain_ = true;

  if (!BelongsToDecoderThread()) {
    decoder_thread_->job_queue()->Schedule(
        std::bind(&GpuVideoDecoderBase::OnDecoderDrained, this));
    return;
  }

  if (decoder_behavior_.load() == kEndingStream) {
    decoder_status_cb_(kBufferFull, VideoFrame::CreateEOSFrame());
  }
  decoder_behavior_.store(kDecodingStopped);
}

void GpuVideoDecoderBase::ClearCachedImages() {
  SB_DCHECK(output_queue_.empty());
  // All cached images should be released.
  decode_target_context_runner_.RunOnGlesContext(
      std::bind(&GpuVideoDecoderBase::ClearPresentingDecodeTargets, this));
}

void GpuVideoDecoderBase::ReportError(const SbPlayerError error,
                                      const std::string& error_message) {
  SB_DCHECK(error_cb_);
  if (!error_occured_.exchange(true)) {
    SB_LOG(ERROR) << error_message << " (error code: " << error << " )";
    error_cb_(error, error_message);
  }
}

void GpuVideoDecoderBase::DecodeOneBuffer() {
  SB_DCHECK(decoder_thread_);
  SB_DCHECK(BelongsToDecoderThread());

  if (decoder_behavior_.load() == kResettingDecoder || error_occured_) {
    return;
  }

  // Both decoders av1 & vp9 return decoded frames in separate thread,
  // so there isn't danger of deadlock in DecodeOneBuffer() and there isn't
  // necessity of IsCacheFull call
  scoped_refptr<InputBuffer> input = 0;
  bool needs_more_input = false;
  {
    ScopedLock pending_inputs_lock(pending_inputs_mutex_);
    SB_DCHECK(!pending_inputs_.empty());
    input = pending_inputs_.front();
    pending_inputs_.pop_front();
    if (pending_inputs_.size() < kMaxNumberOfPendingBuffers) {
      needs_more_input = true;
    }
  }
  {
    ScopedLock input_queue_lock(written_inputs_mutex_);
    written_inputs_.push_back(input);
  }
  if (needs_more_input) {
    decoder_status_cb_(kNeedMoreInput, nullptr);
  }
  DecodeInternal(input);
}

void GpuVideoDecoderBase::DecodeEndOfStream() {
  SB_DCHECK(decoder_thread_);
  SB_DCHECK(BelongsToDecoderThread());
  SB_DCHECK(decoder_status_cb_);

  if (decoder_behavior_.load() == kResettingDecoder || error_occured_) {
    return;
  }

  {
    ScopedLock pending_inputs_lock(pending_inputs_mutex_);
    if (!pending_inputs_.empty()) {
      decoder_thread_->job_queue()->Schedule(
          std::bind(&GpuVideoDecoderBase::DecodeEndOfStream, this),
          kSbTimeMillisecond);
      return;
    }
  }
  DrainDecoder();
}

void GpuVideoDecoderBase::DrainDecoder() {
  SB_DCHECK(BelongsToDecoderThread());
  // Use |is_drain_decoder_called_| to prevent calling DrainDecoderInternal()
  // twice. Theoretically, if Reset() is called during DecodeEndOfStream()
  // executing, DrainDecoderInternal() could be called twice, one from
  // DecodeEndOfStream(), and one from Reset().
  if (!is_drain_decoder_called_) {
    is_drain_decoder_called_ = true;
    DrainDecoderInternal();
    // DrainDecoderInternal is sync command, after it finished, we can be sure
    // that drain really completed.
    OnDecoderDrained();
  }
}

void GpuVideoDecoderBase::DeleteVideoFrame(const VideoFrame* video_frame) {
  ScopedLock output_queue_lock(output_queue_mutex_);
  RemoveByTimestamp(&output_queue_, video_frame->timestamp());
}

void GpuVideoDecoderBase::UpdateHdrMetadata(
    const SbMediaColorMetadata& color_metadata) {
  SB_DCHECK(is_hdr_video_);
  if (!ApplicationUwp::Get()->IsHdrSupported()) {
    ReportError(kSbPlayerErrorCapabilityChanged,
                "HDR sink lost while HDR video playing.");
    return;
  }
  if (!needs_hdr_metadata_update_) {
    return;
  }
  needs_hdr_metadata_update_ = false;
  if (!IsHdrAngleModeEnabled()) {
    SetHdrAngleModeEnabled(true);
  }
  if (memcmp(&color_metadata, &last_presented_color_metadata_,
             sizeof(color_metadata)) != 0) {
    last_presented_color_metadata_ = color_metadata;
    UpdateHdrColorMetadataToCurrentDisplay(color_metadata);
  }
}

void GpuVideoDecoderBase::ClearPresentingDecodeTargets() {
  // Delete all unused decode targets.
  while (!presenting_decode_targets_.empty() &&
         presenting_decode_targets_.front()->refcount == 1) {
    SbDecodeTargetRelease(presenting_decode_targets_.front());
    presenting_decode_targets_.pop_front();
  }
  // The remaining decode targets are still used by the render pipeline. Force
  // to release the underlying image to release the codec resources and
  // decrement the refcount.
  for (auto it = presenting_decode_targets_.begin();
       it != presenting_decode_targets_.end(); ++it) {
    (*it)->ReleaseImage();
    SbDecodeTargetRelease(*it);
  }
  presenting_decode_targets_.clear();
  number_of_presenting_decode_targets_ = 0;
}

HRESULT GpuVideoDecoderBase::AllocateFrameBuffers(uint16_t width,
                                                  uint16_t height) {
  HRESULT hr = S_OK;
  DXGI_FORMAT dxgi_format =
      is_hdr_video_ ? (is_10x3_preferred_ ? DXGI_FORMAT_R10G10B10A2_UNORM
                                          : DXGI_FORMAT_R16_UNORM)
                    : DXGI_FORMAT_R8_UNORM;
  return GetGpuFrameBufferPool()->AllocateFrameBuffers(
      width, height, dxgi_format, d3d11_device_, d3d12_device_);
}

void GpuVideoDecoderBase::ReleaseFrameBuffer(GpuFrameBuffer* frame_buffer) {
  SB_DCHECK(frame_buffer);
  ScopedLock lock(frame_buffers_mutex_);
  frame_buffer->Release();
  SB_DCHECK(frame_buffer->HasOneRef());
  frame_buffers_condition_.Signal();
}

void GpuVideoDecoderBase::ClearFrameBuffersPool() {
  GetGpuFrameBufferPool()->Clear();
}

GpuVideoDecoderBase::GpuFrameBuffer*
GpuVideoDecoderBase::GetAvailableFrameBuffer(uint16_t width, uint16_t height) {
  if (decoder_behavior_.load() == kResettingDecoder) {
    return nullptr;
  }

  GpuFrameBuffer* frame_buffer = nullptr;
  bool is_resetting = false;
  while (!frame_buffer) {
    ScopedLock lock(frame_buffers_mutex_);
    frame_buffer = GetGpuFrameBufferPool()->GetFreeBuffer();
    // Wait until we get next free frame buffer.
    if (!frame_buffer) {
      if (is_resetting) {
        // We should have enough free frame buffers during resetting. If that
        // error happens it means that the frames are not released properly by
        // either GpuVideoDecoderBase or VideoRenderer.
        SB_NOTREACHED();
        ReportError(kSbPlayerErrorDecode,
                    "Timed out on waiting for available frame buffer.");
        return nullptr;
      }
      is_resetting = decoder_behavior_.load() == kResettingDecoder;
      frame_buffers_condition_.WaitTimed(50 * kSbTimeMillisecond);
      continue;
    }
  }

  // Increment the refcount for |frame_buffer| so that its data buffer
  // persists until ReleaseFrameBuffer is called.
  frame_buffer->AddRef();
  return frame_buffer;
}
}  // namespace shared
}  // namespace xb1
}  // namespace starboard
