1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_local_audio_track.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/renderer/media_stream_audio_sink.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/renderer/media/media_stream_audio_level_calculator.h" 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/renderer/media/media_stream_audio_processor.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/renderer/media/media_stream_audio_sink_owner.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/renderer/media/media_stream_audio_track_sink.h" 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/renderer/media/peer_connection_audio_sink_owner.h" 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/renderer/media/webaudio_capturer_source.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_capturer.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content { 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)WebRtcLocalAudioTrack::WebRtcLocalAudioTrack( 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebRtcLocalAudioTrackAdapter* adapter, 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const scoped_refptr<WebRtcAudioCapturer>& capturer, 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebAudioCapturerSource* webaudio_source) 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : MediaStreamTrack(adapter, true), 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) adapter_(adapter), 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_(capturer), 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webaudio_source_(webaudio_source) { 27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(capturer.get() || webaudio_source); 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) adapter_->Initialize(this); 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()"; 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() { 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(main_render_thread_checker_.CalledOnValidThread()); 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()"; 377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Users might not call Stop() on the track. 38bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch Stop(); 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcLocalAudioTrack::Capture(const int16* audio_data, 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeDelta delay, 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int volume, 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool key_pressed, 45ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch bool need_audio_processing, 46ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch bool force_report_nonzero_energy) { 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(capture_thread_checker_.CalledOnValidThread()); 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Calculate the signal level regardless if the track is disabled or enabled. 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int signal_level = level_calculator_->Calculate( 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_data, audio_parameters_.channels(), 52ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch audio_parameters_.frames_per_buffer(), force_report_nonzero_energy); 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) adapter_->SetSignalLevel(signal_level); 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 55bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> capturer; 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SinkList::ItemList sinks; 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SinkList::ItemList sinks_to_notify_format; 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::AutoLock auto_lock(lock_); 60bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch capturer = capturer_; 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sinks = sinks_.Items(); 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sinks_.RetrieveAndClearTags(&sinks_to_notify_format); 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Notify the tracks on when the format changes. This will do nothing if 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // |sinks_to_notify_format| is empty. 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (SinkList::ItemList::const_iterator it = sinks_to_notify_format.begin(); 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it != sinks_to_notify_format.end(); ++it) { 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*it)->OnSetFormat(audio_parameters_); 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Feed the data to the sinks. 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(jiayl): we should not pass the real audio data down if the track is 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // disabled. This is currently done so to feed input to WebRTC typing 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // detection and should be changed when audio processing is moved from 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // WebRTC to the track. 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<int> voe_channels = adapter_->VoeChannels(); 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (SinkList::ItemList::const_iterator it = sinks.begin(); 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != sinks.end(); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int new_volume = (*it)->OnData(audio_data, 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_parameters_.sample_rate(), 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_parameters_.channels(), 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_parameters_.frames_per_buffer(), 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) voe_channels, 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delay.InMilliseconds(), 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) volume, 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) need_audio_processing, 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key_pressed); 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (new_volume != 0 && capturer.get() && !webaudio_source_.get()) { 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Feed the new volume to WebRtc while changing the volume on the 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // browser. 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) capturer->SetVolume(new_volume); 94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void WebRtcLocalAudioTrack::OnSetFormat( 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters& params) { 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "WebRtcLocalAudioTrack::OnSetFormat()"; 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If the source is restarted, we might have changed to another capture 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // thread. 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) capture_thread_checker_.DetachFromThread(); 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(capture_thread_checker_.CalledOnValidThread()); 105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_parameters_ = params; 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) level_calculator_.reset(new MediaStreamAudioLevelCalculator()); 108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::AutoLock auto_lock(lock_); 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Remember to notify all sinks of the new format. 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sinks_.TagAll(); 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebRtcLocalAudioTrack::SetAudioProcessor( 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const scoped_refptr<MediaStreamAudioProcessor>& processor) { 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // if the |processor| does not have audio processing, which can happen if 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // kDisableAudioTrackProcessing is set set or all the constraints in 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // the |processor| are turned off. In such case, we pass NULL to the 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // adapter to indicate that no stats can be gotten from the processor. 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) adapter_->SetAudioProcessor(processor->has_audio_processing() ? 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) processor : NULL); 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) { 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(main_render_thread_checker_.CalledOnValidThread()); 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::AutoLock auto_lock(lock_); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Verify that |sink| is not already added to the list. 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(!sinks_.Contains( 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink))); 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create (and add to the list) a new MediaStreamAudioTrackSink 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // which owns the |sink| and delagates all calls to the 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // MediaStreamAudioSink interface. It will be tagged in the list, so 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // we remember to call OnSetFormat() on the new sink. 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<MediaStreamAudioTrackSink> sink_owner( 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new MediaStreamAudioSinkOwner(sink)); 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sinks_.AddAndTag(sink_owner.get()); 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void WebRtcLocalAudioTrack::RemoveSink(MediaStreamAudioSink* sink) { 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(main_render_thread_checker_.CalledOnValidThread()); 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()"; 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::AutoLock auto_lock(lock_); 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<MediaStreamAudioTrackSink> removed_item = sinks_.Remove( 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink)); 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Clear the delegate to ensure that no more capture callbacks will 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // be sent to this sink. Also avoids a possible crash which can happen 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // if this method is called while capturing is active. 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (removed_item.get()) 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) removed_item->Reset(); 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void WebRtcLocalAudioTrack::AddSink(PeerConnectionAudioSink* sink) { 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(main_render_thread_checker_.CalledOnValidThread()); 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::AutoLock auto_lock(lock_); 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Verify that |sink| is not already added to the list. 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(!sinks_.Contains( 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink))); 166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create (and add to the list) a new MediaStreamAudioTrackSink 168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // which owns the |sink| and delagates all calls to the 169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // MediaStreamAudioSink interface. It will be tagged in the list, so 170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // we remember to call OnSetFormat() on the new sink. 171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<MediaStreamAudioTrackSink> sink_owner( 172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new PeerConnectionAudioSinkOwner(sink)); 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sinks_.AddAndTag(sink_owner.get()); 174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void WebRtcLocalAudioTrack::RemoveSink(PeerConnectionAudioSink* sink) { 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(main_render_thread_checker_.CalledOnValidThread()); 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()"; 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::AutoLock auto_lock(lock_); 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<MediaStreamAudioTrackSink> removed_item = sinks_.Remove( 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink)); 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Clear the delegate to ensure that no more capture callbacks will 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // be sent to this sink. Also avoids a possible crash which can happen 186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // if this method is called while capturing is active. 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (removed_item.get()) 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) removed_item->Reset(); 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void WebRtcLocalAudioTrack::Start() { 192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(main_render_thread_checker_.CalledOnValidThread()); 1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DVLOG(1) << "WebRtcLocalAudioTrack::Start()"; 194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (webaudio_source_.get()) { 195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If the track is hooking up with WebAudio, do NOT add the track to the 196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // capturer as its sink otherwise two streams in different clock will be 197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // pushed through the same track. 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webaudio_source_->Start(this, capturer_.get()); 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (capturer_.get()) { 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) capturer_->AddTrack(this); 201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SinkList::ItemList sinks; 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::AutoLock auto_lock(lock_); 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sinks = sinks_.Items(); 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (SinkList::ItemList::const_iterator it = sinks.begin(); 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != sinks.end(); 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateLive); 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void WebRtcLocalAudioTrack::Stop() { 216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(main_render_thread_checker_.CalledOnValidThread()); 2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DVLOG(1) << "WebRtcLocalAudioTrack::Stop()"; 218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!capturer_.get() && !webaudio_source_.get()) 219bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return; 220bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (webaudio_source_.get()) { 222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Called Stop() on the |webaudio_source_| explicitly so that 223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |webaudio_source_| won't push more data to the track anymore. 224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Also note that the track is not registered as a sink to the |capturer_| 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // in such case and no need to call RemoveTrack(). 226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webaudio_source_->Stop(); 227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // It is necessary to call RemoveTrack on the |capturer_| to avoid getting 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // audio callback after Stop(). 230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) capturer_->RemoveTrack(this); 231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 232bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 233bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Protect the pointers using the lock when accessing |sinks_| and 234bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // setting the |capturer_| to NULL. 235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SinkList::ItemList sinks; 236bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch { 237bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch base::AutoLock auto_lock(lock_); 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sinks = sinks_.Items(); 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sinks_.Clear(); 240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webaudio_source_ = NULL; 2417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) capturer_ = NULL; 2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 243bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (SinkList::ItemList::const_iterator it = sinks.begin(); 245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) it != sinks.end(); 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it){ 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded); 248bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch (*it)->Reset(); 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace content 253