// Copyright 2022 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/shared/openh264/openh264_video_decoder.h"

#include "starboard/common/log.h"
#include "starboard/common/string.h"
#include "starboard/linux/shared/decode_target_internal.h"
#include "starboard/memory.h"
#include "starboard/shared/openh264/openh264_library_loader.h"
#include "starboard/shared/starboard/player/filter/cpu_video_frame.h"
#include "starboard/shared/starboard/player/job_queue.h"

namespace starboard {
namespace shared {
namespace openh264 {

namespace {

using shared::starboard::media::VideoConfig;
using starboard::player::InputBuffer;
using starboard::player::JobThread;
using starboard::player::filter::CpuVideoFrame;

}  // namespace

VideoDecoder::VideoDecoder(SbMediaVideoCodec video_codec,
                           SbPlayerOutputMode output_mode,
                           SbDecodeTargetGraphicsContextProvider*
                               decode_target_graphics_context_provider)
    : output_mode_(output_mode),
      decode_target_graphics_context_provider_(
          decode_target_graphics_context_provider) {
  SB_DCHECK(video_codec == kSbMediaVideoCodecH264);
}

VideoDecoder::~VideoDecoder() {
  SB_DCHECK(BelongsToCurrentThread());
  Reset();
}

void VideoDecoder::Initialize(const DecoderStatusCB& decoder_status_cb,
                              const ErrorCB& error_cb) {
  SB_DCHECK(BelongsToCurrentThread());
  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;
}

void VideoDecoder::Reset() {
  SB_DCHECK(BelongsToCurrentThread());

  if (decoder_thread_) {
    decoder_thread_->job_queue()->Schedule(
        std::bind(&VideoDecoder::TeardownCodec, this));
    // Join the thread to ensure that all callbacks in process are finished.
    decoder_thread_.reset();
  }

  video_config_ = nullopt;
  stream_ended_ = false;

  CancelPendingJobs();
  frames_being_decoded_ = 0;
  time_sequential_queue_ = TimeSequentialQueue();

  ScopedLock lock(decode_target_mutex_);
  frames_ = std::queue<scoped_refptr<CpuVideoFrame>>();
}

void VideoDecoder::InitializeCodec() {
  SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());
  SB_DCHECK(!decoder_);

  int result = WelsCreateDecoder(&decoder_);
  if (result != 0) {
    decoder_ = nullptr;
    ReportError(
        FormatString("WelsCreateDecoder() failed with status %d.", result));
    return;
  }
  SDecodingParam sDecParam;
  sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
  sDecParam.bParseOnly = false;
  result = decoder_->Initialize(&sDecParam);
  if (result != 0) {
    WelsDestroyDecoder(decoder_);
    decoder_ = nullptr;
    ReportError(
        FormatString("Decoder Initialize() failed with status %d.", result));
    return;
  }
}

void VideoDecoder::TeardownCodec() {
  SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());
  if (decoder_) {
    decoder_->Uninitialize();
    WelsDestroyDecoder(decoder_);
    decoder_ = nullptr;
  }
  if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
    SbDecodeTarget decode_target_to_release;
    {
      ScopedLock lock(decode_target_mutex_);
      decode_target_to_release = decode_target_;
      decode_target_ = kSbDecodeTargetInvalid;
    }

    if (SbDecodeTargetIsValid(decode_target_to_release)) {
      DecodeTargetRelease(decode_target_graphics_context_provider_,
                          decode_target_to_release);
    }
  }
}

void VideoDecoder::WriteInputBuffers(const InputBuffers& input_buffers) {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(input_buffers.size() == 1);
  SB_DCHECK(input_buffers[0]);
  SB_DCHECK(decoder_status_cb_);

  if (stream_ended_) {
    ReportError("WriteInputBuffer() was called after WriteEndOfStream().");
    return;
  }
  if (!decoder_thread_) {
    decoder_thread_.reset(new JobThread("openh264_video_decoder"));
    SB_DCHECK(decoder_thread_);
  }
  const auto& input_buffer = input_buffers[0];
  decoder_thread_->job_queue()->Schedule(
      std::bind(&VideoDecoder::DecodeOneBuffer, this, input_buffer));
}

void VideoDecoder::DecodeOneBuffer(
    const scoped_refptr<InputBuffer>& input_buffer) {
  SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());
  SB_DCHECK(input_buffer);

  if (input_buffer->video_sample_info().is_key_frame) {
    VideoConfig new_config(input_buffer->video_stream_info(),
                           input_buffer->data(), input_buffer->size());
    if (!video_config_ || video_config_.value() != new_config) {
      video_config_ = new_config;
      if (decoder_) {
        FlushFrames();
      }
      TeardownCodec();
      InitializeCodec();
    }
  }
  SB_DCHECK(decoder_);
  unsigned char* decoded_frame[3];
  SBufferInfo buffer_info;
  buffer_info.uiInBsTimeStamp = input_buffer->timestamp();
  DECODING_STATE status = decoder_->DecodeFrameNoDelay(
      input_buffer->data(), input_buffer->size(), decoded_frame, &buffer_info);
  if (status != dsErrorFree) {
    ReportError(
        FormatString("DecodeFrameNoDelay() failed with status %d.", status));
    return;
  }
  ++frames_being_decoded_;

  if (buffer_info.iBufferStatus == 1) {
    ProcessDecodedImage(decoded_frame, buffer_info, false);
  } else {
    Schedule(std::bind(decoder_status_cb_, kNeedMoreInput, nullptr));
  }
}

void VideoDecoder::FlushFrames() {
  SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());
  SB_DCHECK(decoder_);

  int num_of_frames_in_buffer = 0;
  unsigned char* decoded_frame[3];
  SBufferInfo buffer_info;
  decoder_->GetOption(DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER,
                      &num_of_frames_in_buffer);
  for (int i = 0; i < num_of_frames_in_buffer; ++i) {
    decoder_->FlushFrame(decoded_frame, &buffer_info);
    if (buffer_info.iBufferStatus == 1) {
      ProcessDecodedImage(decoded_frame, buffer_info, true);
    } else {
      SB_LOG(WARNING) << "Cannot get decoded frame by calling FlushFrame()!";
    }
  }
  if (frames_being_decoded_ != 0) {
    SB_LOG(WARNING) << "Inconsistency in the number of input/output frames";
  }

  while (!time_sequential_queue_.empty()) {
    auto output_frame = time_sequential_queue_.top();
    if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
      ScopedLock lock(decode_target_mutex_);
      frames_.push(output_frame);
    }
    Schedule(std::bind(decoder_status_cb_, kBufferFull, output_frame));
    time_sequential_queue_.pop();
  }
}

void VideoDecoder::ProcessDecodedImage(unsigned char* decoded_frame[],
                                       const SBufferInfo& buffer_info,
                                       bool flushing) {
  SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());
  if (buffer_info.UsrData.sSystemBuffer.iFormat != videoFormatI420) {
    ReportError(FormatString("Invalid video format %d.",
                             buffer_info.UsrData.sSystemBuffer.iFormat));
    return;
  }
  for (int i = 0; i < 3; i++) {
    SB_DCHECK(decoded_frame[i]);
  }

  --frames_being_decoded_;
  scoped_refptr<CpuVideoFrame> frame = CpuVideoFrame::CreateYV12Frame(
      kDefaultOpenH264BitsDepth, buffer_info.UsrData.sSystemBuffer.iWidth,
      buffer_info.UsrData.sSystemBuffer.iHeight,
      buffer_info.UsrData.sSystemBuffer.iStride[0],
      buffer_info.UsrData.sSystemBuffer.iStride[1],
      buffer_info.uiOutYuvTimeStamp, decoded_frame[0], decoded_frame[1],
      decoded_frame[2]);

  bool has_new_output = false;
  while (!time_sequential_queue_.empty() &&
         time_sequential_queue_.top()->timestamp() < frame->timestamp()) {
    has_new_output = true;
    auto output_frame = time_sequential_queue_.top();
    if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
      ScopedLock lock(decode_target_mutex_);
      frames_.push(output_frame);
    }
    if (flushing) {
      Schedule(std::bind(decoder_status_cb_, kBufferFull, output_frame));
    } else {
      Schedule(std::bind(decoder_status_cb_, kNeedMoreInput, output_frame));
    }
    time_sequential_queue_.pop();
  }
  time_sequential_queue_.push(frame);

  if (!has_new_output) {
    Schedule(std::bind(decoder_status_cb_, kNeedMoreInput, nullptr));
  }
}

void VideoDecoder::WriteEndOfStream() {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(decoder_status_cb_);

  // We have to flush the decoder to decode the rest frames and to ensure that
  // Decode() is not called when the stream is ended.
  stream_ended_ = true;

  if (!decoder_thread_) {
    // In case there is no WriteInputBuffer() call before WriteEndOfStream(),
    // don't create the decoder thread and send the EOS frame directly.
    decoder_status_cb_(kBufferFull, VideoFrame::CreateEOSFrame());
    return;
  }
  decoder_thread_->job_queue()->Schedule(
      std::bind(&VideoDecoder::DecodeEndOfStream, this));
}

void VideoDecoder::DecodeEndOfStream() {
  SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());
  FlushFrames();
  Schedule(
      std::bind(decoder_status_cb_, kBufferFull, VideoFrame::CreateEOSFrame()));
}

void VideoDecoder::UpdateDecodeTarget_Locked(
    const scoped_refptr<CpuVideoFrame>& frame) {
  SbDecodeTarget decode_target = DecodeTargetCreate(
      decode_target_graphics_context_provider_, frame, decode_target_);

  // Lock only after the post to the renderer thread, to prevent deadlock.
  decode_target_ = decode_target;

  if (!SbDecodeTargetIsValid(decode_target)) {
    SB_LOG(ERROR) << "Could not acquire a decode target from provider.";
  }
}

// When in decode-to-texture mode, this returns the current decoded video frame.
SbDecodeTarget VideoDecoder::GetCurrentDecodeTarget() {
  SB_DCHECK(output_mode_ == kSbPlayerOutputModeDecodeToTexture);

  // We must take a lock here since this function can be called from a
  // separate thread.
  ScopedLock lock(decode_target_mutex_);
  while (frames_.size() > 1 && frames_.front()->HasOneRef()) {
    frames_.pop();
  }
  if (!frames_.empty()) {
    UpdateDecodeTarget_Locked(frames_.front());
  }
  if (SbDecodeTargetIsValid(decode_target_)) {
    // Make a disposable copy, since the state is internally reused by this
    // class (to avoid recreating GL objects).
    return DecodeTargetCopy(decode_target_);
  } else {
    return kSbDecodeTargetInvalid;
  }
}

void VideoDecoder::ReportError(const std::string& error_message) {
  SB_DCHECK(error_cb_);

  if (!BelongsToCurrentThread()) {
    Schedule(std::bind(error_cb_, kSbPlayerErrorDecode, error_message));
    return;
  }
  error_cb_(kSbPlayerErrorDecode, error_message);
}

}  // namespace openh264
}  // namespace shared
}  // namespace starboard
