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/mojo/services/demuxer_stream_provider_shim.h"
18 #include "media/mojo/services/renderer_config.h"
19 #include "media/renderers/audio_renderer_impl.h"
20 #include "media/renderers/renderer_impl.h"
21 #include "media/renderers/video_renderer_impl.h"
25 // Time interval to update media time.
26 const int kTimeUpdateIntervalMs
= 50;
28 static void LogMediaSourceError(const scoped_refptr
<MediaLog
>& media_log
,
29 const std::string
& error
) {
30 media_log
->AddEvent(media_log
->CreateMediaSourceErrorEvent(error
));
33 static void PaintNothing(const scoped_refptr
<VideoFrame
>& frame
) {
36 MojoRendererService::MojoRendererService()
37 : state_(STATE_UNINITIALIZED
),
38 last_media_time_usec_(0),
40 weak_this_
= weak_factory_
.GetWeakPtr();
41 DVLOG(1) << __FUNCTION__
;
43 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner(
44 base::MessageLoop::current()->task_runner());
45 scoped_refptr
<MediaLog
> media_log(new MediaLog());
46 RendererConfig
* renderer_config
= RendererConfig::Get();
47 audio_renderer_sink_
= renderer_config
->GetAudioRendererSink();
49 scoped_ptr
<AudioRenderer
> audio_renderer(new AudioRendererImpl(
50 task_runner
, audio_renderer_sink_
.get(),
51 renderer_config
->GetAudioDecoders(
53 base::Bind(&LogMediaSourceError
, media_log
)).Pass(),
54 renderer_config
->GetAudioHardwareConfig(), media_log
));
56 scoped_ptr
<VideoRenderer
> video_renderer(new VideoRendererImpl(
58 renderer_config
->GetVideoDecoders(
60 base::Bind(&LogMediaSourceError
, media_log
)).Pass(),
64 renderer_
.reset(new RendererImpl(
65 task_runner
, audio_renderer
.Pass(), video_renderer
.Pass()));
68 MojoRendererService::~MojoRendererService() {
71 void MojoRendererService::Initialize(mojo::MediaRendererClientPtr client
,
72 mojo::DemuxerStreamPtr audio
,
73 mojo::DemuxerStreamPtr video
,
74 const mojo::Closure
& callback
) {
75 DVLOG(1) << __FUNCTION__
;
76 DCHECK_EQ(state_
, STATE_UNINITIALIZED
);
77 client_
= client
.Pass();
78 state_
= STATE_INITIALIZING
;
79 stream_provider_
.reset(new DemuxerStreamProviderShim(
82 base::Bind(&MojoRendererService::OnStreamReady
, weak_this_
, callback
)));
85 void MojoRendererService::Flush(const mojo::Closure
& callback
) {
86 DVLOG(2) << __FUNCTION__
;
87 DCHECK_EQ(state_
, STATE_PLAYING
);
89 state_
= STATE_FLUSHING
;
90 CancelPeriodicMediaTimeUpdates();
92 base::Bind(&MojoRendererService::OnFlushCompleted
, weak_this_
, callback
));
95 void MojoRendererService::StartPlayingFrom(int64_t time_delta_usec
) {
96 DVLOG(2) << __FUNCTION__
<< ": " << time_delta_usec
;
97 renderer_
->StartPlayingFrom(
98 base::TimeDelta::FromMicroseconds(time_delta_usec
));
99 SchedulePeriodicMediaTimeUpdates();
102 void MojoRendererService::SetPlaybackRate(float playback_rate
) {
103 DVLOG(2) << __FUNCTION__
<< ": " << playback_rate
;
104 DCHECK_EQ(state_
, STATE_PLAYING
);
105 renderer_
->SetPlaybackRate(playback_rate
);
108 void MojoRendererService::SetVolume(float volume
) {
109 renderer_
->SetVolume(volume
);
112 void MojoRendererService::OnStreamReady(const mojo::Closure
& callback
) {
113 DCHECK_EQ(state_
, STATE_INITIALIZING
);
115 renderer_
->Initialize(
116 stream_provider_
.get(),
118 &MojoRendererService::OnRendererInitializeDone
, weak_this_
, callback
),
119 base::Bind(&MojoRendererService::OnUpdateStatistics
, weak_this_
),
120 base::Bind(&MojoRendererService::OnBufferingStateChanged
, weak_this_
),
121 base::Bind(&PaintNothing
),
122 base::Bind(&MojoRendererService::OnRendererEnded
, weak_this_
),
123 base::Bind(&MojoRendererService::OnError
, weak_this_
),
124 base::Bind(base::DoNothing
));
127 void MojoRendererService::OnRendererInitializeDone(
128 const mojo::Closure
& callback
, PipelineStatus status
) {
129 DVLOG(1) << __FUNCTION__
;
131 if (status
!= PIPELINE_OK
&& state_
!= STATE_ERROR
)
134 if (state_
== STATE_ERROR
) {
137 DCHECK_EQ(state_
, STATE_INITIALIZING
);
138 state_
= STATE_PLAYING
;
144 void MojoRendererService::OnUpdateStatistics(const PipelineStatistics
& stats
) {
147 void MojoRendererService::UpdateMediaTime(bool force
) {
148 const uint64_t media_time
= renderer_
->GetMediaTime().InMicroseconds();
149 if (!force
&& media_time
== last_media_time_usec_
)
152 client_
->OnTimeUpdate(media_time
, media_time
);
153 last_media_time_usec_
= media_time
;
156 void MojoRendererService::CancelPeriodicMediaTimeUpdates() {
157 UpdateMediaTime(false);
158 time_update_timer_
.Reset();
161 void MojoRendererService::SchedulePeriodicMediaTimeUpdates() {
162 UpdateMediaTime(true);
163 time_update_timer_
.Start(
165 base::TimeDelta::FromMilliseconds(kTimeUpdateIntervalMs
),
166 base::Bind(&MojoRendererService::UpdateMediaTime
, weak_this_
, false));
169 void MojoRendererService::OnBufferingStateChanged(
170 BufferingState new_buffering_state
) {
171 DVLOG(2) << __FUNCTION__
<< "(" << new_buffering_state
<< ") ";
172 client_
->OnBufferingStateChange(
173 static_cast<mojo::BufferingState
>(new_buffering_state
));
176 void MojoRendererService::OnRendererEnded() {
177 DVLOG(1) << __FUNCTION__
;
178 CancelPeriodicMediaTimeUpdates();
182 void MojoRendererService::OnError(PipelineStatus error
) {
183 DVLOG(1) << __FUNCTION__
;
184 state_
= STATE_ERROR
;
188 void MojoRendererService::OnFlushCompleted(const mojo::Closure
& callback
) {
189 DVLOG(1) << __FUNCTION__
;
190 DCHECK_EQ(state_
, STATE_FLUSHING
);
191 state_
= STATE_PLAYING
;