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 "base/message_loop/message_loop.h"
11 #include "media/base/audio_decoder.h"
12 #include "media/base/audio_renderer.h"
13 #include "media/base/audio_renderer_sink.h"
14 #include "media/base/decryptor.h"
15 #include "media/base/media_log.h"
16 #include "media/base/video_renderer.h"
17 #include "media/base/video_renderer_sink.h"
18 #include "media/mojo/services/demuxer_stream_provider_shim.h"
19 #include "media/mojo/services/renderer_config.h"
20 #include "media/renderers/audio_renderer_impl.h"
21 #include "media/renderers/renderer_impl.h"
22 #include "media/renderers/video_renderer_impl.h"
26 // Time interval to update media time.
27 const int kTimeUpdateIntervalMs
= 50;
29 MojoRendererService::MojoRendererService()
30 : state_(STATE_UNINITIALIZED
),
31 last_media_time_usec_(0),
33 weak_this_
= weak_factory_
.GetWeakPtr();
34 DVLOG(1) << __FUNCTION__
;
36 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner(
37 base::MessageLoop::current()->task_runner());
38 scoped_refptr
<MediaLog
> media_log(new MediaLog());
39 RendererConfig
* renderer_config
= RendererConfig::Get();
40 audio_renderer_sink_
= renderer_config
->GetAudioRendererSink();
41 video_renderer_sink_
= renderer_config
->GetVideoRendererSink();
43 scoped_ptr
<AudioRenderer
> audio_renderer(new AudioRendererImpl(
44 task_runner
, audio_renderer_sink_
.get(),
45 renderer_config
->GetAudioDecoders(task_runner
,
46 base::Bind(&MediaLog::AddLogEvent
,
48 renderer_config
->GetAudioHardwareConfig(), media_log
));
50 scoped_ptr
<VideoRenderer
> video_renderer(new VideoRendererImpl(
51 task_runner
, video_renderer_sink_
.get(),
52 renderer_config
->GetVideoDecoders(task_runner
,
53 base::Bind(&MediaLog::AddLogEvent
,
58 renderer_
.reset(new RendererImpl(
59 task_runner
, audio_renderer
.Pass(), video_renderer
.Pass()));
62 MojoRendererService::~MojoRendererService() {
65 void MojoRendererService::Initialize(mojo::MediaRendererClientPtr client
,
66 mojo::DemuxerStreamPtr audio
,
67 mojo::DemuxerStreamPtr video
,
68 const mojo::Closure
& callback
) {
69 DVLOG(1) << __FUNCTION__
;
70 DCHECK_EQ(state_
, STATE_UNINITIALIZED
);
71 client_
= client
.Pass();
72 state_
= STATE_INITIALIZING
;
73 stream_provider_
.reset(new DemuxerStreamProviderShim(
76 base::Bind(&MojoRendererService::OnStreamReady
, weak_this_
, callback
)));
79 void MojoRendererService::Flush(const mojo::Closure
& callback
) {
80 DVLOG(2) << __FUNCTION__
;
81 DCHECK_EQ(state_
, STATE_PLAYING
);
83 state_
= STATE_FLUSHING
;
84 CancelPeriodicMediaTimeUpdates();
86 base::Bind(&MojoRendererService::OnFlushCompleted
, weak_this_
, callback
));
89 void MojoRendererService::StartPlayingFrom(int64_t time_delta_usec
) {
90 DVLOG(2) << __FUNCTION__
<< ": " << time_delta_usec
;
91 renderer_
->StartPlayingFrom(
92 base::TimeDelta::FromMicroseconds(time_delta_usec
));
93 SchedulePeriodicMediaTimeUpdates();
96 void MojoRendererService::SetPlaybackRate(double playback_rate
) {
97 DVLOG(2) << __FUNCTION__
<< ": " << playback_rate
;
98 DCHECK_EQ(state_
, STATE_PLAYING
);
99 renderer_
->SetPlaybackRate(playback_rate
);
102 void MojoRendererService::SetVolume(float volume
) {
103 renderer_
->SetVolume(volume
);
106 void MojoRendererService::OnStreamReady(const mojo::Closure
& callback
) {
107 DCHECK_EQ(state_
, STATE_INITIALIZING
);
109 renderer_
->Initialize(
110 stream_provider_
.get(),
112 &MojoRendererService::OnRendererInitializeDone
, weak_this_
, callback
),
113 base::Bind(&MojoRendererService::OnUpdateStatistics
, weak_this_
),
114 base::Bind(&MojoRendererService::OnBufferingStateChanged
, weak_this_
),
115 base::Bind(&MojoRendererService::OnRendererEnded
, weak_this_
),
116 base::Bind(&MojoRendererService::OnError
, weak_this_
),
117 base::Bind(base::DoNothing
));
120 void MojoRendererService::OnRendererInitializeDone(
121 const mojo::Closure
& callback
, PipelineStatus status
) {
122 DVLOG(1) << __FUNCTION__
;
124 if (status
!= PIPELINE_OK
&& state_
!= STATE_ERROR
)
127 if (state_
== STATE_ERROR
) {
130 DCHECK_EQ(state_
, STATE_INITIALIZING
);
131 state_
= STATE_PLAYING
;
137 void MojoRendererService::OnUpdateStatistics(const PipelineStatistics
& stats
) {
140 void MojoRendererService::UpdateMediaTime(bool force
) {
141 const uint64_t media_time
= renderer_
->GetMediaTime().InMicroseconds();
142 if (!force
&& media_time
== last_media_time_usec_
)
145 client_
->OnTimeUpdate(media_time
, media_time
);
146 last_media_time_usec_
= media_time
;
149 void MojoRendererService::CancelPeriodicMediaTimeUpdates() {
150 UpdateMediaTime(false);
151 time_update_timer_
.Reset();
154 void MojoRendererService::SchedulePeriodicMediaTimeUpdates() {
155 UpdateMediaTime(true);
156 time_update_timer_
.Start(
158 base::TimeDelta::FromMilliseconds(kTimeUpdateIntervalMs
),
159 base::Bind(&MojoRendererService::UpdateMediaTime
, weak_this_
, false));
162 void MojoRendererService::OnBufferingStateChanged(
163 BufferingState new_buffering_state
) {
164 DVLOG(2) << __FUNCTION__
<< "(" << new_buffering_state
<< ") ";
165 client_
->OnBufferingStateChange(
166 static_cast<mojo::BufferingState
>(new_buffering_state
));
169 void MojoRendererService::OnRendererEnded() {
170 DVLOG(1) << __FUNCTION__
;
171 CancelPeriodicMediaTimeUpdates();
175 void MojoRendererService::OnError(PipelineStatus error
) {
176 DVLOG(1) << __FUNCTION__
;
177 state_
= STATE_ERROR
;
181 void MojoRendererService::OnFlushCompleted(const mojo::Closure
& callback
) {
182 DVLOG(1) << __FUNCTION__
;
183 DCHECK_EQ(state_
, STATE_FLUSHING
);
184 state_
= STATE_PLAYING
;