| 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 |