• 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 #include "ipc/ipc_sender.h"
14 
15 namespace {
16 
17 const int kStreamIDNotSet = -1;
18 
LogMessage(int stream_id,const std::string & msg)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 
AudioInputMessageFilter(const scoped_refptr<base::MessageLoopProxy> & io_message_loop)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 
~AudioInputMessageFilter()63 AudioInputMessageFilter::~AudioInputMessageFilter() {
64   DCHECK_EQ(g_filter, this);
65   g_filter = NULL;
66 }
67 
68 // static
Get()69 AudioInputMessageFilter* AudioInputMessageFilter::Get() {
70   return g_filter;
71 }
72 
Send(IPC::Message * message)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 
OnMessageReceived(const IPC::Message & message)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 
OnFilterAdded(IPC::Sender * sender)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 
OnFilterRemoved()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 
OnChannelClosing()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 
OnStreamCreated(int stream_id,base::SharedMemoryHandle handle,base::SyncSocket::TransitDescriptor socket_descriptor,uint32 length,uint32 total_segments)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 
OnStreamVolume(int stream_id,double volume)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 
OnStreamStateChanged(int stream_id,media::AudioInputIPCDelegate::State state)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 
AudioInputIPCImpl(const scoped_refptr<AudioInputMessageFilter> & filter,int render_view_id)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 
~AudioInputIPCImpl()178 AudioInputMessageFilter::AudioInputIPCImpl::~AudioInputIPCImpl() {}
179 
CreateAudioInputIPC(int render_view_id)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 
CreateStream(media::AudioInputIPCDelegate * delegate,int session_id,const media::AudioParameters & params,bool automatic_gain_control,uint32 total_segments)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 
RecordStream()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 
SetVolume(double volume)215 void AudioInputMessageFilter::AudioInputIPCImpl::SetVolume(double volume) {
216   DCHECK_NE(stream_id_, kStreamIDNotSet);
217   filter_->Send(new AudioInputHostMsg_SetVolume(stream_id_, volume));
218 }
219 
CloseStream()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