Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / media / mojo / services / mojo_renderer_impl.cc
blobf34b4c89970f2e43c79eb93107862abb9bbcc238
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"
16 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h"
18 namespace media {
20 MojoRendererImpl::MojoRendererImpl(
21 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
22 interfaces::MediaRendererPtr remote_media_renderer)
23 : task_runner_(task_runner),
24 remote_media_renderer_(remote_media_renderer.Pass()),
25 binding_(this),
26 weak_factory_(this) {
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 |waiting_for_decryption_key_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 base::Closure& ended_cb,
43 const PipelineStatusCB& error_cb,
44 const base::Closure& /* waiting_for_decryption_key_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_ = init_cb;
51 ended_cb_ = ended_cb;
52 error_cb_ = error_cb;
53 buffering_state_cb_ = buffering_state_cb;
55 // Create audio and video interfaces::DemuxerStream and bind its lifetime to
56 // the pipe.
57 DemuxerStream* const audio =
58 demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO);
59 DemuxerStream* const video =
60 demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO);
62 interfaces::DemuxerStreamPtr audio_stream;
63 if (audio)
64 new MojoDemuxerStreamImpl(audio, GetProxy(&audio_stream));
66 interfaces::DemuxerStreamPtr video_stream;
67 if (video)
68 new MojoDemuxerStreamImpl(video, GetProxy(&video_stream));
70 interfaces::MediaRendererClientPtr client_ptr;
71 binding_.Bind(GetProxy(&client_ptr));
72 remote_media_renderer_->Initialize(
73 client_ptr.Pass(),
74 audio_stream.Pass(),
75 video_stream.Pass(),
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 int32_t cdm_id = cdm_context->GetCdmId();
86 if (cdm_id == CdmContext::kInvalidCdmId) {
87 DVLOG(2) << "MojoRendererImpl only works with remote CDMs but the CDM ID "
88 "is invalid.";
89 cdm_attached_cb.Run(false);
90 return;
93 remote_media_renderer_->SetCdm(cdm_id, cdm_attached_cb);
96 void MojoRendererImpl::Flush(const base::Closure& flush_cb) {
97 DVLOG(2) << __FUNCTION__;
98 DCHECK(task_runner_->BelongsToCurrentThread());
99 remote_media_renderer_->Flush(flush_cb);
102 void MojoRendererImpl::StartPlayingFrom(base::TimeDelta time) {
103 DVLOG(2) << __FUNCTION__;
104 DCHECK(task_runner_->BelongsToCurrentThread());
107 base::AutoLock auto_lock(lock_);
108 time_ = time;
111 remote_media_renderer_->StartPlayingFrom(time.InMicroseconds());
114 void MojoRendererImpl::SetPlaybackRate(double playback_rate) {
115 DVLOG(2) << __FUNCTION__;
116 DCHECK(task_runner_->BelongsToCurrentThread());
117 remote_media_renderer_->SetPlaybackRate(playback_rate);
120 void MojoRendererImpl::SetVolume(float volume) {
121 DVLOG(2) << __FUNCTION__;
122 DCHECK(task_runner_->BelongsToCurrentThread());
123 remote_media_renderer_->SetVolume(volume);
126 base::TimeDelta MojoRendererImpl::GetMediaTime() {
127 base::AutoLock auto_lock(lock_);
128 DVLOG(3) << __FUNCTION__ << ": " << time_.InMilliseconds() << " ms";
129 return time_;
132 bool MojoRendererImpl::HasAudio() {
133 DVLOG(1) << __FUNCTION__;
134 DCHECK(task_runner_->BelongsToCurrentThread());
135 DCHECK(remote_media_renderer_.get()); // We always bind the renderer.
136 return !!demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO);
139 bool MojoRendererImpl::HasVideo() {
140 DVLOG(1) << __FUNCTION__;
141 DCHECK(task_runner_->BelongsToCurrentThread());
142 return !!demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO);
145 void MojoRendererImpl::OnTimeUpdate(int64_t time_usec, int64_t max_time_usec) {
146 DVLOG(3) << __FUNCTION__ << ": " << time_usec << ", " << max_time_usec;
148 if (!task_runner_->BelongsToCurrentThread()) {
149 task_runner_->PostTask(FROM_HERE,
150 base::Bind(&MojoRendererImpl::OnTimeUpdate,
151 weak_factory_.GetWeakPtr(),
152 time_usec,
153 max_time_usec));
154 return;
157 base::AutoLock auto_lock(lock_);
158 time_ = base::TimeDelta::FromMicroseconds(time_usec);
159 max_time_ = base::TimeDelta::FromMicroseconds(max_time_usec);
162 void MojoRendererImpl::OnBufferingStateChange(
163 interfaces::BufferingState state) {
164 DVLOG(2) << __FUNCTION__;
166 if (!task_runner_->BelongsToCurrentThread()) {
167 task_runner_->PostTask(FROM_HERE,
168 base::Bind(&MojoRendererImpl::OnBufferingStateChange,
169 weak_factory_.GetWeakPtr(),
170 state));
171 return;
174 buffering_state_cb_.Run(static_cast<media::BufferingState>(state));
177 void MojoRendererImpl::OnEnded() {
178 DVLOG(1) << __FUNCTION__;
180 if (!task_runner_->BelongsToCurrentThread()) {
181 task_runner_->PostTask(
182 FROM_HERE,
183 base::Bind(&MojoRendererImpl::OnEnded, weak_factory_.GetWeakPtr()));
184 return;
187 ended_cb_.Run();
190 void MojoRendererImpl::OnError() {
191 DVLOG(1) << __FUNCTION__;
192 DCHECK(init_cb_.is_null());
194 if (!task_runner_->BelongsToCurrentThread()) {
195 task_runner_->PostTask(
196 FROM_HERE,
197 base::Bind(&MojoRendererImpl::OnError, weak_factory_.GetWeakPtr()));
198 return;
201 // TODO(tim): Should we plumb error code from remote renderer?
202 // http://crbug.com/410451.
203 error_cb_.Run(PIPELINE_ERROR_DECODE);
206 void MojoRendererImpl::OnInitialized(bool success) {
207 DVLOG(1) << __FUNCTION__;
208 DCHECK(task_runner_->BelongsToCurrentThread());
209 DCHECK(!init_cb_.is_null());
211 base::ResetAndReturn(&init_cb_)
212 .Run(success ? PIPELINE_OK : PIPELINE_ERROR_INITIALIZATION_FAILED);
215 } // namespace media