/*
 * Copyright 2015 Google Inc. 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/sandbox/demuxer_helper.h"

#include <queue>

#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "cobalt/media/fetcher_buffered_data_source.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/bind_to_loop.h"
#include "media/base/decoder_buffer.h"
#include "media/base/video_decoder_config.h"
#include "media/filters/shell_demuxer.h"

namespace cobalt {
namespace media {
namespace sandbox {

namespace {

using ::media::AudioDecoderConfig;
using ::media::BindToCurrentLoop;
using ::media::DecoderBuffer;
using ::media::DemuxerStream;
using ::media::VideoDecoderConfig;

// A DemuxerStream that caches media data in memory.  Note that it is only for
// test purpose and no synchronization is provided.
class DemuxerStreamCache : public ::media::DemuxerStream {
 public:
  explicit DemuxerStreamCache(const AudioDecoderConfig& audio_decoder_config)
      : type_(AUDIO) {
    audio_decoder_config_.CopyFrom(audio_decoder_config);
  }
  explicit DemuxerStreamCache(const VideoDecoderConfig& video_decoder_config)
      : type_(VIDEO) {
    video_decoder_config_.CopyFrom(video_decoder_config);
  }

  void Append(const scoped_refptr<DecoderBuffer>& buffer) {
    DCHECK(buffer);
    DCHECK(!buffer->IsEndOfStream());
    buffers_.push(buffer);
  }

 private:
  // DemuxerStream methods.
  void Read(const ReadCB& read_cb) OVERRIDE {
    scoped_refptr<DecoderBuffer> buffer;
    if (buffers_.empty()) {
      buffer = DecoderBuffer::CreateEOSBuffer(base::TimeDelta());
    } else {
      buffer = buffers_.front();
      buffers_.pop();
    }
    read_cb.Run(kOk, buffer);
  }
  const AudioDecoderConfig& audio_decoder_config() OVERRIDE {
    DCHECK_EQ(type_, AUDIO);
    return audio_decoder_config_;
  }
  const VideoDecoderConfig& video_decoder_config() OVERRIDE {
    DCHECK_EQ(type_, VIDEO);
    return video_decoder_config_;
  }
  Type type() OVERRIDE { return type_; }
  void EnableBitstreamConverter() OVERRIDE {}
  bool StreamWasEncrypted() const OVERRIDE { return false; }

  Type type_;
  AudioDecoderConfig audio_decoder_config_;
  VideoDecoderConfig video_decoder_config_;
  std::queue<scoped_refptr<DecoderBuffer> > buffers_;
};

// A Demuxer that caches media data in memory.  Note that it is only for test
// purpose and no synchronization is provided.
class DemuxerCache : public ::media::Demuxer {
 public:
  DemuxerCache(const scoped_refptr<Demuxer>& demuxer, uint64 bytes_to_cache,
               const DemuxerHelper::DemuxerReadyCB& demuxer_ready_cb) {
    if (demuxer->GetStream(DemuxerStream::AUDIO)) {
      audio_stream_ = new DemuxerStreamCache(
          demuxer->GetStream(DemuxerStream::AUDIO)->audio_decoder_config());
    }
    if (demuxer->GetStream(DemuxerStream::VIDEO)) {
      video_stream_ = new DemuxerStreamCache(
          demuxer->GetStream(DemuxerStream::VIDEO)->video_decoder_config());
    }
    DCHECK(audio_stream_ || video_stream_);
    CacheState cache_state;
    cache_state.demuxer = demuxer;
    cache_state.bytes_to_cache = bytes_to_cache;
    cache_state.audio_eos = !audio_stream_;
    cache_state.video_eos = !video_stream_;
    cache_state.demuxer_ready_cb = demuxer_ready_cb;

    if (audio_stream_) {
      cache_state.last_read_type = DemuxerStream::AUDIO;
    } else {
      cache_state.last_read_type = DemuxerStream::VIDEO;
    }
    demuxer->GetStream(cache_state.last_read_type)
        ->Read(BindToCurrentLoop(
            base::Bind(&DemuxerCache::CacheBuffer, this, cache_state)));
  }

 private:
  struct CacheState {
    scoped_refptr<Demuxer> demuxer;
    uint64 bytes_to_cache;
    base::TimeDelta last_audio_buffer_timestamp;
    bool audio_eos;
    base::TimeDelta last_video_buffer_timestamp;
    bool video_eos;
    DemuxerHelper::DemuxerReadyCB demuxer_ready_cb;
    DemuxerStream::Type last_read_type;
  };

  void CacheBuffer(CacheState cache_state, DemuxerStream::Status status,
                   const scoped_refptr<DecoderBuffer>& buffer) {
    DCHECK_EQ(status, DemuxerStream::kOk);
    DCHECK(buffer);

    if (cache_state.last_read_type == DemuxerStream::AUDIO) {
      if (buffer->IsEndOfStream()) {
        cache_state.audio_eos = true;
      } else {
        cache_state.last_audio_buffer_timestamp = buffer->GetTimestamp();
        if (cache_state.bytes_to_cache >= buffer->GetDataSize()) {
          cache_state.bytes_to_cache -= buffer->GetDataSize();
          audio_stream_->Append(buffer);
        } else {
          cache_state.bytes_to_cache = 0;
        }
      }
    } else {
      DCHECK_EQ(cache_state.last_read_type, DemuxerStream::VIDEO);
      if (buffer->IsEndOfStream()) {
        cache_state.video_eos = true;
      } else {
        cache_state.last_video_buffer_timestamp = buffer->GetTimestamp();
        if (cache_state.bytes_to_cache >= buffer->GetDataSize()) {
          cache_state.bytes_to_cache -= buffer->GetDataSize();
          video_stream_->Append(buffer);
        } else {
          cache_state.bytes_to_cache = 0;
        }
      }
    }
    if ((cache_state.audio_eos && cache_state.video_eos) ||
        cache_state.bytes_to_cache == 0) {
      cache_state.demuxer->Stop(base::Bind(cache_state.demuxer_ready_cb,
                                           scoped_refptr<Demuxer>(this)));
      return;
    }
    cache_state.last_read_type = DemuxerStream::AUDIO;
    if (cache_state.audio_eos) {
      cache_state.last_read_type = DemuxerStream::VIDEO;
    } else if (!cache_state.video_eos) {
      if (cache_state.last_video_buffer_timestamp <
          cache_state.last_audio_buffer_timestamp) {
        cache_state.last_read_type = DemuxerStream::VIDEO;
      }
    }

    cache_state.demuxer->GetStream(cache_state.last_read_type)
        ->Read(BindToCurrentLoop(
            base::Bind(&DemuxerCache::CacheBuffer, this, cache_state)));
  }

  // Demuxer methods.
  void Initialize(::media::DemuxerHost* host,
                  const ::media::PipelineStatusCB& status_cb) OVERRIDE {
    NOTREACHED();
  }
  void Stop(const base::Closure& callback) OVERRIDE {
    DCHECK(!callback.is_null());
    callback.Run();
  }
  scoped_refptr<DemuxerStream> GetStream(DemuxerStream::Type type) OVERRIDE {
    if (type == DemuxerStream::AUDIO) {
      return audio_stream_;
    } else if (type == DemuxerStream::VIDEO) {
      return video_stream_;
    }
    NOTREACHED();
    return NULL;
  }
  base::TimeDelta GetStartTime() const OVERRIDE { return base::TimeDelta(); }

  scoped_refptr<DemuxerStreamCache> audio_stream_;
  scoped_refptr<DemuxerStreamCache> video_stream_;
};

}  // namespace

class DemuxerHelper::DemuxerHostStub : public ::media::DemuxerHost {
 private:
  // DataSourceHost methods
  void SetTotalBytes(int64 total_bytes) OVERRIDE {
    UNREFERENCED_PARAMETER(total_bytes);
  }
  void AddBufferedByteRange(int64 start, int64 end) OVERRIDE {
    UNREFERENCED_PARAMETER(start);
    UNREFERENCED_PARAMETER(end);
  }
  void AddBufferedTimeRange(base::TimeDelta start,
                            base::TimeDelta end) OVERRIDE {
    UNREFERENCED_PARAMETER(start);
    UNREFERENCED_PARAMETER(end);
  }

  // DemuxerHost methods
  void SetDuration(base::TimeDelta duration) OVERRIDE {
    UNREFERENCED_PARAMETER(duration);
  }
  void OnDemuxerError(::media::PipelineStatus error) OVERRIDE {
    UNREFERENCED_PARAMETER(error);
  }
};

DemuxerHelper::DemuxerHelper(
    const scoped_refptr<base::MessageLoopProxy>& media_message_loop,
    loader::FetcherFactory* fetcher_factory, const GURL& video_url,
    const DemuxerReadyCB& demuxer_ready_cb)
    : host_(new DemuxerHostStub) {
  CreateDemuxer(media_message_loop, fetcher_factory, video_url,
                demuxer_ready_cb, 0);
}

DemuxerHelper::DemuxerHelper(
    const scoped_refptr<base::MessageLoopProxy>& media_message_loop,
    loader::FetcherFactory* fetcher_factory, const GURL& video_url,
    const DemuxerReadyCB& demuxer_ready_cb, uint64 bytes_to_cache)
    : host_(new DemuxerHostStub) {
  DCHECK_GE(bytes_to_cache, 0);

  CreateDemuxer(media_message_loop, fetcher_factory, video_url,
                demuxer_ready_cb, bytes_to_cache);
}

DemuxerHelper::~DemuxerHelper() { delete host_; }

void DemuxerHelper::CreateDemuxer(
    const scoped_refptr<base::MessageLoopProxy>& media_message_loop,
    loader::FetcherFactory* fetcher_factory, const GURL& video_url,
    const DemuxerReadyCB& demuxer_ready_cb, uint64 bytes_to_cache) {
  DCHECK(media_message_loop);
  DCHECK(fetcher_factory);
  DCHECK(!demuxer_ready_cb.is_null());

  scoped_refptr<FetcherBufferedDataSource> data_source(
      new FetcherBufferedDataSource(media_message_loop, video_url,
                                    csp::SecurityCallback(),
                                    fetcher_factory->network_module()));
  scoped_refptr<Demuxer> demuxer =
      new ::media::ShellDemuxer(media_message_loop, data_source);
  demuxer->Initialize(
      host_, base::Bind(&DemuxerHelper::OnDemuxerReady, base::Unretained(this),
                        demuxer, demuxer_ready_cb, bytes_to_cache));
}

void DemuxerHelper::OnDemuxerReady(const scoped_refptr<Demuxer>& demuxer,
                                   const DemuxerReadyCB& demuxer_ready_cb,
                                   uint64 bytes_to_cache,
                                   ::media::PipelineStatus status) {
  DCHECK_EQ(status, ::media::PIPELINE_OK);

  if (bytes_to_cache == 0) {
    demuxer_ready_cb.Run(demuxer);
    return;
  }

  // The newly created object is reference counted and will be passed back
  // through demuxer_ready_cb.
  new DemuxerCache(demuxer, bytes_to_cache, demuxer_ready_cb);
}

}  // namespace sandbox
}  // namespace media
}  // namespace cobalt
