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_local_audio_track.h" | 5 #include "content/renderer/media/webrtc_local_audio_track.h" |
6 | 6 |
| 7 #include "content/public/renderer/media_stream_audio_sink.h" |
| 8 #include "content/renderer/media/media_stream_audio_sink_owner.h" |
| 9 #include "content/renderer/media/media_stream_audio_track_sink.h" |
| 10 #include "content/renderer/media/peer_connection_audio_sink_owner.h" |
7 #include "content/renderer/media/webaudio_capturer_source.h" | 11 #include "content/renderer/media/webaudio_capturer_source.h" |
8 #include "content/renderer/media/webrtc_audio_capturer.h" | 12 #include "content/renderer/media/webrtc_audio_capturer.h" |
9 #include "content/renderer/media/webrtc_audio_capturer_sink_owner.h" | |
10 #include "content/renderer/media/webrtc_local_audio_source_provider.h" | 13 #include "content/renderer/media/webrtc_local_audio_source_provider.h" |
11 #include "media/base/audio_fifo.h" | 14 #include "media/base/audio_fifo.h" |
12 #include "third_party/libjingle/source/talk/media/base/audiorenderer.h" | 15 #include "third_party/libjingle/source/talk/media/base/audiorenderer.h" |
13 | 16 |
14 namespace content { | 17 namespace content { |
15 | 18 |
16 static const size_t kMaxNumberOfBuffersInFifo = 2; | 19 static const size_t kMaxNumberOfBuffersInFifo = 2; |
17 static const char kAudioTrackKind[] = "audio"; | 20 static const char kAudioTrackKind[] = "audio"; |
18 | 21 |
19 namespace { | 22 namespace { |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 voe_channels = voe_channels_; | 175 voe_channels = voe_channels_; |
173 sinks = sinks_; | 176 sinks = sinks_; |
174 std::swap(sinks_to_notify_format_, sinks_to_notify_format); | 177 std::swap(sinks_to_notify_format_, sinks_to_notify_format); |
175 is_webaudio_source = (webaudio_source_.get() != NULL); | 178 is_webaudio_source = (webaudio_source_.get() != NULL); |
176 } | 179 } |
177 | 180 |
178 // Notify the tracks on when the format changes. This will do nothing if | 181 // Notify the tracks on when the format changes. This will do nothing if |
179 // |sinks_to_notify_format| is empty. | 182 // |sinks_to_notify_format| is empty. |
180 for (SinkList::const_iterator it = sinks_to_notify_format.begin(); | 183 for (SinkList::const_iterator it = sinks_to_notify_format.begin(); |
181 it != sinks_to_notify_format.end(); ++it) { | 184 it != sinks_to_notify_format.end(); ++it) { |
182 (*it)->SetCaptureFormat(buffer_->params()); | 185 (*it)->OnSetFormat(buffer_->params()); |
183 } | 186 } |
184 | 187 |
185 // Push the data to the fifo. | 188 // Push the data to the fifo. |
186 buffer_->Push(audio_source); | 189 buffer_->Push(audio_source); |
187 | 190 |
188 // When the source is WebAudio, turn off the audio processing if the delay | 191 // When the source is WebAudio, turn off the audio processing if the delay |
189 // value is 0 even though the constraint is set to true. In such case, it | 192 // value is 0 even though the constraint is set to true. In such case, it |
190 // indicates the data is not from microphone. | 193 // indicates the data is not from microphone. |
191 // TODO(xians): remove the flag when supporting one APM per audio track. | 194 // TODO(xians): remove the flag when supporting one APM per audio track. |
192 // See crbug/264611 for details. | 195 // See crbug/264611 for details. |
193 bool need_audio_processing = need_audio_processing_; | 196 bool need_audio_processing = need_audio_processing_; |
194 if (is_webaudio_source && need_audio_processing) | 197 if (is_webaudio_source && need_audio_processing) |
195 need_audio_processing = (audio_delay_milliseconds != 0); | 198 need_audio_processing = (audio_delay_milliseconds != 0); |
196 | 199 |
197 int current_volume = volume; | 200 int current_volume = volume; |
198 while (buffer_->Consume()) { | 201 while (buffer_->Consume()) { |
199 // Feed the data to the sinks. | 202 // Feed the data to the sinks. |
200 // TODO (jiayl): we should not pass the real audio data down if the track is | 203 // TODO (jiayl): we should not pass the real audio data down if the track is |
201 // disabled. This is currently done so to feed input to WebRTC typing | 204 // disabled. This is currently done so to feed input to WebRTC typing |
202 // detection and should be changed when audio processing is moved from | 205 // detection and should be changed when audio processing is moved from |
203 // WebRTC to the track. | 206 // WebRTC to the track. |
204 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) { | 207 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) { |
205 int new_volume = (*it)->CaptureData(voe_channels, | 208 int new_volume = (*it)->OnData(buffer_->buffer(), |
206 buffer_->buffer(), | 209 buffer_->params().sample_rate(), |
207 buffer_->params().sample_rate(), | 210 buffer_->params().channels(), |
208 buffer_->params().channels(), | 211 buffer_->params().frames_per_buffer(), |
209 buffer_->params().frames_per_buffer(), | 212 voe_channels, |
210 audio_delay_milliseconds, | 213 audio_delay_milliseconds, |
211 current_volume, | 214 current_volume, |
212 need_audio_processing, | 215 need_audio_processing, |
213 key_pressed); | 216 key_pressed); |
214 if (new_volume != 0 && capturer.get()) { | 217 if (new_volume != 0 && capturer.get()) { |
215 // Feed the new volume to WebRtc while changing the volume on the | 218 // Feed the new volume to WebRtc while changing the volume on the |
216 // browser. | 219 // browser. |
217 capturer->SetVolume(new_volume); | 220 capturer->SetVolume(new_volume); |
218 current_volume = new_volume; | 221 current_volume = new_volume; |
219 } | 222 } |
220 } | 223 } |
221 } | 224 } |
222 } | 225 } |
223 | 226 |
224 void WebRtcLocalAudioTrack::SetCaptureFormat( | 227 void WebRtcLocalAudioTrack::OnSetFormat( |
225 const media::AudioParameters& params) { | 228 const media::AudioParameters& params) { |
226 DVLOG(1) << "WebRtcLocalAudioTrack::SetCaptureFormat()"; | 229 DVLOG(1) << "WebRtcLocalAudioTrack::OnSetFormat()"; |
227 // If the source is restarted, we might have changed to another capture | 230 // If the source is restarted, we might have changed to another capture |
228 // thread. | 231 // thread. |
229 capture_thread_checker_.DetachFromThread(); | 232 capture_thread_checker_.DetachFromThread(); |
230 DCHECK(capture_thread_checker_.CalledOnValidThread()); | 233 DCHECK(capture_thread_checker_.CalledOnValidThread()); |
231 | 234 |
232 DCHECK(params.IsValid()); | 235 DCHECK(params.IsValid()); |
233 buffer_->Configure(params); | 236 buffer_->Configure(params); |
234 | 237 |
235 base::AutoLock auto_lock(lock_); | 238 base::AutoLock auto_lock(lock_); |
236 // Copy |sinks_| to |sinks_to_notify_format_| to notify all the sinks | 239 // Copy |sinks_| to |sinks_to_notify_format_| to notify all the sinks |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 } | 271 } |
269 | 272 |
270 cricket::AudioRenderer* WebRtcLocalAudioTrack::GetRenderer() { | 273 cricket::AudioRenderer* WebRtcLocalAudioTrack::GetRenderer() { |
271 return this; | 274 return this; |
272 } | 275 } |
273 | 276 |
274 std::string WebRtcLocalAudioTrack::kind() const { | 277 std::string WebRtcLocalAudioTrack::kind() const { |
275 return kAudioTrackKind; | 278 return kAudioTrackKind; |
276 } | 279 } |
277 | 280 |
278 void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) { | 281 void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) { |
279 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 282 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
280 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; | 283 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; |
281 base::AutoLock auto_lock(lock_); | 284 base::AutoLock auto_lock(lock_); |
282 | 285 |
283 // Verify that |sink| is not already added to the list. | 286 // Verify that |sink| is not already added to the list. |
284 DCHECK(std::find_if( | 287 DCHECK(std::find_if( |
285 sinks_.begin(), sinks_.end(), | 288 sinks_.begin(), sinks_.end(), |
286 WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end()); | 289 MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink)) == sinks_.end()); |
287 | 290 |
288 // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns | 291 // Create (and add to the list) a new MediaStreamAudioTrackSink which owns |
289 // the |sink| and delagates all calls to the WebRtcAudioCapturerSink | 292 // the |sink| and delagates all calls to the MediaStreamAudioSink |
290 // interface. | 293 // interface. |
291 scoped_refptr<WebRtcAudioCapturerSinkOwner> sink_owner( | 294 scoped_refptr<MediaStreamAudioTrackSink> sink_owner( |
292 new WebRtcAudioCapturerSinkOwner(sink)); | 295 new MediaStreamAudioSinkOwner(sink)); |
293 sinks_.push_back(sink_owner); | 296 sinks_.push_back(sink_owner); |
294 | 297 |
295 // Also push the |sink_owner| to |sinks_to_notify_format_| so that we will | 298 // Also push the |sink_owner| to |sinks_to_notify_format_| so that we will |
296 // call SetCaptureFormat() on the new sink. | 299 // call OnSetFormat() on the new sink. |
297 sinks_to_notify_format_.push_back(sink_owner); | 300 sinks_to_notify_format_.push_back(sink_owner); |
298 } | 301 } |
299 | 302 |
300 void WebRtcLocalAudioTrack::RemoveSink( | 303 void WebRtcLocalAudioTrack::RemoveSink(MediaStreamAudioSink* sink) { |
301 WebRtcAudioCapturerSink* sink) { | |
302 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 304 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
303 DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()"; | 305 DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()"; |
304 | 306 |
305 base::AutoLock auto_lock(lock_); | 307 base::AutoLock auto_lock(lock_); |
306 // Remove the item on |tracks_to_notify_format_|. | 308 // Remove the item on |tracks_to_notify_format_|. |
307 // This has to be done before remove the element in |sinks_| since there it | 309 // This has to be done before remove the element in |sinks_| since there it |
308 // will clear the delegate. | 310 // will clear the delegate. |
309 SinkList::iterator it = std::find_if( | 311 SinkList::iterator it = std::find_if( |
310 sinks_to_notify_format_.begin(), sinks_to_notify_format_.end(), | 312 sinks_to_notify_format_.begin(), sinks_to_notify_format_.end(), |
311 WebRtcAudioCapturerSinkOwner::WrapsSink(sink)); | 313 MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink)); |
312 if (it != sinks_to_notify_format_.end()) | 314 if (it != sinks_to_notify_format_.end()) |
313 sinks_to_notify_format_.erase(it); | 315 sinks_to_notify_format_.erase(it); |
314 | 316 |
315 // Get iterator to the first element for which WrapsSink(sink) returns true. | 317 // Get iterator to the first element for which WrapsSink(sink) returns true. |
316 it = std::find_if(sinks_.begin(), sinks_.end(), | 318 it = std::find_if(sinks_.begin(), sinks_.end(), |
317 WebRtcAudioCapturerSinkOwner::WrapsSink(sink)); | 319 MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink)); |
318 if (it != sinks_.end()) { | 320 if (it != sinks_.end()) { |
319 // Clear the delegate to ensure that no more capture callbacks will | 321 // Clear the delegate to ensure that no more capture callbacks will |
320 // be sent to this sink. Also avoids a possible crash which can happen | 322 // be sent to this sink. Also avoids a possible crash which can happen |
| 323 // if this method is called while capturing is active. |
| 324 (*it)->Reset(); |
| 325 sinks_.erase(it); |
| 326 } |
| 327 } |
| 328 |
| 329 void WebRtcLocalAudioTrack::AddSink(PeerConnectionAudioSink* sink) { |
| 330 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 331 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; |
| 332 base::AutoLock auto_lock(lock_); |
| 333 |
| 334 // Verify that |sink| is not already added to the list. |
| 335 DCHECK(std::find_if( |
| 336 sinks_.begin(), sinks_.end(), |
| 337 MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink)) == |
| 338 sinks_.end()); |
| 339 |
| 340 // Create (and add to the list) a new MediaStreamAudioTrackSink which owns |
| 341 // the |sink| and delagates all calls to the MediaStreamAudioSink |
| 342 // interface. |
| 343 scoped_refptr<MediaStreamAudioTrackSink> sink_owner( |
| 344 new PeerConnectionAudioSinkOwner(sink)); |
| 345 sinks_.push_back(sink_owner); |
| 346 |
| 347 // Also push the |sink_owner| to |sinks_to_notify_format_| so that we will |
| 348 // call OnSetFormat() on the new sink. |
| 349 sinks_to_notify_format_.push_back(sink_owner); |
| 350 } |
| 351 |
| 352 void WebRtcLocalAudioTrack::RemoveSink(PeerConnectionAudioSink* sink) { |
| 353 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 354 DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()"; |
| 355 |
| 356 base::AutoLock auto_lock(lock_); |
| 357 // Remove the item on |tracks_to_notify_format_|. |
| 358 // This has to be done before remove the element in |sinks_| since there it |
| 359 // will clear the delegate. |
| 360 SinkList::iterator it = std::find_if( |
| 361 sinks_to_notify_format_.begin(), sinks_to_notify_format_.end(), |
| 362 MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink)); |
| 363 if (it != sinks_to_notify_format_.end()) |
| 364 sinks_to_notify_format_.erase(it); |
| 365 |
| 366 // Get iterator to the first element for which WrapsPeerConnectionSink(sink) |
| 367 // returns true. |
| 368 it = std::find_if(sinks_.begin(), sinks_.end(), |
| 369 MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink)); |
| 370 if (it != sinks_.end()) { |
| 371 // Clear the delegate to ensure that no more capture callbacks will |
| 372 // be sent to this sink. Also avoids a possible crash which can happen |
321 // if this method is called while capturing is active. | 373 // if this method is called while capturing is active. |
322 (*it)->Reset(); | 374 (*it)->Reset(); |
323 sinks_.erase(it); | 375 sinks_.erase(it); |
324 } | 376 } |
325 } | 377 } |
326 | 378 |
327 void WebRtcLocalAudioTrack::Start() { | 379 void WebRtcLocalAudioTrack::Start() { |
328 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 380 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
329 DVLOG(1) << "WebRtcLocalAudioTrack::Start()"; | 381 DVLOG(1) << "WebRtcLocalAudioTrack::Start()"; |
330 if (webaudio_source_.get()) { | 382 if (webaudio_source_.get()) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 sinks_to_notify_format_.clear(); | 418 sinks_to_notify_format_.clear(); |
367 webaudio_source_ = NULL; | 419 webaudio_source_ = NULL; |
368 capturer_ = NULL; | 420 capturer_ = NULL; |
369 } | 421 } |
370 | 422 |
371 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) | 423 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) |
372 (*it)->Reset(); | 424 (*it)->Reset(); |
373 } | 425 } |
374 | 426 |
375 } // namespace content | 427 } // namespace content |
OLD | NEW |