// 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 (audio_renderer_sink) {
    filter_collection_->AddAudioRenderer(ShellAudioRenderer::Create(
        audio_renderer_sink, set_decryptor_ready_cb, pipeline_message_loop));
  }

  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,
    scoped_ptr<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.Pass());

  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();
  }
  return NULL;
}

void WebMediaPlayerImpl::PutCurrentFrame(
    const scoped_refptr<VideoFrame>& video_frame) {
  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_->SetDecodeToTextureOutputMode(client_->PreferDecodeToTexture());
  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
