// 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 "cobalt/media/player/web_media_player_impl.h"

#include <math.h>

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

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/media/base/bind_to_current_loop.h"
#include "cobalt/media/base/drm_system.h"
#include "cobalt/media/base/limits.h"
#include "cobalt/media/base/media_log.h"
#include "cobalt/media/filters/chunk_demuxer.h"
#include "cobalt/media/filters/shell_demuxer.h"
#include "cobalt/media/player/web_media_player_proxy.h"
#include "starboard/double.h"
#include "starboard/types.h"

namespace cobalt {
namespace media {

namespace {

// Used to ensure that there is no more than one instance of WebMediaPlayerImpl.
WebMediaPlayerImpl* s_instance;

// 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 WebMediaPlayerImpl* wmpi, double position) {
  float duration = wmpi->GetDuration();
  if (SbDoubleIsFinite(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

#define BIND_TO_RENDER_LOOP(function) \
  BindToCurrentLoop(base::Bind(function, AsWeakPtr()))

#define BIND_TO_RENDER_LOOP_2(function, arg1, arg2) \
  BindToCurrentLoop(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&,
                            std::unique_ptr<uint8[]>, int)>
    OnNeedKeyCB;

WebMediaPlayerImpl::WebMediaPlayerImpl(
    PipelineWindow window,
    const Pipeline::GetDecodeTargetGraphicsContextProviderFunc&
        get_decode_target_graphics_context_provider_func,
    WebMediaPlayerClient* client, WebMediaPlayerDelegate* delegate,
    DecoderBuffer::Allocator* buffer_allocator, bool allow_resume_after_suspend,
    const scoped_refptr<MediaLog>& media_log)
    : pipeline_thread_("media_pipeline"),
      network_state_(WebMediaPlayer::kNetworkStateEmpty),
      ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
      main_loop_(base::MessageLoop::current()),
      client_(client),
      delegate_(delegate),
      buffer_allocator_(buffer_allocator),
      allow_resume_after_suspend_(allow_resume_after_suspend),
      proxy_(new WebMediaPlayerProxy(main_loop_->task_runner(), this)),
      media_log_(media_log),
      incremented_externally_allocated_memory_(false),
      is_local_source_(false),
      supports_save_(true),
      suppress_destruction_errors_(false),
      drm_system_(NULL) {
  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::WebMediaPlayerImpl");

  video_frame_provider_ = new VideoFrameProvider();

  DLOG_IF(ERROR, s_instance)
      << "More than one WebMediaPlayerImpl has been created.";
  s_instance = this;

  DCHECK(buffer_allocator_);
  media_log_->AddEvent(
      media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));

  pipeline_thread_.Start();
  pipeline_ = Pipeline::Create(window, pipeline_thread_.task_runner(),
                               get_decode_target_graphics_context_provider_func,
                               allow_resume_after_suspend_, media_log_.get(),
                               video_frame_provider_.get());

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

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

WebMediaPlayerImpl::~WebMediaPlayerImpl() {
  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::~WebMediaPlayerImpl");

  DCHECK(!main_loop_ || main_loop_ == base::MessageLoop::current());

  DLOG_IF(ERROR, s_instance != this)
      << "More than one WebMediaPlayerImpl has been created.";
  s_instance = NULL;

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

  Destroy();
  progressive_demuxer_.reset();
  chunk_demuxer_.reset();

  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);
  }
  pipeline_thread_.Stop();
}

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

#if SB_HAS(PLAYER_WITH_URL)
void WebMediaPlayerImpl::LoadUrl(const GURL& url) {
  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::LoadUrl");
  DCHECK_EQ(main_loop_, base::MessageLoop::current());

  UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url), kMaxURLScheme);
  DLOG(INFO) << "Start URL playback";

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

  // TODO: Set networkState to WebMediaPlayer::kNetworkStateIdle on stop.
  SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
  SetReadyState(WebMediaPlayer::kReadyStateHaveNothing);
  media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));

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

  StartPipeline(url);
}
#endif  // SB_HAS(PLAYER_WITH_URL)

void WebMediaPlayerImpl::LoadMediaSource() {
  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::LoadMediaSource");
  DCHECK_EQ(main_loop_, base::MessageLoop::current());

  DLOG(INFO) << "Start MEDIASOURCE playback";

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

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

  // Media source pipelines can start immediately.
  chunk_demuxer_.reset(new ChunkDemuxer(
      buffer_allocator_,
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
      BIND_TO_RENDER_LOOP(
          &WebMediaPlayerImpl::OnEncryptedMediaInitDataEncountered),
      media_log_, true));

  supports_save_ = false;
  state_.is_media_source = true;
  StartPipeline(chunk_demuxer_.get());
}

void WebMediaPlayerImpl::LoadProgressive(
    const GURL& url, std::unique_ptr<BufferedDataSource> data_source) {
  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::LoadProgressive");
  DCHECK_EQ(main_loop_, base::MessageLoop::current());

  UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url), kMaxURLScheme);
  DLOG(INFO) << "Start PROGRESSIVE playback";

  // 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()));

  data_source->SetDownloadingStatusCB(
      base::Bind(&WebMediaPlayerImpl::OnDownloadingStatusChanged, AsWeakPtr()));
  proxy_->set_data_source(std::move(data_source));

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

  progressive_demuxer_.reset(
      new ShellDemuxer(pipeline_thread_.task_runner(), buffer_allocator_,
                       proxy_->data_source(), media_log_));

  state_.is_progressive = true;
  StartPipeline(progressive_demuxer_.get());
}

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

void WebMediaPlayerImpl::Play() {
  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::Play");

  DCHECK_EQ(main_loop_, base::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_, base::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_, base::MessageLoop::current());
  return true;
}

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

void WebMediaPlayerImpl::Seek(float seconds) {
  DCHECK_EQ(main_loop_, base::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(ConvertSecondsToTimestamp(seconds));
    }
    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(seek_time);
  }

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

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

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

void WebMediaPlayerImpl::SetRate(float rate) {
  DCHECK_EQ(main_loop_, base::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_, base::MessageLoop::current());

  pipeline_->SetVolume(volume);
}

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

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

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

  return pipeline_->HasVideo();
}

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

  return pipeline_->HasAudio();
}

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

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

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

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

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

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

  return state_.seeking;
}

float WebMediaPlayerImpl::GetDuration() const {
  DCHECK_EQ(main_loop_, base::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());
}

#if SB_HAS(PLAYER_WITH_URL)
base::Time WebMediaPlayerImpl::GetStartDate() const {
  DCHECK_EQ(main_loop_, base::MessageLoop::current());

  if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
    return base::Time();

  base::TimeDelta start_date = pipeline_->GetMediaStartDate();

  return base::Time::FromSbTime(start_date.InMicroseconds());
}
#endif  // SB_HAS(PLAYER_WITH_URL)

float WebMediaPlayerImpl::GetCurrentTime() const {
  DCHECK_EQ(main_loop_, base::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_, base::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_, base::MessageLoop::current());
  return network_state_;
}

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

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

float WebMediaPlayerImpl::GetMaxTimeSeekable() const {
  DCHECK_EQ(main_loop_, base::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_, base::MessageLoop::current());
  return pipeline_->DidLoadingProgress();
}

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

WebMediaPlayer::PlayerStatistics WebMediaPlayerImpl::GetStatistics() const {
  DCHECK_EQ(main_loop_, base::MessageLoop::current());

  PlayerStatistics statistics;
  PipelineStatistics pipeline_stats = pipeline_->GetStatistics();
  statistics.audio_bytes_decoded = pipeline_stats.audio_bytes_decoded;
  statistics.video_bytes_decoded = pipeline_stats.video_bytes_decoded;
  statistics.video_frames_decoded = pipeline_stats.video_frames_decoded;
  statistics.video_frames_dropped = pipeline_stats.video_frames_dropped;
  return statistics;
}

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

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

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::SetDrmSystem(
    const scoped_refptr<media::DrmSystem>& drm_system) {
  DCHECK_EQ(static_cast<DrmSystem*>(NULL), drm_system_.get());
  DCHECK_NE(static_cast<DrmSystem*>(NULL), drm_system.get());

  drm_system_ = drm_system;
  if (!drm_system_ready_cb_.is_null()) {
    drm_system_ready_cb_.Run(drm_system_->wrapped_drm_system());
  }
}

void WebMediaPlayerImpl::SetDrmSystemReadyCB(
    const DrmSystemReadyCB& drm_system_ready_cb) {
  drm_system_ready_cb_ = drm_system_ready_cb;
  if (drm_system_) {
    drm_system_ready_cb_.Run(drm_system_->wrapped_drm_system());
  }
}

void WebMediaPlayerImpl::OnPipelineSeek(PipelineStatus status,
                                        bool is_initial_preroll) {
  DCHECK_EQ(main_loop_, base::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, "Failed pipeline seek.");
    return;
  }

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

  if (is_initial_preroll) {
    const bool kEosPlayed = false;
    GetClient()->TimeChanged(kEosPlayed);
  }
}

void WebMediaPlayerImpl::OnPipelineEnded(PipelineStatus status) {
  DCHECK_EQ(main_loop_, base::MessageLoop::current());
  if (status != PIPELINE_OK) {
    OnPipelineError(status, "Failed pipeline end.");
    return;
  }

  const bool kEosPlayed = true;
  GetClient()->TimeChanged(kEosPlayed);
}

void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error,
                                         const std::string& message) {
  DCHECK_EQ(main_loop_, base::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.
    SetNetworkError(WebMediaPlayer::kNetworkStateFormatError,
                    "Ready state have nothing.");
    return;
  }

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

    case PIPELINE_ERROR_NETWORK:
      SetNetworkError(WebMediaPlayer::kNetworkStateNetworkError,
                      message.empty() ? "Pipeline network error." : message);
      break;
    case PIPELINE_ERROR_READ:
      SetNetworkError(WebMediaPlayer::kNetworkStateNetworkError,
                      message.empty() ? "Pipeline read error." : message);
      break;
    case CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR:
      SetNetworkError(
          WebMediaPlayer::kNetworkStateNetworkError,
          message.empty() ? "Chunk demuxer eos network error." : message);
      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:
      SetNetworkError(
          WebMediaPlayer::kNetworkStateFormatError,
          message.empty() ? "Pipeline initialization failed." : message);
      break;
    case PIPELINE_ERROR_COULD_NOT_RENDER:
      SetNetworkError(WebMediaPlayer::kNetworkStateFormatError,
                      message.empty() ? "Pipeline could not render." : message);
      break;
    case PIPELINE_ERROR_EXTERNAL_RENDERER_FAILED:
      SetNetworkError(
          WebMediaPlayer::kNetworkStateFormatError,
          message.empty() ? "Pipeline extenrnal renderer failed." : message);
      break;
    case DEMUXER_ERROR_COULD_NOT_OPEN:
      SetNetworkError(WebMediaPlayer::kNetworkStateFormatError,
                      message.empty() ? "Demuxer could not open." : message);
      break;
    case DEMUXER_ERROR_COULD_NOT_PARSE:
      SetNetworkError(WebMediaPlayer::kNetworkStateFormatError,
                      message.empty() ? "Demuxer could not parse." : message);
      break;
    case DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
      SetNetworkError(
          WebMediaPlayer::kNetworkStateFormatError,
          message.empty() ? "Demuxer no supported streams." : message);
      break;
    case DECODER_ERROR_NOT_SUPPORTED:
      SetNetworkError(WebMediaPlayer::kNetworkStateFormatError,
                      message.empty() ? "Decoder not supported." : message);
      break;

    case PIPELINE_ERROR_DECODE:
      SetNetworkError(WebMediaPlayer::kNetworkStateDecodeError,
                      message.empty() ? "Pipeline decode error." : message);
      break;
    case PIPELINE_ERROR_ABORT:
      SetNetworkError(WebMediaPlayer::kNetworkStateDecodeError,
                      message.empty() ? "Pipeline abort." : message);
      break;
    case PIPELINE_ERROR_INVALID_STATE:
      SetNetworkError(WebMediaPlayer::kNetworkStateDecodeError,
                      message.empty() ? "Pipeline invalid state." : message);
      break;
    case CHUNK_DEMUXER_ERROR_APPEND_FAILED:
      SetNetworkError(
          WebMediaPlayer::kNetworkStateDecodeError,
          message.empty() ? "Chunk demuxer append failed." : message);
      break;
    case CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR:
      SetNetworkError(
          WebMediaPlayer::kNetworkStateDecodeError,
          message.empty() ? "Chunk demuxer eos decode error." : message);
      break;
    case AUDIO_RENDERER_ERROR:
      SetNetworkError(WebMediaPlayer::kNetworkStateDecodeError,
                      message.empty() ? "Audio renderer error." : message);
      break;
    case AUDIO_RENDERER_ERROR_SPLICE_FAILED:
      SetNetworkError(
          WebMediaPlayer::kNetworkStateDecodeError,
          message.empty() ? "Audio renderer splice failed." : message);
      break;
    case PLAYBACK_CAPABILITY_CHANGED:
      SetNetworkError(WebMediaPlayer::kNetworkStateCapabilityChangedError,
                      message.empty() ? "Capability changed." : message);
      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() {
  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::OnDemuxerOpened");
  DCHECK_EQ(main_loop_, base::MessageLoop::current());
  DCHECK(chunk_demuxer_);

  GetClient()->SourceOpened(chunk_demuxer_.get());
}

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

  GetClient()->SetOpaque(opaque);
}

void WebMediaPlayerImpl::OnDownloadingStatusChanged(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));
}

#if SB_HAS(PLAYER_WITH_URL)
void WebMediaPlayerImpl::StartPipeline(const GURL& url) {
  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::StartPipeline");

  state_.starting = true;

  pipeline_->SetDecodeToTextureOutputMode(client_->PreferDecodeToTexture());
  pipeline_->Start(
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetDrmSystemReadyCB),
      BIND_TO_RENDER_LOOP(
          &WebMediaPlayerImpl::OnEncryptedMediaInitDataEncountered),
      url.spec(), 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),
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOutputModeChanged),
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnContentSizeChanged));
}
#endif  // SB_HAS(PLAYER_WITH_URL)
void WebMediaPlayerImpl::StartPipeline(Demuxer* demuxer) {
  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::StartPipeline");

  state_.starting = true;

  pipeline_->SetDecodeToTextureOutputMode(client_->PreferDecodeToTexture());
  pipeline_->Start(
      demuxer, BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetDrmSystemReadyCB),
      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),
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOutputModeChanged),
      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnContentSizeChanged),
      GetClient()->MaxVideoCapabilities());
}

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

void WebMediaPlayerImpl::SetNetworkError(WebMediaPlayer::NetworkState state,
                                         const std::string& message) {
  DCHECK_EQ(main_loop_, base::MessageLoop::current());
  DVLOG(1) << "SetNetworkError: " << state << " message: " << message;
  network_state_ = state;
  // Always notify to ensure client has the latest value.
  GetClient()->NetworkError(message);
}

void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
  DCHECK_EQ(main_loop_, base::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() {
  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::Destroy");

  DCHECK(!main_loop_ || main_loop_ == base::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(!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();
  }

  // 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(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                             base::WaitableEvent::InitialState::NOT_SIGNALED);
  DLOG(INFO) << "Trying to stop media pipeline.";
  pipeline_->Stop(
      base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
  waiter.Wait();
  DLOG(INFO) << "Media pipeline stopped.";

  // 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;
}

void WebMediaPlayerImpl::OnEncryptedMediaInitDataEncountered(
    EmeInitDataType init_data_type, const std::vector<uint8_t>& init_data) {
  DCHECK_EQ(main_loop_, base::MessageLoop::current());

  GetClient()->EncryptedMediaInitDataEncountered(init_data_type, &init_data[0],
                                                 init_data.size());
}

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

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

  GetClient()->DurationChanged();
}

void WebMediaPlayerImpl::OnOutputModeChanged() {
  GetClient()->OutputModeChanged();
}

void WebMediaPlayerImpl::OnContentSizeChanged() {
  GetClient()->ContentSizeChanged();
}

}  // namespace media
}  // namespace cobalt
