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 44 int stream_id() const { 45 return stream_id_; 46 } 47 48 int render_view_id() const { 49 return render_view_id_; 50 } 51 52 int render_frame_id() const { return render_frame_id_; } 53 54 media::AudioOutputController* controller() const { return controller_.get(); } 55 56 base::SharedMemory* shared_memory() { 57 return shared_memory_.get(); 58 } 59 60 media::AudioOutputController::SyncReader* reader() const { 61 return reader_.get(); 62 } 63 64 bool playing() const { return 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 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 119 AudioRendererHost::AudioEntry::~AudioEntry() {} 120 121 /////////////////////////////////////////////////////////////////////////////// 122 // AudioRendererHost implementations. 123 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 142 AudioRendererHost::~AudioRendererHost() { 143 DCHECK(audio_entries_.empty()); 144 } 145 146 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 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 165 void AudioRendererHost::OnDestruct() const { 166 BrowserThread::DeleteOnIOThread::Destruct(this); 167 } 168 169 void AudioRendererHost::AudioEntry::OnCreated() { 170 BrowserThread::PostTask( 171 BrowserThread::IO, 172 FROM_HERE, 173 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_)); 174 } 175 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 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 196 void AudioRendererHost::AudioEntry::OnError() { 197 BrowserThread::PostTask( 198 BrowserThread::IO, 199 FROM_HERE, 200 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_)); 201 } 202 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 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 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 302 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 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 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 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 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 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 440 void AudioRendererHost::SendErrorMessage(int stream_id) { 441 Send(new AudioMsg_NotifyStreamStateChanged( 442 stream_id, media::AudioOutputIPCDelegate::kError)); 443 } 444 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 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 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 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 503 bool AudioRendererHost::HasActiveAudio() { 504 return !base::AtomicRefCountIsZero(&num_playing_streams_); 505 } 506 507 } // namespace content 508