Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / mojo / services / mojo_renderer_service.cc
blob9efde200d3bc5b4457ac67ee500aab89f05cf0e3
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"
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/message_loop/message_loop.h"
10 #include "media/base/audio_decoder.h"
11 #include "media/base/audio_renderer.h"
12 #include "media/base/audio_renderer_sink.h"
13 #include "media/base/cdm_context.h"
14 #include "media/base/decryptor.h"
15 #include "media/base/media_log.h"
16 #include "media/base/renderer_factory.h"
17 #include "media/base/video_renderer.h"
18 #include "media/base/video_renderer_sink.h"
19 #include "media/mojo/services/demuxer_stream_provider_shim.h"
20 #include "media/mojo/services/mojo_media_client.h"
21 #include "media/renderers/audio_renderer_impl.h"
22 #include "media/renderers/renderer_impl.h"
23 #include "media/renderers/video_renderer_impl.h"
25 namespace media {
27 // Time interval to update media time.
28 const int kTimeUpdateIntervalMs = 50;
30 MojoRendererService::MojoRendererService(
31 base::WeakPtr<CdmContextProvider> cdm_context_provider,
32 RendererFactory* renderer_factory,
33 const scoped_refptr<MediaLog>& media_log,
34 mojo::InterfaceRequest<interfaces::Renderer> request)
35 : binding_(this, request.Pass()),
36 cdm_context_provider_(cdm_context_provider),
37 state_(STATE_UNINITIALIZED),
38 last_media_time_usec_(0),
39 weak_factory_(this) {
40 weak_this_ = weak_factory_.GetWeakPtr();
41 DVLOG(1) << __FUNCTION__;
43 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
44 base::MessageLoop::current()->task_runner());
45 MojoMediaClient* mojo_media_client = MojoMediaClient::Get();
46 audio_renderer_sink_ = mojo_media_client->CreateAudioRendererSink();
47 video_renderer_sink_ =
48 mojo_media_client->CreateVideoRendererSink(task_runner);
50 // Create renderer.
51 if (renderer_factory) {
52 renderer_ = renderer_factory->CreateRenderer(task_runner, task_runner,
53 audio_renderer_sink_.get(),
54 video_renderer_sink_.get());
55 } else {
56 scoped_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl(
57 task_runner, audio_renderer_sink_.get(),
58 mojo_media_client->CreateAudioDecoders(task_runner, media_log).Pass(),
59 mojo_media_client->GetAudioHardwareConfig(), media_log));
60 scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl(
61 task_runner, task_runner, video_renderer_sink_.get(),
62 mojo_media_client->CreateVideoDecoders(task_runner, media_log).Pass(),
63 true, nullptr, media_log));
64 renderer_.reset(new RendererImpl(task_runner, audio_renderer.Pass(),
65 video_renderer.Pass()));
69 MojoRendererService::~MojoRendererService() {
72 void MojoRendererService::Initialize(
73 interfaces::RendererClientPtr client,
74 interfaces::DemuxerStreamPtr audio,
75 interfaces::DemuxerStreamPtr video,
76 const mojo::Callback<void(bool)>& callback) {
77 DVLOG(1) << __FUNCTION__;
78 DCHECK_EQ(state_, STATE_UNINITIALIZED);
79 client_ = client.Pass();
80 state_ = STATE_INITIALIZING;
81 stream_provider_.reset(new DemuxerStreamProviderShim(
82 audio.Pass(),
83 video.Pass(),
84 base::Bind(&MojoRendererService::OnStreamReady, weak_this_, callback)));
87 void MojoRendererService::Flush(const mojo::Closure& callback) {
88 DVLOG(2) << __FUNCTION__;
89 DCHECK_EQ(state_, STATE_PLAYING);
91 state_ = STATE_FLUSHING;
92 CancelPeriodicMediaTimeUpdates();
93 renderer_->Flush(
94 base::Bind(&MojoRendererService::OnFlushCompleted, weak_this_, callback));
97 void MojoRendererService::StartPlayingFrom(int64_t time_delta_usec) {
98 DVLOG(2) << __FUNCTION__ << ": " << time_delta_usec;
99 renderer_->StartPlayingFrom(
100 base::TimeDelta::FromMicroseconds(time_delta_usec));
101 SchedulePeriodicMediaTimeUpdates();
104 void MojoRendererService::SetPlaybackRate(double playback_rate) {
105 DVLOG(2) << __FUNCTION__ << ": " << playback_rate;
106 DCHECK_EQ(state_, STATE_PLAYING);
107 renderer_->SetPlaybackRate(playback_rate);
110 void MojoRendererService::SetVolume(float volume) {
111 renderer_->SetVolume(volume);
114 void MojoRendererService::SetCdm(int32_t cdm_id,
115 const mojo::Callback<void(bool)>& callback) {
116 if (!cdm_context_provider_) {
117 LOG(ERROR) << "CDM context provider not available.";
118 callback.Run(false);
119 return;
122 CdmContext* cdm_context = cdm_context_provider_->GetCdmContext(cdm_id);
123 if (!cdm_context) {
124 LOG(ERROR) << "CDM context not found: " << cdm_id;
125 callback.Run(false);
126 return;
129 renderer_->SetCdm(cdm_context, base::Bind(&MojoRendererService::OnCdmAttached,
130 weak_this_, callback));
133 void MojoRendererService::OnStreamReady(
134 const mojo::Callback<void(bool)>& callback) {
135 DCHECK_EQ(state_, STATE_INITIALIZING);
137 renderer_->Initialize(
138 stream_provider_.get(),
139 base::Bind(
140 &MojoRendererService::OnRendererInitializeDone, weak_this_, callback),
141 base::Bind(&MojoRendererService::OnUpdateStatistics, weak_this_),
142 base::Bind(&MojoRendererService::OnBufferingStateChanged, weak_this_),
143 base::Bind(&MojoRendererService::OnRendererEnded, weak_this_),
144 base::Bind(&MojoRendererService::OnError, weak_this_),
145 base::Bind(base::DoNothing));
148 void MojoRendererService::OnRendererInitializeDone(
149 const mojo::Callback<void(bool)>& callback,
150 PipelineStatus status) {
151 DVLOG(1) << __FUNCTION__;
152 DCHECK_EQ(state_, STATE_INITIALIZING);
154 if (status != PIPELINE_OK) {
155 state_ = STATE_ERROR;
156 callback.Run(false);
157 return;
160 state_ = STATE_PLAYING;
161 callback.Run(true);
164 void MojoRendererService::OnUpdateStatistics(const PipelineStatistics& stats) {
167 void MojoRendererService::UpdateMediaTime(bool force) {
168 const uint64_t media_time = renderer_->GetMediaTime().InMicroseconds();
169 if (!force && media_time == last_media_time_usec_)
170 return;
172 client_->OnTimeUpdate(media_time, media_time);
173 last_media_time_usec_ = media_time;
176 void MojoRendererService::CancelPeriodicMediaTimeUpdates() {
177 DVLOG(2) << __FUNCTION__;
178 UpdateMediaTime(false);
179 time_update_timer_.Stop();
182 void MojoRendererService::SchedulePeriodicMediaTimeUpdates() {
183 DVLOG(2) << __FUNCTION__;
184 UpdateMediaTime(true);
185 time_update_timer_.Start(
186 FROM_HERE,
187 base::TimeDelta::FromMilliseconds(kTimeUpdateIntervalMs),
188 base::Bind(&MojoRendererService::UpdateMediaTime, weak_this_, false));
191 void MojoRendererService::OnBufferingStateChanged(
192 BufferingState new_buffering_state) {
193 DVLOG(2) << __FUNCTION__ << "(" << new_buffering_state << ")";
194 client_->OnBufferingStateChange(
195 static_cast<interfaces::BufferingState>(new_buffering_state));
198 void MojoRendererService::OnRendererEnded() {
199 DVLOG(1) << __FUNCTION__;
200 CancelPeriodicMediaTimeUpdates();
201 client_->OnEnded();
204 void MojoRendererService::OnError(PipelineStatus error) {
205 DVLOG(1) << __FUNCTION__ << "(" << error << ")";
206 state_ = STATE_ERROR;
207 client_->OnError();
210 void MojoRendererService::OnFlushCompleted(const mojo::Closure& callback) {
211 DVLOG(1) << __FUNCTION__;
212 DCHECK_EQ(state_, STATE_FLUSHING);
213 state_ = STATE_PLAYING;
214 callback.Run();
217 void MojoRendererService::OnCdmAttached(
218 const mojo::Callback<void(bool)>& callback,
219 bool success) {
220 DVLOG(1) << __FUNCTION__ << "(" << success << ")";
221 callback.Run(success);
224 } // namespace media