Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: chromecast/renderer/media/media_pipeline_proxy.cc

Issue 814403002: [Chromecast] Add CmaMediaRendererFactory and IPC proxy components (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "chromecast/renderer/media/media_pipeline_proxy.h"
6
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "chromecast/common/media/cma_messages.h"
13 #include "chromecast/media/cma/base/coded_frame_provider.h"
14 #include "chromecast/renderer/media/audio_pipeline_proxy.h"
15 #include "chromecast/renderer/media/media_channel_proxy.h"
16 #include "chromecast/renderer/media/video_pipeline_proxy.h"
17
18 namespace chromecast {
19 namespace cma {
20
21 // MediaPipelineProxyInternal -
22 // This class is not thread safe and should run on the same thread
23 // as the media channel proxy.
24 class MediaPipelineProxyInternal {
25 public:
26 static void Release(scoped_ptr<MediaPipelineProxyInternal> proxy);
27
28 explicit MediaPipelineProxyInternal(
29 scoped_refptr<MediaChannelProxy> media_channel_proxy);
30 virtual ~MediaPipelineProxyInternal();
31
32 void SetClient(const chromecast::media::MediaPipelineClient& client);
33 void SetCdm(int render_frame_id, int cdm_id);
34 void StartPlayingFrom(const base::TimeDelta& time);
35 void Flush(const ::media::PipelineStatusCB& status_cb);
36 void Stop();
37 void SetPlaybackRate(float playback_rate);
38
39 private:
40 void Shutdown();
41
42 // Callbacks for CmaMessageFilterHost::MediaDelegate.
43 void OnStateChanged(::media::PipelineStatus status);
44
45 base::ThreadChecker thread_checker_;
46
47 scoped_refptr<MediaChannelProxy> media_channel_proxy_;
48
49 chromecast::media::MediaPipelineClient client_;
50
51 // Store the callback for a pending state transition.
52 ::media::PipelineStatusCB status_cb_;
53
54 DISALLOW_COPY_AND_ASSIGN(MediaPipelineProxyInternal);
gunsch 2014/12/20 22:41:34 base/macros.h
erickung1 2014/12/21 11:10:47 may not need it since media_pipeline_proxy.h alrea
55 };
56
57 // static
58 void MediaPipelineProxyInternal::Release(
59 scoped_ptr<MediaPipelineProxyInternal> proxy) {
60 proxy->Shutdown();
61 }
62
63 MediaPipelineProxyInternal::MediaPipelineProxyInternal(
64 scoped_refptr<MediaChannelProxy> media_channel_proxy)
65 : media_channel_proxy_(media_channel_proxy) {
66 DCHECK(media_channel_proxy.get());
67
68 // Creation can be done on a different thread.
69 thread_checker_.DetachFromThread();
70 }
71
72 MediaPipelineProxyInternal::~MediaPipelineProxyInternal() {
73 }
74
75 void MediaPipelineProxyInternal::Shutdown() {
76 DCHECK(thread_checker_.CalledOnValidThread());
77
78 // Remove any callback on VideoPipelineProxyInternal.
79 media_channel_proxy_->SetMediaDelegate(
80 CmaMessageFilterProxy::MediaDelegate());
81 }
82
83 void MediaPipelineProxyInternal::SetClient(
84 const chromecast::media::MediaPipelineClient& client) {
85 DCHECK(thread_checker_.CalledOnValidThread());
86 DCHECK(!client.error_cb.is_null());
87 DCHECK(!client.buffering_state_cb.is_null());
88 client_ = client;
89
90 CmaMessageFilterProxy::MediaDelegate delegate;
91 delegate.state_changed_cb =
92 base::Bind(&MediaPipelineProxyInternal::OnStateChanged,
93 base::Unretained(this));
94 delegate.client = client;
95 bool success = media_channel_proxy_->SetMediaDelegate(delegate);
96 CHECK(success);
97 }
98
99 void MediaPipelineProxyInternal::SetCdm(int render_frame_id, int cdm_id) {
100 DCHECK(thread_checker_.CalledOnValidThread());
101 bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
102 new CmaHostMsg_SetCdm(media_channel_proxy_->GetId(),
103 render_frame_id,
104 cdm_id)));
105 LOG_IF(ERROR, !success) << "Failed to send SetCdm=" << cdm_id;
106 }
107
108 void MediaPipelineProxyInternal::Flush(
109 const ::media::PipelineStatusCB& status_cb) {
110 DCHECK(thread_checker_.CalledOnValidThread());
111 bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
112 new CmaHostMsg_Flush(media_channel_proxy_->GetId())));
113 if (!success) {
114 status_cb.Run(::media::PIPELINE_ERROR_ABORT);
115 return;
116 }
117 DCHECK(status_cb_.is_null());
118 status_cb_ = status_cb;
119 }
120
121 void MediaPipelineProxyInternal::Stop() {
122 DCHECK(thread_checker_.CalledOnValidThread());
123 bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
124 new CmaHostMsg_Stop(media_channel_proxy_->GetId())));
125 if (!success)
126 client_.error_cb.Run(::media::PIPELINE_ERROR_ABORT);
127 }
128
129 void MediaPipelineProxyInternal::StartPlayingFrom(const base::TimeDelta& time) {
130 DCHECK(thread_checker_.CalledOnValidThread());
131 bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
132 new CmaHostMsg_StartPlayingFrom(
133 media_channel_proxy_->GetId(), time)));
134 if (!success)
135 client_.error_cb.Run(::media::PIPELINE_ERROR_ABORT);
136 }
137
138 void MediaPipelineProxyInternal::SetPlaybackRate(float playback_rate) {
139 DCHECK(thread_checker_.CalledOnValidThread());
140 media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
141 new CmaHostMsg_SetPlaybackRate(
142 media_channel_proxy_->GetId(), playback_rate)));
143 }
144
145 void MediaPipelineProxyInternal::OnStateChanged(
146 ::media::PipelineStatus status) {
147 DCHECK(thread_checker_.CalledOnValidThread());
148 DCHECK(!status_cb_.is_null());
149 base::ResetAndReturn(&status_cb_).Run(status);
150 }
151
152
153 #define FORWARD_ON_IO_0(param_fn) \
gunsch 2014/12/20 22:41:34 same comment: can these be merged using ##__VA_ARG
erickung1 2014/12/21 11:10:47 Done.
154 io_message_loop_proxy_->PostTask( \
155 FROM_HERE, \
156 base::Bind(&MediaPipelineProxyInternal::param_fn, \
157 base::Unretained(proxy_.get())))
158 #define FORWARD_ON_IO_1(param_fn, param_arg1) \
159 io_message_loop_proxy_->PostTask( \
160 FROM_HERE, \
161 base::Bind(&MediaPipelineProxyInternal::param_fn, \
162 base::Unretained(proxy_.get()), (param_arg1)))
163 #define FORWARD_ON_IO_2(param_fn, param_arg1, param_arg2) \
164 io_message_loop_proxy_->PostTask( \
165 FROM_HERE, \
166 base::Bind(&MediaPipelineProxyInternal::param_fn, \
167 base::Unretained(proxy_.get()), (param_arg1), (param_arg2)))
168
169 MediaPipelineProxy::MediaPipelineProxy(
170 int render_frame_id,
171 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy,
172 chromecast::media::LoadType load_type)
173 : io_message_loop_proxy_(io_message_loop_proxy),
174 render_frame_id_(render_frame_id),
175 media_channel_proxy_(new MediaChannelProxy),
176 proxy_(new MediaPipelineProxyInternal(media_channel_proxy_)),
177 has_audio_(false),
178 has_video_(false),
179 audio_pipeline_(new AudioPipelineProxy(
180 io_message_loop_proxy, media_channel_proxy_)),
181 video_pipeline_(new VideoPipelineProxy(
182 io_message_loop_proxy, media_channel_proxy_)),
183 weak_factory_(this) {
184 weak_this_ = weak_factory_.GetWeakPtr();
185 io_message_loop_proxy_->PostTask(
186 FROM_HERE,
187 base::Bind(&MediaChannelProxy::Open, media_channel_proxy_,
188 load_type));
189 thread_checker_.DetachFromThread();
190 }
191
192 MediaPipelineProxy::~MediaPipelineProxy() {
193 io_message_loop_proxy_->PostTask(
194 FROM_HERE,
195 base::Bind(&MediaPipelineProxyInternal::Release, base::Passed(&proxy_)));
196 io_message_loop_proxy_->PostTask(
197 FROM_HERE,
198 base::Bind(&MediaChannelProxy::Close, media_channel_proxy_));
199 }
200
201 void MediaPipelineProxy::SetClient(
202 const chromecast::media::MediaPipelineClient& client) {
203 DCHECK(thread_checker_.CalledOnValidThread());
204 FORWARD_ON_IO_1(SetClient, client);
205 }
206
207 void MediaPipelineProxy::SetCdm(int cdm_id) {
208 DCHECK(thread_checker_.CalledOnValidThread());
209 FORWARD_ON_IO_2(SetCdm, render_frame_id_, cdm_id);
210 }
211
212 chromecast::media::AudioPipeline*
213 MediaPipelineProxy::GetAudioPipeline() const {
214 return audio_pipeline_.get();
215 }
216
217 chromecast::media::VideoPipeline*
218 MediaPipelineProxy::GetVideoPipeline() const {
219 return video_pipeline_.get();
220 }
221
222 void MediaPipelineProxy::InitializeAudio(
223 const ::media::AudioDecoderConfig& config,
224 scoped_ptr<chromecast::media::CodedFrameProvider> frame_provider,
225 const ::media::PipelineStatusCB& status_cb) {
226 DCHECK(thread_checker_.CalledOnValidThread());
227 has_audio_ = true;
228 audio_pipeline_->Initialize(config, frame_provider.Pass(), status_cb);
229 }
230
231 void MediaPipelineProxy::InitializeVideo(
232 const ::media::VideoDecoderConfig& config,
233 scoped_ptr<chromecast::media::CodedFrameProvider> frame_provider,
234 const ::media::PipelineStatusCB& status_cb) {
235 DCHECK(thread_checker_.CalledOnValidThread());
236 has_video_ = true;
237 video_pipeline_->Initialize(config, frame_provider.Pass(), status_cb);
238 }
239
240 void MediaPipelineProxy::StartPlayingFrom(base::TimeDelta time) {
241 DCHECK(thread_checker_.CalledOnValidThread());
242 if (has_audio_)
243 audio_pipeline_->StartFeeding();
244 if (has_video_)
245 video_pipeline_->StartFeeding();
246 FORWARD_ON_IO_1(StartPlayingFrom, time);
247 }
248
249 void MediaPipelineProxy::Flush(const ::media::PipelineStatusCB& status_cb) {
250 DCHECK(thread_checker_.CalledOnValidThread());
251 DCHECK(has_audio_ || has_video_);
252
253 ::media::SerialRunner::Queue bound_fns;
254 if (has_audio_) {
255 bound_fns.Push(base::Bind(&AudioPipelineProxy::Flush,
256 base::Unretained(audio_pipeline_.get())));
257 }
258 if (has_video_) {
259 bound_fns.Push(base::Bind(&VideoPipelineProxy::Flush,
260 base::Unretained(video_pipeline_.get())));
261 }
262 ::media::PipelineStatusCB cb =
263 base::Bind(&MediaPipelineProxy::OnProxyFlushDone, weak_this_, status_cb);
264 pending_callbacks_ = ::media::SerialRunner::Run(bound_fns, cb);
265 }
266
267 void MediaPipelineProxy::OnProxyFlushDone(
268 const ::media::PipelineStatusCB& status_cb,
269 ::media::PipelineStatus status) {
270 DCHECK(thread_checker_.CalledOnValidThread());
271 DCHECK_EQ(status, ::media::PIPELINE_OK);
272 pending_callbacks_.reset();
273 FORWARD_ON_IO_1(Flush, status_cb);
274 }
275
276 void MediaPipelineProxy::Stop() {
277 DCHECK(thread_checker_.CalledOnValidThread());
278 DCHECK(has_audio_ || has_video_);
279
280 if (has_audio_)
281 audio_pipeline_->Stop();
282 if (has_video_)
283 video_pipeline_->Stop();
284
285 FORWARD_ON_IO_0(Stop);
286 }
287
288 void MediaPipelineProxy::SetPlaybackRate(float playback_rate) {
289 DCHECK(thread_checker_.CalledOnValidThread());
290 FORWARD_ON_IO_1(SetPlaybackRate, playback_rate);
291 }
292
293 } // namespace cma
294 } // namespace chromecast
295
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698