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/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