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/media_internals.h"
14 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
15 #include "content/browser/renderer_host/media/audio_mirroring_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,
37 const media::AudioParameters& params,
38 const std::string& output_device_id,
39 scoped_ptr<base::SharedMemory> shared_memory,
40 scoped_ptr<media::AudioOutputController::SyncReader> reader);
41 virtual ~AudioEntry();
43 int stream_id() const {
47 int render_view_id() const {
48 return render_view_id_;
51 media::AudioOutputController* controller() const { return controller_.get(); }
53 base::SharedMemory* shared_memory() {
54 return shared_memory_.get();
57 media::AudioOutputController::SyncReader* reader() const {
62 // media::AudioOutputController::EventHandler implementation.
63 virtual void OnCreated() OVERRIDE;
64 virtual void OnPlaying() OVERRIDE;
65 virtual void OnPowerMeasured(float power_dbfs, bool clipped) OVERRIDE;
66 virtual void OnPaused() OVERRIDE;
67 virtual void OnError() OVERRIDE;
68 virtual void OnDeviceChange(int new_buffer_size, int new_sample_rate)
71 AudioRendererHost* const host_;
74 // The routing ID of the source render view.
75 const int render_view_id_;
77 // The AudioOutputController that manages the audio stream.
78 const scoped_refptr<media::AudioOutputController> controller_;
80 // Shared memory for transmission of the audio data.
81 const scoped_ptr<base::SharedMemory> shared_memory_;
83 // The synchronous reader to be used by the controller.
84 const scoped_ptr<media::AudioOutputController::SyncReader> reader_;
87 AudioRendererHost::AudioEntry::AudioEntry(
88 AudioRendererHost* host, int stream_id, int render_view_id,
89 const media::AudioParameters& params,
90 const std::string& output_device_id,
91 scoped_ptr<base::SharedMemory> shared_memory,
92 scoped_ptr<media::AudioOutputController::SyncReader> reader)
94 stream_id_(stream_id),
95 render_view_id_(render_view_id),
96 controller_(media::AudioOutputController::Create(
97 host->audio_manager_, this, params, output_device_id, reader.get())),
98 shared_memory_(shared_memory.Pass()),
99 reader_(reader.Pass()) {
100 DCHECK(controller_.get());
103 AudioRendererHost::AudioEntry::~AudioEntry() {}
105 ///////////////////////////////////////////////////////////////////////////////
106 // AudioRendererHost implementations.
108 AudioRendererHost::AudioRendererHost(
109 int render_process_id,
110 media::AudioManager* audio_manager,
111 AudioMirroringManager* mirroring_manager,
112 MediaInternals* media_internals,
113 MediaStreamManager* media_stream_manager)
114 : render_process_id_(render_process_id),
115 audio_manager_(audio_manager),
116 mirroring_manager_(mirroring_manager),
117 audio_log_(media_internals->CreateAudioLog(
118 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)),
119 media_stream_manager_(media_stream_manager) {
120 DCHECK(audio_manager_);
121 DCHECK(media_stream_manager_);
124 AudioRendererHost::~AudioRendererHost() {
125 DCHECK(audio_entries_.empty());
128 void AudioRendererHost::GetOutputControllers(
130 const RenderViewHost::GetAudioOutputControllersCallback& callback) const {
131 BrowserThread::PostTaskAndReplyWithResult(
134 base::Bind(&AudioRendererHost::DoGetOutputControllers, this,
139 void AudioRendererHost::OnChannelClosing() {
140 // Since the IPC channel is gone, close all requested audio streams.
141 while (!audio_entries_.empty()) {
142 // Note: OnCloseStream() removes the entries from audio_entries_.
143 OnCloseStream(audio_entries_.begin()->first);
147 void AudioRendererHost::OnDestruct() const {
148 BrowserThread::DeleteOnIOThread::Destruct(this);
151 void AudioRendererHost::AudioEntry::OnCreated() {
152 BrowserThread::PostTask(
155 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_));
158 void AudioRendererHost::AudioEntry::OnPlaying() {
159 BrowserThread::PostTask(
163 base::IgnoreResult(&AudioRendererHost::Send), host_,
164 new AudioMsg_NotifyStreamStateChanged(
165 stream_id_, media::AudioOutputIPCDelegate::kPlaying)));
168 void AudioRendererHost::AudioEntry::OnPowerMeasured(float power_dbfs,
170 BrowserThread::PostTask(
173 base::Bind(&AudioRendererHost::DoNotifyAudioPowerLevel, host_,
174 stream_id_, power_dbfs, clipped));
177 void AudioRendererHost::AudioEntry::OnPaused() {
178 BrowserThread::PostTask(
182 base::IgnoreResult(&AudioRendererHost::Send), host_,
183 new AudioMsg_NotifyStreamStateChanged(
184 stream_id_, media::AudioOutputIPCDelegate::kPaused)));
187 void AudioRendererHost::AudioEntry::OnError() {
188 BrowserThread::PostTask(
191 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_));
194 void AudioRendererHost::AudioEntry::OnDeviceChange(int new_buffer_size,
195 int new_sample_rate) {
196 BrowserThread::PostTask(
199 base::Bind(base::IgnoreResult(&AudioRendererHost::Send), host_,
200 new AudioMsg_NotifyDeviceChanged(
201 stream_id_, new_buffer_size, new_sample_rate)));
204 void AudioRendererHost::DoCompleteCreation(int stream_id) {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
208 DLOG(WARNING) << "Renderer process handle is invalid.";
209 ReportErrorAndClose(stream_id);
213 AudioEntry* const entry = LookupById(stream_id);
215 ReportErrorAndClose(stream_id);
219 // Once the audio stream is created then complete the creation process by
220 // mapping shared memory and sharing with the renderer process.
221 base::SharedMemoryHandle foreign_memory_handle;
222 if (!entry->shared_memory()->ShareToProcess(PeerHandle(),
223 &foreign_memory_handle)) {
224 // If we failed to map and share the shared memory then close the audio
225 // stream and send an error message.
226 ReportErrorAndClose(entry->stream_id());
230 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader());
233 base::SyncSocket::Handle foreign_socket_handle;
235 base::FileDescriptor foreign_socket_handle;
238 // If we failed to prepare the sync socket for the renderer then we fail
239 // the construction of audio stream.
240 if (!reader->PrepareForeignSocketHandle(PeerHandle(),
241 &foreign_socket_handle)) {
242 ReportErrorAndClose(entry->stream_id());
246 Send(new AudioMsg_NotifyStreamCreated(
248 foreign_memory_handle,
249 foreign_socket_handle,
250 entry->shared_memory()->requested_size()));
253 RenderViewHost::AudioOutputControllerList
254 AudioRendererHost::DoGetOutputControllers(int render_view_id) const {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
257 RenderViewHost::AudioOutputControllerList controllers;
258 AudioEntryMap::const_iterator it = audio_entries_.begin();
259 for (; it != audio_entries_.end(); ++it) {
260 AudioEntry* entry = it->second;
261 if (entry->render_view_id() == render_view_id)
262 controllers.push_back(entry->controller());
268 void AudioRendererHost::DoNotifyAudioPowerLevel(int stream_id,
271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
273 MediaObserver* const media_observer =
274 GetContentClient()->browser()->GetMediaObserver();
275 if (media_observer) {
276 AudioEntry* const entry = LookupById(stream_id);
278 media_observer->OnAudioStreamPlayingChanged(
279 render_process_id_, entry->render_view_id(), entry->stream_id(),
280 true, power_dbfs, clipped);
285 ///////////////////////////////////////////////////////////////////////////////
286 // IPC Messages handler
287 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message,
288 bool* message_was_ok) {
290 IPC_BEGIN_MESSAGE_MAP_EX(AudioRendererHost, message, *message_was_ok)
291 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
292 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
293 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
294 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream)
295 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume)
296 IPC_MESSAGE_UNHANDLED(handled = false)
297 IPC_END_MESSAGE_MAP_EX()
302 void AudioRendererHost::OnCreateStream(
303 int stream_id, int render_view_id, int render_frame_id, int session_id,
304 const media::AudioParameters& params) {
305 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
307 DVLOG(1) << "AudioRendererHost@" << this
308 << "::OnCreateStream(stream_id=" << stream_id
309 << ", render_view_id=" << render_view_id
310 << ", session_id=" << session_id << ")";
311 DCHECK_GT(render_view_id, 0);
313 // media::AudioParameters is validated in the deserializer.
314 if (LookupById(stream_id) != NULL) {
315 SendErrorMessage(stream_id);
319 // Initialize the |output_device_id| to an empty string which indicates that
320 // the default device should be used. If a StreamDeviceInfo instance was found
321 // though, then we use the matched output device.
322 std::string output_device_id;
323 const StreamDeviceInfo* info = media_stream_manager_->
324 audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
326 output_device_id = info->device.matched_output_device_id;
328 // Create the shared memory and share with the renderer process.
329 // For synchronized I/O (if input_channels > 0) then we allocate
330 // extra memory after the output data for the input data.
331 uint32 shared_memory_size = AudioBus::CalculateMemorySize(params);;
332 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
333 if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
334 SendErrorMessage(stream_id);
338 scoped_ptr<AudioSyncReader> reader(
339 new AudioSyncReader(shared_memory.get(), params));
340 if (!reader->Init()) {
341 SendErrorMessage(stream_id);
345 MediaObserver* const media_observer =
346 GetContentClient()->browser()->GetMediaObserver();
348 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
350 scoped_ptr<AudioEntry> entry(new AudioEntry(
351 this, stream_id, render_view_id, params, output_device_id,
352 shared_memory.Pass(),
353 reader.PassAs<media::AudioOutputController::SyncReader>()));
354 if (mirroring_manager_) {
355 mirroring_manager_->AddDiverter(
356 render_process_id_, entry->render_view_id(), entry->controller());
358 audio_entries_.insert(std::make_pair(stream_id, entry.release()));
359 audio_log_->OnCreated(stream_id, params, output_device_id);
362 void AudioRendererHost::OnPlayStream(int stream_id) {
363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
365 AudioEntry* entry = LookupById(stream_id);
367 SendErrorMessage(stream_id);
371 entry->controller()->Play();
372 audio_log_->OnStarted(stream_id);
375 void AudioRendererHost::OnPauseStream(int stream_id) {
376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
378 AudioEntry* entry = LookupById(stream_id);
380 SendErrorMessage(stream_id);
384 entry->controller()->Pause();
385 audio_log_->OnStopped(stream_id);
388 void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
391 AudioEntry* entry = LookupById(stream_id);
393 SendErrorMessage(stream_id);
397 // Make sure the volume is valid.
398 if (volume < 0 || volume > 1.0)
400 entry->controller()->SetVolume(volume);
401 audio_log_->OnSetVolume(stream_id, volume);
404 void AudioRendererHost::SendErrorMessage(int stream_id) {
405 Send(new AudioMsg_NotifyStreamStateChanged(
406 stream_id, media::AudioOutputIPCDelegate::kError));
409 void AudioRendererHost::OnCloseStream(int stream_id) {
410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
412 // Prevent oustanding callbacks from attempting to close/delete the same
414 AudioEntryMap::iterator i = audio_entries_.find(stream_id);
415 if (i == audio_entries_.end())
417 scoped_ptr<AudioEntry> entry(i->second);
418 audio_entries_.erase(i);
420 media::AudioOutputController* const controller = entry->controller();
421 if (mirroring_manager_) {
422 mirroring_manager_->RemoveDiverter(
423 render_process_id_, entry->render_view_id(), controller);
426 base::Bind(&AudioRendererHost::DeleteEntry, this, base::Passed(&entry)));
427 audio_log_->OnClosed(stream_id);
430 void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
431 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
433 // At this point, make the final "say" in audio playback state.
434 MediaObserver* const media_observer =
435 GetContentClient()->browser()->GetMediaObserver();
436 if (media_observer) {
437 media_observer->OnAudioStreamPlayingChanged(
438 render_process_id_, entry->render_view_id(), entry->stream_id(),
439 false, -std::numeric_limits<float>::infinity(), false);
443 void AudioRendererHost::ReportErrorAndClose(int stream_id) {
444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
446 // Make sure this isn't a stray callback executing after the stream has been
447 // closed, so error notifications aren't sent after clients believe the stream
449 if (!LookupById(stream_id))
452 SendErrorMessage(stream_id);
454 audio_log_->OnError(stream_id);
455 OnCloseStream(stream_id);
458 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
459 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
461 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
462 return i != audio_entries_.end() ? i->second : NULL;
465 } // namespace content