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