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

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

Powered by Google App Engine
This is Rietveld 408576698