Hook the WebThreadImplForMessageLoop up to post taks through the blink
[chromium-blink-merge.git] / media / mojo / services / mojo_renderer_impl.cc
blob9ed903f0a31e40ea4fffc01cad5a26605888ed05
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"
7 #include "base/bind.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 "mojo/public/cpp/application/connect.h"
15 #include "mojo/public/cpp/bindings/interface_impl.h"
16 #include "mojo/public/interfaces/application/service_provider.mojom.h"
18 namespace media {
20 MojoRendererImpl::MojoRendererImpl(
21 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
22 mojo::ServiceProvider* audio_renderer_provider)
23 : task_runner_(task_runner),
24 weak_factory_(this) {
25 DVLOG(1) << __FUNCTION__;
26 // For now we only support audio and there must be a provider.
27 DCHECK(audio_renderer_provider);
28 mojo::ConnectToService(audio_renderer_provider, &remote_audio_renderer_);
29 remote_audio_renderer_.set_client(this);
32 MojoRendererImpl::~MojoRendererImpl() {
33 DVLOG(1) << __FUNCTION__;
34 DCHECK(task_runner_->BelongsToCurrentThread());
35 // Connection to |remote_audio_renderer_| will error-out here.
38 void MojoRendererImpl::Initialize(
39 DemuxerStreamProvider* demuxer_stream_provider,
40 const base::Closure& init_cb,
41 const StatisticsCB& statistics_cb,
42 const base::Closure& ended_cb,
43 const PipelineStatusCB& error_cb,
44 const BufferingStateCB& buffering_state_cb) {
45 DVLOG(1) << __FUNCTION__;
46 DCHECK(task_runner_->BelongsToCurrentThread());
47 DCHECK(demuxer_stream_provider);
49 demuxer_stream_provider_ = demuxer_stream_provider;
50 // |init_cb| can be called on other thread.
51 init_cb_ = init_cb;
52 ended_cb_ = ended_cb;
53 error_cb_ = error_cb;
54 buffering_state_cb_ = buffering_state_cb;
56 // Create audio and video mojo::DemuxerStream and bind its lifetime to the
57 // pipe.
58 DemuxerStream* const audio =
59 demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO);
60 DemuxerStream* const video =
61 demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO);
63 mojo::DemuxerStreamPtr audio_stream;
64 if (audio)
65 mojo::BindToProxy(new MojoDemuxerStreamImpl(audio), &audio_stream);
67 mojo::DemuxerStreamPtr video_stream;
68 if (video)
69 mojo::BindToProxy(new MojoDemuxerStreamImpl(video), &video_stream);
71 remote_audio_renderer_->Initialize(
72 audio_stream.Pass(),
73 video_stream.Pass(),
74 BindToCurrentLoop(base::Bind(&MojoRendererImpl::OnInitialized,
75 weak_factory_.GetWeakPtr())));
78 void MojoRendererImpl::Flush(const base::Closure& flush_cb) {
79 DVLOG(2) << __FUNCTION__;
80 DCHECK(task_runner_->BelongsToCurrentThread());
81 remote_audio_renderer_->Flush(flush_cb);
84 void MojoRendererImpl::StartPlayingFrom(base::TimeDelta time) {
85 DVLOG(2) << __FUNCTION__;
86 DCHECK(task_runner_->BelongsToCurrentThread());
89 base::AutoLock auto_lock(lock_);
90 time_ = time;
93 remote_audio_renderer_->StartPlayingFrom(time.InMicroseconds());
96 void MojoRendererImpl::SetPlaybackRate(float playback_rate) {
97 DVLOG(2) << __FUNCTION__;
98 DCHECK(task_runner_->BelongsToCurrentThread());
99 remote_audio_renderer_->SetPlaybackRate(playback_rate);
102 void MojoRendererImpl::SetVolume(float volume) {
103 DVLOG(2) << __FUNCTION__;
104 DCHECK(task_runner_->BelongsToCurrentThread());
105 remote_audio_renderer_->SetVolume(volume);
108 base::TimeDelta MojoRendererImpl::GetMediaTime() {
109 base::AutoLock auto_lock(lock_);
110 DVLOG(3) << __FUNCTION__ << ": " << time_.InMilliseconds() << " ms";
111 return time_;
114 bool MojoRendererImpl::HasAudio() {
115 DVLOG(1) << __FUNCTION__;
116 DCHECK(task_runner_->BelongsToCurrentThread());
117 DCHECK(remote_audio_renderer_.get()); // We always bind the renderer.
118 return !!demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO);
121 bool MojoRendererImpl::HasVideo() {
122 DVLOG(1) << __FUNCTION__;
123 DCHECK(task_runner_->BelongsToCurrentThread());
124 return !!demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO);
127 void MojoRendererImpl::SetCdm(MediaKeys* cdm) {
128 DVLOG(1) << __FUNCTION__;
129 DCHECK(task_runner_->BelongsToCurrentThread());
130 NOTIMPLEMENTED();
133 void MojoRendererImpl::OnTimeUpdate(int64_t time_usec, int64_t max_time_usec) {
134 DVLOG(3) << __FUNCTION__ << ": " << time_usec << ", " << max_time_usec;
136 if (!task_runner_->BelongsToCurrentThread()) {
137 task_runner_->PostTask(FROM_HERE,
138 base::Bind(&MojoRendererImpl::OnTimeUpdate,
139 weak_factory_.GetWeakPtr(),
140 time_usec,
141 max_time_usec));
142 return;
145 base::AutoLock auto_lock(lock_);
146 time_ = base::TimeDelta::FromMicroseconds(time_usec);
147 max_time_ = base::TimeDelta::FromMicroseconds(max_time_usec);
150 void MojoRendererImpl::OnBufferingStateChange(mojo::BufferingState state) {
151 DVLOG(2) << __FUNCTION__;
153 if (!task_runner_->BelongsToCurrentThread()) {
154 task_runner_->PostTask(FROM_HERE,
155 base::Bind(&MojoRendererImpl::OnBufferingStateChange,
156 weak_factory_.GetWeakPtr(),
157 state));
158 return;
161 buffering_state_cb_.Run(static_cast<media::BufferingState>(state));
164 void MojoRendererImpl::OnEnded() {
165 DVLOG(1) << __FUNCTION__;
167 if (!task_runner_->BelongsToCurrentThread()) {
168 task_runner_->PostTask(
169 FROM_HERE,
170 base::Bind(&MojoRendererImpl::OnEnded, weak_factory_.GetWeakPtr()));
171 return;
174 base::ResetAndReturn(&ended_cb_).Run();
177 void MojoRendererImpl::OnError() {
178 DVLOG(1) << __FUNCTION__;
180 if (!task_runner_->BelongsToCurrentThread()) {
181 task_runner_->PostTask(
182 FROM_HERE,
183 base::Bind(&MojoRendererImpl::OnError, weak_factory_.GetWeakPtr()));
184 return;
187 // TODO(tim): Should we plumb error code from remote renderer?
188 // http://crbug.com/410451.
189 if (init_cb_.is_null()) // We have initialized already.
190 error_cb_.Run(PIPELINE_ERROR_DECODE);
191 else
192 error_cb_.Run(PIPELINE_ERROR_COULD_NOT_RENDER);
195 void MojoRendererImpl::OnInitialized() {
196 DVLOG(1) << __FUNCTION__;
197 DCHECK(task_runner_->BelongsToCurrentThread());
198 DCHECK(!init_cb_.is_null());
200 base::ResetAndReturn(&init_cb_).Run();
203 } // namespace media