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

Side by Side Diff: chromecast/renderer/media/video_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/video_pipeline_proxy.h"
6
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/memory/shared_memory.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/threading/thread_checker.h"
12 #include "chromecast/common/media/cma_ipc_common.h"
13 #include "chromecast/common/media/cma_messages.h"
14 #include "chromecast/common/media/shared_memory_chunk.h"
15 #include "chromecast/media/cma/base/buffering_defs.h"
16 #include "chromecast/media/cma/base/cma_logging.h"
17 #include "chromecast/media/cma/base/coded_frame_provider.h"
18 #include "chromecast/media/cma/ipc/media_message_fifo.h"
19 #include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h"
20 #include "chromecast/renderer/media/cma_message_filter_proxy.h"
21 #include "chromecast/renderer/media/media_channel_proxy.h"
22 #include "media/base/bind_to_current_loop.h"
23 #include "media/base/pipeline_status.h"
24
25 namespace chromecast {
26 namespace cma {
27
28 namespace {
29
30 void Noop() {
gunsch 2014/12/20 22:41:34 prefer name ilke IgnoreResult
erickung1 2014/12/21 11:10:48 Done.
31 }
32
33 } // namespace
34
35 // VideoPipelineProxyInternal -
36 // This class is not thread safe and should run on the same thread
37 // as the media channel proxy.
38 class VideoPipelineProxyInternal {
39 public:
40 typedef base::Callback<void(scoped_ptr<base::SharedMemory>)> SharedMemCB;
41
42 static void Release(scoped_ptr<VideoPipelineProxyInternal> proxy);
43
44 explicit VideoPipelineProxyInternal(
45 scoped_refptr<MediaChannelProxy> media_channel_proxy);
46 virtual ~VideoPipelineProxyInternal();
47
48 // Notify the other side (browser process) of some activity on the video pipe.
49 // TODO(damienv): either send an IPC message or write a byte on the
gunsch 2014/12/20 22:41:34 same comment
erickung1 2014/12/21 11:10:48 Done.
50 // SyncSocket.
51 void NotifyPipeWrite();
52
53 // These functions are almost a one to one correspondence with VideoPipeline
54 // but this is an internal class and there is no reason to derive from
55 // VideoPipeline.
56 void SetClient(const base::Closure& pipe_read_cb,
57 const chromecast::media::VideoPipelineClient& client);
58 void CreateAvPipe(const SharedMemCB& shared_mem_cb);
59 void Initialize(const ::media::VideoDecoderConfig& config,
60 const ::media::PipelineStatusCB& status_cb);
61
62 private:
63 void Shutdown();
64
65 // Callbacks for CmaMessageFilterHost::VideoDelegate.
66 void OnAvPipeCreated(bool status,
67 base::SharedMemoryHandle shared_mem_handle,
68 base::FileDescriptor socket);
69 void OnStateChanged(::media::PipelineStatus status);
70
71 base::ThreadChecker thread_checker_;
72
73 scoped_refptr<MediaChannelProxy> media_channel_proxy_;
74
75 // Store the callback for a pending state transition.
76 ::media::PipelineStatusCB status_cb_;
77
78 SharedMemCB shared_mem_cb_;
79
80 DISALLOW_COPY_AND_ASSIGN(VideoPipelineProxyInternal);
gunsch 2014/12/20 22:41:34 base/macros.h
erickung1 2014/12/21 11:10:48 video_pipeline_proxy.h has included base/macros.h
81 };
82
83 // static
84 void VideoPipelineProxyInternal::Release(
85 scoped_ptr<VideoPipelineProxyInternal> proxy) {
86 proxy->Shutdown();
87 }
88
89 VideoPipelineProxyInternal::VideoPipelineProxyInternal(
90 scoped_refptr<MediaChannelProxy> media_channel_proxy)
91 : media_channel_proxy_(media_channel_proxy) {
92 DCHECK(media_channel_proxy.get());
93
94 // Creation can be done on a different thread.
95 thread_checker_.DetachFromThread();
96 }
97
98 VideoPipelineProxyInternal::~VideoPipelineProxyInternal() {
99 }
100
101 void VideoPipelineProxyInternal::Shutdown() {
102 DCHECK(thread_checker_.CalledOnValidThread());
103
104 // Remove any callback on VideoPipelineProxyInternal.
105 media_channel_proxy_->SetVideoDelegate(
106 CmaMessageFilterProxy::VideoDelegate());
107 }
108
109 void VideoPipelineProxyInternal::NotifyPipeWrite() {
110 DCHECK(thread_checker_.CalledOnValidThread());
111
112 // TODO(damienv): An alternative way would be to use a dedicated socket for
113 // this event.
114 bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
115 new CmaHostMsg_NotifyPipeWrite(
116 media_channel_proxy_->GetId(), chromecast::media::kVideoTrackId)));
117 VLOG_IF(4, !success) << "Sending msg failed";
118 }
119
120 void VideoPipelineProxyInternal::SetClient(
121 const base::Closure& pipe_read_cb,
122 const chromecast::media::VideoPipelineClient& video_client) {
123 DCHECK(thread_checker_.CalledOnValidThread());
124
125 CmaMessageFilterProxy::VideoDelegate delegate;
126 delegate.av_pipe_cb =
127 base::Bind(&VideoPipelineProxyInternal::OnAvPipeCreated,
128 base::Unretained(this));
129 delegate.state_changed_cb =
130 base::Bind(&VideoPipelineProxyInternal::OnStateChanged,
131 base::Unretained(this));
132 delegate.pipe_read_cb = pipe_read_cb;
133 delegate.client = video_client;
134 bool success = media_channel_proxy_->SetVideoDelegate(delegate);
135 CHECK(success);
136 }
137
138 void VideoPipelineProxyInternal::CreateAvPipe(
139 const SharedMemCB& shared_mem_cb) {
140 DCHECK(thread_checker_.CalledOnValidThread());
141 DCHECK(shared_mem_cb_.is_null());
142 bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
143 new CmaHostMsg_CreateAvPipe(
144 media_channel_proxy_->GetId(), chromecast::media::kVideoTrackId,
145 chromecast::media::kAppVideoBufferSize)));
146 if (!success) {
147 shared_mem_cb.Run(scoped_ptr<base::SharedMemory>());
148 return;
149 }
150 shared_mem_cb_ = shared_mem_cb;
151 }
152
153 void VideoPipelineProxyInternal::OnAvPipeCreated(
154 bool success,
155 base::SharedMemoryHandle shared_mem_handle,
156 base::FileDescriptor socket) {
157 DCHECK(thread_checker_.CalledOnValidThread());
158 DCHECK(!shared_mem_cb_.is_null());
159 if (!success) {
160 shared_mem_cb_.Run(scoped_ptr<base::SharedMemory>());
161 return;
162 }
163
164 CHECK(base::SharedMemory::IsHandleValid(shared_mem_handle));
165 shared_mem_cb_.Run(scoped_ptr<base::SharedMemory>(
166 new base::SharedMemory(shared_mem_handle, false)));
167 }
168
169 #define DEFINE_STATE_TRANSITION_1(param_fn, param_msg, param_type1) \
gunsch 2014/12/20 22:41:34 only used one place, please unroll
erickung1 2014/12/21 11:10:48 Done.
170 void VideoPipelineProxyInternal::param_fn( \
171 const param_type1& arg1, \
172 const ::media::PipelineStatusCB& status_cb) { \
173 DCHECK(thread_checker_.CalledOnValidThread()); \
174 bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>( \
175 new param_msg(media_channel_proxy_->GetId(), \
176 chromecast::media::kVideoTrackId, arg1))); \
177 if (!success) { \
178 status_cb.Run( \
179 ::media::PIPELINE_ERROR_INITIALIZATION_FAILED); \
180 return; \
181 } \
182 DCHECK(status_cb_.is_null()); \
183 status_cb_ = status_cb; \
184 }
185
186 DEFINE_STATE_TRANSITION_1(Initialize, CmaHostMsg_VideoInitialize,
187 ::media::VideoDecoderConfig)
188
189 void VideoPipelineProxyInternal::OnStateChanged(
190 ::media::PipelineStatus status) {
191 DCHECK(thread_checker_.CalledOnValidThread());
192 DCHECK(!status_cb_.is_null());
193 base::ResetAndReturn(&status_cb_).Run(status);
194 }
195
196 #define FORWARD_ON_IO_0(param_fn) \
gunsch 2014/12/20 22:41:34 same comment, can these be merged
erickung1 2014/12/21 11:10:48 Done.
197 io_message_loop_proxy_->PostTask( \
198 FROM_HERE, \
199 base::Bind(&VideoPipelineProxyInternal::param_fn, \
200 base::Unretained(proxy_.get())))
201 #define FORWARD_ON_IO_1(param_fn, param_arg1) \
202 io_message_loop_proxy_->PostTask( \
203 FROM_HERE, \
204 base::Bind(&VideoPipelineProxyInternal::param_fn, \
205 base::Unretained(proxy_.get()), (param_arg1)))
206 #define FORWARD_ON_IO_2(param_fn, param_arg1, param_arg2) \
207 io_message_loop_proxy_->PostTask( \
208 FROM_HERE, \
209 base::Bind(&VideoPipelineProxyInternal::param_fn, \
210 base::Unretained(proxy_.get()), (param_arg1), (param_arg2)))
211
212 VideoPipelineProxy::VideoPipelineProxy(
213 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy,
214 scoped_refptr<MediaChannelProxy> media_channel_proxy)
215 : io_message_loop_proxy_(io_message_loop_proxy),
gunsch 2014/12/20 22:41:34 indentation
erickung1 2014/12/21 11:10:48 Done.
216 proxy_(new VideoPipelineProxyInternal(media_channel_proxy)),
217 video_streamer_(new chromecast::media::AvStreamerProxy()),
218 weak_factory_(this) {
219 DCHECK(io_message_loop_proxy_.get());
220 weak_this_ = weak_factory_.GetWeakPtr();
221 thread_checker_.DetachFromThread();
222 }
223
224 VideoPipelineProxy::~VideoPipelineProxy() {
225 DCHECK(thread_checker_.CalledOnValidThread());
226 // Release the underlying object on the right thread.
227 io_message_loop_proxy_->PostTask(
228 FROM_HERE,
229 base::Bind(&VideoPipelineProxyInternal::Release, base::Passed(&proxy_)));
230 }
231
232 void VideoPipelineProxy::SetClient(
233 const chromecast::media::VideoPipelineClient& video_client) {
234 DCHECK(thread_checker_.CalledOnValidThread());
235 base::Closure pipe_read_cb =
236 ::media::BindToCurrentLoop(
237 base::Bind(&VideoPipelineProxy::OnPipeRead, weak_this_));
238 FORWARD_ON_IO_2(SetClient, pipe_read_cb, video_client);
239 }
240
241 void VideoPipelineProxy::Initialize(
242 const ::media::VideoDecoderConfig& config,
243 scoped_ptr<chromecast::media::CodedFrameProvider> frame_provider,
244 const ::media::PipelineStatusCB& status_cb) {
245 CMALOG(chromecast::media::kLogControl) << "VideoPipelineProxy::Initialize";
246 DCHECK(thread_checker_.CalledOnValidThread());
247 video_streamer_->SetCodedFrameProvider(frame_provider.Pass());
248
249 VideoPipelineProxyInternal::SharedMemCB shared_mem_cb =
250 ::media::BindToCurrentLoop(base::Bind(
251 &VideoPipelineProxy::OnAvPipeCreated, weak_this_,
252 config, status_cb));
253 FORWARD_ON_IO_1(CreateAvPipe, shared_mem_cb);
254 }
255
256 void VideoPipelineProxy::OnAvPipeCreated(
257 const ::media::VideoDecoderConfig& config,
258 const ::media::PipelineStatusCB& status_cb,
259 scoped_ptr<base::SharedMemory> shared_memory) {
260 CMALOG(chromecast::media::kLogControl)
261 << "VideoPipelineProxy::OnAvPipeCreated";
262 DCHECK(thread_checker_.CalledOnValidThread());
263 if (!shared_memory ||
264 !shared_memory->Map(chromecast::media::kAppVideoBufferSize)) {
265 status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
266 return;
267 }
268 CHECK(shared_memory->memory());
269
270 scoped_ptr<chromecast::media::MediaMemoryChunk> shared_memory_chunk(
271 new chromecast::media::SharedMemoryChunk(
272 shared_memory.Pass(), chromecast::media::kAppVideoBufferSize));
273 scoped_ptr<chromecast::media::MediaMessageFifo> video_pipe(
274 new chromecast::media::MediaMessageFifo(
275 shared_memory_chunk.Pass(), false));
276 video_pipe->ObserveWriteActivity(
277 base::Bind(&VideoPipelineProxy::OnPipeWrite, weak_this_));
278
279 video_streamer_->SetMediaMessageFifo(video_pipe.Pass());
280
281 // Now proceed to the decoder/renderer initialization.
282 FORWARD_ON_IO_2(Initialize, config, status_cb);
283 }
284
285 void VideoPipelineProxy::StartFeeding() {
286 DCHECK(thread_checker_.CalledOnValidThread());
287 DCHECK(video_streamer_);
288 video_streamer_->Start();
289 }
290
291 void VideoPipelineProxy::Flush(const base::Closure& done_cb) {
292 DCHECK(thread_checker_.CalledOnValidThread());
293 DCHECK(video_streamer_);
294 video_streamer_->StopAndFlush(done_cb);
295 }
296
297 void VideoPipelineProxy::Stop() {
298 DCHECK(thread_checker_.CalledOnValidThread());
299 if (!video_streamer_)
300 return;
301 video_streamer_->StopAndFlush(base::Bind(&Noop));
302 }
303
304 void VideoPipelineProxy::OnPipeWrite() {
305 DCHECK(thread_checker_.CalledOnValidThread());
306 FORWARD_ON_IO_0(NotifyPipeWrite);
307 }
308
309 void VideoPipelineProxy::OnPipeRead() {
310 DCHECK(thread_checker_.CalledOnValidThread());
311 if (video_streamer_)
312 video_streamer_->OnFifoReadEvent();
313 }
314
315 } // namespace cma
316 } // namespace chromecast
317
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698