1 // Copyright (c) 2012 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 "content/browser/renderer_host/media/audio_renderer_host.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/memory/shared_memory.h"
10 #include "base/metrics/histogram.h"
11 #include "base/process/process.h"
12 #include "content/browser/browser_main_loop.h"
13 #include "content/browser/media/capture/audio_mirroring_manager.h"
14 #include "content/browser/media/media_internals.h"
15 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
16 #include "content/browser/renderer_host/media/audio_sync_reader.h"
17 #include "content/browser/renderer_host/media/media_stream_manager.h"
18 #include "content/common/media/audio_messages.h"
19 #include "content/public/browser/content_browser_client.h"
20 #include "content/public/browser/media_observer.h"
21 #include "content/public/common/content_switches.h"
22 #include "media/audio/audio_manager_base.h"
23 #include "media/base/audio_bus.h"
24 #include "media/base/limits.h"
25
26 using media::AudioBus;
27 using media::AudioManager;
28
29 namespace content {
30
31 class AudioRendererHost::AudioEntry
32 : public media::AudioOutputController::EventHandler {
33 public:
34 AudioEntry(AudioRendererHost* host,
35 int stream_id,
36 int render_view_id,
37 int render_frame_id,
38 const media::AudioParameters& params,
39 const std::string& output_device_id,
40 scoped_ptr<base::SharedMemory> shared_memory,
41 scoped_ptr<media::AudioOutputController::SyncReader> reader);
42 virtual ~AudioEntry();
43
stream_id() const44 int stream_id() const {
45 return stream_id_;
46 }
47
render_view_id() const48 int render_view_id() const {
49 return render_view_id_;
50 }
51
render_frame_id() const52 int render_frame_id() const { return render_frame_id_; }
53
controller() const54 media::AudioOutputController* controller() const { return controller_.get(); }
55
shared_memory()56 base::SharedMemory* shared_memory() {
57 return shared_memory_.get();
58 }
59
reader() const60 media::AudioOutputController::SyncReader* reader() const {
61 return reader_.get();
62 }
63
playing() const64 bool playing() const { return playing_; }
set_playing(bool playing)65 void set_playing(bool playing) { playing_ = playing; }
66
67 private:
68 // media::AudioOutputController::EventHandler implementation.
69 virtual void OnCreated() OVERRIDE;
70 virtual void OnPlaying() OVERRIDE;
71 virtual void OnPaused() OVERRIDE;
72 virtual void OnError() OVERRIDE;
73 virtual void OnDeviceChange(int new_buffer_size, int new_sample_rate)
74 OVERRIDE;
75
76 AudioRendererHost* const host_;
77 const int stream_id_;
78
79 // The routing ID of the source render view/frame.
80 const int render_view_id_;
81 const int render_frame_id_;
82
83 // Shared memory for transmission of the audio data. Used by |reader_|.
84 const scoped_ptr<base::SharedMemory> shared_memory_;
85
86 // The synchronous reader to be used by |controller_|.
87 const scoped_ptr<media::AudioOutputController::SyncReader> reader_;
88
89 // The AudioOutputController that manages the audio stream.
90 const scoped_refptr<media::AudioOutputController> controller_;
91
92 bool playing_;
93 };
94
AudioEntry(AudioRendererHost * host,int stream_id,int render_view_id,int render_frame_id,const media::AudioParameters & params,const std::string & output_device_id,scoped_ptr<base::SharedMemory> shared_memory,scoped_ptr<media::AudioOutputController::SyncReader> reader)95 AudioRendererHost::AudioEntry::AudioEntry(
96 AudioRendererHost* host,
97 int stream_id,
98 int render_view_id,
99 int render_frame_id,
100 const media::AudioParameters& params,
101 const std::string& output_device_id,
102 scoped_ptr<base::SharedMemory> shared_memory,
103 scoped_ptr<media::AudioOutputController::SyncReader> reader)
104 : host_(host),
105 stream_id_(stream_id),
106 render_view_id_(render_view_id),
107 render_frame_id_(render_frame_id),
108 shared_memory_(shared_memory.Pass()),
109 reader_(reader.Pass()),
110 controller_(media::AudioOutputController::Create(host->audio_manager_,
111 this,
112 params,
113 output_device_id,
114 reader_.get())),
115 playing_(false) {
116 DCHECK(controller_.get());
117 }
118
~AudioEntry()119 AudioRendererHost::AudioEntry::~AudioEntry() {}
120
121 ///////////////////////////////////////////////////////////////////////////////
122 // AudioRendererHost implementations.
123
AudioRendererHost(int render_process_id,media::AudioManager * audio_manager,AudioMirroringManager * mirroring_manager,MediaInternals * media_internals,MediaStreamManager * media_stream_manager)124 AudioRendererHost::AudioRendererHost(
125 int render_process_id,
126 media::AudioManager* audio_manager,
127 AudioMirroringManager* mirroring_manager,
128 MediaInternals* media_internals,
129 MediaStreamManager* media_stream_manager)
130 : BrowserMessageFilter(AudioMsgStart),
131 render_process_id_(render_process_id),
132 audio_manager_(audio_manager),
133 mirroring_manager_(mirroring_manager),
134 audio_log_(media_internals->CreateAudioLog(
135 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)),
136 media_stream_manager_(media_stream_manager),
137 num_playing_streams_(0) {
138 DCHECK(audio_manager_);
139 DCHECK(media_stream_manager_);
140 }
141
~AudioRendererHost()142 AudioRendererHost::~AudioRendererHost() {
143 DCHECK(audio_entries_.empty());
144 }
145
GetOutputControllers(int render_view_id,const RenderViewHost::GetAudioOutputControllersCallback & callback) const146 void AudioRendererHost::GetOutputControllers(
147 int render_view_id,
148 const RenderViewHost::GetAudioOutputControllersCallback& callback) const {
149 BrowserThread::PostTaskAndReplyWithResult(
150 BrowserThread::IO,
151 FROM_HERE,
152 base::Bind(&AudioRendererHost::DoGetOutputControllers, this,
153 render_view_id),
154 callback);
155 }
156
OnChannelClosing()157 void AudioRendererHost::OnChannelClosing() {
158 // Since the IPC sender is gone, close all requested audio streams.
159 while (!audio_entries_.empty()) {
160 // Note: OnCloseStream() removes the entries from audio_entries_.
161 OnCloseStream(audio_entries_.begin()->first);
162 }
163 }
164
OnDestruct() const165 void AudioRendererHost::OnDestruct() const {
166 BrowserThread::DeleteOnIOThread::Destruct(this);
167 }
168
OnCreated()169 void AudioRendererHost::AudioEntry::OnCreated() {
170 BrowserThread::PostTask(
171 BrowserThread::IO,
172 FROM_HERE,
173 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_));
174 }
175
OnPlaying()176 void AudioRendererHost::AudioEntry::OnPlaying() {
177 BrowserThread::PostTask(
178 BrowserThread::IO,
179 FROM_HERE,
180 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
181 host_,
182 stream_id_,
183 true));
184 }
185
OnPaused()186 void AudioRendererHost::AudioEntry::OnPaused() {
187 BrowserThread::PostTask(
188 BrowserThread::IO,
189 FROM_HERE,
190 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
191 host_,
192 stream_id_,
193 false));
194 }
195
OnError()196 void AudioRendererHost::AudioEntry::OnError() {
197 BrowserThread::PostTask(
198 BrowserThread::IO,
199 FROM_HERE,
200 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_));
201 }
202
OnDeviceChange(int new_buffer_size,int new_sample_rate)203 void AudioRendererHost::AudioEntry::OnDeviceChange(int new_buffer_size,
204 int new_sample_rate) {
205 BrowserThread::PostTask(
206 BrowserThread::IO,
207 FROM_HERE,
208 base::Bind(base::IgnoreResult(&AudioRendererHost::Send), host_,
209 new AudioMsg_NotifyDeviceChanged(
210 stream_id_, new_buffer_size, new_sample_rate)));
211 }
212
DoCompleteCreation(int stream_id)213 void AudioRendererHost::DoCompleteCreation(int stream_id) {
214 DCHECK_CURRENTLY_ON(BrowserThread::IO);
215
216 if (!PeerHandle()) {
217 DLOG(WARNING) << "Renderer process handle is invalid.";
218 ReportErrorAndClose(stream_id);
219 return;
220 }
221
222 AudioEntry* const entry = LookupById(stream_id);
223 if (!entry) {
224 ReportErrorAndClose(stream_id);
225 return;
226 }
227
228 // Once the audio stream is created then complete the creation process by
229 // mapping shared memory and sharing with the renderer process.
230 base::SharedMemoryHandle foreign_memory_handle;
231 if (!entry->shared_memory()->ShareToProcess(PeerHandle(),
232 &foreign_memory_handle)) {
233 // If we failed to map and share the shared memory then close the audio
234 // stream and send an error message.
235 ReportErrorAndClose(entry->stream_id());
236 return;
237 }
238
239 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader());
240
241 #if defined(OS_WIN)
242 base::SyncSocket::Handle foreign_socket_handle;
243 #else
244 base::FileDescriptor foreign_socket_handle;
245 #endif
246
247 // If we failed to prepare the sync socket for the renderer then we fail
248 // the construction of audio stream.
249 if (!reader->PrepareForeignSocketHandle(PeerHandle(),
250 &foreign_socket_handle)) {
251 ReportErrorAndClose(entry->stream_id());
252 return;
253 }
254
255 Send(new AudioMsg_NotifyStreamCreated(
256 entry->stream_id(),
257 foreign_memory_handle,
258 foreign_socket_handle,
259 entry->shared_memory()->requested_size()));
260 }
261
DoNotifyStreamStateChanged(int stream_id,bool is_playing)262 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id,
263 bool is_playing) {
264 DCHECK_CURRENTLY_ON(BrowserThread::IO);
265
266 AudioEntry* const entry = LookupById(stream_id);
267 if (!entry)
268 return;
269
270 Send(new AudioMsg_NotifyStreamStateChanged(
271 stream_id,
272 is_playing ? media::AudioOutputIPCDelegate::kPlaying
273 : media::AudioOutputIPCDelegate::kPaused));
274
275 MediaObserver* const media_observer =
276 GetContentClient()->browser()->GetMediaObserver();
277 if (media_observer) {
278 if (is_playing) {
279 media_observer->OnAudioStreamPlaying(
280 render_process_id_,
281 entry->render_frame_id(),
282 entry->stream_id(),
283 base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip,
284 entry->controller()));
285 if (!entry->playing()) {
286 entry->set_playing(true);
287 base::AtomicRefCountInc(&num_playing_streams_);
288 }
289 } else {
290 media_observer->OnAudioStreamStopped(render_process_id_,
291 entry->render_frame_id(),
292 entry->stream_id());
293 if (entry->playing()) {
294 entry->set_playing(false);
295 base::AtomicRefCountDec(&num_playing_streams_);
296 }
297 }
298 }
299 }
300
301 RenderViewHost::AudioOutputControllerList
DoGetOutputControllers(int render_view_id) const302 AudioRendererHost::DoGetOutputControllers(int render_view_id) const {
303 DCHECK_CURRENTLY_ON(BrowserThread::IO);
304
305 RenderViewHost::AudioOutputControllerList controllers;
306 AudioEntryMap::const_iterator it = audio_entries_.begin();
307 for (; it != audio_entries_.end(); ++it) {
308 AudioEntry* entry = it->second;
309 if (entry->render_view_id() == render_view_id)
310 controllers.push_back(entry->controller());
311 }
312
313 return controllers;
314 }
315
316 ///////////////////////////////////////////////////////////////////////////////
317 // IPC Messages handler
OnMessageReceived(const IPC::Message & message)318 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) {
319 bool handled = true;
320 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message)
321 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
322 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
323 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
324 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream)
325 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume)
326 IPC_MESSAGE_UNHANDLED(handled = false)
327 IPC_END_MESSAGE_MAP()
328
329 return handled;
330 }
331
OnCreateStream(int stream_id,int render_view_id,int render_frame_id,int session_id,const media::AudioParameters & params)332 void AudioRendererHost::OnCreateStream(
333 int stream_id, int render_view_id, int render_frame_id, int session_id,
334 const media::AudioParameters& params) {
335 DCHECK_CURRENTLY_ON(BrowserThread::IO);
336
337 DVLOG(1) << "AudioRendererHost@" << this
338 << "::OnCreateStream(stream_id=" << stream_id
339 << ", render_view_id=" << render_view_id
340 << ", session_id=" << session_id << ")";
341 DCHECK_GT(render_view_id, 0);
342 DCHECK_GT(render_frame_id, 0);
343
344 // media::AudioParameters is validated in the deserializer.
345 if (LookupById(stream_id) != NULL) {
346 SendErrorMessage(stream_id);
347 return;
348 }
349
350 // Initialize the |output_device_id| to an empty string which indicates that
351 // the default device should be used. If a StreamDeviceInfo instance was found
352 // though, then we use the matched output device.
353 std::string output_device_id;
354 const StreamDeviceInfo* info = media_stream_manager_->
355 audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
356 if (info)
357 output_device_id = info->device.matched_output_device_id;
358
359 // Create the shared memory and share with the renderer process.
360 // For synchronized I/O (if input_channels > 0) then we allocate
361 // extra memory after the output data for the input data.
362 uint32 shared_memory_size = AudioBus::CalculateMemorySize(params);
363 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
364 if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
365 SendErrorMessage(stream_id);
366 return;
367 }
368
369 scoped_ptr<AudioSyncReader> reader(
370 new AudioSyncReader(shared_memory.get(), params));
371 if (!reader->Init()) {
372 SendErrorMessage(stream_id);
373 return;
374 }
375
376 MediaObserver* const media_observer =
377 GetContentClient()->browser()->GetMediaObserver();
378 if (media_observer)
379 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
380
381 scoped_ptr<AudioEntry> entry(new AudioEntry(
382 this,
383 stream_id,
384 render_view_id,
385 render_frame_id,
386 params,
387 output_device_id,
388 shared_memory.Pass(),
389 reader.PassAs<media::AudioOutputController::SyncReader>()));
390 if (mirroring_manager_) {
391 mirroring_manager_->AddDiverter(
392 render_process_id_, entry->render_view_id(), entry->controller());
393 }
394 audio_entries_.insert(std::make_pair(stream_id, entry.release()));
395 audio_log_->OnCreated(stream_id, params, output_device_id);
396 }
397
OnPlayStream(int stream_id)398 void AudioRendererHost::OnPlayStream(int stream_id) {
399 DCHECK_CURRENTLY_ON(BrowserThread::IO);
400
401 AudioEntry* entry = LookupById(stream_id);
402 if (!entry) {
403 SendErrorMessage(stream_id);
404 return;
405 }
406
407 entry->controller()->Play();
408 audio_log_->OnStarted(stream_id);
409 }
410
OnPauseStream(int stream_id)411 void AudioRendererHost::OnPauseStream(int stream_id) {
412 DCHECK_CURRENTLY_ON(BrowserThread::IO);
413
414 AudioEntry* entry = LookupById(stream_id);
415 if (!entry) {
416 SendErrorMessage(stream_id);
417 return;
418 }
419
420 entry->controller()->Pause();
421 audio_log_->OnStopped(stream_id);
422 }
423
OnSetVolume(int stream_id,double volume)424 void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
425 DCHECK_CURRENTLY_ON(BrowserThread::IO);
426
427 AudioEntry* entry = LookupById(stream_id);
428 if (!entry) {
429 SendErrorMessage(stream_id);
430 return;
431 }
432
433 // Make sure the volume is valid.
434 if (volume < 0 || volume > 1.0)
435 return;
436 entry->controller()->SetVolume(volume);
437 audio_log_->OnSetVolume(stream_id, volume);
438 }
439
SendErrorMessage(int stream_id)440 void AudioRendererHost::SendErrorMessage(int stream_id) {
441 Send(new AudioMsg_NotifyStreamStateChanged(
442 stream_id, media::AudioOutputIPCDelegate::kError));
443 }
444
OnCloseStream(int stream_id)445 void AudioRendererHost::OnCloseStream(int stream_id) {
446 DCHECK_CURRENTLY_ON(BrowserThread::IO);
447
448 // Prevent oustanding callbacks from attempting to close/delete the same
449 // AudioEntry twice.
450 AudioEntryMap::iterator i = audio_entries_.find(stream_id);
451 if (i == audio_entries_.end())
452 return;
453 scoped_ptr<AudioEntry> entry(i->second);
454 audio_entries_.erase(i);
455
456 media::AudioOutputController* const controller = entry->controller();
457 if (mirroring_manager_) {
458 mirroring_manager_->RemoveDiverter(
459 render_process_id_, entry->render_view_id(), controller);
460 }
461 controller->Close(
462 base::Bind(&AudioRendererHost::DeleteEntry, this, base::Passed(&entry)));
463 audio_log_->OnClosed(stream_id);
464 }
465
DeleteEntry(scoped_ptr<AudioEntry> entry)466 void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
467 DCHECK_CURRENTLY_ON(BrowserThread::IO);
468
469 // At this point, make the final "say" in audio playback state.
470 MediaObserver* const media_observer =
471 GetContentClient()->browser()->GetMediaObserver();
472 if (media_observer) {
473 media_observer->OnAudioStreamStopped(render_process_id_,
474 entry->render_frame_id(),
475 entry->stream_id());
476 if (entry->playing())
477 base::AtomicRefCountDec(&num_playing_streams_);
478 }
479 }
480
ReportErrorAndClose(int stream_id)481 void AudioRendererHost::ReportErrorAndClose(int stream_id) {
482 DCHECK_CURRENTLY_ON(BrowserThread::IO);
483
484 // Make sure this isn't a stray callback executing after the stream has been
485 // closed, so error notifications aren't sent after clients believe the stream
486 // is closed.
487 if (!LookupById(stream_id))
488 return;
489
490 SendErrorMessage(stream_id);
491
492 audio_log_->OnError(stream_id);
493 OnCloseStream(stream_id);
494 }
495
LookupById(int stream_id)496 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
497 DCHECK_CURRENTLY_ON(BrowserThread::IO);
498
499 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
500 return i != audio_entries_.end() ? i->second : NULL;
501 }
502
HasActiveAudio()503 bool AudioRendererHost::HasActiveAudio() {
504 return !base::AtomicRefCountIsZero(&num_playing_streams_);
505 }
506
507 } // namespace content
508