Hook the WebThreadImplForMessageLoop up to post taks through the blink
[chromium-blink-merge.git] / media / mojo / services / mojo_renderer_service.cc
blob03b5040b2f3f2c733d53af9f99fdf31576400420
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/memory/scoped_vector.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/decryptor.h"
14 #include "media/base/media_log.h"
15 #include "media/base/video_renderer.h"
16 #include "media/filters/audio_renderer_impl.h"
17 #include "media/filters/renderer_impl.h"
18 #include "media/filters/video_renderer_impl.h"
19 #include "media/mojo/services/demuxer_stream_provider_shim.h"
20 #include "media/mojo/services/mojo_demuxer_stream_adapter.h"
21 #include "media/mojo/services/renderer_config.h"
22 #include "mojo/application/application_runner_chromium.h"
23 #include "mojo/public/c/system/main.h"
24 #include "mojo/public/cpp/application/application_connection.h"
25 #include "mojo/public/cpp/application/application_delegate.h"
26 #include "mojo/public/cpp/application/interface_factory_impl.h"
28 namespace media {
30 // Time interval to update media time.
31 const int kTimeUpdateIntervalMs = 50;
33 static void LogMediaSourceError(const scoped_refptr<MediaLog>& media_log,
34 const std::string& error) {
35 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
38 static void PaintNothing(const scoped_refptr<VideoFrame>& frame) {
41 class MojoRendererApplication
42 : public mojo::ApplicationDelegate,
43 public mojo::InterfaceFactory<mojo::MediaRenderer> {
44 public:
45 // mojo::ApplicationDelegate implementation.
46 bool ConfigureIncomingConnection(
47 mojo::ApplicationConnection* connection) override {
48 connection->AddService(this);
49 return true;
52 // mojo::InterfaceFactory<mojo::MediaRenderer> implementation.
53 void Create(mojo::ApplicationConnection* connection,
54 mojo::InterfaceRequest<mojo::MediaRenderer> request) override {
55 mojo::BindToRequest(new MojoRendererService(connection), &request);
59 static void MojoTrampoline(const mojo::Closure& closure) {
60 closure.Run();
63 MojoRendererService::MojoRendererService(
64 mojo::ApplicationConnection* connection)
65 : state_(STATE_UNINITIALIZED),
66 last_media_time_usec_(0),
67 weak_factory_(this),
68 weak_this_(weak_factory_.GetWeakPtr()) {
69 DVLOG(1) << __FUNCTION__;
71 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
72 base::MessageLoop::current()->task_runner());
73 scoped_refptr<MediaLog> media_log(new MediaLog());
74 RendererConfig* renderer_config = RendererConfig::Get();
75 audio_renderer_sink_ = renderer_config->GetAudioRendererSink();
77 scoped_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl(
78 task_runner,
79 audio_renderer_sink_.get(),
80 renderer_config->GetAudioDecoders(
81 task_runner,
82 base::Bind(&LogMediaSourceError, media_log)).Pass(),
83 SetDecryptorReadyCB(),
84 renderer_config->GetAudioHardwareConfig(),
85 media_log));
87 scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl(
88 task_runner,
89 renderer_config->GetVideoDecoders(
90 task_runner,
91 base::Bind(&LogMediaSourceError, media_log)).Pass(),
92 SetDecryptorReadyCB(),
93 base::Bind(&PaintNothing),
94 true,
95 media_log));
97 // Create renderer.
98 renderer_.reset(new RendererImpl(
99 task_runner, audio_renderer.Pass(), video_renderer.Pass()));
102 MojoRendererService::~MojoRendererService() {
105 void MojoRendererService::Initialize(mojo::DemuxerStreamPtr audio,
106 mojo::DemuxerStreamPtr video,
107 const mojo::Closure& callback) {
108 DVLOG(1) << __FUNCTION__;
109 DCHECK_EQ(state_, STATE_UNINITIALIZED);
110 DCHECK(client());
112 state_ = STATE_INITIALIZING;
113 stream_provider_.reset(new DemuxerStreamProviderShim(
114 audio.Pass(),
115 video.Pass(),
116 base::Bind(&MojoRendererService::OnStreamReady, weak_this_, callback)));
119 void MojoRendererService::Flush(const mojo::Closure& callback) {
120 DVLOG(2) << __FUNCTION__;
121 DCHECK_EQ(state_, STATE_PLAYING);
123 state_ = STATE_FLUSHING;
124 time_update_timer_.Reset();
125 renderer_->Flush(base::Bind(&MojoTrampoline, callback));
128 void MojoRendererService::StartPlayingFrom(int64_t time_delta_usec) {
129 DVLOG(2) << __FUNCTION__ << ": " << time_delta_usec;
130 renderer_->StartPlayingFrom(
131 base::TimeDelta::FromMicroseconds(time_delta_usec));
132 SchedulePeriodicMediaTimeUpdates();
135 void MojoRendererService::SetPlaybackRate(float playback_rate) {
136 DVLOG(2) << __FUNCTION__ << ": " << playback_rate;
137 DCHECK_EQ(state_, STATE_PLAYING);
138 renderer_->SetPlaybackRate(playback_rate);
141 void MojoRendererService::SetVolume(float volume) {
142 renderer_->SetVolume(volume);
145 void MojoRendererService::OnStreamReady(const mojo::Closure& callback) {
146 DCHECK_EQ(state_, STATE_INITIALIZING);
148 renderer_->Initialize(
149 stream_provider_.get(),
150 base::Bind(
151 &MojoRendererService::OnRendererInitializeDone, weak_this_, callback),
152 base::Bind(&MojoRendererService::OnUpdateStatistics, weak_this_),
153 base::Bind(&MojoRendererService::OnRendererEnded, weak_this_),
154 base::Bind(&MojoRendererService::OnError, weak_this_),
155 base::Bind(&MojoRendererService::OnBufferingStateChanged, weak_this_));
158 void MojoRendererService::OnRendererInitializeDone(
159 const mojo::Closure& callback) {
160 DVLOG(1) << __FUNCTION__;
162 if (state_ == STATE_ERROR) {
163 renderer_.reset();
164 } else {
165 DCHECK_EQ(state_, STATE_INITIALIZING);
166 state_ = STATE_PLAYING;
169 callback.Run();
172 void MojoRendererService::OnUpdateStatistics(const PipelineStatistics& stats) {
175 void MojoRendererService::UpdateMediaTime(bool force) {
176 const uint64_t media_time = renderer_->GetMediaTime().InMicroseconds();
177 if (!force && media_time == last_media_time_usec_)
178 return;
180 client()->OnTimeUpdate(media_time, media_time);
181 last_media_time_usec_ = media_time;
184 void MojoRendererService::SchedulePeriodicMediaTimeUpdates() {
185 UpdateMediaTime(true);
186 time_update_timer_.Start(
187 FROM_HERE,
188 base::TimeDelta::FromMilliseconds(kTimeUpdateIntervalMs),
189 base::Bind(&MojoRendererService::UpdateMediaTime, weak_this_, false));
192 void MojoRendererService::OnBufferingStateChanged(
193 BufferingState new_buffering_state) {
194 DVLOG(2) << __FUNCTION__ << "(" << new_buffering_state << ") ";
195 client()->OnBufferingStateChange(
196 static_cast<mojo::BufferingState>(new_buffering_state));
199 void MojoRendererService::OnRendererEnded() {
200 DVLOG(1) << __FUNCTION__;
201 client()->OnEnded();
202 time_update_timer_.Reset();
205 void MojoRendererService::OnError(PipelineStatus error) {
206 DVLOG(1) << __FUNCTION__;
207 state_ = STATE_ERROR;
208 client()->OnError();
211 } // namespace media
213 MojoResult MojoMain(MojoHandle shell_handle) {
214 mojo::ApplicationRunnerChromium runner(new media::MojoRendererApplication);
215 return runner.Run(shell_handle);