// Copyright 2018 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/starboard/player/filter/stub_video_decoder.h"

#include <string>

#include "starboard/common/media.h"
#include "starboard/shared/starboard/player/filter/cpu_video_frame.h"

namespace starboard {
namespace shared {
namespace starboard {
namespace player {
namespace filter {

void StubVideoDecoder::Initialize(const DecoderStatusCB& decoder_status_cb,
                                  const ErrorCB& error_cb) {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(decoder_status_cb);
  SB_DCHECK(!decoder_status_cb_);
  decoder_status_cb_ = decoder_status_cb;
}

size_t StubVideoDecoder::GetPrerollFrameCount() const {
  return 1;
}

int64_t StubVideoDecoder::GetPrerollTimeout() const {
  return kSbInt64Max;
}

size_t StubVideoDecoder::GetMaxNumberOfCachedFrames() const {
  return 12;
}

void StubVideoDecoder::WriteInputBuffers(const InputBuffers& input_buffers) {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(!input_buffers.empty());

  if (!decoder_thread_) {
    decoder_thread_.reset(new JobThread("stub_video_decoder"));
  }
  decoder_thread_->job_queue()->Schedule(
      std::bind(&StubVideoDecoder::DecodeBuffers, this, input_buffers));
}

void StubVideoDecoder::WriteEndOfStream() {
  SB_DCHECK(BelongsToCurrentThread());

  if (decoder_thread_) {
    decoder_thread_->job_queue()->Schedule(
        std::bind(&StubVideoDecoder::DecodeEndOfStream, this));
    return;
  }
  decoder_status_cb_(kBufferFull, VideoFrame::CreateEOSFrame());
}

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

  video_stream_info_ = media::VideoStreamInfo();
  decoder_thread_.reset();
  output_frame_timestamps_.clear();
  total_input_count_ = 0;
  CancelPendingJobs();
}

SbDecodeTarget StubVideoDecoder::GetCurrentDecodeTarget() {
  return kSbDecodeTargetInvalid;
}

void StubVideoDecoder::DecodeBuffers(const InputBuffers& input_buffers) {
  SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());
  for (const auto& input_buffer : input_buffers) {
    auto& video_sample_info = input_buffer->video_sample_info();
    if (video_sample_info.is_key_frame) {
      if (video_stream_info_ != input_buffer->video_stream_info()) {
        SB_LOG(INFO) << "New video sample info: " << video_sample_info;
        video_stream_info_ = input_buffer->video_stream_info();
      }
    }

    // Defer sending frames out until we've accumulated a reasonable number.
    // This allows for input buffers to be out of order, and we expect that
    // after buffering 8 (arbitrarily chosen) that the first timestamp in the
    // sorted buffer will be the "correct" timestamp to send out.
    const int kMaxFramesToDelay = 8;
    // Send kBufferFull on every 5th input buffer received, starting with the
    // first.
    const int kMaxInputBeforeBufferFull = 5;
    scoped_refptr<VideoFrame> output_frame = NULL;

    output_frame_timestamps_.insert(input_buffer->timestamp());
    if (output_frame_timestamps_.size() > kMaxFramesToDelay) {
      output_frame = CreateOutputFrame(*output_frame_timestamps_.begin());
      output_frame_timestamps_.erase(output_frame_timestamps_.begin());
    }

    if (total_input_count_ % kMaxInputBeforeBufferFull == 0) {
      total_input_count_++;
      decoder_status_cb_(kBufferFull, output_frame);
      decoder_status_cb_(kNeedMoreInput, nullptr);
      continue;
    }
    total_input_count_++;
    decoder_status_cb_(kNeedMoreInput, output_frame);
  }
}

void StubVideoDecoder::DecodeEndOfStream() {
  SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());

  // If there are any remaining frames we need to output, send them all out
  // before writing EOS.
  for (const auto time : output_frame_timestamps_) {
    scoped_refptr<VideoFrame> output_frame = CreateOutputFrame(time);
    decoder_status_cb_(kBufferFull, output_frame);
  }
  decoder_status_cb_(kBufferFull, VideoFrame::CreateEOSFrame());
}

scoped_refptr<VideoFrame> StubVideoDecoder::CreateOutputFrame(
    int64_t timestamp) const {
  int bits_per_channel = video_stream_info_.color_metadata.bits_per_channel;
  if (bits_per_channel == 0) {
    // Assume 8 bits when |bits_per_channel| is unknown (0).
    bits_per_channel = 8;
  }
  int uv_stride = bits_per_channel > 8 ? video_stream_info_.frame_width
                                       : video_stream_info_.frame_width / 2;
  int y_stride = uv_stride * 2;
  std::string data(y_stride * video_stream_info_.frame_height, 0);

  return CpuVideoFrame::CreateYV12Frame(
      bits_per_channel, video_stream_info_.frame_width,
      video_stream_info_.frame_height, y_stride, uv_stride, timestamp,
      reinterpret_cast<const uint8_t*>(data.data()),
      reinterpret_cast<const uint8_t*>(data.data()),
      reinterpret_cast<const uint8_t*>(data.data()));
}

}  // namespace filter
}  // namespace player
}  // namespace starboard
}  // namespace shared
}  // namespace starboard
