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_impl.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h"
11 #include "media/base/bind_to_current_loop.h"
12 #include "media/base/demuxer_stream_provider.h"
13 #include "media/mojo/services/mojo_demuxer_stream_impl.h"
14 #include "third_party/mojo/src/mojo/public/cpp/application/connect.h"
15 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h"
16 #include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h"
20 MojoRendererImpl::MojoRendererImpl(
21 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
22 mojo::MediaRendererPtr remote_media_renderer
)
23 : task_runner_(task_runner
),
24 remote_media_renderer_(remote_media_renderer
.Pass()),
27 DVLOG(1) << __FUNCTION__
;
30 MojoRendererImpl::~MojoRendererImpl() {
31 DVLOG(1) << __FUNCTION__
;
32 DCHECK(task_runner_
->BelongsToCurrentThread());
33 // Connection to |remote_media_renderer_| will error-out here.
36 // TODO(xhwang): Support |paint_cb| if needed.
37 void MojoRendererImpl::Initialize(
38 DemuxerStreamProvider
* demuxer_stream_provider
,
39 const PipelineStatusCB
& init_cb
,
40 const StatisticsCB
& statistics_cb
,
41 const BufferingStateCB
& buffering_state_cb
,
42 const PaintCB
& /* paint_cb */,
43 const base::Closure
& ended_cb
,
44 const PipelineStatusCB
& error_cb
) {
45 DVLOG(1) << __FUNCTION__
;
46 DCHECK(task_runner_
->BelongsToCurrentThread());
47 DCHECK(demuxer_stream_provider
);
49 demuxer_stream_provider_
= demuxer_stream_provider
;
53 buffering_state_cb_
= buffering_state_cb
;
55 // Create audio and video mojo::DemuxerStream and bind its lifetime to the
57 DemuxerStream
* const audio
=
58 demuxer_stream_provider_
->GetStream(DemuxerStream::AUDIO
);
59 DemuxerStream
* const video
=
60 demuxer_stream_provider_
->GetStream(DemuxerStream::VIDEO
);
62 mojo::DemuxerStreamPtr audio_stream
;
64 mojo::BindToProxy(new MojoDemuxerStreamImpl(audio
), &audio_stream
);
66 mojo::DemuxerStreamPtr video_stream
;
68 mojo::BindToProxy(new MojoDemuxerStreamImpl(video
), &video_stream
);
70 mojo::MediaRendererClientPtr client_ptr
;
71 binding_
.Bind(GetProxy(&client_ptr
));
72 remote_media_renderer_
->Initialize(
76 BindToCurrentLoop(base::Bind(&MojoRendererImpl::OnInitialized
,
77 weak_factory_
.GetWeakPtr())));
80 void MojoRendererImpl::SetCdm(CdmContext
* cdm_context
,
81 const CdmAttachedCB
& cdm_attached_cb
) {
82 DVLOG(1) << __FUNCTION__
;
83 DCHECK(task_runner_
->BelongsToCurrentThread());
85 cdm_attached_cb
.Run(false);
88 void MojoRendererImpl::Flush(const base::Closure
& flush_cb
) {
89 DVLOG(2) << __FUNCTION__
;
90 DCHECK(task_runner_
->BelongsToCurrentThread());
91 remote_media_renderer_
->Flush(flush_cb
);
94 void MojoRendererImpl::StartPlayingFrom(base::TimeDelta time
) {
95 DVLOG(2) << __FUNCTION__
;
96 DCHECK(task_runner_
->BelongsToCurrentThread());
99 base::AutoLock
auto_lock(lock_
);
103 remote_media_renderer_
->StartPlayingFrom(time
.InMicroseconds());
106 void MojoRendererImpl::SetPlaybackRate(float playback_rate
) {
107 DVLOG(2) << __FUNCTION__
;
108 DCHECK(task_runner_
->BelongsToCurrentThread());
109 remote_media_renderer_
->SetPlaybackRate(playback_rate
);
112 void MojoRendererImpl::SetVolume(float volume
) {
113 DVLOG(2) << __FUNCTION__
;
114 DCHECK(task_runner_
->BelongsToCurrentThread());
115 remote_media_renderer_
->SetVolume(volume
);
118 base::TimeDelta
MojoRendererImpl::GetMediaTime() {
119 base::AutoLock
auto_lock(lock_
);
120 DVLOG(3) << __FUNCTION__
<< ": " << time_
.InMilliseconds() << " ms";
124 bool MojoRendererImpl::HasAudio() {
125 DVLOG(1) << __FUNCTION__
;
126 DCHECK(task_runner_
->BelongsToCurrentThread());
127 DCHECK(remote_media_renderer_
.get()); // We always bind the renderer.
128 return !!demuxer_stream_provider_
->GetStream(DemuxerStream::AUDIO
);
131 bool MojoRendererImpl::HasVideo() {
132 DVLOG(1) << __FUNCTION__
;
133 DCHECK(task_runner_
->BelongsToCurrentThread());
134 return !!demuxer_stream_provider_
->GetStream(DemuxerStream::VIDEO
);
137 void MojoRendererImpl::OnTimeUpdate(int64_t time_usec
, int64_t max_time_usec
) {
138 DVLOG(3) << __FUNCTION__
<< ": " << time_usec
<< ", " << max_time_usec
;
140 if (!task_runner_
->BelongsToCurrentThread()) {
141 task_runner_
->PostTask(FROM_HERE
,
142 base::Bind(&MojoRendererImpl::OnTimeUpdate
,
143 weak_factory_
.GetWeakPtr(),
149 base::AutoLock
auto_lock(lock_
);
150 time_
= base::TimeDelta::FromMicroseconds(time_usec
);
151 max_time_
= base::TimeDelta::FromMicroseconds(max_time_usec
);
154 void MojoRendererImpl::OnBufferingStateChange(mojo::BufferingState state
) {
155 DVLOG(2) << __FUNCTION__
;
157 if (!task_runner_
->BelongsToCurrentThread()) {
158 task_runner_
->PostTask(FROM_HERE
,
159 base::Bind(&MojoRendererImpl::OnBufferingStateChange
,
160 weak_factory_
.GetWeakPtr(),
165 buffering_state_cb_
.Run(static_cast<media::BufferingState
>(state
));
168 void MojoRendererImpl::OnEnded() {
169 DVLOG(1) << __FUNCTION__
;
171 if (!task_runner_
->BelongsToCurrentThread()) {
172 task_runner_
->PostTask(
174 base::Bind(&MojoRendererImpl::OnEnded
, weak_factory_
.GetWeakPtr()));
181 void MojoRendererImpl::OnError() {
182 DVLOG(1) << __FUNCTION__
;
184 if (!task_runner_
->BelongsToCurrentThread()) {
185 task_runner_
->PostTask(
187 base::Bind(&MojoRendererImpl::OnError
, weak_factory_
.GetWeakPtr()));
191 // TODO(tim): Should we plumb error code from remote renderer?
192 // http://crbug.com/410451.
193 if (init_cb_
.is_null()) // We have initialized already.
194 error_cb_
.Run(PIPELINE_ERROR_DECODE
);
196 init_cb_
.Run(PIPELINE_ERROR_COULD_NOT_RENDER
);
199 void MojoRendererImpl::OnInitialized() {
200 DVLOG(1) << __FUNCTION__
;
201 DCHECK(task_runner_
->BelongsToCurrentThread());
202 if (!init_cb_
.is_null())
203 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);