// Copyright 2014 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/mojo/services/mojo_renderer_service.h" #include "base/bind.h" #include "base/memory/scoped_vector.h" #include "media/audio/null_audio_sink.h" #include "media/base/audio_decoder.h" #include "media/base/audio_renderer.h" #include "media/base/audio_renderer_sink.h" #include "media/base/decryptor.h" #include "media/base/media_log.h" #include "media/filters/audio_renderer_impl.h" #include "media/mojo/services/mojo_demuxer_stream_adapter.h" #include "mojo/application/application_runner_chromium.h" #include "mojo/public/c/system/main.h" #include "mojo/public/cpp/application/application_connection.h" #include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/interface_factory_impl.h" namespace media { class MojoRendererApplication : public mojo::ApplicationDelegate, public mojo::InterfaceFactory<mojo::MediaRenderer> { public: // mojo::ApplicationDelegate implementation. virtual bool ConfigureIncomingConnection( mojo::ApplicationConnection* connection) OVERRIDE { connection->AddService(this); return true; } // mojo::InterfaceFactory<mojo::MediaRenderer> implementation. virtual void Create( mojo::ApplicationConnection* connection, mojo::InterfaceRequest<mojo::MediaRenderer> request) OVERRIDE { mojo::BindToRequest(new MojoRendererService(connection), &request); } }; MojoRendererService::MojoRendererService( mojo::ApplicationConnection* connection) : hardware_config_(AudioParameters(), AudioParameters()), weak_factory_(this), weak_this_(weak_factory_.GetWeakPtr()) { scoped_refptr<base::SingleThreadTaskRunner> runner( base::MessageLoop::current()->task_runner()); scoped_refptr<MediaLog> media_log(new MediaLog()); audio_renderer_.reset(new AudioRendererImpl( runner, // TODO(tim): We should use |connection| passed to MojoRendererService // to connect to a MojoAudioRendererSink implementation that we would // wrap in an AudioRendererSink and pass in here. new NullAudioSink(runner), // TODO(tim): Figure out how to select decoders. ScopedVector<AudioDecoder>(), // TODO(tim): Not needed for now? SetDecryptorReadyCB(), hardware_config_, media_log)); } MojoRendererService::~MojoRendererService() { } void MojoRendererService::Initialize(mojo::DemuxerStreamPtr stream, const mojo::Callback<void()>& callback) { DCHECK(client()); stream_.reset(new MojoDemuxerStreamAdapter( stream.Pass(), base::Bind(&MojoRendererService::OnStreamReady, weak_this_))); init_cb_ = callback; } void MojoRendererService::Flush(const mojo::Callback<void()>& callback) { NOTIMPLEMENTED(); } void MojoRendererService::StartPlayingFrom(int64_t time_delta_usec) { NOTIMPLEMENTED(); } void MojoRendererService::SetPlaybackRate(float playback_rate) { NOTIMPLEMENTED(); } void MojoRendererService::SetVolume(float volume) { NOTIMPLEMENTED(); } void MojoRendererService::OnStreamReady() { audio_renderer_->Initialize( stream_.get(), base::Bind(&MojoRendererService::OnAudioRendererInitializeDone, weak_this_), base::Bind(&MojoRendererService::OnUpdateStatistics, weak_this_), base::Bind(&MojoRendererService::OnBufferingStateChanged, weak_this_), base::Bind(&MojoRendererService::OnAudioRendererEnded, weak_this_), base::Bind(&MojoRendererService::OnError, weak_this_)); } void MojoRendererService::OnAudioRendererInitializeDone(PipelineStatus status) { if (status != PIPELINE_OK) { audio_renderer_.reset(); client()->OnError(); } init_cb_.Run(); } void MojoRendererService::OnUpdateStatistics(const PipelineStatistics& stats) { NOTIMPLEMENTED(); } void MojoRendererService::OnAudioTimeUpdate(base::TimeDelta time, base::TimeDelta max_time) { client()->OnTimeUpdate(time.InMicroseconds(), max_time.InMicroseconds()); } void MojoRendererService::OnBufferingStateChanged( media::BufferingState new_buffering_state) { client()->OnBufferingStateChange( static_cast<mojo::BufferingState>(new_buffering_state)); } void MojoRendererService::OnAudioRendererEnded() { client()->OnEnded(); } void MojoRendererService::OnError(PipelineStatus error) { client()->OnError(); } } // namespace media MojoResult MojoMain(MojoHandle shell_handle) { mojo::ApplicationRunnerChromium runner(new media::MojoRendererApplication); return runner.Run(shell_handle); }