Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / mojo / services / mojo_renderer_impl.cc
blob3355d14f95c7d99db83d94dfa2998d5bca42bb67
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/application/public/cpp/connect.h"
15 #include "mojo/application/public/interfaces/service_provider.mojom.h"
17 namespace media {
19 MojoRendererImpl::MojoRendererImpl(
20 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
21 interfaces::RendererPtr remote_renderer)
22 : task_runner_(task_runner),
23 remote_renderer_(remote_renderer.Pass()),
24 binding_(this),
25 weak_factory_(this) {
26 DVLOG(1) << __FUNCTION__;
29 MojoRendererImpl::~MojoRendererImpl() {
30 DVLOG(1) << __FUNCTION__;
31 DCHECK(task_runner_->BelongsToCurrentThread());
32 // Connection to |remote_renderer_| will error-out here.
35 // TODO(xhwang): Support |waiting_for_decryption_key_cb| if needed.
36 void MojoRendererImpl::Initialize(
37 DemuxerStreamProvider* demuxer_stream_provider,
38 const PipelineStatusCB& init_cb,
39 const StatisticsCB& statistics_cb,
40 const BufferingStateCB& buffering_state_cb,
41 const base::Closure& ended_cb,
42 const PipelineStatusCB& error_cb,
43 const base::Closure& /* waiting_for_decryption_key_cb */) {
44 DVLOG(1) << __FUNCTION__;
45 DCHECK(task_runner_->BelongsToCurrentThread());
46 DCHECK(demuxer_stream_provider);
48 demuxer_stream_provider_ = demuxer_stream_provider;
49 init_cb_ = init_cb;
50 ended_cb_ = ended_cb;
51 error_cb_ = error_cb;
52 buffering_state_cb_ = buffering_state_cb;
54 // Create audio and video interfaces::DemuxerStream and bind its lifetime to
55 // the pipe.
56 DemuxerStream* const audio =
57 demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO);
58 DemuxerStream* const video =
59 demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO);
61 interfaces::DemuxerStreamPtr audio_stream;
62 if (audio)
63 new MojoDemuxerStreamImpl(audio, GetProxy(&audio_stream));
65 interfaces::DemuxerStreamPtr video_stream;
66 if (video)
67 new MojoDemuxerStreamImpl(video, GetProxy(&video_stream));
69 interfaces::RendererClientPtr client_ptr;
70 binding_.Bind(GetProxy(&client_ptr));
71 remote_renderer_->Initialize(
72 client_ptr.Pass(), audio_stream.Pass(), video_stream.Pass(),
73 BindToCurrentLoop(base::Bind(&MojoRendererImpl::OnInitialized,
74 weak_factory_.GetWeakPtr())));
77 void MojoRendererImpl::SetCdm(CdmContext* cdm_context,
78 const CdmAttachedCB& cdm_attached_cb) {
79 DVLOG(1) << __FUNCTION__;
80 DCHECK(task_runner_->BelongsToCurrentThread());
82 int32_t cdm_id = cdm_context->GetCdmId();
83 if (cdm_id == CdmContext::kInvalidCdmId) {
84 DVLOG(2) << "MojoRendererImpl only works with remote CDMs but the CDM ID "
85 "is invalid.";
86 cdm_attached_cb.Run(false);
87 return;
90 remote_renderer_->SetCdm(cdm_id, cdm_attached_cb);
93 void MojoRendererImpl::Flush(const base::Closure& flush_cb) {
94 DVLOG(2) << __FUNCTION__;
95 DCHECK(task_runner_->BelongsToCurrentThread());
96 remote_renderer_->Flush(flush_cb);
99 void MojoRendererImpl::StartPlayingFrom(base::TimeDelta time) {
100 DVLOG(2) << __FUNCTION__;
101 DCHECK(task_runner_->BelongsToCurrentThread());
104 base::AutoLock auto_lock(lock_);
105 time_ = time;
108 remote_renderer_->StartPlayingFrom(time.InMicroseconds());
111 void MojoRendererImpl::SetPlaybackRate(double playback_rate) {
112 DVLOG(2) << __FUNCTION__;
113 DCHECK(task_runner_->BelongsToCurrentThread());
114 remote_renderer_->SetPlaybackRate(playback_rate);
117 void MojoRendererImpl::SetVolume(float volume) {
118 DVLOG(2) << __FUNCTION__;
119 DCHECK(task_runner_->BelongsToCurrentThread());
120 remote_renderer_->SetVolume(volume);
123 base::TimeDelta MojoRendererImpl::GetMediaTime() {
124 base::AutoLock auto_lock(lock_);
125 DVLOG(3) << __FUNCTION__ << ": " << time_.InMilliseconds() << " ms";
126 return time_;
129 bool MojoRendererImpl::HasAudio() {
130 DVLOG(1) << __FUNCTION__;
131 DCHECK(task_runner_->BelongsToCurrentThread());
132 DCHECK(remote_renderer_.get()); // We always bind the renderer.
133 return !!demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO);
136 bool MojoRendererImpl::HasVideo() {
137 DVLOG(1) << __FUNCTION__;
138 DCHECK(task_runner_->BelongsToCurrentThread());
139 return !!demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO);
142 void MojoRendererImpl::OnTimeUpdate(int64_t time_usec, int64_t max_time_usec) {
143 DVLOG(3) << __FUNCTION__ << ": " << time_usec << ", " << max_time_usec;
145 if (!task_runner_->BelongsToCurrentThread()) {
146 task_runner_->PostTask(FROM_HERE,
147 base::Bind(&MojoRendererImpl::OnTimeUpdate,
148 weak_factory_.GetWeakPtr(),
149 time_usec,
150 max_time_usec));
151 return;
154 base::AutoLock auto_lock(lock_);
155 time_ = base::TimeDelta::FromMicroseconds(time_usec);
156 max_time_ = base::TimeDelta::FromMicroseconds(max_time_usec);
159 void MojoRendererImpl::OnBufferingStateChange(
160 interfaces::BufferingState state) {
161 DVLOG(2) << __FUNCTION__;
163 if (!task_runner_->BelongsToCurrentThread()) {
164 task_runner_->PostTask(FROM_HERE,
165 base::Bind(&MojoRendererImpl::OnBufferingStateChange,
166 weak_factory_.GetWeakPtr(),
167 state));
168 return;
171 buffering_state_cb_.Run(static_cast<media::BufferingState>(state));
174 void MojoRendererImpl::OnEnded() {
175 DVLOG(1) << __FUNCTION__;
177 if (!task_runner_->BelongsToCurrentThread()) {
178 task_runner_->PostTask(
179 FROM_HERE,
180 base::Bind(&MojoRendererImpl::OnEnded, weak_factory_.GetWeakPtr()));
181 return;
184 ended_cb_.Run();
187 void MojoRendererImpl::OnError() {
188 DVLOG(1) << __FUNCTION__;
189 DCHECK(init_cb_.is_null());
191 if (!task_runner_->BelongsToCurrentThread()) {
192 task_runner_->PostTask(
193 FROM_HERE,
194 base::Bind(&MojoRendererImpl::OnError, weak_factory_.GetWeakPtr()));
195 return;
198 // TODO(tim): Should we plumb error code from remote renderer?
199 // http://crbug.com/410451.
200 error_cb_.Run(PIPELINE_ERROR_DECODE);
203 void MojoRendererImpl::OnInitialized(bool success) {
204 DVLOG(1) << __FUNCTION__;
205 DCHECK(task_runner_->BelongsToCurrentThread());
206 DCHECK(!init_cb_.is_null());
208 base::ResetAndReturn(&init_cb_)
209 .Run(success ? PIPELINE_OK : PIPELINE_ERROR_INITIALIZATION_FAILED);
212 } // namespace media