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.
5 #include "media/mojo/services/mojo_renderer_service.h"
8 #include "base/callback_helpers.h"
9 #include "base/memory/scoped_vector.h"
10 #include "media/base/audio_decoder.h"
11 #include "media/base/audio_renderer.h"
12 #include "media/base/audio_renderer_sink.h"
13 #include "media/base/decryptor.h"
14 #include "media/base/media_log.h"
15 #include "media/base/video_renderer.h"
16 #include "media/filters/audio_renderer_impl.h"
17 #include "media/filters/renderer_impl.h"
18 #include "media/filters/video_renderer_impl.h"
19 #include "media/mojo/services/demuxer_stream_provider_shim.h"
20 #include "media/mojo/services/mojo_demuxer_stream_adapter.h"
21 #include "media/mojo/services/renderer_config.h"
22 #include "mojo/application/application_runner_chromium.h"
23 #include "mojo/public/c/system/main.h"
24 #include "mojo/public/cpp/application/application_connection.h"
25 #include "mojo/public/cpp/application/application_delegate.h"
26 #include "mojo/public/cpp/application/interface_factory_impl.h"
30 // Time interval to update media time.
31 const int kTimeUpdateIntervalMs
= 50;
33 static void LogMediaSourceError(const scoped_refptr
<MediaLog
>& media_log
,
34 const std::string
& error
) {
35 media_log
->AddEvent(media_log
->CreateMediaSourceErrorEvent(error
));
38 static void PaintNothing(const scoped_refptr
<VideoFrame
>& frame
) {
41 class MojoRendererApplication
42 : public mojo::ApplicationDelegate
,
43 public mojo::InterfaceFactory
<mojo::MediaRenderer
> {
45 // mojo::ApplicationDelegate implementation.
46 bool ConfigureIncomingConnection(
47 mojo::ApplicationConnection
* connection
) override
{
48 connection
->AddService(this);
52 // mojo::InterfaceFactory<mojo::MediaRenderer> implementation.
53 void Create(mojo::ApplicationConnection
* connection
,
54 mojo::InterfaceRequest
<mojo::MediaRenderer
> request
) override
{
55 mojo::BindToRequest(new MojoRendererService(connection
), &request
);
59 static void MojoTrampoline(const mojo::Closure
& closure
) {
63 MojoRendererService::MojoRendererService(
64 mojo::ApplicationConnection
* connection
)
65 : state_(STATE_UNINITIALIZED
),
66 last_media_time_usec_(0),
68 weak_this_(weak_factory_
.GetWeakPtr()) {
69 DVLOG(1) << __FUNCTION__
;
71 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner(
72 base::MessageLoop::current()->task_runner());
73 scoped_refptr
<MediaLog
> media_log(new MediaLog());
74 RendererConfig
* renderer_config
= RendererConfig::Get();
75 audio_renderer_sink_
= renderer_config
->GetAudioRendererSink();
77 scoped_ptr
<AudioRenderer
> audio_renderer(new AudioRendererImpl(
79 audio_renderer_sink_
.get(),
80 renderer_config
->GetAudioDecoders(
82 base::Bind(&LogMediaSourceError
, media_log
)).Pass(),
83 SetDecryptorReadyCB(),
84 renderer_config
->GetAudioHardwareConfig(),
87 scoped_ptr
<VideoRenderer
> video_renderer(new VideoRendererImpl(
89 renderer_config
->GetVideoDecoders(
91 base::Bind(&LogMediaSourceError
, media_log
)).Pass(),
92 SetDecryptorReadyCB(),
93 base::Bind(&PaintNothing
),
98 renderer_
.reset(new RendererImpl(
99 task_runner
, audio_renderer
.Pass(), video_renderer
.Pass()));
102 MojoRendererService::~MojoRendererService() {
105 void MojoRendererService::Initialize(mojo::DemuxerStreamPtr audio
,
106 mojo::DemuxerStreamPtr video
,
107 const mojo::Closure
& callback
) {
108 DVLOG(1) << __FUNCTION__
;
109 DCHECK_EQ(state_
, STATE_UNINITIALIZED
);
112 state_
= STATE_INITIALIZING
;
113 stream_provider_
.reset(new DemuxerStreamProviderShim(
116 base::Bind(&MojoRendererService::OnStreamReady
, weak_this_
, callback
)));
119 void MojoRendererService::Flush(const mojo::Closure
& callback
) {
120 DVLOG(2) << __FUNCTION__
;
121 DCHECK_EQ(state_
, STATE_PLAYING
);
123 state_
= STATE_FLUSHING
;
124 time_update_timer_
.Reset();
125 renderer_
->Flush(base::Bind(&MojoTrampoline
, callback
));
128 void MojoRendererService::StartPlayingFrom(int64_t time_delta_usec
) {
129 DVLOG(2) << __FUNCTION__
<< ": " << time_delta_usec
;
130 renderer_
->StartPlayingFrom(
131 base::TimeDelta::FromMicroseconds(time_delta_usec
));
132 SchedulePeriodicMediaTimeUpdates();
135 void MojoRendererService::SetPlaybackRate(float playback_rate
) {
136 DVLOG(2) << __FUNCTION__
<< ": " << playback_rate
;
137 DCHECK_EQ(state_
, STATE_PLAYING
);
138 renderer_
->SetPlaybackRate(playback_rate
);
141 void MojoRendererService::SetVolume(float volume
) {
142 renderer_
->SetVolume(volume
);
145 void MojoRendererService::OnStreamReady(const mojo::Closure
& callback
) {
146 DCHECK_EQ(state_
, STATE_INITIALIZING
);
148 renderer_
->Initialize(
149 stream_provider_
.get(),
151 &MojoRendererService::OnRendererInitializeDone
, weak_this_
, callback
),
152 base::Bind(&MojoRendererService::OnUpdateStatistics
, weak_this_
),
153 base::Bind(&MojoRendererService::OnRendererEnded
, weak_this_
),
154 base::Bind(&MojoRendererService::OnError
, weak_this_
),
155 base::Bind(&MojoRendererService::OnBufferingStateChanged
, weak_this_
));
158 void MojoRendererService::OnRendererInitializeDone(
159 const mojo::Closure
& callback
) {
160 DVLOG(1) << __FUNCTION__
;
162 if (state_
== STATE_ERROR
) {
165 DCHECK_EQ(state_
, STATE_INITIALIZING
);
166 state_
= STATE_PLAYING
;
172 void MojoRendererService::OnUpdateStatistics(const PipelineStatistics
& stats
) {
175 void MojoRendererService::UpdateMediaTime(bool force
) {
176 const uint64_t media_time
= renderer_
->GetMediaTime().InMicroseconds();
177 if (!force
&& media_time
== last_media_time_usec_
)
180 client()->OnTimeUpdate(media_time
, media_time
);
181 last_media_time_usec_
= media_time
;
184 void MojoRendererService::SchedulePeriodicMediaTimeUpdates() {
185 UpdateMediaTime(true);
186 time_update_timer_
.Start(
188 base::TimeDelta::FromMilliseconds(kTimeUpdateIntervalMs
),
189 base::Bind(&MojoRendererService::UpdateMediaTime
, weak_this_
, false));
192 void MojoRendererService::OnBufferingStateChanged(
193 BufferingState new_buffering_state
) {
194 DVLOG(2) << __FUNCTION__
<< "(" << new_buffering_state
<< ") ";
195 client()->OnBufferingStateChange(
196 static_cast<mojo::BufferingState
>(new_buffering_state
));
199 void MojoRendererService::OnRendererEnded() {
200 DVLOG(1) << __FUNCTION__
;
202 time_update_timer_
.Reset();
205 void MojoRendererService::OnError(PipelineStatus error
) {
206 DVLOG(1) << __FUNCTION__
;
207 state_
= STATE_ERROR
;
213 MojoResult
MojoMain(MojoHandle shell_handle
) {
214 mojo::ApplicationRunnerChromium
runner(new media::MojoRendererApplication
);
215 return runner
.Run(shell_handle
);