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/command_line.h"
     10 #include "base/memory/shared_memory.h"
     11 #include "base/metrics/histogram.h"
     12 #include "base/process/process.h"
     13 #include "content/browser/browser_main_loop.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_mirroring_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/audio/shared_memory_util.h"
     25 #include "media/base/audio_bus.h"
     26 #include "media/base/limits.h"
     27 
     28 using media::AudioBus;
     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              const media::AudioParameters& params,
     39              const std::string& input_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   media::AudioOutputController* controller() const { return controller_.get(); }
     53 
     54   base::SharedMemory* shared_memory() {
     55     return shared_memory_.get();
     56   }
     57 
     58   media::AudioOutputController::SyncReader* reader() const {
     59     return reader_.get();
     60   }
     61 
     62  private:
     63   // media::AudioOutputController::EventHandler implementation.
     64   virtual void OnCreated() OVERRIDE;
     65   virtual void OnPlaying() OVERRIDE;
     66   virtual void OnPowerMeasured(float power_dbfs, bool clipped) OVERRIDE;
     67   virtual void OnPaused() OVERRIDE;
     68   virtual void OnError() OVERRIDE;
     69   virtual void OnDeviceChange(int new_buffer_size, int new_sample_rate)
     70       OVERRIDE;
     71 
     72   AudioRendererHost* const host_;
     73   const int stream_id_;
     74 
     75   // The routing ID of the source render view.
     76   const int render_view_id_;
     77 
     78   // The AudioOutputController that manages the audio stream.
     79   const scoped_refptr<media::AudioOutputController> controller_;
     80 
     81   // Shared memory for transmission of the audio data.
     82   const scoped_ptr<base::SharedMemory> shared_memory_;
     83 
     84   // The synchronous reader to be used by the controller.
     85   const scoped_ptr<media::AudioOutputController::SyncReader> reader_;
     86 };
     87 
     88 AudioRendererHost::AudioEntry::AudioEntry(
     89     AudioRendererHost* host, int stream_id, int render_view_id,
     90     const media::AudioParameters& params,
     91     const std::string& input_device_id,
     92     scoped_ptr<base::SharedMemory> shared_memory,
     93     scoped_ptr<media::AudioOutputController::SyncReader> reader)
     94     : host_(host),
     95       stream_id_(stream_id),
     96       render_view_id_(render_view_id),
     97       controller_(media::AudioOutputController::Create(
     98           host->audio_manager_, this, params, input_device_id, reader.get())),
     99       shared_memory_(shared_memory.Pass()),
    100       reader_(reader.Pass()) {
    101   DCHECK(controller_.get());
    102 }
    103 
    104 AudioRendererHost::AudioEntry::~AudioEntry() {}
    105 
    106 ///////////////////////////////////////////////////////////////////////////////
    107 // 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       media_internals_(media_internals),
    118       media_stream_manager_(media_stream_manager) {
    119   DCHECK(audio_manager_);
    120   DCHECK(media_stream_manager_);
    121 }
    122 
    123 AudioRendererHost::~AudioRendererHost() {
    124   DCHECK(audio_entries_.empty());
    125 }
    126 
    127 void AudioRendererHost::OnChannelClosing() {
    128   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    129 
    130   BrowserMessageFilter::OnChannelClosing();
    131 
    132   // Since the IPC channel is gone, close all requested audio streams.
    133   while (!audio_entries_.empty()) {
    134     // Note: OnCloseStream() removes the entries from audio_entries_.
    135     OnCloseStream(audio_entries_.begin()->first);
    136   }
    137 }
    138 
    139 void AudioRendererHost::OnDestruct() const {
    140   BrowserThread::DeleteOnIOThread::Destruct(this);
    141 }
    142 
    143 void AudioRendererHost::AudioEntry::OnCreated() {
    144   BrowserThread::PostTask(
    145       BrowserThread::IO,
    146       FROM_HERE,
    147       base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_));
    148 }
    149 
    150 void AudioRendererHost::AudioEntry::OnPlaying() {
    151   BrowserThread::PostTask(
    152       BrowserThread::IO,
    153       FROM_HERE,
    154       base::Bind(
    155           base::IgnoreResult(&AudioRendererHost::Send), host_,
    156           new AudioMsg_NotifyStreamStateChanged(
    157               stream_id_, media::AudioOutputIPCDelegate::kPlaying)));
    158 }
    159 
    160 void AudioRendererHost::AudioEntry::OnPowerMeasured(float power_dbfs,
    161                                                     bool clipped) {
    162   BrowserThread::PostTask(
    163       BrowserThread::IO,
    164       FROM_HERE,
    165       base::Bind(&AudioRendererHost::DoNotifyAudioPowerLevel, host_,
    166                  stream_id_, power_dbfs, clipped));
    167 }
    168 
    169 void AudioRendererHost::AudioEntry::OnPaused() {
    170   BrowserThread::PostTask(
    171       BrowserThread::IO,
    172       FROM_HERE,
    173       base::Bind(
    174           base::IgnoreResult(&AudioRendererHost::Send), host_,
    175           new AudioMsg_NotifyStreamStateChanged(
    176               stream_id_, media::AudioOutputIPCDelegate::kPaused)));
    177 }
    178 
    179 void AudioRendererHost::AudioEntry::OnError() {
    180   BrowserThread::PostTask(
    181       BrowserThread::IO,
    182       FROM_HERE,
    183       base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_));
    184 }
    185 
    186 void AudioRendererHost::AudioEntry::OnDeviceChange(int new_buffer_size,
    187                                                    int new_sample_rate) {
    188   BrowserThread::PostTask(
    189       BrowserThread::IO,
    190       FROM_HERE,
    191       base::Bind(base::IgnoreResult(&AudioRendererHost::Send), host_,
    192                  new AudioMsg_NotifyDeviceChanged(
    193                      stream_id_, new_buffer_size, new_sample_rate)));
    194 }
    195 
    196 void AudioRendererHost::DoCompleteCreation(int stream_id) {
    197   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    198 
    199   if (!PeerHandle()) {
    200     NOTREACHED() << "Renderer process handle is invalid.";
    201     ReportErrorAndClose(stream_id);
    202     return;
    203   }
    204 
    205   AudioEntry* const entry = LookupById(stream_id);
    206   if (!entry) {
    207     ReportErrorAndClose(stream_id);
    208     return;
    209   }
    210 
    211   // Once the audio stream is created then complete the creation process by
    212   // mapping shared memory and sharing with the renderer process.
    213   base::SharedMemoryHandle foreign_memory_handle;
    214   if (!entry->shared_memory()->ShareToProcess(PeerHandle(),
    215                                               &foreign_memory_handle)) {
    216     // If we failed to map and share the shared memory then close the audio
    217     // stream and send an error message.
    218     ReportErrorAndClose(entry->stream_id());
    219     return;
    220   }
    221 
    222   AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader());
    223 
    224 #if defined(OS_WIN)
    225   base::SyncSocket::Handle foreign_socket_handle;
    226 #else
    227   base::FileDescriptor foreign_socket_handle;
    228 #endif
    229 
    230   // If we failed to prepare the sync socket for the renderer then we fail
    231   // the construction of audio stream.
    232   if (!reader->PrepareForeignSocketHandle(PeerHandle(),
    233                                           &foreign_socket_handle)) {
    234     ReportErrorAndClose(entry->stream_id());
    235     return;
    236   }
    237 
    238   Send(new AudioMsg_NotifyStreamCreated(
    239       entry->stream_id(),
    240       foreign_memory_handle,
    241       foreign_socket_handle,
    242       media::PacketSizeInBytes(entry->shared_memory()->requested_size())));
    243 }
    244 
    245 void AudioRendererHost::DoNotifyAudioPowerLevel(int stream_id,
    246                                                 float power_dbfs,
    247                                                 bool clipped) {
    248   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    249 
    250   MediaObserver* const media_observer =
    251       GetContentClient()->browser()->GetMediaObserver();
    252   if (media_observer) {
    253     if (CommandLine::ForCurrentProcess()->HasSwitch(
    254             switches::kEnableAudibleNotifications)) {
    255       AudioEntry* const entry = LookupById(stream_id);
    256       if (entry) {
    257         media_observer->OnAudioStreamPlayingChanged(
    258             render_process_id_, entry->render_view_id(), entry->stream_id(),
    259             true, power_dbfs, clipped);
    260       }
    261     }
    262   }
    263 }
    264 
    265 ///////////////////////////////////////////////////////////////////////////////
    266 // IPC Messages handler
    267 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message,
    268                                           bool* message_was_ok) {
    269   bool handled = true;
    270   IPC_BEGIN_MESSAGE_MAP_EX(AudioRendererHost, message, *message_was_ok)
    271     IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
    272     IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
    273     IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
    274     IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream)
    275     IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume)
    276     IPC_MESSAGE_UNHANDLED(handled = false)
    277   IPC_END_MESSAGE_MAP_EX()
    278 
    279   return handled;
    280 }
    281 
    282 void AudioRendererHost::OnCreateStream(
    283     int stream_id, int render_view_id, int session_id,
    284     const media::AudioParameters& params) {
    285   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    286 
    287   DVLOG(1) << "AudioRendererHost@" << this
    288            << "::OnCreateStream(stream_id=" << stream_id
    289            << ", render_view_id=" << render_view_id
    290            << ", session_id=" << session_id << ")";
    291   DCHECK_GT(render_view_id, 0);
    292 
    293   // media::AudioParameters is validated in the deserializer.
    294   int input_channels = params.input_channels();
    295   if (input_channels < 0 ||
    296       input_channels > media::limits::kMaxChannels ||
    297       LookupById(stream_id) != NULL) {
    298     SendErrorMessage(stream_id);
    299     return;
    300   }
    301 
    302   // When the |input_channels| is valid, clients are trying to create a unified
    303   // IO stream which opens an input device mapping to the |session_id|.
    304   std::string input_device_id;
    305   if (input_channels > 0) {
    306     const StreamDeviceInfo* info = media_stream_manager_->
    307         audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
    308     if (!info) {
    309       SendErrorMessage(stream_id);
    310       DLOG(WARNING) << "No permission has been granted to input stream with "
    311                     << "session_id=" << session_id;
    312       return;
    313     }
    314 
    315     input_device_id = info->device.id;
    316   }
    317 
    318   // Calculate output and input memory size.
    319   int output_memory_size = AudioBus::CalculateMemorySize(params);
    320   int frames = params.frames_per_buffer();
    321   int input_memory_size =
    322       AudioBus::CalculateMemorySize(input_channels, frames);
    323 
    324   // Create the shared memory and share with the renderer process.
    325   // For synchronized I/O (if input_channels > 0) then we allocate
    326   // extra memory after the output data for the input data.
    327   uint32 io_buffer_size = output_memory_size + input_memory_size;
    328   uint32 shared_memory_size =
    329       media::TotalSharedMemorySizeInBytes(io_buffer_size);
    330   scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
    331   if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
    332     SendErrorMessage(stream_id);
    333     return;
    334   }
    335 
    336   scoped_ptr<AudioSyncReader> reader(
    337       new AudioSyncReader(shared_memory.get(), params, input_channels));
    338   if (!reader->Init()) {
    339     SendErrorMessage(stream_id);
    340     return;
    341   }
    342 
    343   MediaObserver* const media_observer =
    344       GetContentClient()->browser()->GetMediaObserver();
    345   if (media_observer)
    346     media_observer->OnCreatingAudioStream(render_process_id_, render_view_id);
    347 
    348   scoped_ptr<AudioEntry> entry(new AudioEntry(
    349       this, stream_id, render_view_id, params, input_device_id,
    350       shared_memory.Pass(),
    351       reader.PassAs<media::AudioOutputController::SyncReader>()));
    352   if (mirroring_manager_) {
    353     mirroring_manager_->AddDiverter(
    354         render_process_id_, entry->render_view_id(), entry->controller());
    355   }
    356   audio_entries_.insert(std::make_pair(stream_id, entry.release()));
    357   if (media_internals_)
    358     media_internals_->OnSetAudioStreamStatus(this, stream_id, "created");
    359 }
    360 
    361 void AudioRendererHost::OnPlayStream(int stream_id) {
    362   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    363 
    364   AudioEntry* entry = LookupById(stream_id);
    365   if (!entry) {
    366     SendErrorMessage(stream_id);
    367     return;
    368   }
    369 
    370   entry->controller()->Play();
    371   if (media_internals_)
    372     media_internals_->OnSetAudioStreamPlaying(this, stream_id, true);
    373 }
    374 
    375 void AudioRendererHost::OnPauseStream(int stream_id) {
    376   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    377 
    378   AudioEntry* entry = LookupById(stream_id);
    379   if (!entry) {
    380     SendErrorMessage(stream_id);
    381     return;
    382   }
    383 
    384   entry->controller()->Pause();
    385   if (media_internals_)
    386     media_internals_->OnSetAudioStreamPlaying(this, stream_id, false);
    387 }
    388 
    389 void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
    390   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    391 
    392   AudioEntry* entry = LookupById(stream_id);
    393   if (!entry) {
    394     SendErrorMessage(stream_id);
    395     return;
    396   }
    397 
    398   // Make sure the volume is valid.
    399   if (volume < 0 || volume > 1.0)
    400     return;
    401   entry->controller()->SetVolume(volume);
    402   if (media_internals_)
    403     media_internals_->OnSetAudioStreamVolume(this, stream_id, volume);
    404 }
    405 
    406 void AudioRendererHost::SendErrorMessage(int stream_id) {
    407   Send(new AudioMsg_NotifyStreamStateChanged(
    408       stream_id, media::AudioOutputIPCDelegate::kError));
    409 }
    410 
    411 void AudioRendererHost::OnCloseStream(int stream_id) {
    412   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    413 
    414   // Prevent oustanding callbacks from attempting to close/delete the same
    415   // AudioEntry twice.
    416   AudioEntryMap::iterator i = audio_entries_.find(stream_id);
    417   if (i == audio_entries_.end())
    418     return;
    419   scoped_ptr<AudioEntry> entry(i->second);
    420   audio_entries_.erase(i);
    421 
    422   media::AudioOutputController* const controller = entry->controller();
    423   if (mirroring_manager_) {
    424     mirroring_manager_->RemoveDiverter(
    425         render_process_id_, entry->render_view_id(), controller);
    426   }
    427   controller->Close(
    428       base::Bind(&AudioRendererHost::DeleteEntry, this, base::Passed(&entry)));
    429 
    430   if (media_internals_)
    431     media_internals_->OnSetAudioStreamStatus(this, stream_id, "closed");
    432 }
    433 
    434 void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
    435   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    436 
    437   // At this point, make the final "say" in audio playback state.
    438   MediaObserver* const media_observer =
    439       GetContentClient()->browser()->GetMediaObserver();
    440   if (media_observer) {
    441     media_observer->OnAudioStreamPlayingChanged(
    442         render_process_id_, entry->render_view_id(), entry->stream_id(),
    443         false, -std::numeric_limits<float>::infinity(), false);
    444   }
    445 
    446   // Notify the media observer.
    447   if (media_internals_)
    448     media_internals_->OnDeleteAudioStream(this, entry->stream_id());
    449 
    450   // Note: |entry| will be deleted upon leaving this scope.
    451 }
    452 
    453 void AudioRendererHost::ReportErrorAndClose(int stream_id) {
    454   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    455 
    456   // Make sure this isn't a stray callback executing after the stream has been
    457   // closed, so error notifications aren't sent after clients believe the stream
    458   // is closed.
    459   if (!LookupById(stream_id))
    460     return;
    461 
    462   SendErrorMessage(stream_id);
    463 
    464   if (media_internals_)
    465     media_internals_->OnSetAudioStreamStatus(this, stream_id, "error");
    466 
    467   OnCloseStream(stream_id);
    468 }
    469 
    470 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
    471   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    472 
    473   AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
    474   return i != audio_entries_.end() ? i->second : NULL;
    475 }
    476 
    477 }  // namespace content
    478