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