// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/base/android/media_source_player.h"

#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread.h"
#include "media/base/android/media_codec_bridge.h"
#include "media/base/android/media_drm_bridge.h"
#include "media/base/android/media_player_manager.h"
#include "media/base/audio_timestamp_helper.h"

namespace {

// Timeout value for media codec operations. Because the first
// DequeInputBuffer() can take about 150 milliseconds, use 250 milliseconds
// here. See b/9357571.
const int kMediaCodecTimeoutInMilliseconds = 250;

// Use 16bit PCM for audio output. Keep this value in sync with the output
// format we passed to AudioTrack in MediaCodecBridge.
const int kBytesPerAudioOutputSample = 2;

class DecoderThread : public base::Thread {
 public:
  virtual ~DecoderThread() {}
 protected:
  DecoderThread(const char* name) : base::Thread(name) { Start(); }
};

class AudioDecoderThread : public DecoderThread {
 public:
  AudioDecoderThread() : DecoderThread("MediaSource_AudioDecoderThread") {}
};

class VideoDecoderThread : public DecoderThread {
 public:
  VideoDecoderThread() : DecoderThread("MediaSource_VideoDecoderThread") {}
};

// TODO(qinmin): Check if it is tolerable to use worker pool to handle all the
// decoding tasks so that we don't need the global threads here.
// http://crbug.com/245750
base::LazyInstance<AudioDecoderThread>::Leaky
    g_audio_decoder_thread = LAZY_INSTANCE_INITIALIZER;

base::LazyInstance<VideoDecoderThread>::Leaky
    g_video_decoder_thread = LAZY_INSTANCE_INITIALIZER;

}

namespace media {

MediaDecoderJob::MediaDecoderJob(
    const scoped_refptr<base::MessageLoopProxy>& decoder_loop,
    MediaCodecBridge* media_codec_bridge,
    bool is_audio)
    : ui_loop_(base::MessageLoopProxy::current()),
      decoder_loop_(decoder_loop),
      media_codec_bridge_(media_codec_bridge),
      needs_flush_(false),
      is_audio_(is_audio),
      input_eos_encountered_(false),
      weak_this_(this),
      is_decoding_(false) {
}

MediaDecoderJob::~MediaDecoderJob() {}

// Class for managing audio decoding jobs.
class AudioDecoderJob : public MediaDecoderJob {
 public:
  virtual ~AudioDecoderJob() {}

  static AudioDecoderJob* Create(
      const AudioCodec audio_codec, int sample_rate, int channel_count,
      const uint8* extra_data, size_t extra_data_size, jobject media_crypto);

  void SetVolume(double volume);

 private:
  AudioDecoderJob(MediaCodecBridge* media_codec_bridge);
};

// Class for managing video decoding jobs.
class VideoDecoderJob : public MediaDecoderJob {
 public:
  virtual ~VideoDecoderJob() {}

  static VideoDecoderJob* Create(
      const VideoCodec video_codec, const gfx::Size& size, jobject surface,
      jobject media_crypto);

 private:
  VideoDecoderJob(MediaCodecBridge* media_codec_bridge);
};

void MediaDecoderJob::Decode(
    const AccessUnit& unit,
    const base::TimeTicks& start_time_ticks,
    const base::TimeDelta& start_presentation_timestamp,
    const MediaDecoderJob::DecoderCallback& callback) {
  DCHECK(!is_decoding_);
  DCHECK(ui_loop_->BelongsToCurrentThread());
  is_decoding_ = true;
  decoder_loop_->PostTask(FROM_HERE, base::Bind(
      &MediaDecoderJob::DecodeInternal, base::Unretained(this), unit,
      start_time_ticks, start_presentation_timestamp, needs_flush_,
      callback));
  needs_flush_ = false;
}

MediaDecoderJob::DecodeStatus MediaDecoderJob::QueueInputBuffer(
    const AccessUnit& unit) {
  base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(
      kMediaCodecTimeoutInMilliseconds);
  int input_buf_index = media_codec_bridge_->DequeueInputBuffer(timeout);
  if (input_buf_index == MediaCodecBridge::INFO_MEDIA_CODEC_ERROR)
    return DECODE_FAILED;
  if (input_buf_index == MediaCodecBridge::INFO_TRY_AGAIN_LATER)
    return DECODE_TRY_ENQUEUE_INPUT_AGAIN_LATER;

  // TODO(qinmin): skip frames if video is falling far behind.
  DCHECK(input_buf_index >= 0);
  if (unit.end_of_stream || unit.data.empty()) {
    media_codec_bridge_->QueueEOS(input_buf_index);
    return DECODE_INPUT_END_OF_STREAM;
  }
  if (unit.key_id.empty()) {
    media_codec_bridge_->QueueInputBuffer(
        input_buf_index, &unit.data[0], unit.data.size(), unit.timestamp);
  } else {
    if (unit.iv.empty() || unit.subsamples.empty()) {
      LOG(ERROR) << "The access unit doesn't have iv or subsamples while it "
                 << "has key IDs!";
      return DECODE_FAILED;
    }
    media_codec_bridge_->QueueSecureInputBuffer(
        input_buf_index, &unit.data[0], unit.data.size(),
        reinterpret_cast<const uint8*>(&unit.key_id[0]), unit.key_id.size(),
        reinterpret_cast<const uint8*>(&unit.iv[0]), unit.iv.size(),
        &unit.subsamples[0], unit.subsamples.size(), unit.timestamp);
  }

  return DECODE_SUCCEEDED;
}

void MediaDecoderJob::DecodeInternal(
    const AccessUnit& unit,
    const base::TimeTicks& start_time_ticks,
    const base::TimeDelta& start_presentation_timestamp,
    bool needs_flush,
    const MediaDecoderJob::DecoderCallback& callback) {
  if (needs_flush) {
    DVLOG(1) << "DecodeInternal needs flush.";
    input_eos_encountered_ = false;
    media_codec_bridge_->Reset();
  }

  DecodeStatus decode_status = DECODE_INPUT_END_OF_STREAM;
  if (!input_eos_encountered_) {
    decode_status = QueueInputBuffer(unit);
    if (decode_status == DECODE_INPUT_END_OF_STREAM) {
      input_eos_encountered_ = true;
    } else if (decode_status != DECODE_SUCCEEDED) {
      ui_loop_->PostTask(FROM_HERE,
                         base::Bind(callback, decode_status,
                                    start_presentation_timestamp, 0));
      return;
    }
  }

  size_t offset = 0;
  size_t size = 0;
  base::TimeDelta presentation_timestamp;
  bool end_of_stream = false;

  base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(
      kMediaCodecTimeoutInMilliseconds);
  int outputBufferIndex = media_codec_bridge_->DequeueOutputBuffer(
      timeout, &offset, &size, &presentation_timestamp, &end_of_stream);

  if (end_of_stream)
    decode_status = DECODE_OUTPUT_END_OF_STREAM;
  switch (outputBufferIndex) {
    case MediaCodecBridge::INFO_OUTPUT_BUFFERS_CHANGED:
      DCHECK(decode_status != DECODE_INPUT_END_OF_STREAM);
      media_codec_bridge_->GetOutputBuffers();
      break;
    case MediaCodecBridge::INFO_OUTPUT_FORMAT_CHANGED:
      DCHECK(decode_status != DECODE_INPUT_END_OF_STREAM);
      // TODO(qinmin): figure out what we should do if format changes.
      decode_status = DECODE_FORMAT_CHANGED;
      break;
    case MediaCodecBridge::INFO_TRY_AGAIN_LATER:
      decode_status = DECODE_TRY_DEQUEUE_OUTPUT_AGAIN_LATER;
      break;
    case MediaCodecBridge::INFO_MEDIA_CODEC_ERROR:
      decode_status = DECODE_FAILED;
      break;
    default:
      DCHECK_LE(0, outputBufferIndex);
      base::TimeDelta time_to_render;
      DCHECK(!start_time_ticks.is_null());
      if (!is_audio_) {
        time_to_render = presentation_timestamp - (base::TimeTicks::Now() -
            start_time_ticks + start_presentation_timestamp);
      }
      if (time_to_render >= base::TimeDelta()) {
        base::MessageLoop::current()->PostDelayedTask(
            FROM_HERE,
            base::Bind(&MediaDecoderJob::ReleaseOutputBuffer,
                       weak_this_.GetWeakPtr(), outputBufferIndex, size,
                       presentation_timestamp, callback, decode_status),
            time_to_render);
      } else {
        // TODO(qinmin): The codec is lagging behind, need to recalculate the
        // |start_presentation_timestamp_| and |start_time_ticks_|.
        DVLOG(1) << (is_audio_ ? "audio " : "video ")
            << "codec is lagging behind :" << time_to_render.InMicroseconds();
        ReleaseOutputBuffer(outputBufferIndex, size, presentation_timestamp,
                            callback, decode_status);
      }
      return;
  }
  ui_loop_->PostTask(FROM_HERE, base::Bind(
      callback, decode_status, start_presentation_timestamp, 0));
}

void MediaDecoderJob::ReleaseOutputBuffer(
    int outputBufferIndex, size_t size,
    const base::TimeDelta& presentation_timestamp,
    const MediaDecoderJob::DecoderCallback& callback, DecodeStatus status) {
  // TODO(qinmin): Refactor this function. Maybe AudioDecoderJob should provide
  // its own ReleaseOutputBuffer().
  if (is_audio_) {
    static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->PlayOutputBuffer(
        outputBufferIndex, size);
  }
  if (status != DECODE_OUTPUT_END_OF_STREAM || size != 0u)
    media_codec_bridge_->ReleaseOutputBuffer(outputBufferIndex, !is_audio_);
  ui_loop_->PostTask(FROM_HERE, base::Bind(
      callback, status, presentation_timestamp, is_audio_ ? size : 0));
}

void MediaDecoderJob::OnDecodeCompleted() {
  DCHECK(ui_loop_->BelongsToCurrentThread());
  is_decoding_ = false;
}

void MediaDecoderJob::Flush() {
  // Do nothing, flush when the next Decode() happens.
  needs_flush_ = true;
}

void MediaDecoderJob::Release() {
  // If |decoding_| is false, there is nothing running on the decoder thread.
  // So it is safe to delete the MediaDecoderJob on the UI thread. However,
  // if we post a task to the decoder thread to delete object, then we cannot
  // immediately pass the surface to a new MediaDecoderJob instance because
  // the java surface is still owned by the old object. New decoder creation
  // will be blocked on the UI thread until the previous decoder gets deleted.
  // This introduces extra latency during config changes, and makes the logic in
  // MediaSourcePlayer more complicated.
  //
  // TODO(qinmin): Figure out the logic to passing the surface to a new
  // MediaDecoderJob instance after the previous one gets deleted on the decoder
  // thread.
  if (is_decoding_ && !decoder_loop_->BelongsToCurrentThread()) {
    DCHECK(ui_loop_->BelongsToCurrentThread());
    decoder_loop_->DeleteSoon(FROM_HERE, this);
  } else {
    delete this;
  }
}

VideoDecoderJob* VideoDecoderJob::Create(
    const VideoCodec video_codec, const gfx::Size& size, jobject surface,
    jobject media_crypto) {
  scoped_ptr<VideoCodecBridge> codec(VideoCodecBridge::Create(video_codec));
  if (codec && codec->Start(video_codec, size, surface, media_crypto))
    return new VideoDecoderJob(codec.release());
  return NULL;
}

VideoDecoderJob::VideoDecoderJob(MediaCodecBridge* media_codec_bridge)
    : MediaDecoderJob(g_video_decoder_thread.Pointer()->message_loop_proxy(),
                      media_codec_bridge,
                      false) {}

AudioDecoderJob* AudioDecoderJob::Create(
    const AudioCodec audio_codec,
    int sample_rate,
    int channel_count,
    const uint8* extra_data,
    size_t extra_data_size,
    jobject media_crypto) {
  scoped_ptr<AudioCodecBridge> codec(AudioCodecBridge::Create(audio_codec));
  if (codec && codec->Start(audio_codec, sample_rate, channel_count, extra_data,
                            extra_data_size, true, media_crypto)) {
    return new AudioDecoderJob(codec.release());
  }
  return NULL;
}

AudioDecoderJob::AudioDecoderJob(MediaCodecBridge* media_codec_bridge)
    : MediaDecoderJob(g_audio_decoder_thread.Pointer()->message_loop_proxy(),
                      media_codec_bridge,
                      true) {}

void AudioDecoderJob::SetVolume(double volume) {
  static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->SetVolume(volume);
}

MediaSourcePlayer::MediaSourcePlayer(
    int player_id,
    MediaPlayerManager* manager)
    : MediaPlayerAndroid(player_id, manager),
      pending_event_(NO_EVENT_PENDING),
      seek_request_id_(0),
      width_(0),
      height_(0),
      audio_codec_(kUnknownAudioCodec),
      video_codec_(kUnknownVideoCodec),
      num_channels_(0),
      sampling_rate_(0),
      audio_finished_(true),
      video_finished_(true),
      playing_(false),
      is_audio_encrypted_(false),
      is_video_encrypted_(false),
      volume_(-1.0),
      clock_(&default_tick_clock_),
      reconfig_audio_decoder_(false),
      reconfig_video_decoder_(false),
      audio_access_unit_index_(0),
      video_access_unit_index_(0),
      waiting_for_audio_data_(false),
      waiting_for_video_data_(false),
      sync_decoder_jobs_(true),
      weak_this_(this),
      drm_bridge_(NULL) {
}

MediaSourcePlayer::~MediaSourcePlayer() {
  Release();
}

void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) {
  // Ignore non-empty surface that is unprotected if |is_video_encrypted_| is
  // true.
  if (is_video_encrypted_ && !surface.IsEmpty() && !surface.is_protected())
    return;

  surface_ =  surface.Pass();
  pending_event_ |= SURFACE_CHANGE_EVENT_PENDING;
  if (pending_event_ & SEEK_EVENT_PENDING) {
    // Waiting for the seek to finish.
    return;
  }
  // Setting a new surface will require a new MediaCodec to be created.
  // Request a seek so that the new decoder will decode an I-frame first.
  // Or otherwise, the new MediaCodec might crash. See b/8950387.
  pending_event_ |= SEEK_EVENT_PENDING;
  ProcessPendingEvents();
}

bool MediaSourcePlayer::Seekable() {
  // If the duration TimeDelta, converted to milliseconds from microseconds,
  // is >= 2^31, then the media is assumed to be unbounded and unseekable.
  // 2^31 is the bound due to java player using 32-bit integer for time
  // values at millisecond resolution.
  return duration_ <
         base::TimeDelta::FromMilliseconds(std::numeric_limits<int32>::max());
}

void MediaSourcePlayer::Start() {
  playing_ = true;

  if (is_video_encrypted_)
    manager()->OnProtectedSurfaceRequested(player_id());

  StartInternal();
}

void MediaSourcePlayer::Pause() {
  // Since decoder jobs have their own thread, decoding is not fully paused
  // until all the decoder jobs call MediaDecoderCallback(). It is possible
  // that Start() is called while the player is waiting for
  // MediaDecoderCallback(). In that case, decoding will continue when
  // MediaDecoderCallback() is called.
  playing_ = false;
  start_time_ticks_ = base::TimeTicks();
}

bool MediaSourcePlayer::IsPlaying() {
  return playing_;
}

int MediaSourcePlayer::GetVideoWidth() {
  return width_;
}

int MediaSourcePlayer::GetVideoHeight() {
  return height_;
}

void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) {
  clock_.SetTime(timestamp, timestamp);
  if (audio_timestamp_helper_)
    audio_timestamp_helper_->SetBaseTimestamp(timestamp);
  pending_event_ |= SEEK_EVENT_PENDING;
  ProcessPendingEvents();
}

base::TimeDelta MediaSourcePlayer::GetCurrentTime() {
  return clock_.Elapsed();
}

base::TimeDelta MediaSourcePlayer::GetDuration() {
  return duration_;
}

void MediaSourcePlayer::Release() {
  ClearDecodingData();
  audio_decoder_job_.reset();
  video_decoder_job_.reset();
  reconfig_audio_decoder_ = false;
  reconfig_video_decoder_ = false;
  playing_ = false;
  pending_event_ = NO_EVENT_PENDING;
  surface_ = gfx::ScopedJavaSurface();
  ReleaseMediaResourcesFromManager();
}

void MediaSourcePlayer::SetVolume(double volume) {
  volume_ = volume;
  SetVolumeInternal();
}

bool MediaSourcePlayer::CanPause() {
  return Seekable();
}

bool MediaSourcePlayer::CanSeekForward() {
  return Seekable();
}

bool MediaSourcePlayer::CanSeekBackward() {
  return Seekable();
}

bool MediaSourcePlayer::IsPlayerReady() {
  return audio_decoder_job_ || video_decoder_job_;
}

void MediaSourcePlayer::StartInternal() {
  // If there are pending events, wait for them finish.
  if (pending_event_ != NO_EVENT_PENDING)
    return;

  // Create decoder jobs if they are not created
  ConfigureAudioDecoderJob();
  ConfigureVideoDecoderJob();


  // If one of the decoder job is not ready, do nothing.
  if ((HasAudio() && !audio_decoder_job_) ||
      (HasVideo() && !video_decoder_job_)) {
    return;
  }

  audio_finished_ = false;
  video_finished_ = false;
  sync_decoder_jobs_ = true;
  SyncAndStartDecoderJobs();
}

void MediaSourcePlayer::DemuxerReady(
    const MediaPlayerHostMsg_DemuxerReady_Params& params) {
  duration_ = base::TimeDelta::FromMilliseconds(params.duration_ms);
  clock_.SetDuration(duration_);

  audio_codec_ = params.audio_codec;
  num_channels_ = params.audio_channels;
  sampling_rate_ = params.audio_sampling_rate;
  is_audio_encrypted_ = params.is_audio_encrypted;
  audio_extra_data_ = params.audio_extra_data;
  if (HasAudio()) {
    DCHECK_GT(num_channels_, 0);
    audio_timestamp_helper_.reset(new AudioTimestampHelper(sampling_rate_));
    audio_timestamp_helper_->SetBaseTimestamp(GetCurrentTime());
  } else {
    audio_timestamp_helper_.reset();
  }

  video_codec_ = params.video_codec;
  width_ = params.video_size.width();
  height_ = params.video_size.height();
  is_video_encrypted_ = params.is_video_encrypted;

  OnMediaMetadataChanged(duration_, width_, height_, true);

  if (pending_event_ & CONFIG_CHANGE_EVENT_PENDING) {
    if (reconfig_audio_decoder_)
      ConfigureAudioDecoderJob();

    // If there is a pending surface change, we can merge it with the config
    // change.
    if (reconfig_video_decoder_) {
      pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
      ConfigureVideoDecoderJob();
    }
    pending_event_ &= ~CONFIG_CHANGE_EVENT_PENDING;
    if (playing_)
      StartInternal();
  }
}

void MediaSourcePlayer::ReadFromDemuxerAck(
    const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
  DCHECK_LT(0u, params.access_units.size());
  if (params.type == DemuxerStream::AUDIO)
    waiting_for_audio_data_ = false;
  else
    waiting_for_video_data_ = false;

  // If there is a pending seek request, ignore the data from the chunk demuxer.
  // The data will be requested later when OnSeekRequestAck() is called.
  if (pending_event_ & SEEK_EVENT_PENDING)
    return;

  if (params.type == DemuxerStream::AUDIO) {
    DCHECK_EQ(0u, audio_access_unit_index_);
    received_audio_ = params;
  } else {
    DCHECK_EQ(0u, video_access_unit_index_);
    received_video_ = params;
  }

  if (pending_event_ != NO_EVENT_PENDING || !playing_)
    return;

  if (sync_decoder_jobs_) {
    SyncAndStartDecoderJobs();
    return;
  }

  if (params.type == DemuxerStream::AUDIO)
    DecodeMoreAudio();
  else
    DecodeMoreVideo();
}

void MediaSourcePlayer::DurationChanged(const base::TimeDelta& duration) {
  duration_ = duration;
  clock_.SetDuration(duration_);
}

void MediaSourcePlayer::SetDrmBridge(MediaDrmBridge* drm_bridge) {
  // Currently we don't support DRM change during the middle of playback, even
  // if the player is paused.
  // TODO(qinmin): support DRM change after playback has started.
  // http://crbug.com/253792.
  if (GetCurrentTime() > base::TimeDelta()) {
    LOG(INFO) << "Setting DRM bridge after play back has started. "
              << "This is not well supported!";
  }

  drm_bridge_ = drm_bridge;

  if (playing_)
    StartInternal();
}

void MediaSourcePlayer::OnSeekRequestAck(unsigned seek_request_id) {
  DVLOG(1) << "OnSeekRequestAck(" << seek_request_id << ")";
  // Do nothing until the most recent seek request is processed.
  if (seek_request_id_ != seek_request_id)
    return;
  pending_event_ &= ~SEEK_EVENT_PENDING;
  OnSeekComplete();
  ProcessPendingEvents();
}

void MediaSourcePlayer::UpdateTimestamps(
    const base::TimeDelta& presentation_timestamp, size_t audio_output_bytes) {
  if (audio_output_bytes > 0) {
    audio_timestamp_helper_->AddFrames(
        audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_));
    clock_.SetMaxTime(audio_timestamp_helper_->GetTimestamp());
  } else {
    clock_.SetMaxTime(presentation_timestamp);
  }

  OnTimeUpdated();
}

void MediaSourcePlayer::ProcessPendingEvents() {
  // Wait for all the decoding jobs to finish before processing pending tasks.
  if ((audio_decoder_job_ && audio_decoder_job_->is_decoding()) ||
      (video_decoder_job_ && video_decoder_job_->is_decoding())) {
    return;
  }

  if (pending_event_ & SEEK_EVENT_PENDING) {
    ClearDecodingData();
    manager()->OnMediaSeekRequest(
        player_id(), GetCurrentTime(), ++seek_request_id_);
    return;
  }

  start_time_ticks_ = base::TimeTicks();
  if (pending_event_ & CONFIG_CHANGE_EVENT_PENDING) {
    DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_);
    manager()->OnMediaConfigRequest(player_id());
    return;
  }

  if (pending_event_ & SURFACE_CHANGE_EVENT_PENDING) {
    video_decoder_job_.reset();
    ConfigureVideoDecoderJob();
    pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
  }

  if (playing_)
    StartInternal();
}

void MediaSourcePlayer::MediaDecoderCallback(
    bool is_audio, MediaDecoderJob::DecodeStatus decode_status,
    const base::TimeDelta& presentation_timestamp, size_t audio_output_bytes) {
  if (is_audio && audio_decoder_job_)
    audio_decoder_job_->OnDecodeCompleted();
  if (!is_audio && video_decoder_job_)
    video_decoder_job_->OnDecodeCompleted();

  if (is_audio)
    decoder_starvation_callback_.Cancel();

  if (decode_status == MediaDecoderJob::DECODE_FAILED) {
    Release();
    OnMediaError(MEDIA_ERROR_DECODE);
    return;
  }

  // If the input reaches input EOS, there is no need to request new data.
  if (decode_status != MediaDecoderJob::DECODE_TRY_ENQUEUE_INPUT_AGAIN_LATER &&
      decode_status != MediaDecoderJob::DECODE_INPUT_END_OF_STREAM) {
    if (is_audio)
      audio_access_unit_index_++;
    else
      video_access_unit_index_++;
  }

  if (pending_event_ != NO_EVENT_PENDING) {
    ProcessPendingEvents();
    return;
  }

  if (decode_status == MediaDecoderJob::DECODE_SUCCEEDED &&
      (is_audio || !HasAudio())) {
    UpdateTimestamps(presentation_timestamp, audio_output_bytes);
  }

  if (decode_status == MediaDecoderJob::DECODE_OUTPUT_END_OF_STREAM) {
    PlaybackCompleted(is_audio);
    return;
  }

  if (!playing_) {
    if (is_audio || !HasAudio())
      clock_.Pause();
    return;
  }

  if (sync_decoder_jobs_) {
    SyncAndStartDecoderJobs();
    return;
  }

  base::TimeDelta current_timestamp = GetCurrentTime();
  if (is_audio) {
    if (decode_status == MediaDecoderJob::DECODE_SUCCEEDED) {
      base::TimeDelta timeout =
          audio_timestamp_helper_->GetTimestamp() - current_timestamp;
      StartStarvationCallback(timeout);
    }
    if (!HasAudioData())
      RequestAudioData();
    else
      DecodeMoreAudio();
    return;
  }

  if (!HasAudio() && decode_status == MediaDecoderJob::DECODE_SUCCEEDED) {
    DCHECK(current_timestamp <= presentation_timestamp);
    // For video only streams, fps can be estimated from the difference
    // between the previous and current presentation timestamps. The
    // previous presentation timestamp is equal to current_timestamp.
    // TODO(qinmin): determine whether 2 is a good coefficient for estimating
    // video frame timeout.
    StartStarvationCallback(2 * (presentation_timestamp - current_timestamp));
  }
  if (!HasVideoData())
    RequestVideoData();
  else
    DecodeMoreVideo();
}

void MediaSourcePlayer::DecodeMoreAudio() {
  DCHECK(!audio_decoder_job_->is_decoding());
  DCHECK(HasAudioData());

  if (DemuxerStream::kConfigChanged ==
      received_audio_.access_units[audio_access_unit_index_].status) {
    // Wait for demuxer ready message.
    reconfig_audio_decoder_ = true;
    pending_event_ |= CONFIG_CHANGE_EVENT_PENDING;
    received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
    audio_access_unit_index_ = 0;
    ProcessPendingEvents();
    return;
  }

  audio_decoder_job_->Decode(
      received_audio_.access_units[audio_access_unit_index_],
      start_time_ticks_, start_presentation_timestamp_,
      base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
                 weak_this_.GetWeakPtr(), true));
}

void MediaSourcePlayer::DecodeMoreVideo() {
  DVLOG(1) << "DecodeMoreVideo()";
  DCHECK(!video_decoder_job_->is_decoding());
  DCHECK(HasVideoData());

  if (DemuxerStream::kConfigChanged ==
      received_video_.access_units[video_access_unit_index_].status) {
    // Wait for demuxer ready message.
    reconfig_video_decoder_ = true;
    pending_event_ |= CONFIG_CHANGE_EVENT_PENDING;
    received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
    video_access_unit_index_ = 0;
    ProcessPendingEvents();
    return;
  }

  DVLOG(3) << "VideoDecoderJob::Decode(" << video_access_unit_index_ << ", "
           << start_time_ticks_.ToInternalValue() << ", "
           << start_presentation_timestamp_.InMilliseconds() << ")";
  video_decoder_job_->Decode(
      received_video_.access_units[video_access_unit_index_],
      start_time_ticks_, start_presentation_timestamp_,
      base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
                 weak_this_.GetWeakPtr(), false));
}

void MediaSourcePlayer::PlaybackCompleted(bool is_audio) {
  if (is_audio)
    audio_finished_ = true;
  else
    video_finished_ = true;

  if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) {
    playing_ = false;
    clock_.Pause();
    start_time_ticks_ = base::TimeTicks();
    OnPlaybackComplete();
  }
}

void MediaSourcePlayer::ClearDecodingData() {
  DVLOG(1) << "ClearDecodingData()";
  if (audio_decoder_job_)
    audio_decoder_job_->Flush();
  if (video_decoder_job_)
    video_decoder_job_->Flush();
  start_time_ticks_ = base::TimeTicks();
  received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
  received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
  audio_access_unit_index_ = 0;
  video_access_unit_index_ = 0;
  waiting_for_audio_data_ = false;
  waiting_for_video_data_ = false;
}

bool MediaSourcePlayer::HasVideo() {
  return kUnknownVideoCodec != video_codec_;
}

bool MediaSourcePlayer::HasAudio() {
  return kUnknownAudioCodec != audio_codec_;
}

void MediaSourcePlayer::ConfigureAudioDecoderJob() {
  if (!HasAudio()) {
    audio_decoder_job_.reset();
    return;
  }

  // Create audio decoder job only if config changes.
  if (audio_decoder_job_ && !reconfig_audio_decoder_)
    return;

  base::android::ScopedJavaLocalRef<jobject> media_codec;
  if (is_audio_encrypted_) {
    if (drm_bridge_) {
      media_codec = drm_bridge_->GetMediaCrypto();
      // TODO(qinmin): currently we assume MediaCrypto is available whenever
      // MediaDrmBridge is constructed. This will change if we want to support
      // more general uses cases of EME.
      DCHECK(!media_codec.is_null());
    } else {
      // Don't create the decoder job if |drm_bridge_| is not set,
      // so StartInternal() will not proceed.
      LOG(INFO) << "MediaDrmBridge is not available when creating decoder "
                << "for encrypted audio stream.";
      return;
    }
  }

  audio_decoder_job_.reset(AudioDecoderJob::Create(
      audio_codec_, sampling_rate_, num_channels_, &audio_extra_data_[0],
      audio_extra_data_.size(), media_codec.obj()));

  if (audio_decoder_job_) {
    SetVolumeInternal();
    reconfig_audio_decoder_ =  false;
  }
}

void MediaSourcePlayer::ConfigureVideoDecoderJob() {
  if (!HasVideo() || surface_.IsEmpty()) {
    video_decoder_job_.reset();
    return;
  }

  // Create video decoder job only if config changes.
  if (video_decoder_job_ && !reconfig_video_decoder_)
    return;

  base::android::ScopedJavaLocalRef<jobject> media_codec;
  if (is_video_encrypted_) {
    if (drm_bridge_) {
      media_codec = drm_bridge_->GetMediaCrypto();
      DCHECK(!media_codec.is_null());
    } else {
      LOG(INFO) << "MediaDrmBridge is not available when creating decoder "
                << "for encrypted video stream.";
      return;
    }
  }

  // Release the old VideoDecoderJob first so the surface can get released.
  // Android does not allow 2 MediaCodec instances use the same surface.
  video_decoder_job_.reset();
  // Create the new VideoDecoderJob.
  video_decoder_job_.reset(VideoDecoderJob::Create(
      video_codec_, gfx::Size(width_, height_), surface_.j_surface().obj(),
      media_codec.obj()));
  if (video_decoder_job_)
    reconfig_video_decoder_ = false;

  // Inform the fullscreen view the player is ready.
  // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way
  // to inform ContentVideoView.
  OnMediaMetadataChanged(duration_, width_, height_, true);
}

void MediaSourcePlayer::OnDecoderStarved() {
  sync_decoder_jobs_ = true;
}

void MediaSourcePlayer::StartStarvationCallback(
    const base::TimeDelta& timeout) {
  decoder_starvation_callback_.Reset(
      base::Bind(&MediaSourcePlayer::OnDecoderStarved,
                 weak_this_.GetWeakPtr()));
  base::MessageLoop::current()->PostDelayedTask(
      FROM_HERE, decoder_starvation_callback_.callback(), timeout);
}

void MediaSourcePlayer::SyncAndStartDecoderJobs() {
  // For streams with both audio and video, send the request for video too.
  // However, don't wait for the response so that we won't have lots of
  // noticeable pauses in the audio. Video will sync with audio by itself.
  if (HasVideo() && !HasVideoData()) {
    RequestVideoData();
    if (!HasAudio())
      return;
  }
  if (HasAudio() && !HasAudioData()) {
    RequestAudioData();
    return;
  }
  start_time_ticks_ = base::TimeTicks::Now();
  start_presentation_timestamp_ = GetCurrentTime();
  if (!clock_.IsPlaying())
    clock_.Play();
  if (HasAudioData() && !audio_decoder_job_->is_decoding())
    DecodeMoreAudio();
  if (HasVideoData() && !video_decoder_job_->is_decoding())
    DecodeMoreVideo();
  sync_decoder_jobs_ = false;
}

void MediaSourcePlayer::RequestAudioData() {
  DVLOG(2) << "RequestAudioData()";
  DCHECK(HasAudio());

  if (waiting_for_audio_data_)
    return;

  manager()->OnReadFromDemuxer(player_id(), DemuxerStream::AUDIO);
  received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
  audio_access_unit_index_ = 0;
  waiting_for_audio_data_ = true;
}

void MediaSourcePlayer::RequestVideoData() {
  DVLOG(2) << "RequestVideoData()";
  DCHECK(HasVideo());
  if (waiting_for_video_data_)
    return;

  manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO);
  received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
  video_access_unit_index_ = 0;
  waiting_for_video_data_ = true;
}

bool MediaSourcePlayer::HasAudioData() const {
  return audio_access_unit_index_ < received_audio_.access_units.size();
}

bool MediaSourcePlayer::HasVideoData() const {
  return video_access_unit_index_ < received_video_.access_units.size();
}

void MediaSourcePlayer::SetVolumeInternal() {
  if (audio_decoder_job_ && volume_ >= 0)
    audio_decoder_job_.get()->SetVolume(volume_);
}

}  // namespace media
