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