// Copyright 2012 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 "cobalt/media/progressive/progressive_demuxer.h"

#include <inttypes.h>

#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/media/base/data_source.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/starboard_utils.h"
#include "media/base/timestamp_constants.h"
#include "starboard/types.h"

namespace cobalt {
namespace media {
namespace {

using ::media::AudioDecoderConfig;
using ::media::kNoTimestamp;
using ::media::VideoDecoderConfig;

}  // namespace

ProgressiveDemuxerStream::ProgressiveDemuxerStream(ProgressiveDemuxer* demuxer,
                                                   Type type)
    : demuxer_(demuxer), type_(type) {
  TRACE_EVENT0("media_stack",
               "ProgressiveDemuxerStream::ProgressiveDemuxerStream()");
  DCHECK(demuxer_);
}

void ProgressiveDemuxerStream::Read(int max_number_of_buffers_to_read,
                                    ReadCB read_cb) {
  TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::Read()");
  DCHECK(!read_cb.is_null());

  base::AutoLock auto_lock(lock_);

  // Don't accept any additional reads if we've been told to stop.
  // The demuxer_ may have been destroyed in the pipeline thread.
  if (stopped_) {
    TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::Read() EOS sent.");
    std::move(read_cb).Run(DemuxerStream::kOk,
                           {DecoderBuffer::CreateEOSBuffer()});
    return;
  }

  // Buffers are only queued when there are no pending reads.
  DCHECK(buffer_queue_.empty() || read_queue_.empty());

  if (!buffer_queue_.empty()) {
    // Send the oldest buffer back.
    scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front();
    if (buffer->end_of_stream()) {
      TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::Read() EOS sent.");
    } else {
      // Do not pop EOS buffers, so that subsequent read requests also get EOS
      total_buffer_size_ -= buffer->data_size();
      --total_buffer_count_;
      buffer_queue_.pop_front();
    }
    std::move(read_cb).Run(DemuxerStream::kOk, {buffer});
  } else {
    TRACE_EVENT0("media_stack",
                 "ProgressiveDemuxerStream::Read() request queued.");
    read_queue_.push_back(std::move(read_cb));
  }
}

AudioDecoderConfig ProgressiveDemuxerStream::audio_decoder_config() {
  return demuxer_->AudioConfig();
}

VideoDecoderConfig ProgressiveDemuxerStream::video_decoder_config() {
  return demuxer_->VideoConfig();
}

::media::Ranges<base::TimeDelta> ProgressiveDemuxerStream::GetBufferedRanges() {
  base::AutoLock auto_lock(lock_);
  return buffered_ranges_;
}

::media::DemuxerStream::Type ProgressiveDemuxerStream::type() const {
  return type_;
}

void ProgressiveDemuxerStream::EnableBitstreamConverter() { NOTIMPLEMENTED(); }

void ProgressiveDemuxerStream::EnqueueBuffer(
    scoped_refptr<DecoderBuffer> buffer) {
  TRACE_EVENT1(
      "media_stack", "ProgressiveDemuxerStream::EnqueueBuffer()", "timestamp",
      buffer->end_of_stream() ? -1 : buffer->timestamp().InMicroseconds());
  base::AutoLock auto_lock(lock_);
  if (stopped_) {
    // it's possible due to pipelining both downstream and within the
    // demuxer that several pipelined reads will be enqueuing packets
    // on a stopped stream. Drop them after complaining.
    DLOG(WARNING) << "attempted to enqueue packet on stopped stream";
    return;
  }

  if (buffer->end_of_stream()) {
    TRACE_EVENT0("media_stack",
                 "ProgressiveDemuxerStream::EnqueueBuffer() EOS received.");
  } else if (buffer->timestamp() != kNoTimestamp) {
    if (last_buffer_timestamp_ != kNoTimestamp &&
        last_buffer_timestamp_ < buffer->timestamp()) {
      buffered_ranges_.Add(last_buffer_timestamp_, buffer->timestamp());
    }
    last_buffer_timestamp_ = buffer->timestamp();
  } else {
    DLOG(WARNING) << "bad timestamp info on enqueued buffer.";
  }

  // Check for any already waiting reads, service oldest read if there
  if (read_queue_.size()) {
    // assumption here is that buffer queue is empty
    DCHECK_EQ(buffer_queue_.size(), 0);
    ReadCB read_cb = std::move(read_queue_.front());
    read_queue_.pop_front();
    std::move(read_cb).Run(DemuxerStream::kOk, {buffer});
  } else {
    // save the buffer for next read request
    buffer_queue_.push_back(buffer);
    if (!buffer->end_of_stream()) {
      total_buffer_size_ += buffer->data_size();
      ++total_buffer_count_;
    }
  }
}

base::TimeDelta ProgressiveDemuxerStream::GetLastBufferTimestamp() const {
  base::AutoLock auto_lock(lock_);
  return last_buffer_timestamp_;
}

size_t ProgressiveDemuxerStream::GetTotalBufferSize() const {
  base::AutoLock auto_lock(lock_);
  return total_buffer_size_;
}

size_t ProgressiveDemuxerStream::GetTotalBufferCount() const {
  base::AutoLock auto_lock(lock_);
  return total_buffer_count_;
}

void ProgressiveDemuxerStream::FlushBuffers() {
  TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::FlushBuffers()");
  base::AutoLock auto_lock(lock_);
  // TODO: Investigate if the following warning is valid.
  DLOG_IF(WARNING, !read_queue_.empty()) << "Read requests should be empty";
  buffer_queue_.clear();
  total_buffer_size_ = 0;
  total_buffer_count_ = 0;
  last_buffer_timestamp_ = kNoTimestamp;
}

void ProgressiveDemuxerStream::Stop() {
  TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::Stop()");
  DCHECK(demuxer_->MessageLoopBelongsToCurrentThread());
  base::AutoLock auto_lock(lock_);
  buffer_queue_.clear();
  total_buffer_size_ = 0;
  total_buffer_count_ = 0;
  last_buffer_timestamp_ = kNoTimestamp;
  // fulfill any pending callbacks with EOS buffers set to end timestamp
  for (ReadQueue::iterator it = read_queue_.begin(); it != read_queue_.end();
       ++it) {
    TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::Stop() EOS sent.");
    std::move(*it).Run(DemuxerStream::kOk, {DecoderBuffer::CreateEOSBuffer()});
  }
  read_queue_.clear();
  stopped_ = true;
}

//
// ProgressiveDemuxer
//
ProgressiveDemuxer::ProgressiveDemuxer(
    const scoped_refptr<base::SingleThreadTaskRunner>& message_loop,
    DataSource* data_source, MediaLog* const media_log)
    : message_loop_(message_loop),
      host_(NULL),
      blocking_thread_("ProgDemuxerBlk"),
      data_source_(data_source),
      media_log_(media_log),
      stopped_(false),
      flushing_(false),
      audio_reached_eos_(false),
      video_reached_eos_(false) {
  DCHECK(message_loop_);
  DCHECK(data_source_);
  DCHECK(media_log_);
  reader_ = new DataSourceReader();
  reader_->SetDataSource(data_source_);
}

ProgressiveDemuxer::~ProgressiveDemuxer() {
  // Explicitly stop |blocking_thread_| to ensure that it stops before the
  // destructing of any other members.
  blocking_thread_.Stop();
}

void ProgressiveDemuxer::Initialize(DemuxerHost* host,
                                    PipelineStatusCallback status_cb) {
  TRACE_EVENT0("media_stack", "ProgressiveDemuxer::Initialize()");
  DCHECK(MessageLoopBelongsToCurrentThread());
  DCHECK(reader_);
  DCHECK(!parser_);

  DLOG(INFO) << "this is a PROGRESSIVE playback.";

  host_ = host;

  // create audio and video demuxer stream objects
  audio_demuxer_stream_.reset(
      new ProgressiveDemuxerStream(this, DemuxerStream::AUDIO));
  video_demuxer_stream_.reset(
      new ProgressiveDemuxerStream(this, DemuxerStream::VIDEO));

  // start the blocking thread and have it download and parse the media config
  if (!blocking_thread_.Start()) {
    std::move(status_cb).Run(::media::DEMUXER_ERROR_COULD_NOT_PARSE);
    return;
  }

  blocking_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ProgressiveDemuxer::ParseConfigBlocking,
                                base::Unretained(this), std::move(status_cb)));
}

void ProgressiveDemuxer::ParseConfigBlocking(PipelineStatusCallback status_cb) {
  DCHECK(blocking_thread_.task_runner()->BelongsToCurrentThread());
  DCHECK(!parser_);

  // construct stream parser with error callback
  PipelineStatus status =
      ProgressiveParser::Construct(reader_, &parser_, media_log_);
  // if we can't construct a parser for this stream it's a fatal error, return
  // false so ParseConfigDone will notify the caller to Initialize() via
  // status_cb.
  if (!parser_ || status != ::media::PIPELINE_OK) {
    DCHECK(!parser_);
    DCHECK_NE(status, ::media::PIPELINE_OK);
    if (status == ::media::PIPELINE_OK) {
      status = ::media::DEMUXER_ERROR_COULD_NOT_PARSE;
    }
    ParseConfigDone(std::move(status_cb), status);
    return;
  }

  // instruct the parser to extract audio and video config from the file
  if (!parser_->ParseConfig()) {
    ParseConfigDone(std::move(status_cb),
                    ::media::DEMUXER_ERROR_COULD_NOT_PARSE);
    return;
  }

  // make sure we got a valid and complete configuration
  if (!parser_->IsConfigComplete()) {
    ParseConfigDone(std::move(status_cb),
                    ::media::DEMUXER_ERROR_COULD_NOT_PARSE);
    return;
  }

  // IsConfigComplete() should guarantee we know the duration
  DCHECK(parser_->Duration() != ::media::kInfiniteDuration);
  host_->SetDuration(parser_->Duration());

  // successful parse of config data, inform the nonblocking demuxer thread
  DCHECK_EQ(status, ::media::PIPELINE_OK);
  ParseConfigDone(std::move(status_cb), ::media::PIPELINE_OK);
}

void ProgressiveDemuxer::ParseConfigDone(PipelineStatusCallback status_cb,
                                         PipelineStatus status) {
  DCHECK(blocking_thread_.task_runner()->BelongsToCurrentThread());

  if (HasStopCalled()) {
    return;
  }

  // if the blocking parser thread cannot parse config we're done.
  if (status != ::media::PIPELINE_OK) {
    std::move(status_cb).Run(status);
    return;
  }
  DCHECK(parser_);
  // start downloading data
  Request(DemuxerStream::AUDIO);

  std::move(status_cb).Run(::media::PIPELINE_OK);
}

void ProgressiveDemuxer::Request(DemuxerStream::Type type) {
  if (!blocking_thread_.task_runner()->BelongsToCurrentThread()) {
    blocking_thread_.task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&ProgressiveDemuxer::Request, base::Unretained(this), type));
    return;
  }

  DCHECK(!requested_au_) << "overlapping requests not supported!";
  flushing_ = false;
  // Ask parser for next AU
  scoped_refptr<AvcAccessUnit> au = parser_->GetNextAU(type);
  // fatal parsing error returns NULL or malformed AU
  if (!au || !au->IsValid()) {
    if (!HasStopCalled()) {
      DLOG(ERROR) << "got back bad AU from parser";
      host_->OnDemuxerError(::media::DEMUXER_ERROR_COULD_NOT_PARSE);
    }
    return;
  }

  // make sure we got back an AU of the correct type
  DCHECK(au->GetType() == type);

  const char* ALLOW_UNUSED_TYPE event_type =
      type == DemuxerStream::AUDIO ? "audio" : "video";
  TRACE_EVENT2("media_stack", "ProgressiveDemuxer::RequestTask()", "type",
               event_type, "timestamp", au->GetTimestamp().InMicroseconds());

  // don't issue allocation requests for EOS AUs
  if (au->IsEndOfStream()) {
    TRACE_EVENT0("media_stack", "ProgressiveDemuxer::RequestTask() EOS sent");
    // enqueue EOS buffer with correct stream
    scoped_refptr<DecoderBuffer> eos_buffer = DecoderBuffer::CreateEOSBuffer();
    if (type == DemuxerStream::AUDIO) {
      audio_reached_eos_ = true;
      audio_demuxer_stream_->EnqueueBuffer(eos_buffer);
    } else if (type == DemuxerStream::VIDEO) {
      video_reached_eos_ = true;
      video_demuxer_stream_->EnqueueBuffer(eos_buffer);
    }
    IssueNextRequest();
    return;
  }

  // enqueue the request
  requested_au_ = au;

  AllocateBuffer();
}

void ProgressiveDemuxer::AllocateBuffer() {
  DCHECK(requested_au_);

  if (HasStopCalled()) {
    return;
  }

  if (requested_au_) {
    size_t total_buffer_size = audio_demuxer_stream_->GetTotalBufferSize() +
                               video_demuxer_stream_->GetTotalBufferSize();
    size_t total_buffer_count = audio_demuxer_stream_->GetTotalBufferCount() +
                                video_demuxer_stream_->GetTotalBufferCount();
    // Only sdr video is supported in progressive mode.
    const int kBitDepth = 8;
    int progressive_budget = SbMediaGetProgressiveBufferBudget(
        MediaVideoCodecToSbMediaVideoCodec(VideoConfig().codec()),
        VideoConfig().visible_rect().size().width(),
        VideoConfig().visible_rect().size().height(), kBitDepth);
    base::TimeDelta progressive_duration_cap =
        base::TimeDelta::FromMicroseconds(
            SbMediaGetBufferGarbageCollectionDurationThreshold());
    const int kEstimatedBufferCountPerSeconds = 70;
    int progressive_buffer_count_cap =
        progressive_duration_cap.InSeconds() * kEstimatedBufferCountPerSeconds;
    if (total_buffer_size >= progressive_budget ||
        total_buffer_count > progressive_buffer_count_cap) {
      // Retry after 100 milliseconds.
      const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(100);
      blocking_thread_.message_loop()->task_runner()->PostDelayedTask(
          FROM_HERE,
          base::Bind(&ProgressiveDemuxer::AllocateBuffer,
                     base::Unretained(this)),
          kDelay);
      return;
    }

    scoped_refptr<DecoderBuffer> decoder_buffer(
        new DecoderBuffer(requested_au_->GetMaxSize()));
    DCHECK(decoder_buffer);
    decoder_buffer->set_is_key_frame(requested_au_->IsKeyframe());
    Download(decoder_buffer);
  }
}

void ProgressiveDemuxer::Download(scoped_refptr<DecoderBuffer> buffer) {
  DCHECK(base::ThreadTaskRunnerHandle::Get()->BelongsToCurrentThread());
  // We need a requested_au_ or to have canceled this request and
  // are buffering to a new location for this to make sense
  DCHECK(requested_au_);

  const char* ALLOW_UNUSED_TYPE event_type =
      requested_au_->GetType() == DemuxerStream::AUDIO ? "audio" : "video";
  TRACE_EVENT2("media_stack", "ProgressiveDemuxer::Download()", "type",
               event_type, "timestamp",
               requested_au_->GetTimestamp().InMicroseconds());
  // do nothing if stopped
  if (HasStopCalled()) {
    DLOG(INFO) << "aborting download task, stopped";
    return;
  }

  // Flushing is a signal to restart the request->download cycle with
  // a new request. Drop current request and issue a new one.
  // flushing_ will be reset by the next call to RequestTask()
  if (flushing_) {
    DLOG(INFO) << "skipped AU download due to flush";
    requested_au_ = NULL;
    IssueNextRequest();
    return;
  }

  if (!requested_au_->Read(reader_.get(), buffer.get())) {
    DLOG(ERROR) << "au read failed";
    host_->OnDemuxerError(::media::PIPELINE_ERROR_READ);
    return;
  }

  // copy timestamp and duration values
  buffer->set_timestamp(requested_au_->GetTimestamp());
  buffer->set_duration(requested_au_->GetDuration());

  // enqueue buffer into appropriate stream
  if (requested_au_->GetType() == DemuxerStream::AUDIO) {
    audio_demuxer_stream_->EnqueueBuffer(buffer);
  } else if (requested_au_->GetType() == DemuxerStream::VIDEO) {
    video_demuxer_stream_->EnqueueBuffer(buffer);
  } else {
    NOTREACHED() << "invalid buffer type enqueued";
  }

  // finished with this au, deref
  requested_au_ = NULL;

  // Calculate total range of buffered data for both audio and video.
  ::media::Ranges<base::TimeDelta> buffered(
      audio_demuxer_stream_->GetBufferedRanges().IntersectionWith(
          video_demuxer_stream_->GetBufferedRanges()));
  // Notify host of each disjoint range.
  host_->OnBufferedTimeRangesChanged(buffered);

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(&ProgressiveDemuxer::IssueNextRequest,
                            base::Unretained(this)));
}

void ProgressiveDemuxer::IssueNextRequest() {
  DCHECK(!requested_au_);
  // if we're stopped don't download anymore
  if (HasStopCalled()) {
    DLOG(INFO) << "stopped so request loop is stopping";
    return;
  }

  DemuxerStream::Type type = DemuxerStream::UNKNOWN;
  // if we have eos in one or both buffers the decision is easy
  if (audio_reached_eos_ || video_reached_eos_) {
    if (audio_reached_eos_) {
      if (video_reached_eos_) {
        // both are true, issue no more requests!
        DLOG(INFO) << "both streams at EOS, request loop stopping";
        return;
      } else {
        // audio is at eos, video isn't, get more video
        type = DemuxerStream::VIDEO;
      }
    } else {
      // audio is not at eos, video is, get more audio
      type = DemuxerStream::AUDIO;
    }
  } else {
    // priority order for figuring out what to download next
    base::TimeDelta audio_stamp =
        audio_demuxer_stream_->GetLastBufferTimestamp();
    base::TimeDelta video_stamp =
        video_demuxer_stream_->GetLastBufferTimestamp();
    // if the audio demuxer stream is empty, always fill it first
    if (audio_stamp == kNoTimestamp) {
      type = DemuxerStream::AUDIO;
    } else if (video_stamp == kNoTimestamp) {
      // the video demuxer stream is empty, we need data for it
      type = DemuxerStream::VIDEO;
    } else if (video_stamp < audio_stamp) {
      // video is earlier, fill it first
      type = DemuxerStream::VIDEO;
    } else {
      type = DemuxerStream::AUDIO;
    }
  }
  DCHECK_NE(type, DemuxerStream::UNKNOWN);
  // We cannot call Request() directly even if this function is also run on
  // |blocking_thread_| as otherwise it is possible that this function is
  // running in a tight loop and seek or stop request has no chance to kick in.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::Bind(&ProgressiveDemuxer::Request, base::Unretained(this), type));
}

void ProgressiveDemuxer::Stop() {
  DCHECK(MessageLoopBelongsToCurrentThread());
  // set our internal stop flag, to not treat read failures as
  // errors anymore but as a natural part of stopping
  {
    base::AutoLock auto_lock(lock_for_stopped_);
    stopped_ = true;
  }

  // stop the reader, which will stop the datasource and call back
  reader_->Stop();
}

bool ProgressiveDemuxer::HasStopCalled() {
  base::AutoLock auto_lock(lock_for_stopped_);
  return stopped_;
}

void ProgressiveDemuxer::Seek(base::TimeDelta time, PipelineStatusCallback cb) {
  blocking_thread_.message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&ProgressiveDemuxer::SeekTask, base::Unretained(this),
                     time, ::media::BindToCurrentLoop(std::move(cb))));
}

// runs on blocking thread
void ProgressiveDemuxer::SeekTask(base::TimeDelta time,
                                  PipelineStatusCallback cb) {
  TRACE_EVENT1("media_stack", "ProgressiveDemuxer::SeekTask()", "timestamp",
               time.InMicroseconds());
  DLOG(INFO) << base::StringPrintf("seek to: %" PRId64 " ms",
                                   time.InMilliseconds());
  // clear any enqueued buffers on demuxer streams
  audio_demuxer_stream_->FlushBuffers();
  video_demuxer_stream_->FlushBuffers();
  // advance parser to new timestamp
  if (!parser_->SeekTo(time)) {
    DLOG(ERROR) << "parser seek failed.";
    std::move(cb).Run(::media::PIPELINE_ERROR_READ);
    return;
  }
  // if both streams had finished downloading, we need to restart the request
  bool issue_new_request = audio_reached_eos_ && video_reached_eos_;
  audio_reached_eos_ = false;
  video_reached_eos_ = false;
  flushing_ = true;
  std::move(cb).Run(::media::PIPELINE_OK);
  if (issue_new_request) {
    DLOG(INFO) << "restarting stopped request loop";
    Request(DemuxerStream::AUDIO);
  }
}

std::vector<::media::DemuxerStream*> ProgressiveDemuxer::GetAllStreams() {
  return std::vector<DemuxerStream*>(
      {audio_demuxer_stream_.get(), video_demuxer_stream_.get()});
}

base::TimeDelta ProgressiveDemuxer::GetStartTime() const {
  // we always assume a start time of 0
  return base::TimeDelta();
}

const AudioDecoderConfig& ProgressiveDemuxer::AudioConfig() {
  return parser_->AudioConfig();
}

const VideoDecoderConfig& ProgressiveDemuxer::VideoConfig() {
  return parser_->VideoConfig();
}

bool ProgressiveDemuxer::MessageLoopBelongsToCurrentThread() const {
  return message_loop_->BelongsToCurrentThread();
}

}  // namespace media
}  // namespace cobalt
