OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/webrtc_audio_capturer.h" | 5 #include "content/renderer/media/webrtc_audio_capturer.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
11 #include "content/child/child_process.h" | 11 #include "content/child/child_process.h" |
12 #include "content/renderer/media/audio_device_factory.h" | 12 #include "content/renderer/media/audio_device_factory.h" |
13 #include "content/renderer/media/webrtc_audio_device_impl.h" | 13 #include "content/renderer/media/webrtc_audio_device_impl.h" |
14 #include "content/renderer/media/webrtc_local_audio_source_provider.h" | |
14 #include "content/renderer/media/webrtc_local_audio_track.h" | 15 #include "content/renderer/media/webrtc_local_audio_track.h" |
16 #include "content/renderer/render_thread_impl.h" | |
15 #include "media/audio/audio_util.h" | 17 #include "media/audio/audio_util.h" |
16 #include "media/audio/sample_rates.h" | 18 #include "media/audio/sample_rates.h" |
19 #include "media/base/audio_hardware_config.h" | |
17 | 20 |
18 namespace content { | 21 namespace content { |
19 | 22 |
20 namespace { | 23 namespace { |
21 | 24 |
22 // Supported hardware sample rates for input and output sides. | 25 // Supported hardware sample rates for input and output sides. |
23 #if defined(OS_WIN) || defined(OS_MACOSX) | 26 #if defined(OS_WIN) || defined(OS_MACOSX) |
24 // media::GetAudioInputHardwareSampleRate() asks the audio layer | 27 // media::GetAudioInputHardwareSampleRate() asks the audio layer |
25 // for its current sample rate (set by the user) on Windows and Mac OS X. | 28 // for its current sample rate (set by the user) on Windows and Mac OS X. |
26 // The listed rates below adds restrictions and WebRtcAudioDeviceImpl::Init() | 29 // The listed rates below adds restrictions and WebRtcAudioDeviceImpl::Init() |
27 // will fail if the user selects any rate outside these ranges. | 30 // will fail if the user selects any rate outside these ranges. |
28 const int kValidInputRates[] = {96000, 48000, 44100, 32000, 16000, 8000}; | 31 const int kValidInputRates[] = {96000, 48000, 44100, 32000, 16000, 8000}; |
29 #elif defined(OS_LINUX) || defined(OS_OPENBSD) | 32 #elif defined(OS_LINUX) || defined(OS_OPENBSD) |
30 const int kValidInputRates[] = {48000, 44100}; | 33 const int kValidInputRates[] = {48000, 44100}; |
31 #elif defined(OS_ANDROID) | 34 #elif defined(OS_ANDROID) |
32 const int kValidInputRates[] = {48000, 44100}; | 35 const int kValidInputRates[] = {48000, 44100}; |
33 #else | 36 #else |
34 const int kValidInputRates[] = {44100}; | 37 const int kValidInputRates[] = {44100}; |
35 #endif | 38 #endif |
36 | 39 |
37 int GetBufferSizeForSampleRate(int sample_rate) { | |
38 int buffer_size = 0; | |
39 #if defined(OS_WIN) || defined(OS_MACOSX) | |
40 // Use a buffer size of 10ms. | |
41 buffer_size = (sample_rate / 100); | |
42 #elif defined(OS_LINUX) || defined(OS_OPENBSD) | |
43 // Based on tests using the current ALSA implementation in Chrome, we have | |
44 // found that the best combination is 20ms on the input side and 10ms on the | |
45 // output side. | |
46 buffer_size = 2 * sample_rate / 100; | |
47 #elif defined(OS_ANDROID) | |
48 // TODO(leozwang): Tune and adjust buffer size on Android. | |
49 buffer_size = 2 * sample_rate / 100; | |
50 #endif | |
51 return buffer_size; | |
52 } | |
53 | |
54 } // namespace | 40 } // namespace |
55 | 41 |
56 // This is a temporary audio buffer with parameters used to send data to | |
57 // callbacks. | |
58 class WebRtcAudioCapturer::ConfiguredBuffer : | |
59 public base::RefCounted<WebRtcAudioCapturer::ConfiguredBuffer> { | |
60 public: | |
61 ConfiguredBuffer() {} | |
62 | |
63 bool Initialize(int sample_rate, | |
64 media::ChannelLayout channel_layout) { | |
65 int buffer_size = GetBufferSizeForSampleRate(sample_rate); | |
66 DVLOG(1) << "Using WebRTC input buffer size: " << buffer_size; | |
67 | |
68 media::AudioParameters::Format format = | |
69 media::AudioParameters::AUDIO_PCM_LOW_LATENCY; | |
70 | |
71 // bits_per_sample is always 16 for now. | |
72 int bits_per_sample = 16; | |
73 int channels = ChannelLayoutToChannelCount(channel_layout); | |
74 params_.Reset(format, channel_layout, channels, 0, | |
75 sample_rate, bits_per_sample, buffer_size); | |
76 buffer_.reset(new int16[params_.frames_per_buffer() * params_.channels()]); | |
77 | |
78 return true; | |
79 } | |
80 | |
81 int16* buffer() const { return buffer_.get(); } | |
82 const media::AudioParameters& params() const { return params_; } | |
83 | |
84 private: | |
85 ~ConfiguredBuffer() {} | |
86 friend class base::RefCounted<WebRtcAudioCapturer::ConfiguredBuffer>; | |
87 | |
88 scoped_ptr<int16[]> buffer_; | |
89 | |
90 // Cached values of utilized audio parameters. | |
91 media::AudioParameters params_; | |
92 }; | |
93 | |
94 // Reference counted container of WebRtcLocalAudioTrack delegate. | 42 // Reference counted container of WebRtcLocalAudioTrack delegate. |
95 class WebRtcAudioCapturer::TrackOwner | 43 class WebRtcAudioCapturer::TrackOwner |
96 : public base::RefCountedThreadSafe<WebRtcAudioCapturer::TrackOwner> { | 44 : public base::RefCountedThreadSafe<WebRtcAudioCapturer::TrackOwner> { |
97 public: | 45 public: |
98 explicit TrackOwner(WebRtcLocalAudioTrack* track) | 46 explicit TrackOwner(WebRtcLocalAudioTrack* track) |
99 : delegate_(track) {} | 47 : delegate_(track) {} |
100 | 48 |
101 void CaptureData(const int16* audio_data, | 49 void Capture(media::AudioBus* audio_source, |
102 int number_of_channels, | 50 int audio_delay_milliseconds, |
103 int number_of_frames, | 51 double volume, |
104 int audio_delay_milliseconds, | 52 bool key_pressed) { |
105 int volume, | |
106 bool key_pressed) { | |
107 base::AutoLock lock(lock_); | 53 base::AutoLock lock(lock_); |
108 if (delegate_) { | 54 if (delegate_) { |
109 delegate_->CaptureData(audio_data, | 55 delegate_->Capture(audio_source, |
110 number_of_channels, | 56 audio_delay_milliseconds, |
111 number_of_frames, | 57 volume, |
112 audio_delay_milliseconds, | 58 key_pressed); |
113 volume, | |
114 key_pressed); | |
115 } | 59 } |
116 } | 60 } |
117 | 61 |
118 void SetCaptureFormat(const media::AudioParameters& params) { | 62 void SetCaptureFormat(const media::AudioParameters& params) { |
119 base::AutoLock lock(lock_); | 63 base::AutoLock lock(lock_); |
120 if (delegate_) | 64 if (delegate_) |
121 delegate_->SetCaptureFormat(params); | 65 delegate_->SetCaptureFormat(params); |
122 } | 66 } |
123 | 67 |
124 void Reset() { | 68 void Reset() { |
(...skipping 29 matching lines...) Expand all Loading... | |
154 | 98 |
155 DISALLOW_COPY_AND_ASSIGN(TrackOwner); | 99 DISALLOW_COPY_AND_ASSIGN(TrackOwner); |
156 }; | 100 }; |
157 | 101 |
158 // static | 102 // static |
159 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() { | 103 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() { |
160 scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(); | 104 scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(); |
161 return capturer; | 105 return capturer; |
162 } | 106 } |
163 | 107 |
164 bool WebRtcAudioCapturer::Reconfigure(int sample_rate, | 108 void WebRtcAudioCapturer::Reconfigure(int sample_rate, |
165 media::ChannelLayout channel_layout) { | 109 media::ChannelLayout channel_layout) { |
166 scoped_refptr<ConfiguredBuffer> new_buffer(new ConfiguredBuffer()); | 110 DCHECK(thread_checker_.CalledOnValidThread()); |
167 if (!new_buffer->Initialize(sample_rate, channel_layout)) | 111 int buffer_size = GetBufferSize(sample_rate); |
168 return false; | 112 DVLOG(1) << "Using WebRTC input buffer size: " << buffer_size; |
113 | |
114 media::AudioParameters::Format format = | |
115 media::AudioParameters::AUDIO_PCM_LOW_LATENCY; | |
116 | |
117 // bits_per_sample is always 16 for now. | |
118 int bits_per_sample = 16; | |
119 media::AudioParameters params(format, channel_layout, sample_rate, | |
120 bits_per_sample, buffer_size); | |
169 | 121 |
170 TrackList tracks; | 122 TrackList tracks; |
171 { | 123 { |
172 base::AutoLock auto_lock(lock_); | 124 base::AutoLock auto_lock(lock_); |
173 | |
174 buffer_ = new_buffer; | |
175 tracks = tracks_; | 125 tracks = tracks_; |
126 params_ = params; | |
176 } | 127 } |
177 | 128 |
178 // Tell all audio_tracks which format we use. | 129 // Tell all audio_tracks which format we use. |
179 for (TrackList::const_iterator it = tracks.begin(); | 130 for (TrackList::const_iterator it = tracks.begin(); |
180 it != tracks.end(); ++it) | 131 it != tracks.end(); ++it) |
181 (*it)->SetCaptureFormat(new_buffer->params()); | 132 (*it)->SetCaptureFormat(params); |
182 | |
183 return true; | |
184 } | 133 } |
185 | 134 |
186 bool WebRtcAudioCapturer::Initialize(int render_view_id, | 135 bool WebRtcAudioCapturer::Initialize(int render_view_id, |
187 media::ChannelLayout channel_layout, | 136 media::ChannelLayout channel_layout, |
188 int sample_rate, | 137 int sample_rate, |
189 int session_id, | 138 int session_id, |
190 const std::string& device_id) { | 139 const std::string& device_id) { |
191 DCHECK(thread_checker_.CalledOnValidThread()); | 140 DCHECK(thread_checker_.CalledOnValidThread()); |
141 DCHECK_GE(render_view_id, 0); | |
192 DVLOG(1) << "WebRtcAudioCapturer::Initialize()"; | 142 DVLOG(1) << "WebRtcAudioCapturer::Initialize()"; |
193 | 143 |
194 DVLOG(1) << "Audio input hardware channel layout: " << channel_layout; | 144 DVLOG(1) << "Audio input hardware channel layout: " << channel_layout; |
195 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout", | 145 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout", |
196 channel_layout, media::CHANNEL_LAYOUT_MAX); | 146 channel_layout, media::CHANNEL_LAYOUT_MAX); |
197 | 147 |
148 render_view_id_ = render_view_id; | |
198 session_id_ = session_id; | 149 session_id_ = session_id; |
199 device_id_ = device_id; | 150 device_id_ = device_id; |
151 | |
200 if (render_view_id == -1) { | 152 if (render_view_id == -1) { |
tommi (sloooow) - chröme
2013/09/06 11:20:30
this should never happen now that you've added the
no longer working on chromium
2013/09/10 12:43:15
This happens and is needed for testing cases. Also
| |
201 // This capturer is used by WebAudio, return true without creating a | 153 // Return true here to allow injecting a new source via SetCapturerSource() |
202 // default capturing source. WebAudio will inject its own source via | 154 // at a later state. |
203 // SetCapturerSource() at a later state. | |
204 DCHECK(device_id.empty()); | |
205 return true; | 155 return true; |
206 } | 156 } |
207 | 157 |
208 // Verify that the reported input channel configuration is supported. | 158 // Verify that the reported input channel configuration is supported. |
209 if (channel_layout != media::CHANNEL_LAYOUT_MONO && | 159 if (channel_layout != media::CHANNEL_LAYOUT_MONO && |
210 channel_layout != media::CHANNEL_LAYOUT_STEREO) { | 160 channel_layout != media::CHANNEL_LAYOUT_STEREO) { |
211 DLOG(ERROR) << channel_layout | 161 DLOG(ERROR) << channel_layout |
212 << " is not a supported input channel configuration."; | 162 << " is not a supported input channel configuration."; |
213 return false; | 163 return false; |
214 } | 164 } |
(...skipping 10 matching lines...) Expand all Loading... | |
225 // Verify that the reported input hardware sample rate is supported | 175 // Verify that the reported input hardware sample rate is supported |
226 // on the current platform. | 176 // on the current platform. |
227 if (std::find(&kValidInputRates[0], | 177 if (std::find(&kValidInputRates[0], |
228 &kValidInputRates[0] + arraysize(kValidInputRates), | 178 &kValidInputRates[0] + arraysize(kValidInputRates), |
229 sample_rate) == | 179 sample_rate) == |
230 &kValidInputRates[arraysize(kValidInputRates)]) { | 180 &kValidInputRates[arraysize(kValidInputRates)]) { |
231 DLOG(ERROR) << sample_rate << " is not a supported input rate."; | 181 DLOG(ERROR) << sample_rate << " is not a supported input rate."; |
232 return false; | 182 return false; |
233 } | 183 } |
234 | 184 |
235 if (!Reconfigure(sample_rate, channel_layout)) | 185 Reconfigure(sample_rate, channel_layout); |
236 return false; | |
237 | 186 |
238 // Create and configure the default audio capturing source. The |source_| | 187 // Create and configure the default audio capturing source. The |source_| |
239 // will be overwritten if an external client later calls SetCapturerSource() | 188 // will be overwritten if an external client later calls SetCapturerSource() |
240 // providing an alternative media::AudioCapturerSource. | 189 // providing an alternative media::AudioCapturerSource. |
241 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id), | 190 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id), |
242 channel_layout, | 191 channel_layout, |
243 static_cast<float>(sample_rate)); | 192 static_cast<float>(sample_rate)); |
244 | 193 |
245 return true; | 194 return true; |
246 } | 195 } |
247 | 196 |
248 WebRtcAudioCapturer::WebRtcAudioCapturer() | 197 WebRtcAudioCapturer::WebRtcAudioCapturer() |
249 : source_(NULL), | 198 : source_(NULL), |
250 running_(false), | 199 running_(false), |
251 agc_is_enabled_(false), | 200 agc_is_enabled_(false), |
201 render_view_id_(-1), | |
252 session_id_(0), | 202 session_id_(0), |
253 volume_(0) { | 203 volume_(0), |
204 source_provider_(new WebRtcLocalAudioSourceProvider()), | |
205 peer_connection_mode_(false) { | |
206 DCHECK(source_provider_.get()); | |
254 DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()"; | 207 DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()"; |
255 } | 208 } |
256 | 209 |
257 WebRtcAudioCapturer::~WebRtcAudioCapturer() { | 210 WebRtcAudioCapturer::~WebRtcAudioCapturer() { |
258 DCHECK(thread_checker_.CalledOnValidThread()); | 211 DCHECK(thread_checker_.CalledOnValidThread()); |
259 DCHECK(tracks_.empty()); | 212 DCHECK(tracks_.empty()); |
260 DCHECK(!running_); | 213 DCHECK(!running_); |
261 DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()"; | 214 DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()"; |
262 } | 215 } |
263 | 216 |
264 void WebRtcAudioCapturer::AddTrack(WebRtcLocalAudioTrack* track) { | 217 void WebRtcAudioCapturer::AddTrack(WebRtcLocalAudioTrack* track) { |
265 DCHECK(track); | 218 DCHECK(track); |
266 DVLOG(1) << "WebRtcAudioCapturer::AddTrack()"; | 219 DVLOG(1) << "WebRtcAudioCapturer::AddTrack()"; |
267 | 220 |
268 // Start the source if the first audio track is connected to the capturer. | 221 // Start the source if the first audio track is connected to the capturer. |
269 // Start() will do nothing if the capturer has already been started. | 222 // Start() will do nothing if the capturer has already been started. |
270 Start(); | 223 Start(); |
271 | 224 |
272 base::AutoLock auto_lock(lock_); | 225 base::AutoLock auto_lock(lock_); |
273 // Verify that |track| is not already added to the list. | 226 // Verify that |track| is not already added to the list. |
274 DCHECK(std::find_if(tracks_.begin(), tracks_.end(), | 227 DCHECK(std::find_if(tracks_.begin(), tracks_.end(), |
275 TrackOwner::TrackWrapper(track)) == tracks_.end()); | 228 TrackOwner::TrackWrapper(track)) == tracks_.end()); |
276 | 229 |
277 if (buffer_.get()) { | 230 track->SetCaptureFormat(params_); |
278 track->SetCaptureFormat(buffer_->params()); | |
279 } | |
280 | |
281 tracks_.push_back(new WebRtcAudioCapturer::TrackOwner(track)); | 231 tracks_.push_back(new WebRtcAudioCapturer::TrackOwner(track)); |
282 } | 232 } |
283 | 233 |
284 void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) { | 234 void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) { |
285 DCHECK(thread_checker_.CalledOnValidThread()); | 235 DCHECK(thread_checker_.CalledOnValidThread()); |
286 | 236 |
287 bool stop_source = false; | 237 bool stop_source = false; |
288 { | 238 { |
289 base::AutoLock auto_lock(lock_); | 239 base::AutoLock auto_lock(lock_); |
290 // Get iterator to the first element for which WrapsSink(track) returns | 240 // Get iterator to the first element for which WrapsSink(track) returns |
(...skipping 17 matching lines...) Expand all Loading... | |
308 } | 258 } |
309 | 259 |
310 void WebRtcAudioCapturer::SetCapturerSource( | 260 void WebRtcAudioCapturer::SetCapturerSource( |
311 const scoped_refptr<media::AudioCapturerSource>& source, | 261 const scoped_refptr<media::AudioCapturerSource>& source, |
312 media::ChannelLayout channel_layout, | 262 media::ChannelLayout channel_layout, |
313 float sample_rate) { | 263 float sample_rate) { |
314 DCHECK(thread_checker_.CalledOnValidThread()); | 264 DCHECK(thread_checker_.CalledOnValidThread()); |
315 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," | 265 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," |
316 << "sample_rate=" << sample_rate << ")"; | 266 << "sample_rate=" << sample_rate << ")"; |
317 scoped_refptr<media::AudioCapturerSource> old_source; | 267 scoped_refptr<media::AudioCapturerSource> old_source; |
318 scoped_refptr<ConfiguredBuffer> current_buffer; | |
319 bool restart_source = false; | 268 bool restart_source = false; |
320 { | 269 { |
321 base::AutoLock auto_lock(lock_); | 270 base::AutoLock auto_lock(lock_); |
322 if (source_.get() == source.get()) | 271 if (source_.get() == source.get()) |
323 return; | 272 return; |
324 | 273 |
325 source_.swap(old_source); | 274 source_.swap(old_source); |
326 source_ = source; | 275 source_ = source; |
327 current_buffer = buffer_; | |
328 | 276 |
329 // Reset the flag to allow starting the new source. | 277 // Reset the flag to allow starting the new source. |
330 restart_source = running_; | 278 restart_source = running_; |
331 running_ = false; | 279 running_ = false; |
332 } | 280 } |
333 | 281 |
334 const bool no_default_audio_source_exists = !current_buffer.get(); | |
335 | 282 |
336 // Detach the old source from normal recording or perform first-time | 283 DVLOG(1) << "New capture source will now be utilized."; |
tommi (sloooow) - chröme
2013/09/06 11:20:30
s/utilized/used
suggest "Switching to a new captur
no longer working on chromium
2013/09/10 12:43:15
Done.
| |
337 // initialization if Initialize() has never been called. For the second | 284 if (old_source.get()) |
338 // case, the caller is not "taking over an ongoing session" but instead | 285 old_source->Stop(); |
339 // "taking control over a new session". | |
340 if (old_source.get() || no_default_audio_source_exists) { | |
341 DVLOG(1) << "New capture source will now be utilized."; | |
342 if (old_source.get()) | |
343 old_source->Stop(); | |
344 | 286 |
345 // Dispatch the new parameters both to the sink(s) and to the new source. | 287 // Dispatch the new parameters both to the sink(s) and to the new source. |
346 // The idea is to get rid of any dependency of the microphone parameters | 288 // The idea is to get rid of any dependency of the microphone parameters |
347 // which would normally be used by default. | 289 // which would normally be used by default. |
348 if (!Reconfigure(sample_rate, channel_layout)) { | 290 Reconfigure(sample_rate, channel_layout); |
349 return; | |
350 } else { | |
351 // The buffer has been reconfigured. Update |current_buffer|. | |
352 base::AutoLock auto_lock(lock_); | |
353 current_buffer = buffer_; | |
354 } | |
355 } | |
356 | 291 |
357 if (source.get()) { | 292 // Make sure to grab the new parameters in case they were reconfigured. |
358 // Make sure to grab the new parameters in case they were reconfigured. | 293 media::AudioParameters params = audio_parameters(); |
359 source->Initialize(current_buffer->params(), this, session_id_); | 294 source_provider_->Initialize(params); |
360 } | 295 if (source.get()) |
296 source->Initialize(params, this, session_id_); | |
361 | 297 |
362 if (restart_source) | 298 if (restart_source) |
363 Start(); | 299 Start(); |
364 } | 300 } |
365 | 301 |
302 void WebRtcAudioCapturer::EnablePeerConnectionMode() { | |
303 DCHECK(thread_checker_.CalledOnValidThread()); | |
304 DVLOG(1) << "EnablePeerConnectionMode"; | |
305 // Do nothing if the native mode has been enabled. | |
tommi (sloooow) - chröme
2013/09/06 11:20:30
s/the native mode/peer connection mode
(or just re
no longer working on chromium
2013/09/10 12:43:15
Done.
| |
306 if (peer_connection_mode_) | |
307 return; | |
308 | |
309 DLOG(WARNING) << "EnablePeerConnectionMode"; | |
tommi (sloooow) - chröme
2013/09/06 11:20:30
Remove?
no longer working on chromium
2013/09/10 12:43:15
Done.
| |
310 peer_connection_mode_ = true; | |
311 | |
312 { | |
313 base::AutoLock auto_lock(lock_); | |
314 // Simply return if there is no existing source or the |render_view_id_| is | |
315 // not valid. | |
316 if (!source_.get() || render_view_id_== -1) | |
317 return; | |
318 } | |
319 | |
320 // Create a new audio stream as source which will open the hardware using | |
321 // WebRtc native buffer size. | |
322 media::AudioParameters params = audio_parameters(); | |
323 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id_), | |
tommi (sloooow) - chröme
2013/09/06 11:20:30
Since you're no longer under the lock, is it possi
no longer working on chromium
2013/09/10 12:43:15
SetCapturerSource() can't be called under a lock s
| |
324 params.channel_layout(), | |
325 static_cast<float>(params.sample_rate())); | |
tommi (sloooow) - chröme
2013/09/06 11:20:30
why are we using float for the sample rate?
no longer working on chromium
2013/09/10 12:43:15
Just chatted with Henrik on this, it is simply som
| |
326 } | |
327 | |
366 void WebRtcAudioCapturer::Start() { | 328 void WebRtcAudioCapturer::Start() { |
367 DVLOG(1) << "WebRtcAudioCapturer::Start()"; | 329 DVLOG(1) << "WebRtcAudioCapturer::Start()"; |
368 base::AutoLock auto_lock(lock_); | 330 base::AutoLock auto_lock(lock_); |
369 if (running_) | 331 if (running_) |
370 return; | 332 return; |
371 | 333 |
372 // Start the data source, i.e., start capturing data from the current source. | 334 // Start the data source, i.e., start capturing data from the current source. |
373 // Note that, the source does not have to be a microphone. | 335 // Note that, the source does not have to be a microphone. |
374 if (source_.get()) { | 336 if (source_.get()) { |
375 // We need to set the AGC control before starting the stream. | 337 // We need to set the AGC control before starting the stream. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
436 #elif defined(OS_LINUX) || defined(OS_OPENBSD) | 398 #elif defined(OS_LINUX) || defined(OS_OPENBSD) |
437 // We have a special situation on Linux where the microphone volume can be | 399 // We have a special situation on Linux where the microphone volume can be |
438 // "higher than maximum". The input volume slider in the sound preference | 400 // "higher than maximum". The input volume slider in the sound preference |
439 // allows the user to set a scaling that is higher than 100%. It means that | 401 // allows the user to set a scaling that is higher than 100%. It means that |
440 // even if the reported maximum levels is N, the actual microphone level can | 402 // even if the reported maximum levels is N, the actual microphone level can |
441 // go up to 1.5x*N and that corresponds to a normalized |volume| of 1.5x. | 403 // go up to 1.5x*N and that corresponds to a normalized |volume| of 1.5x. |
442 DCHECK_LE(volume, 1.6); | 404 DCHECK_LE(volume, 1.6); |
443 #endif | 405 #endif |
444 | 406 |
445 TrackList tracks; | 407 TrackList tracks; |
446 scoped_refptr<ConfiguredBuffer> buffer_ref_while_calling; | 408 int current_volume = 0; |
447 { | 409 { |
448 base::AutoLock auto_lock(lock_); | 410 base::AutoLock auto_lock(lock_); |
449 if (!running_) | 411 if (!running_) |
450 return; | 412 return; |
451 | 413 |
452 // Map internal volume range of [0.0, 1.0] into [0, 255] used by the | 414 // Map internal volume range of [0.0, 1.0] into [0, 255] used by the |
453 // webrtc::VoiceEngine. webrtc::VoiceEngine will handle the case when the | 415 // webrtc::VoiceEngine. webrtc::VoiceEngine will handle the case when the |
454 // volume is higher than 255. | 416 // volume is higher than 255. |
455 volume_ = static_cast<int>((volume * MaxVolume()) + 0.5); | 417 volume_ = static_cast<int>((volume * MaxVolume()) + 0.5); |
456 | 418 current_volume = volume_; |
457 // Copy the stuff we will need to local variables. In particular, we grab | |
458 // a reference to the buffer so we can ensure it stays alive even if the | |
459 // buffer is reconfigured while we are calling back. | |
460 buffer_ref_while_calling = buffer_; | |
461 tracks = tracks_; | 419 tracks = tracks_; |
462 } | 420 } |
463 | 421 |
464 int bytes_per_sample = | 422 // Deliver captured data to source provider, which stores the data into FIFO |
465 buffer_ref_while_calling->params().bits_per_sample() / 8; | 423 // for WebAudio to fetch. |
466 | 424 source_provider_->DeliverData(audio_source, audio_delay_milliseconds, |
467 // Interleave, scale, and clip input to int and store result in | 425 current_volume, key_pressed); |
468 // a local byte buffer. | |
469 audio_source->ToInterleaved(audio_source->frames(), bytes_per_sample, | |
470 buffer_ref_while_calling->buffer()); | |
471 | 426 |
472 // Feed the data to the tracks. | 427 // Feed the data to the tracks. |
473 for (TrackList::const_iterator it = tracks.begin(); | 428 for (TrackList::const_iterator it = tracks.begin(); |
474 it != tracks.end(); | 429 it != tracks.end(); |
475 ++it) { | 430 ++it) { |
476 (*it)->CaptureData(buffer_ref_while_calling->buffer(), | 431 (*it)->Capture(audio_source, audio_delay_milliseconds, |
477 audio_source->channels(), | 432 current_volume, key_pressed); |
478 audio_source->frames(), | |
479 audio_delay_milliseconds, | |
480 volume, | |
481 key_pressed); | |
482 } | 433 } |
483 } | 434 } |
484 | 435 |
485 void WebRtcAudioCapturer::OnCaptureError() { | 436 void WebRtcAudioCapturer::OnCaptureError() { |
486 NOTIMPLEMENTED(); | 437 NOTIMPLEMENTED(); |
487 } | 438 } |
488 | 439 |
489 media::AudioParameters WebRtcAudioCapturer::audio_parameters() const { | 440 media::AudioParameters WebRtcAudioCapturer::audio_parameters() const { |
490 base::AutoLock auto_lock(lock_); | 441 base::AutoLock auto_lock(lock_); |
491 // |buffer_| can be NULL when SetCapturerSource() or Initialize() has not | 442 return params_; |
492 // been called. | 443 } |
493 return buffer_.get() ? buffer_->params() : media::AudioParameters(); | 444 |
445 WebKit::WebAudioSourceProvider* | |
446 WebRtcAudioCapturer::AudioSourceProvider() const { | |
447 return source_provider_.get(); | |
tommi (sloooow) - chröme
2013/09/06 11:20:30
since we never change the value of source_provider
no longer working on chromium
2013/09/10 12:43:15
Done with changing the source_provider_ to be cons
| |
448 } | |
449 | |
450 int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const { | |
451 #if defined(OS_ANDROID) | |
452 // TODO(leozwang): Tune and adjust buffer size on Android. | |
453 return (2 * sample_rate / 100); | |
454 #endif | |
455 DLOG(WARNING) << "GetBufferSize " << peer_connection_mode_; | |
tommi (sloooow) - chröme
2013/09/06 11:20:30
remove?
no longer working on chromium
2013/09/10 12:43:15
Done.
| |
456 if (peer_connection_mode_) { | |
tommi (sloooow) - chröme
2013/09/06 11:20:30
before checking this, should we grab the lock? (o
no longer working on chromium
2013/09/10 12:43:15
Done with adding a thread check.
| |
457 // WebRtc is running at a buffer size of 10ms data. Use a multiple of 10ms | |
458 // as the buffer size to achieve the best performance for WebRtc. | |
459 return (sample_rate / 100); | |
460 } | |
461 | |
462 // Use the native hardware buffer size. | |
463 media::AudioHardwareConfig* hardware_config = | |
464 RenderThreadImpl::current()->GetAudioHardwareConfig(); | |
465 return hardware_config->GetInputBufferSize(); | |
494 } | 466 } |
495 | 467 |
496 } // namespace content | 468 } // namespace content |
OLD | NEW |