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.
5 #include "content/browser/renderer_host/media/audio_renderer_host.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"
26 using media::AudioBus
;
27 using media::AudioManager
;
31 class AudioRendererHost::AudioEntry
32 : public media::AudioOutputController::EventHandler
{
34 AudioEntry(AudioRendererHost
* host
,
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();
44 int stream_id() const {
48 int render_view_id() const {
49 return render_view_id_
;
52 int render_frame_id() const { return render_frame_id_
; }
54 media::AudioOutputController
* controller() const { return controller_
.get(); }
56 base::SharedMemory
* shared_memory() {
57 return shared_memory_
.get();
60 media::AudioOutputController::SyncReader
* reader() const {
65 // media::AudioOutputController::EventHandler implementation.
66 virtual void OnCreated() OVERRIDE
;
67 virtual void OnPlaying() OVERRIDE
;
68 virtual void OnPaused() OVERRIDE
;
69 virtual void OnError() OVERRIDE
;
70 virtual void OnDeviceChange(int new_buffer_size
, int new_sample_rate
)
73 AudioRendererHost
* const host_
;
76 // The routing ID of the source render view/frame.
77 const int render_view_id_
;
78 const int render_frame_id_
;
80 // Shared memory for transmission of the audio data. Used by |reader_|.
81 const scoped_ptr
<base::SharedMemory
> shared_memory_
;
83 // The synchronous reader to be used by |controller_|.
84 const scoped_ptr
<media::AudioOutputController::SyncReader
> reader_
;
86 // The AudioOutputController that manages the audio stream.
87 const scoped_refptr
<media::AudioOutputController
> controller_
;
90 AudioRendererHost::AudioEntry::AudioEntry(
91 AudioRendererHost
* host
,
95 const media::AudioParameters
& params
,
96 const std::string
& output_device_id
,
97 scoped_ptr
<base::SharedMemory
> shared_memory
,
98 scoped_ptr
<media::AudioOutputController::SyncReader
> reader
)
100 stream_id_(stream_id
),
101 render_view_id_(render_view_id
),
102 render_frame_id_(render_frame_id
),
103 shared_memory_(shared_memory
.Pass()),
104 reader_(reader
.Pass()),
105 controller_(media::AudioOutputController::Create(host
->audio_manager_
,
110 DCHECK(controller_
.get());
113 AudioRendererHost::AudioEntry::~AudioEntry() {}
115 ///////////////////////////////////////////////////////////////////////////////
116 // AudioRendererHost implementations.
118 AudioRendererHost::AudioRendererHost(
119 int render_process_id
,
120 media::AudioManager
* audio_manager
,
121 AudioMirroringManager
* mirroring_manager
,
122 MediaInternals
* media_internals
,
123 MediaStreamManager
* media_stream_manager
)
124 : BrowserMessageFilter(AudioMsgStart
),
125 render_process_id_(render_process_id
),
126 audio_manager_(audio_manager
),
127 mirroring_manager_(mirroring_manager
),
128 audio_log_(media_internals
->CreateAudioLog(
129 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER
)),
130 media_stream_manager_(media_stream_manager
) {
131 DCHECK(audio_manager_
);
132 DCHECK(media_stream_manager_
);
135 AudioRendererHost::~AudioRendererHost() {
136 DCHECK(audio_entries_
.empty());
139 void AudioRendererHost::GetOutputControllers(
141 const RenderViewHost::GetAudioOutputControllersCallback
& callback
) const {
142 BrowserThread::PostTaskAndReplyWithResult(
145 base::Bind(&AudioRendererHost::DoGetOutputControllers
, this,
150 void AudioRendererHost::OnChannelClosing() {
151 // Since the IPC channel is gone, close all requested audio streams.
152 while (!audio_entries_
.empty()) {
153 // Note: OnCloseStream() removes the entries from audio_entries_.
154 OnCloseStream(audio_entries_
.begin()->first
);
158 void AudioRendererHost::OnDestruct() const {
159 BrowserThread::DeleteOnIOThread::Destruct(this);
162 void AudioRendererHost::AudioEntry::OnCreated() {
163 BrowserThread::PostTask(
166 base::Bind(&AudioRendererHost::DoCompleteCreation
, host_
, stream_id_
));
169 void AudioRendererHost::AudioEntry::OnPlaying() {
170 BrowserThread::PostTask(
173 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged
,
179 void AudioRendererHost::AudioEntry::OnPaused() {
180 BrowserThread::PostTask(
183 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged
,
189 void AudioRendererHost::AudioEntry::OnError() {
190 BrowserThread::PostTask(
193 base::Bind(&AudioRendererHost::ReportErrorAndClose
, host_
, stream_id_
));
196 void AudioRendererHost::AudioEntry::OnDeviceChange(int new_buffer_size
,
197 int new_sample_rate
) {
198 BrowserThread::PostTask(
201 base::Bind(base::IgnoreResult(&AudioRendererHost::Send
), host_
,
202 new AudioMsg_NotifyDeviceChanged(
203 stream_id_
, new_buffer_size
, new_sample_rate
)));
206 void AudioRendererHost::DoCompleteCreation(int stream_id
) {
207 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
210 DLOG(WARNING
) << "Renderer process handle is invalid.";
211 ReportErrorAndClose(stream_id
);
215 AudioEntry
* const entry
= LookupById(stream_id
);
217 ReportErrorAndClose(stream_id
);
221 // Once the audio stream is created then complete the creation process by
222 // mapping shared memory and sharing with the renderer process.
223 base::SharedMemoryHandle foreign_memory_handle
;
224 if (!entry
->shared_memory()->ShareToProcess(PeerHandle(),
225 &foreign_memory_handle
)) {
226 // If we failed to map and share the shared memory then close the audio
227 // stream and send an error message.
228 ReportErrorAndClose(entry
->stream_id());
232 AudioSyncReader
* reader
= static_cast<AudioSyncReader
*>(entry
->reader());
235 base::SyncSocket::Handle foreign_socket_handle
;
237 base::FileDescriptor foreign_socket_handle
;
240 // If we failed to prepare the sync socket for the renderer then we fail
241 // the construction of audio stream.
242 if (!reader
->PrepareForeignSocketHandle(PeerHandle(),
243 &foreign_socket_handle
)) {
244 ReportErrorAndClose(entry
->stream_id());
248 Send(new AudioMsg_NotifyStreamCreated(
250 foreign_memory_handle
,
251 foreign_socket_handle
,
252 entry
->shared_memory()->requested_size()));
255 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id
,
257 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
259 AudioEntry
* const entry
= LookupById(stream_id
);
263 Send(new AudioMsg_NotifyStreamStateChanged(
265 is_playing
? media::AudioOutputIPCDelegate::kPlaying
266 : media::AudioOutputIPCDelegate::kPaused
));
268 MediaObserver
* const media_observer
=
269 GetContentClient()->browser()->GetMediaObserver();
270 if (media_observer
) {
272 media_observer
->OnAudioStreamPlaying(
274 entry
->render_frame_id(),
276 base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip
,
277 entry
->controller()));
279 media_observer
->OnAudioStreamStopped(render_process_id_
,
280 entry
->render_frame_id(),
286 RenderViewHost::AudioOutputControllerList
287 AudioRendererHost::DoGetOutputControllers(int render_view_id
) const {
288 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
290 RenderViewHost::AudioOutputControllerList controllers
;
291 AudioEntryMap::const_iterator it
= audio_entries_
.begin();
292 for (; it
!= audio_entries_
.end(); ++it
) {
293 AudioEntry
* entry
= it
->second
;
294 if (entry
->render_view_id() == render_view_id
)
295 controllers
.push_back(entry
->controller());
301 ///////////////////////////////////////////////////////////////////////////////
302 // IPC Messages handler
303 bool AudioRendererHost::OnMessageReceived(const IPC::Message
& message
,
304 bool* message_was_ok
) {
306 IPC_BEGIN_MESSAGE_MAP_EX(AudioRendererHost
, message
, *message_was_ok
)
307 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream
, OnCreateStream
)
308 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream
, OnPlayStream
)
309 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream
, OnPauseStream
)
310 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream
, OnCloseStream
)
311 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume
, OnSetVolume
)
312 IPC_MESSAGE_UNHANDLED(handled
= false)
313 IPC_END_MESSAGE_MAP_EX()
318 void AudioRendererHost::OnCreateStream(
319 int stream_id
, int render_view_id
, int render_frame_id
, int session_id
,
320 const media::AudioParameters
& params
) {
321 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
323 DVLOG(1) << "AudioRendererHost@" << this
324 << "::OnCreateStream(stream_id=" << stream_id
325 << ", render_view_id=" << render_view_id
326 << ", session_id=" << session_id
<< ")";
327 DCHECK_GT(render_view_id
, 0);
328 DCHECK_GT(render_frame_id
, 0);
330 // media::AudioParameters is validated in the deserializer.
331 if (LookupById(stream_id
) != NULL
) {
332 SendErrorMessage(stream_id
);
336 // Initialize the |output_device_id| to an empty string which indicates that
337 // the default device should be used. If a StreamDeviceInfo instance was found
338 // though, then we use the matched output device.
339 std::string output_device_id
;
340 const StreamDeviceInfo
* info
= media_stream_manager_
->
341 audio_input_device_manager()->GetOpenedDeviceInfoById(session_id
);
343 output_device_id
= info
->device
.matched_output_device_id
;
345 // Create the shared memory and share with the renderer process.
346 // For synchronized I/O (if input_channels > 0) then we allocate
347 // extra memory after the output data for the input data.
348 uint32 shared_memory_size
= AudioBus::CalculateMemorySize(params
);
349 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory());
350 if (!shared_memory
->CreateAndMapAnonymous(shared_memory_size
)) {
351 SendErrorMessage(stream_id
);
355 scoped_ptr
<AudioSyncReader
> reader(
356 new AudioSyncReader(shared_memory
.get(), params
));
357 if (!reader
->Init()) {
358 SendErrorMessage(stream_id
);
362 MediaObserver
* const media_observer
=
363 GetContentClient()->browser()->GetMediaObserver();
365 media_observer
->OnCreatingAudioStream(render_process_id_
, render_frame_id
);
367 scoped_ptr
<AudioEntry
> entry(new AudioEntry(
374 shared_memory
.Pass(),
375 reader
.PassAs
<media::AudioOutputController::SyncReader
>()));
376 if (mirroring_manager_
) {
377 mirroring_manager_
->AddDiverter(
378 render_process_id_
, entry
->render_view_id(), entry
->controller());
380 audio_entries_
.insert(std::make_pair(stream_id
, entry
.release()));
381 audio_log_
->OnCreated(stream_id
, params
, output_device_id
);
384 void AudioRendererHost::OnPlayStream(int stream_id
) {
385 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
387 AudioEntry
* entry
= LookupById(stream_id
);
389 SendErrorMessage(stream_id
);
393 entry
->controller()->Play();
394 audio_log_
->OnStarted(stream_id
);
397 void AudioRendererHost::OnPauseStream(int stream_id
) {
398 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
400 AudioEntry
* entry
= LookupById(stream_id
);
402 SendErrorMessage(stream_id
);
406 entry
->controller()->Pause();
407 audio_log_
->OnStopped(stream_id
);
410 void AudioRendererHost::OnSetVolume(int stream_id
, double volume
) {
411 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
413 AudioEntry
* entry
= LookupById(stream_id
);
415 SendErrorMessage(stream_id
);
419 // Make sure the volume is valid.
420 if (volume
< 0 || volume
> 1.0)
422 entry
->controller()->SetVolume(volume
);
423 audio_log_
->OnSetVolume(stream_id
, volume
);
426 void AudioRendererHost::SendErrorMessage(int stream_id
) {
427 Send(new AudioMsg_NotifyStreamStateChanged(
428 stream_id
, media::AudioOutputIPCDelegate::kError
));
431 void AudioRendererHost::OnCloseStream(int stream_id
) {
432 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
434 // Prevent oustanding callbacks from attempting to close/delete the same
436 AudioEntryMap::iterator i
= audio_entries_
.find(stream_id
);
437 if (i
== audio_entries_
.end())
439 scoped_ptr
<AudioEntry
> entry(i
->second
);
440 audio_entries_
.erase(i
);
442 media::AudioOutputController
* const controller
= entry
->controller();
443 if (mirroring_manager_
) {
444 mirroring_manager_
->RemoveDiverter(
445 render_process_id_
, entry
->render_view_id(), controller
);
448 base::Bind(&AudioRendererHost::DeleteEntry
, this, base::Passed(&entry
)));
449 audio_log_
->OnClosed(stream_id
);
452 void AudioRendererHost::DeleteEntry(scoped_ptr
<AudioEntry
> entry
) {
453 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
455 // At this point, make the final "say" in audio playback state.
456 MediaObserver
* const media_observer
=
457 GetContentClient()->browser()->GetMediaObserver();
458 if (media_observer
) {
459 media_observer
->OnAudioStreamStopped(render_process_id_
,
460 entry
->render_frame_id(),
465 void AudioRendererHost::ReportErrorAndClose(int stream_id
) {
466 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
468 // Make sure this isn't a stray callback executing after the stream has been
469 // closed, so error notifications aren't sent after clients believe the stream
471 if (!LookupById(stream_id
))
474 SendErrorMessage(stream_id
);
476 audio_log_
->OnError(stream_id
);
477 OnCloseStream(stream_id
);
480 AudioRendererHost::AudioEntry
* AudioRendererHost::LookupById(int stream_id
) {
481 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
483 AudioEntryMap::const_iterator i
= audio_entries_
.find(stream_id
);
484 return i
!= audio_entries_
.end() ? i
->second
: NULL
;
487 } // namespace content