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/renderer/media/audio_input_message_filter.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop_proxy.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "content/common/media/audio_messages.h"
     11 #include "content/renderer/media/webrtc_logging.h"
     12 #include "ipc/ipc_logging.h"
     13 #include "ipc/ipc_sender.h"
     14 
     15 namespace {
     16 
     17 const int kStreamIDNotSet = -1;
     18 
     19 void LogMessage(int stream_id, const std::string& msg) {
     20   std::ostringstream oss;
     21   oss << "[stream_id=" << stream_id << "] AIMF::" << msg;
     22   content::WebRtcLogMessage(oss.str());
     23   DVLOG(1) << oss.str();
     24 }
     25 
     26 }  // namespace
     27 
     28 namespace content {
     29 
     30 class AudioInputMessageFilter::AudioInputIPCImpl
     31     : public NON_EXPORTED_BASE(media::AudioInputIPC) {
     32  public:
     33   AudioInputIPCImpl(const scoped_refptr<AudioInputMessageFilter>& filter,
     34                     int render_view_id);
     35   virtual ~AudioInputIPCImpl();
     36 
     37   // media::AudioInputIPC implementation.
     38   virtual void CreateStream(media::AudioInputIPCDelegate* delegate,
     39                             int session_id,
     40                             const media::AudioParameters& params,
     41                             bool automatic_gain_control,
     42                             uint32 total_segments) OVERRIDE;
     43   virtual void RecordStream() OVERRIDE;
     44   virtual void SetVolume(double volume) OVERRIDE;
     45   virtual void CloseStream() OVERRIDE;
     46 
     47  private:
     48   const scoped_refptr<AudioInputMessageFilter> filter_;
     49   const int render_view_id_;
     50   int stream_id_;
     51 };
     52 
     53 AudioInputMessageFilter* AudioInputMessageFilter::g_filter = NULL;
     54 
     55 AudioInputMessageFilter::AudioInputMessageFilter(
     56     const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
     57     : sender_(NULL),
     58       io_message_loop_(io_message_loop) {
     59   DCHECK(!g_filter);
     60   g_filter = this;
     61 }
     62 
     63 AudioInputMessageFilter::~AudioInputMessageFilter() {
     64   DCHECK_EQ(g_filter, this);
     65   g_filter = NULL;
     66 }
     67 
     68 // static
     69 AudioInputMessageFilter* AudioInputMessageFilter::Get() {
     70   return g_filter;
     71 }
     72 
     73 void AudioInputMessageFilter::Send(IPC::Message* message) {
     74   DCHECK(io_message_loop_->BelongsToCurrentThread());
     75   if (!sender_) {
     76     delete message;
     77   } else {
     78     sender_->Send(message);
     79   }
     80 }
     81 
     82 bool AudioInputMessageFilter::OnMessageReceived(const IPC::Message& message) {
     83   DCHECK(io_message_loop_->BelongsToCurrentThread());
     84   bool handled = true;
     85   IPC_BEGIN_MESSAGE_MAP(AudioInputMessageFilter, message)
     86     IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamCreated,
     87                         OnStreamCreated)
     88     IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamVolume, OnStreamVolume)
     89     IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamStateChanged,
     90                         OnStreamStateChanged)
     91     IPC_MESSAGE_UNHANDLED(handled = false)
     92   IPC_END_MESSAGE_MAP()
     93   return handled;
     94 }
     95 
     96 void AudioInputMessageFilter::OnFilterAdded(IPC::Sender* sender) {
     97   DCHECK(io_message_loop_->BelongsToCurrentThread());
     98 
     99   // Captures the sender for IPC.
    100   sender_ = sender;
    101 }
    102 
    103 void AudioInputMessageFilter::OnFilterRemoved() {
    104   DCHECK(io_message_loop_->BelongsToCurrentThread());
    105 
    106   // Once removed, a filter will not be used again.  At this time all
    107   // delegates must be notified so they release their reference.
    108   OnChannelClosing();
    109 }
    110 
    111 void AudioInputMessageFilter::OnChannelClosing() {
    112   DCHECK(io_message_loop_->BelongsToCurrentThread());
    113   sender_ = NULL;
    114 
    115   DLOG_IF(WARNING, !delegates_.IsEmpty())
    116       << "Not all audio devices have been closed.";
    117 
    118   IDMap<media::AudioInputIPCDelegate>::iterator it(&delegates_);
    119   while (!it.IsAtEnd()) {
    120     it.GetCurrentValue()->OnIPCClosed();
    121     delegates_.Remove(it.GetCurrentKey());
    122     it.Advance();
    123   }
    124 }
    125 
    126 void AudioInputMessageFilter::OnStreamCreated(
    127     int stream_id,
    128     base::SharedMemoryHandle handle,
    129     base::SyncSocket::TransitDescriptor socket_descriptor,
    130     uint32 length,
    131     uint32 total_segments) {
    132   DCHECK(io_message_loop_->BelongsToCurrentThread());
    133   LogMessage(stream_id, "OnStreamCreated");
    134 
    135   base::SyncSocket::Handle socket_handle =
    136       base::SyncSocket::UnwrapHandle(socket_descriptor);
    137   media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
    138   if (!delegate) {
    139     DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
    140                   << " audio capturer (stream_id=" << stream_id << ").";
    141     base::SharedMemory::CloseHandle(handle);
    142     base::SyncSocket socket(socket_handle);
    143     return;
    144   }
    145   // Forward message to the stream delegate.
    146   delegate->OnStreamCreated(handle, socket_handle, length, total_segments);
    147 }
    148 
    149 void AudioInputMessageFilter::OnStreamVolume(int stream_id, double volume) {
    150   DCHECK(io_message_loop_->BelongsToCurrentThread());
    151   media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
    152   if (!delegate) {
    153     DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
    154                   << " audio capturer.";
    155     return;
    156   }
    157   delegate->OnVolume(volume);
    158 }
    159 
    160 void AudioInputMessageFilter::OnStreamStateChanged(
    161     int stream_id, media::AudioInputIPCDelegate::State state) {
    162   DCHECK(io_message_loop_->BelongsToCurrentThread());
    163   media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
    164   if (!delegate) {
    165     DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
    166                   << " audio renderer.";
    167     return;
    168   }
    169   delegate->OnStateChanged(state);
    170 }
    171 
    172 AudioInputMessageFilter::AudioInputIPCImpl::AudioInputIPCImpl(
    173     const scoped_refptr<AudioInputMessageFilter>& filter, int render_view_id)
    174     : filter_(filter),
    175       render_view_id_(render_view_id),
    176       stream_id_(kStreamIDNotSet) {}
    177 
    178 AudioInputMessageFilter::AudioInputIPCImpl::~AudioInputIPCImpl() {}
    179 
    180 scoped_ptr<media::AudioInputIPC> AudioInputMessageFilter::CreateAudioInputIPC(
    181     int render_view_id) {
    182   DCHECK_GT(render_view_id, 0);
    183   return scoped_ptr<media::AudioInputIPC>(
    184       new AudioInputIPCImpl(this, render_view_id));
    185 }
    186 
    187 void AudioInputMessageFilter::AudioInputIPCImpl::CreateStream(
    188     media::AudioInputIPCDelegate* delegate,
    189     int session_id,
    190     const media::AudioParameters& params,
    191     bool automatic_gain_control,
    192     uint32 total_segments) {
    193   DCHECK(filter_->io_message_loop_->BelongsToCurrentThread());
    194   DCHECK(delegate);
    195 
    196   stream_id_ = filter_->delegates_.Add(delegate);
    197   // TODO(henrika): remove all LogMessage calls when we have sorted out the
    198   // existing "no input audio" issues.
    199   LogMessage(stream_id_, "CreateStream");
    200 
    201   AudioInputHostMsg_CreateStream_Config config;
    202   config.params = params;
    203   config.automatic_gain_control = automatic_gain_control;
    204   config.shared_memory_count = total_segments;
    205   filter_->Send(new AudioInputHostMsg_CreateStream(
    206       stream_id_, render_view_id_, session_id, config));
    207 }
    208 
    209 void AudioInputMessageFilter::AudioInputIPCImpl::RecordStream() {
    210   DCHECK_NE(stream_id_, kStreamIDNotSet);
    211   LogMessage(stream_id_, "RecordStream");
    212   filter_->Send(new AudioInputHostMsg_RecordStream(stream_id_));
    213 }
    214 
    215 void AudioInputMessageFilter::AudioInputIPCImpl::SetVolume(double volume) {
    216   DCHECK_NE(stream_id_, kStreamIDNotSet);
    217   filter_->Send(new AudioInputHostMsg_SetVolume(stream_id_, volume));
    218 }
    219 
    220 void AudioInputMessageFilter::AudioInputIPCImpl::CloseStream() {
    221   DCHECK(filter_->io_message_loop_->BelongsToCurrentThread());
    222   DCHECK_NE(stream_id_, kStreamIDNotSet);
    223   LogMessage(stream_id_, "CloseStream");
    224   filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_));
    225   filter_->delegates_.Remove(stream_id_);
    226   stream_id_ = kStreamIDNotSet;
    227 }
    228 
    229 }  // namespace content
    230