Home | History | Annotate | Download | only in services
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/mojo/services/mojo_renderer_impl.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback_helpers.h"
      9 #include "base/single_thread_task_runner.h"
     10 #include "media/base/demuxer_stream_provider.h"
     11 #include "media/mojo/services/mojo_demuxer_stream_impl.h"
     12 #include "mojo/public/cpp/application/connect.h"
     13 #include "mojo/public/cpp/bindings/interface_impl.h"
     14 #include "mojo/public/interfaces/application/service_provider.mojom.h"
     15 
     16 namespace media {
     17 
     18 MojoRendererImpl::MojoRendererImpl(
     19     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     20     DemuxerStreamProvider* demuxer_stream_provider,
     21     mojo::ServiceProvider* audio_renderer_provider)
     22     : task_runner_(task_runner),
     23       demuxer_stream_provider_(demuxer_stream_provider),
     24       weak_factory_(this) {
     25   // For now we only support audio and there must be a provider.
     26   DCHECK(audio_renderer_provider);
     27   mojo::ConnectToService(audio_renderer_provider, &remote_audio_renderer_);
     28   remote_audio_renderer_.set_client(this);
     29 }
     30 
     31 MojoRendererImpl::~MojoRendererImpl() {
     32   DCHECK(task_runner_->BelongsToCurrentThread());
     33   // Connection to |remote_audio_renderer_| will error-out here.
     34 }
     35 
     36 void MojoRendererImpl::Initialize(const base::Closure& init_cb,
     37                                   const StatisticsCB& statistics_cb,
     38                                   const base::Closure& ended_cb,
     39                                   const PipelineStatusCB& error_cb,
     40                                   const BufferingStateCB& buffering_state_cb) {
     41   DCHECK(task_runner_->BelongsToCurrentThread());
     42   init_cb_ = init_cb;
     43   ended_cb_ = ended_cb;
     44   error_cb_ = error_cb;
     45   buffering_state_cb_ = buffering_state_cb;
     46 
     47   // Create a mojo::DemuxerStream and bind its lifetime to the pipe.
     48   mojo::DemuxerStreamPtr demuxer_stream;
     49   mojo::BindToProxy(
     50       new MojoDemuxerStreamImpl(
     51           demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO)),
     52       &demuxer_stream);
     53   remote_audio_renderer_->Initialize(demuxer_stream.Pass(), init_cb);
     54 }
     55 
     56 void MojoRendererImpl::Flush(const base::Closure& flush_cb) {
     57   DCHECK(task_runner_->BelongsToCurrentThread());
     58   remote_audio_renderer_->Flush(flush_cb);
     59 }
     60 
     61 void MojoRendererImpl::StartPlayingFrom(base::TimeDelta time) {
     62   DCHECK(task_runner_->BelongsToCurrentThread());
     63   remote_audio_renderer_->StartPlayingFrom(time.InMicroseconds());
     64 }
     65 
     66 void MojoRendererImpl::SetPlaybackRate(float playback_rate) {
     67   DCHECK(task_runner_->BelongsToCurrentThread());
     68   remote_audio_renderer_->SetPlaybackRate(playback_rate);
     69 }
     70 
     71 void MojoRendererImpl::SetVolume(float volume) {
     72   DCHECK(task_runner_->BelongsToCurrentThread());
     73   remote_audio_renderer_->SetVolume(volume);
     74 }
     75 
     76 base::TimeDelta MojoRendererImpl::GetMediaTime() {
     77   NOTIMPLEMENTED();
     78   return base::TimeDelta();
     79 }
     80 
     81 bool MojoRendererImpl::HasAudio() {
     82   DCHECK(task_runner_->BelongsToCurrentThread());
     83   DCHECK(remote_audio_renderer_.get());  // We always bind the renderer.
     84   return true;
     85 }
     86 
     87 bool MojoRendererImpl::HasVideo() {
     88   DCHECK(task_runner_->BelongsToCurrentThread());
     89   return false;
     90 }
     91 
     92 void MojoRendererImpl::SetCdm(MediaKeys* cdm) {
     93   DCHECK(task_runner_->BelongsToCurrentThread());
     94   NOTIMPLEMENTED();
     95 }
     96 
     97 void MojoRendererImpl::OnTimeUpdate(int64_t time_usec, int64_t max_time_usec) {
     98   DCHECK(task_runner_->BelongsToCurrentThread());
     99   NOTIMPLEMENTED();
    100 }
    101 
    102 void MojoRendererImpl::OnBufferingStateChange(mojo::BufferingState state) {
    103   DCHECK(task_runner_->BelongsToCurrentThread());
    104   buffering_state_cb_.Run(static_cast<media::BufferingState>(state));
    105 }
    106 
    107 void MojoRendererImpl::OnEnded() {
    108   DCHECK(task_runner_->BelongsToCurrentThread());
    109   ended_cb_.Run();
    110 }
    111 
    112 void MojoRendererImpl::OnError() {
    113   DCHECK(task_runner_->BelongsToCurrentThread());
    114   // TODO(tim): Should we plumb error code from remote renderer?
    115   // http://crbug.com/410451.
    116   if (init_cb_.is_null())  // We have initialized already.
    117     error_cb_.Run(PIPELINE_ERROR_DECODE);
    118   else
    119     error_cb_.Run(PIPELINE_ERROR_COULD_NOT_RENDER);
    120 }
    121 
    122 void MojoRendererImpl::OnInitialized() {
    123   DCHECK(!init_cb_.is_null());
    124   base::ResetAndReturn(&init_cb_).Run();
    125 }
    126 
    127 }  // namespace media
    128