Home | History | Annotate | Download | only in media
      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