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