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

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

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

Powered by Google App Engine
This is Rietveld 408576698