// Copyright (c) 2012 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/player/web_media_player_impl.h"

#include <math.h>

#include <limits>
#include <string>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/float_util.h"
#include "base/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "media/audio/shell_audio_sink.h"
#include "media/base/bind_to_loop.h"
#include "media/base/filter_collection.h"
#include "media/base/limits.h"
#include "media/base/media_log.h"
#include "media/base/video_frame.h"
#include "media/filters/chunk_demuxer.h"
#include "media/filters/shell_audio_renderer.h"
#include "media/filters/shell_demuxer.h"
#include "media/filters/video_renderer_base.h"
#include "media/player/web_media_player_proxy.h"

namespace {

// Limits the range of playback rate.
//
// TODO(kylep): Revisit these.
//
// Vista has substantially lower performance than XP or Windows7.  If you speed
// up a video too much, it can't keep up, and rendering stops updating except on
// the time bar. For really high speeds, audio becomes a bottleneck and we just
// use up the data we have, which may not achieve the speed requested, but will
// not crash the tab.
//
// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
// like a busy loop). It gets unresponsive, although its not completely dead.
//
// Also our timers are not very accurate (especially for ogg), which becomes
// evident at low speeds and on Vista. Since other speeds are risky and outside
// the norms, we think 1/16x to 16x is a safe and useful range for now.
const float kMinRate = 0.0625f;
const float kMaxRate = 16.0f;

// Prefix for histograms related to Encrypted Media Extensions.
const char* kMediaEme = "Media.EME.";

#if defined(COBALT_SKIP_SEEK_REQUEST_NEAR_END)
// On some platforms, the underlying media player can hang if we keep seeking to
// a position that is near the end of the video. So we ignore any seeks near the
// end of stream position when the current playback position is also near the
// end of the stream. In this case, "near the end of stream" means "position
// greater than or equal to duration() - kEndOfStreamEpsilonInSeconds".
const double kEndOfStreamEpsilonInSeconds = 2.;

bool IsNearTheEndOfStream(const media::WebMediaPlayerImpl* wmpi,
                          double position) {
  float duration = wmpi->GetDuration();
  if (base::IsFinite(duration)) {
    // If video is very short, we always treat a position as near the end.
    if (duration <= kEndOfStreamEpsilonInSeconds)
      return true;
    if (position >= duration - kEndOfStreamEpsilonInSeconds)
      return true;
  }
  return false;
}
#endif  // defined(COBALT_SKIP_SEEK_REQUEST_NEAR_END)

base::TimeDelta ConvertSecondsToTimestamp(float seconds) {
  float microseconds = seconds * base::Time::kMicrosecondsPerSecond;
  float integer = ceilf(microseconds);
  float difference = integer - microseconds;

  // Round down if difference is large enough.
  if ((microseconds > 0 && difference > 0.5f) ||
      (microseconds <= 0 && difference >= 0.5f)) {
    integer -= 1.0f;
  }

  // Now we can safely cast to int64 microseconds.
  return base::TimeDelta::FromMicroseconds(static_cast<int64>(integer));
}

}  // namespace

namespace media {

#define BIND_TO_RENDER_LOOP(function)          \
  BindToLoop(main_loop_->message_loop_proxy(), \
             base::Bind(function, AsWeakPtr()))

#define BIND_TO_RENDER_LOOP_2(function, arg1, arg2) \
  BindToLoop(main_loop_->message_loop_proxy(),      \
             base::Bind(function, AsWeakPtr(), arg1, arg2))

// TODO(acolwell): Investigate whether the key_system & session_id parameters
// are really necessary.
typedef base::Callback<
    void(const std::string&, const std::string&, scoped_array<uint8>, int)>
    OnNeedKeyCB;

static void LogMediaSourceError(const scoped_refptr<MediaLog>& media_log,
                                const std::string& error) {
  media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
}

WebMediaPlayerImpl::WebMediaPlayerImpl(
    PipelineWindow window,
    WebMediaPlayerClient* client,
    WebMediaPlayerDelegate* delegate,
    const scoped_refptr<ShellVideoFrameProvider>& video_frame_provider,
    scoped_ptr<FilterCollection> collection,
    const scoped_refptr<AudioRendererSink>& audio_renderer_sink,
    scoped_ptr<MessageLoopFactory> message_loop_factory,
    const scoped_refptr<MediaLog>& media_log)
    : network_state_(WebMediaPlayer::kNetworkStateEmpty),
      ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
      main_loop_(MessageLoop::current()),
      filter_collection_(collection.Pass()),
      message_loop_factory_(message_loop_factory.Pass()),
      client_(client),
      delegate_(delegate),
      video_frame_provider_(video_frame_provider),
      proxy_(new WebMediaPlayerProxy(main_loop_->message_loop_proxy(), this)),
      media_log_(media_log),
      incremented_externally_allocated_memory_(false),
      audio_renderer_sink_(audio_renderer_sink),
      is_local_source_(false),
      supports_save_(true),
      suppress_destruction_errors_(false) {
  media_log_->AddEvent(
      media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));

  scoped_refptr<base::MessageLoopProxy> pipeline_message_loop =
      message_loop_factory_->GetMessageLoop(MessageLoopFactory::kPipeline);
  pipeline_ = Pipeline::Create(window, pipeline_message_loop, media_log_);

  // Also we want to be notified of |main_loop_| destruction.
  main_loop_->AddDestructionObserver(this);

  SetDecryptorReadyCB set_decryptor_ready_cb;

  decryptor_.reset(new ProxyDecryptor(proxy_.get()));
  set_decryptor_ready_cb = base::Bind(&ProxyDecryptor::SetDecryptorReadyCB,
                                      base::Unretained(decryptor_.get()));

  // Create default video renderer.
  scoped_refptr<VideoRendererBase> video_renderer = new VideoRendererBase(
      pipeline_message_loop, set_decryptor_ready_cb,
      base::Bind(base::DoNothing),
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetOpaque), true);
  filter_collection_->AddVideoRenderer(video_renderer);
  proxy_->set_frame_provider(video_renderer);

#if defined(COBALT_USE_PUNCHOUT)
  // The size passed to CreatePunchOutFrame is used to pass the natural size of
  // the video to the pipeline. The pipeline already gets the natural size of
  // the video from the underlying player so we set this to gfx::Size() to avoid
  // propagating the frame size through the media stack.
  punch_out_video_frame_ = VideoFrame::CreatePunchOutFrame(gfx::Size());
#else   // defined(COBALT_USE_PUNCHOUT)
  DCHECK(audio_renderer_sink);
  filter_collection_->AddAudioRenderer(ShellAudioRenderer::Create(
      audio_renderer_sink, set_decryptor_ready_cb, pipeline_message_loop));
#endif  // defined(COBALT_USE_PUNCHOUT)

  if (video_frame_provider_) {
    media_time_and_seeking_state_cb_ =
        base::Bind(&WebMediaPlayerImpl::GetMediaTimeAndSeekingState,
                   base::Unretained(this));
    video_frame_provider_->RegisterMediaTimeAndSeekingStateCB(
        media_time_and_seeking_state_cb_);
  }
  if (delegate_) {
    delegate_->RegisterPlayer(this);
  }
}

WebMediaPlayerImpl::~WebMediaPlayerImpl() {
  DCHECK(!main_loop_ || main_loop_ == MessageLoop::current());

  if (delegate_) {
    delegate_->UnregisterPlayer(this);
  }

  if (video_frame_provider_) {
    DCHECK(!media_time_and_seeking_state_cb_.is_null());
    video_frame_provider_->UnregisterMediaTimeAndSeekingStateCB(
        media_time_and_seeking_state_cb_);
    media_time_and_seeking_state_cb_.Reset();
  }

#if defined(__LB_ANDROID__)
  audio_focus_bridge_.AbandonAudioFocus();
#endif  // defined(__LB_ANDROID__)

  decryptor_->DestroySoon();
  Destroy();
  media_log_->AddEvent(
      media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));

  // Finally tell the |main_loop_| we don't want to be notified of destruction
  // event.
  if (main_loop_) {
    main_loop_->RemoveDestructionObserver(this);
  }
}

namespace {

// Helper enum for reporting scheme histograms.
enum URLSchemeForHistogram {
  kUnknownURLScheme,
  kMissingURLScheme,
  kHttpURLScheme,
  kHttpsURLScheme,
  kFtpURLScheme,
  kChromeExtensionURLScheme,
  kJavascriptURLScheme,
  kFileURLScheme,
  kBlobURLScheme,
  kDataURLScheme,
  kFileSystemScheme,
  kMaxURLScheme = kFileSystemScheme  // Must be equal to highest enum value.
};

URLSchemeForHistogram URLScheme(const GURL& url) {
  if (!url.has_scheme())
    return kMissingURLScheme;
  if (url.SchemeIs("http"))
    return kHttpURLScheme;
  if (url.SchemeIs("https"))
    return kHttpsURLScheme;
  if (url.SchemeIs("ftp"))
    return kFtpURLScheme;
  if (url.SchemeIs("chrome-extension"))
    return kChromeExtensionURLScheme;
  if (url.SchemeIs("javascript"))
    return kJavascriptURLScheme;
  if (url.SchemeIs("file"))
    return kFileURLScheme;
  if (url.SchemeIs("blob"))
    return kBlobURLScheme;
  if (url.SchemeIs("data"))
    return kDataURLScheme;
  if (url.SchemeIs("filesystem"))
    return kFileSystemScheme;
  return kUnknownURLScheme;
}

}  // anonymous namespace

void WebMediaPlayerImpl::LoadMediaSource() {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  DCHECK(filter_collection_);

  // Handle any volume changes that occured before load().
  SetVolume(GetClient()->Volume());

  SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
  SetReadyState(WebMediaPlayer::kReadyStateHaveNothing);

  scoped_refptr<base::MessageLoopProxy> message_loop =
      message_loop_factory_->GetMessageLoop(MessageLoopFactory::kPipeline);

  // Media source pipelines can start immediately.
  chunk_demuxer_ = new ChunkDemuxer(
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
      BIND_TO_RENDER_LOOP_2(&WebMediaPlayerImpl::OnNeedKey, "", ""),
      base::Bind(&LogMediaSourceError, media_log_));

  filter_collection_->SetDemuxer(chunk_demuxer_);
  supports_save_ = false;
  state_.is_media_source = true;
  StartPipeline();
}

void WebMediaPlayerImpl::LoadProgressive(
    const GURL& url,
    const scoped_refptr<BufferedDataSource>& data_source,
    CORSMode cors_mode) {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  DCHECK(filter_collection_);

  UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url), kMaxURLScheme);

  // Handle any volume changes that occured before load().
  SetVolume(GetClient()->Volume());

  SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
  SetReadyState(WebMediaPlayer::kReadyStateHaveNothing);
  media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));

  scoped_refptr<base::MessageLoopProxy> message_loop =
      message_loop_factory_->GetMessageLoop(MessageLoopFactory::kPipeline);

  proxy_->set_data_source(data_source);

  is_local_source_ = !url.SchemeIs("http") && !url.SchemeIs("https");

  filter_collection_->SetDemuxer(
      new ShellDemuxer(message_loop, proxy_->data_source()));

  state_.is_progressive = true;
  StartPipeline();
}

void WebMediaPlayerImpl::CancelLoad() {
  DCHECK_EQ(main_loop_, MessageLoop::current());
}

void WebMediaPlayerImpl::Play() {
  DCHECK_EQ(main_loop_, MessageLoop::current());
#if defined(__LB_ANDROID__)
  audio_focus_bridge_.RequestAudioFocus();
#endif  // defined(__LB_ANDROID__)

  state_.paused = false;
  pipeline_->SetPlaybackRate(state_.playback_rate);

  media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
}

void WebMediaPlayerImpl::Pause() {
  DCHECK_EQ(main_loop_, MessageLoop::current());
#if defined(__LB_ANDROID__)
  audio_focus_bridge_.AbandonAudioFocus();
#endif  // defined(__LB_ANDROID__)

  state_.paused = true;
  pipeline_->SetPlaybackRate(0.0f);
  state_.paused_time = pipeline_->GetMediaTime();

  media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
}

bool WebMediaPlayerImpl::SupportsFullscreen() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  return true;
}

bool WebMediaPlayerImpl::SupportsSave() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  return supports_save_;
}

void WebMediaPlayerImpl::Seek(float seconds) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

#if defined(COBALT_SKIP_SEEK_REQUEST_NEAR_END)
  // Ignore any seek request that is near the end of the stream when the
  // current playback position is also near the end of the stream to avoid
  // a hang in the MediaEngine.
  if (IsNearTheEndOfStream(this, GetCurrentTime()) &&
      IsNearTheEndOfStream(this, seconds)) {
    return;
  }
#endif  // defined(COBALT_SKIP_SEEK_REQUEST_NEAR_END)

  if (state_.starting || state_.seeking) {
    state_.pending_seek = true;
    state_.pending_seek_seconds = seconds;
    if (chunk_demuxer_) {
      chunk_demuxer_->CancelPendingSeek();
      decryptor_->CancelDecrypt(Decryptor::kAudio);
      decryptor_->CancelDecrypt(Decryptor::kVideo);
    }
    return;
  }

  media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));

  base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);

  // Update our paused time.
  if (state_.paused)
    state_.paused_time = seek_time;

  state_.seeking = true;

  if (chunk_demuxer_) {
    chunk_demuxer_->StartWaitingForSeek();
    decryptor_->CancelDecrypt(Decryptor::kAudio);
    decryptor_->CancelDecrypt(Decryptor::kVideo);
  }

  // Kick off the asynchronous seek!
  pipeline_->Seek(seek_time,
                  BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek));
}

void WebMediaPlayerImpl::SetEndTime(float seconds) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  // TODO(hclam): add method call when it has been implemented.
  return;
}

void WebMediaPlayerImpl::SetRate(float rate) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  // TODO(kylep): Remove when support for negatives is added. Also, modify the
  // following checks so rewind uses reasonable values also.
  if (rate < 0.0f)
    return;

  // Limit rates to reasonable values by clamping.
  if (rate != 0.0f) {
    if (rate < kMinRate)
      rate = kMinRate;
    else if (rate > kMaxRate)
      rate = kMaxRate;
  }

  state_.playback_rate = rate;
  if (!state_.paused) {
    pipeline_->SetPlaybackRate(rate);
  }
}

void WebMediaPlayerImpl::SetVolume(float volume) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  pipeline_->SetVolume(volume);
}

void WebMediaPlayerImpl::SetVisible(bool visible) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  // TODO(hclam): add appropriate method call when pipeline has it implemented.
  return;
}

bool WebMediaPlayerImpl::GetTotalBytesKnown() {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  return pipeline_->GetTotalBytes() != 0;
}

bool WebMediaPlayerImpl::HasVideo() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  return pipeline_->HasVideo();
}

bool WebMediaPlayerImpl::HasAudio() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  return pipeline_->HasAudio();
}

gfx::Size WebMediaPlayerImpl::GetNaturalSize() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  gfx::Size size;
  pipeline_->GetNaturalVideoSize(&size);
  return size;
}

bool WebMediaPlayerImpl::IsPaused() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  return pipeline_->GetPlaybackRate() == 0.0f;
}

bool WebMediaPlayerImpl::IsSeeking() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
    return false;

  return state_.seeking;
}

float WebMediaPlayerImpl::GetDuration() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
    return std::numeric_limits<float>::quiet_NaN();

  base::TimeDelta duration = pipeline_->GetMediaDuration();

  // Return positive infinity if the resource is unbounded.
  // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
  if (duration == kInfiniteDuration())
    return std::numeric_limits<float>::infinity();

  return static_cast<float>(duration.InSecondsF());
}

float WebMediaPlayerImpl::GetCurrentTime() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  if (state_.paused)
    return static_cast<float>(state_.paused_time.InSecondsF());
  return static_cast<float>(pipeline_->GetMediaTime().InSecondsF());
}

int WebMediaPlayerImpl::GetDataRate() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  // TODO(hclam): Add this method call if pipeline has it in the interface.
  return 0;
}

WebMediaPlayer::NetworkState WebMediaPlayerImpl::GetNetworkState() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  return network_state_;
}

WebMediaPlayer::ReadyState WebMediaPlayerImpl::GetReadyState() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  return ready_state_;
}

const Ranges<base::TimeDelta>& WebMediaPlayerImpl::GetBufferedTimeRanges() {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  buffered_ = pipeline_->GetBufferedTimeRanges();
  return buffered_;
}

float WebMediaPlayerImpl::GetMaxTimeSeekable() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  // We don't support seeking in streaming media.
  if (proxy_ && proxy_->data_source() && proxy_->data_source()->IsStreaming())
    return 0.0f;
  return static_cast<float>(pipeline_->GetMediaDuration().InSecondsF());
}

void WebMediaPlayerImpl::Suspend() {
  pipeline_->Suspend();
}

void WebMediaPlayerImpl::Resume() {
  pipeline_->Resume();
}

bool WebMediaPlayerImpl::DidLoadingProgress() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  return pipeline_->DidLoadingProgress();
}

unsigned long long WebMediaPlayerImpl::GetTotalBytes() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  return pipeline_->GetTotalBytes();
}

bool WebMediaPlayerImpl::HasSingleSecurityOrigin() const {
  if (proxy_)
    return proxy_->HasSingleOrigin();
  return true;
}

bool WebMediaPlayerImpl::DidPassCORSAccessCheck() const {
  return proxy_ && proxy_->DidPassCORSAccessCheck();
}

float WebMediaPlayerImpl::MediaTimeForTimeValue(float timeValue) const {
  return ConvertSecondsToTimestamp(timeValue).InSecondsF();
}

unsigned WebMediaPlayerImpl::GetDecodedFrameCount() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  PipelineStatistics stats = pipeline_->GetStatistics();
  return stats.video_frames_decoded;
}

unsigned WebMediaPlayerImpl::GetDroppedFrameCount() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  PipelineStatistics stats = pipeline_->GetStatistics();
  return stats.video_frames_dropped;
}

unsigned WebMediaPlayerImpl::GetAudioDecodedByteCount() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  PipelineStatistics stats = pipeline_->GetStatistics();
  return stats.audio_bytes_decoded;
}

unsigned WebMediaPlayerImpl::GetVideoDecodedByteCount() const {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  PipelineStatistics stats = pipeline_->GetStatistics();
  return stats.video_bytes_decoded;
}

scoped_refptr<ShellVideoFrameProvider>
WebMediaPlayerImpl::GetVideoFrameProvider() {
  return video_frame_provider_;
}

scoped_refptr<VideoFrame> WebMediaPlayerImpl::GetCurrentFrame() {
  if (video_frame_provider_) {
    return video_frame_provider_->GetCurrentFrame();
  }
#if defined(COBALT_USE_PUNCHOUT)
  // We want to give proxy_ a chance to produce a valid frame before returning
  // the punch out frame
  return punch_out_video_frame_;
#else   // defined(COBALT_USE_PUNCHOUT)
  return NULL;
#endif  // defined(COBALT_USE_PUNCHOUT)
}

void WebMediaPlayerImpl::PutCurrentFrame(
    const scoped_refptr<VideoFrame>& video_frame) {
#if defined(COBALT_USE_PUNCHOUT)
  if (video_frame == punch_out_video_frame_) {
    // This happens when proxy_ returns NULL in getCurrentFrame() so we make
    // sure that it gets a NULL back as well
    proxy_->PutCurrentFrame(NULL);
    return;
  }
#endif  // defined(COBALT_USE_PUNCHOUT)
  if (video_frame) {
    proxy_->PutCurrentFrame(video_frame);
  } else {
    proxy_->PutCurrentFrame(NULL);
  }
}

// TODO: Eliminate the duplicated enums.
#define COMPILE_ASSERT_MATCHING_STATUS_ENUM(player_name, chromium_name) \
  COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::player_name) ==       \
                     static_cast<int>(ChunkDemuxer::chromium_name),     \
                 mismatching_status_enums)
COMPILE_ASSERT_MATCHING_STATUS_ENUM(kAddIdStatusOk, kOk);
COMPILE_ASSERT_MATCHING_STATUS_ENUM(kAddIdStatusNotSupported, kNotSupported);
COMPILE_ASSERT_MATCHING_STATUS_ENUM(kAddIdStatusReachedIdLimit,
                                    kReachedIdLimit);
#undef COMPILE_ASSERT_MATCHING_ENUM

WebMediaPlayer::AddIdStatus WebMediaPlayerImpl::SourceAddId(
    const std::string& id,
    const std::string& type,
    const std::vector<std::string>& codecs) {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  std::vector<std::string> new_codecs(codecs.size());
  for (size_t i = 0; i < codecs.size(); ++i)
    new_codecs[i] = codecs[i];

  return static_cast<WebMediaPlayer::AddIdStatus>(
      chunk_demuxer_->AddId(id, type, new_codecs));
}

bool WebMediaPlayerImpl::SourceRemoveId(const std::string& id) {
  DCHECK(!id.empty());
  chunk_demuxer_->RemoveId(id);
  return true;
}

Ranges<base::TimeDelta> WebMediaPlayerImpl::SourceBuffered(
    const std::string& id) {
  return chunk_demuxer_->GetBufferedRanges(id);
}

bool WebMediaPlayerImpl::SourceAppend(const std::string& id,
                                      const unsigned char* data,
                                      unsigned length) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  float old_duration = GetDuration();
  if (!chunk_demuxer_->AppendData(id, data, length))
    return false;

  if (old_duration != GetDuration())
    GetClient()->DurationChanged();

  return true;
}

bool WebMediaPlayerImpl::SourceAbort(const std::string& id) {
  chunk_demuxer_->Abort(id);
  return true;
}

double WebMediaPlayerImpl::SourceGetDuration() const {
  DCHECK(chunk_demuxer_);
  return chunk_demuxer_->GetDuration();
}

void WebMediaPlayerImpl::SourceSetDuration(double new_duration) {
  DCHECK_GE(new_duration, 0);
  DCHECK(chunk_demuxer_);
  chunk_demuxer_->SetDuration(new_duration);
}

void WebMediaPlayerImpl::SourceEndOfStream(
    WebMediaPlayer::EndOfStreamStatus status) {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  PipelineStatus pipeline_status = PIPELINE_OK;

  switch (status) {
    case WebMediaPlayer::kEndOfStreamStatusNoError:
      break;
    case WebMediaPlayer::kEndOfStreamStatusNetworkError:
      pipeline_status = PIPELINE_ERROR_NETWORK;
      break;
    case WebMediaPlayer::kEndOfStreamStatusDecodeError:
      pipeline_status = PIPELINE_ERROR_DECODE;
      break;
    default:
      NOTIMPLEMENTED();
  }

  float old_duration = GetDuration();
  if (!chunk_demuxer_->EndOfStream(pipeline_status))
    DVLOG(1) << "EndOfStream call failed.";

  if (old_duration != GetDuration())
    GetClient()->DurationChanged();
}

bool WebMediaPlayerImpl::SourceSetTimestampOffset(const std::string& id,
                                                  double offset) {
  base::TimeDelta time_offset = base::TimeDelta::FromMicroseconds(
      offset * base::Time::kMicrosecondsPerSecond);
  return chunk_demuxer_->SetTimestampOffset(id, time_offset);
}

// Helper enum for reporting generateKeyRequest/addKey histograms.
enum MediaKeyException {
  kUnknownResultId,
  kSuccess,
  kKeySystemNotSupported,
  kInvalidPlayerState,
  kMaxMediaKeyException
};

static MediaKeyException MediaKeyExceptionForUMA(
    WebMediaPlayer::MediaKeyException e) {
  switch (e) {
    case WebMediaPlayer::kMediaKeyExceptionKeySystemNotSupported:
      return kKeySystemNotSupported;
    case WebMediaPlayer::kMediaKeyExceptionInvalidPlayerState:
      return kInvalidPlayerState;
    case WebMediaPlayer::kMediaKeyExceptionNoError:
      return kSuccess;
    default:
      return kUnknownResultId;
  }
}

// Helper for converting |key_system| name and exception |e| to a pair of enum
// values from above, for reporting to UMA.
static void ReportMediaKeyExceptionToUMA(const std::string& method,
                                         const std::string& key_system,
                                         WebMediaPlayer::MediaKeyException e) {
  MediaKeyException result_id = MediaKeyExceptionForUMA(e);
  DCHECK_NE(result_id, kUnknownResultId) << e;
  base::LinearHistogram::FactoryGet(
      kMediaEme + KeySystemNameForUMA(key_system) + "." + method, 1,
      kMaxMediaKeyException, kMaxMediaKeyException + 1,
      base::Histogram::kUmaTargetedHistogramFlag)
      ->Add(result_id);
}

WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::GenerateKeyRequest(
    const std::string& key_system,
    const unsigned char* init_data,
    unsigned init_data_length) {
  WebMediaPlayer::MediaKeyException e =
      GenerateKeyRequestInternal(key_system, init_data, init_data_length);
  ReportMediaKeyExceptionToUMA("generateKeyRequest", key_system, e);
  return e;
}

WebMediaPlayer::MediaKeyException
WebMediaPlayerImpl::GenerateKeyRequestInternal(const std::string& key_system,
                                               const unsigned char* init_data,
                                               unsigned init_data_length) {
  if (!IsSupportedKeySystem(key_system))
    return WebMediaPlayer::kMediaKeyExceptionKeySystemNotSupported;

  // We do not support run-time switching between key systems for now.
  if (current_key_system_.empty())
    current_key_system_ = key_system;
  else if (key_system != current_key_system_)
    return WebMediaPlayer::kMediaKeyExceptionInvalidPlayerState;

  DVLOG(1) << "generateKeyRequest: " << key_system << ": "
           << std::string(reinterpret_cast<const char*>(init_data),
                          static_cast<size_t>(init_data_length));

  // TODO(xhwang): We assume all streams are from the same container (thus have
  // the same "type") for now. In the future, the "type" should be passed down
  // from the application.
  if (!decryptor_->GenerateKeyRequest(key_system, init_data_type_, init_data,
                                      init_data_length)) {
    current_key_system_.clear();
    return WebMediaPlayer::kMediaKeyExceptionKeySystemNotSupported;
  }

  return WebMediaPlayer::kMediaKeyExceptionNoError;
}

WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::AddKey(
    const std::string& key_system,
    const unsigned char* key,
    unsigned key_length,
    const unsigned char* init_data,
    unsigned init_data_length,
    const std::string& session_id) {
  WebMediaPlayer::MediaKeyException e = AddKeyInternal(
      key_system, key, key_length, init_data, init_data_length, session_id);
  ReportMediaKeyExceptionToUMA("addKey", key_system, e);
  return e;
}

WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::AddKeyInternal(
    const std::string& key_system,
    const unsigned char* key,
    unsigned key_length,
    const unsigned char* init_data,
    unsigned init_data_length,
    const std::string& session_id) {
  DCHECK(key);
  DCHECK_GT(key_length, 0u);

  if (!IsSupportedKeySystem(key_system))
    return WebMediaPlayer::kMediaKeyExceptionKeySystemNotSupported;

  if (current_key_system_.empty() || key_system != current_key_system_)
    return WebMediaPlayer::kMediaKeyExceptionInvalidPlayerState;

  DVLOG(1) << "addKey: " << key_system << ": "
           << base::HexEncode(key, static_cast<size_t>(key_length)) << ", "
           << base::HexEncode(init_data, static_cast<size_t>(init_data_length))
           << " [" << session_id << "]";

  decryptor_->AddKey(key_system, key, key_length, init_data, init_data_length,
                     session_id);
  return WebMediaPlayer::kMediaKeyExceptionNoError;
}

WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::CancelKeyRequest(
    const std::string& key_system,
    const std::string& session_id) {
  WebMediaPlayer::MediaKeyException e =
      CancelKeyRequestInternal(key_system, session_id);
  ReportMediaKeyExceptionToUMA("cancelKeyRequest", key_system, e);
  return e;
}

WebMediaPlayerImpl::SetBoundsCB WebMediaPlayerImpl::GetSetBoundsCB() {
  // |pipeline_| is always valid during WebMediaPlayerImpl's life time.  It is
  // also reference counted so it lives after WebMediaPlayerImpl is destroyed.
  return pipeline_->GetSetBoundsCB();
}

WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::CancelKeyRequestInternal(
    const std::string& key_system,
    const std::string& session_id) {
  if (!IsSupportedKeySystem(key_system))
    return WebMediaPlayer::kMediaKeyExceptionKeySystemNotSupported;

  if (current_key_system_.empty() || key_system != current_key_system_)
    return WebMediaPlayer::kMediaKeyExceptionInvalidPlayerState;

  decryptor_->CancelKeyRequest(key_system, session_id);
  return WebMediaPlayer::kMediaKeyExceptionNoError;
}

void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() {
  Destroy();
  main_loop_ = NULL;
}

bool WebMediaPlayerImpl::GetDebugReportDataAddress(void** out_address,
                                                   size_t* out_size) {
  *out_address = &state_;
  *out_size = sizeof(state_);
  return true;
}

void WebMediaPlayerImpl::OnPipelineSeek(PipelineStatus status) {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  state_.starting = false;
  state_.seeking = false;
  if (state_.pending_seek) {
    state_.pending_seek = false;
    Seek(state_.pending_seek_seconds);
    return;
  }

  if (status != PIPELINE_OK) {
    OnPipelineError(status);
    return;
  }

  // Update our paused time.
  if (state_.paused)
    state_.paused_time = pipeline_->GetMediaTime();

  GetClient()->TimeChanged();
}

void WebMediaPlayerImpl::OnPipelineEnded(PipelineStatus status) {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  if (status != PIPELINE_OK) {
    OnPipelineError(status);
    return;
  }
  GetClient()->TimeChanged();
}

void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  if (suppress_destruction_errors_)
    return;

  media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error));

  if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing) {
    // Any error that occurs before reaching ReadyStateHaveMetadata should
    // be considered a format error.
    SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
    return;
  }

  switch (error) {
    case PIPELINE_OK:
      NOTREACHED() << "PIPELINE_OK isn't an error!";
      break;

    case PIPELINE_ERROR_NETWORK:
    case PIPELINE_ERROR_READ:
      SetNetworkState(WebMediaPlayer::kNetworkStateNetworkError);
      break;

    // TODO(vrk): Because OnPipelineInitialize() directly reports the
    // NetworkStateFormatError instead of calling OnPipelineError(), I believe
    // this block can be deleted. Should look into it! (crbug.com/126070)
    case PIPELINE_ERROR_INITIALIZATION_FAILED:
    case PIPELINE_ERROR_COULD_NOT_RENDER:
    case PIPELINE_ERROR_URL_NOT_FOUND:
    case DEMUXER_ERROR_COULD_NOT_OPEN:
    case DEMUXER_ERROR_COULD_NOT_PARSE:
    case DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
    case DECODER_ERROR_NOT_SUPPORTED:
      SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
      break;

    case PIPELINE_ERROR_DECODE:
    case PIPELINE_ERROR_ABORT:
    case PIPELINE_ERROR_OPERATION_PENDING:
    case PIPELINE_ERROR_INVALID_STATE:
      SetNetworkState(WebMediaPlayer::kNetworkStateDecodeError);
      break;

    case PIPELINE_ERROR_DECRYPT:
      // Decrypt error.
      base::Histogram::FactoryGet(
          (kMediaEme + KeySystemNameForUMA(current_key_system_) +
           ".DecryptError"),
          1, 1000000, 50, base::Histogram::kUmaTargetedHistogramFlag)
          ->Add(1);
      // TODO(xhwang): Change to use NetworkStateDecryptError once it's added in
      // Webkit (see http://crbug.com/124486).
      SetNetworkState(WebMediaPlayer::kNetworkStateDecodeError);
      break;

    case PIPELINE_STATUS_MAX:
      NOTREACHED() << "PIPELINE_STATUS_MAX isn't a real error!";
      break;
  }
}

void WebMediaPlayerImpl::OnPipelineBufferingState(
    Pipeline::BufferingState buffering_state) {
  DVLOG(1) << "OnPipelineBufferingState(" << buffering_state << ")";

  switch (buffering_state) {
    case Pipeline::kHaveMetadata:
      SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
      break;
    case Pipeline::kPrerollCompleted:
      SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData);
      break;
  }
}

void WebMediaPlayerImpl::OnDemuxerOpened() {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  GetClient()->SourceOpened();
}

void WebMediaPlayerImpl::OnKeyAdded(const std::string& key_system,
                                    const std::string& session_id) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  base::Histogram::FactoryGet(
      kMediaEme + KeySystemNameForUMA(key_system) + ".KeyAdded", 1, 1000000, 50,
      base::Histogram::kUmaTargetedHistogramFlag)
      ->Add(1);

  GetClient()->KeyAdded(key_system, session_id);
}

void WebMediaPlayerImpl::OnNeedKey(const std::string& key_system,
                                   const std::string& session_id,
                                   const std::string& type,
                                   scoped_array<uint8> init_data,
                                   int init_data_size) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  // Do not fire NeedKey event if encrypted media is not enabled.
  if (!decryptor_)
    return;

  UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1);

#if !defined(__LB_SHELL__) && !defined(COBALT)
  DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_);
#endif  // !defined(__LB_SHELL__) && !defined(COBALT)

  if (init_data_type_.empty())
    init_data_type_ = type;

  GetClient()->KeyNeeded(key_system, session_id, init_data.get(),
                         init_data_size);
}

// TODO: Eliminate the duplicated enums.
#define COMPILE_ASSERT_MATCHING_ENUM(name)                       \
  COMPILE_ASSERT(static_cast<int>(WebMediaPlayerClient::name) == \
                     static_cast<int>(Decryptor::name),          \
                 mismatching_enums)
COMPILE_ASSERT_MATCHING_ENUM(kUnknownError);
COMPILE_ASSERT_MATCHING_ENUM(kClientError);
COMPILE_ASSERT_MATCHING_ENUM(kServiceError);
COMPILE_ASSERT_MATCHING_ENUM(kOutputError);
COMPILE_ASSERT_MATCHING_ENUM(kHardwareChangeError);
COMPILE_ASSERT_MATCHING_ENUM(kDomainError);
#undef COMPILE_ASSERT_MATCHING_ENUM

void WebMediaPlayerImpl::OnKeyError(const std::string& key_system,
                                    const std::string& session_id,
                                    Decryptor::KeyError error_code,
                                    int system_code) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  base::LinearHistogram::FactoryGet(
      kMediaEme + KeySystemNameForUMA(key_system) + ".KeyError", 1,
      Decryptor::kMaxKeyError, Decryptor::kMaxKeyError + 1,
      base::Histogram::kUmaTargetedHistogramFlag)
      ->Add(error_code);

  GetClient()->KeyError(
      key_system, session_id,
      static_cast<WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
      system_code);
}

void WebMediaPlayerImpl::OnKeyMessage(const std::string& key_system,
                                      const std::string& session_id,
                                      const std::string& message,
                                      const GURL& default_url) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  GetClient()->KeyMessage(key_system, session_id,
                          reinterpret_cast<const uint8*>(message.data()),
                          message.size(), default_url.spec());
}

void WebMediaPlayerImpl::SetOpaque(bool opaque) {
  DCHECK_EQ(main_loop_, MessageLoop::current());

  GetClient()->SetOpaque(opaque);
}

void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
  if (!is_downloading && network_state_ == WebMediaPlayer::kNetworkStateLoading)
    SetNetworkState(WebMediaPlayer::kNetworkStateIdle);
  else if (is_downloading &&
           network_state_ == WebMediaPlayer::kNetworkStateIdle)
    SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
  media_log_->AddEvent(
      media_log_->CreateBooleanEvent(MediaLogEvent::NETWORK_ACTIVITY_SET,
                                     "is_downloading_data", is_downloading));
}

void WebMediaPlayerImpl::StartPipeline() {
  state_.starting = true;

  SetDecryptorReadyCB set_decryptor_ready_cb;
  if (decryptor_) {
    set_decryptor_ready_cb = base::Bind(&ProxyDecryptor::SetDecryptorReadyCB,
                                        base::Unretained(decryptor_.get()));
  }

  pipeline_->Start(
      filter_collection_.Pass(),
      set_decryptor_ready_cb,
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek),
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState),
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged));
}

void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  DVLOG(1) << "SetNetworkState: " << state;
  network_state_ = state;
  // Always notify to ensure client has the latest value.
  GetClient()->NetworkStateChanged();
}

void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  DVLOG(1) << "SetReadyState: " << state;

  if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing &&
      state >= WebMediaPlayer::kReadyStateHaveMetadata) {
    if (!HasVideo())
      GetClient()->DisableAcceleratedCompositing();
  } else if (state == WebMediaPlayer::kReadyStateHaveEnoughData) {
    if (is_local_source_ &&
        network_state_ == WebMediaPlayer::kNetworkStateLoading) {
      SetNetworkState(WebMediaPlayer::kNetworkStateLoaded);
    }
  }

  ready_state_ = state;
  // Always notify to ensure client has the latest value.
  GetClient()->ReadyStateChanged();
}

void WebMediaPlayerImpl::Destroy() {
  DCHECK(!main_loop_ || main_loop_ == MessageLoop::current());

  // If |main_loop_| has already stopped, do nothing here.
  if (!main_loop_) {
    // This may happen if this function was already called by the
    // DestructionObserver override when the thread running this player was
    // stopped. The pipeline should have been shut down.
    DCHECK(!chunk_demuxer_);
    DCHECK(!message_loop_factory_);
    DCHECK(!proxy_);
    return;
  }

  // Tell the data source to abort any pending reads so that the pipeline is
  // not blocked when issuing stop commands to the other filters.
  suppress_destruction_errors_ = true;
  if (proxy_) {
    proxy_->AbortDataSource();
    if (chunk_demuxer_) {
      chunk_demuxer_->Shutdown();
      chunk_demuxer_ = NULL;
    }
  }

  // Make sure to kill the pipeline so there's no more media threads running.
  // Note: stopping the pipeline might block for a long time.
  base::WaitableEvent waiter(false, false);
  DLOG(INFO) << "Trying to stop media pipeline.";
  pipeline_->Stop(
      base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
  waiter.Wait();
  DLOG(INFO) << "Media pipeline stopped.";

  message_loop_factory_.reset();

  // And then detach the proxy, it may live on the render thread for a little
  // longer until all the tasks are finished.
  if (proxy_) {
    proxy_->Detach();
    proxy_ = NULL;
  }
}

void WebMediaPlayerImpl::GetMediaTimeAndSeekingState(
    base::TimeDelta* media_time,
    bool* is_seeking) const {
  DCHECK(media_time);
  DCHECK(is_seeking);
  *media_time = pipeline_->GetMediaTime();
  *is_seeking = state_.seeking;
}

WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() {
  DCHECK_EQ(main_loop_, MessageLoop::current());
  DCHECK(client_);
  return client_;
}

void WebMediaPlayerImpl::OnDurationChanged() {
  if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
    return;

  GetClient()->DurationChanged();
}

}  // namespace media
