1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h" 6 7 #include "base/logging.h" 8 #include "content/renderer/media/media_stream_audio_processor.h" 9 #include "content/renderer/media/webrtc/webrtc_audio_sink_adapter.h" 10 #include "content/renderer/media/webrtc_local_audio_track.h" 11 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" 12 13 namespace content { 14 15 static const char kAudioTrackKind[] = "audio"; 16 17 scoped_refptr<WebRtcLocalAudioTrackAdapter> 18 WebRtcLocalAudioTrackAdapter::Create( 19 const std::string& label, 20 webrtc::AudioSourceInterface* track_source) { 21 talk_base::RefCountedObject<WebRtcLocalAudioTrackAdapter>* adapter = 22 new talk_base::RefCountedObject<WebRtcLocalAudioTrackAdapter>( 23 label, track_source); 24 return adapter; 25 } 26 27 WebRtcLocalAudioTrackAdapter::WebRtcLocalAudioTrackAdapter( 28 const std::string& label, 29 webrtc::AudioSourceInterface* track_source) 30 : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label), 31 owner_(NULL), 32 track_source_(track_source), 33 signal_level_(0) { 34 } 35 36 WebRtcLocalAudioTrackAdapter::~WebRtcLocalAudioTrackAdapter() { 37 } 38 39 void WebRtcLocalAudioTrackAdapter::Initialize(WebRtcLocalAudioTrack* owner) { 40 DCHECK(!owner_); 41 DCHECK(owner); 42 owner_ = owner; 43 } 44 45 void WebRtcLocalAudioTrackAdapter::SetAudioProcessor( 46 const scoped_refptr<MediaStreamAudioProcessor>& processor) { 47 base::AutoLock auto_lock(lock_); 48 audio_processor_ = processor; 49 } 50 51 std::string WebRtcLocalAudioTrackAdapter::kind() const { 52 return kAudioTrackKind; 53 } 54 55 void WebRtcLocalAudioTrackAdapter::AddSink( 56 webrtc::AudioTrackSinkInterface* sink) { 57 DCHECK(sink); 58 #ifndef NDEBUG 59 // Verify that |sink| has not been added. 60 for (ScopedVector<WebRtcAudioSinkAdapter>::const_iterator it = 61 sink_adapters_.begin(); 62 it != sink_adapters_.end(); ++it) { 63 DCHECK(!(*it)->IsEqual(sink)); 64 } 65 #endif 66 67 scoped_ptr<WebRtcAudioSinkAdapter> adapter( 68 new WebRtcAudioSinkAdapter(sink)); 69 owner_->AddSink(adapter.get()); 70 sink_adapters_.push_back(adapter.release()); 71 } 72 73 void WebRtcLocalAudioTrackAdapter::RemoveSink( 74 webrtc::AudioTrackSinkInterface* sink) { 75 DCHECK(sink); 76 for (ScopedVector<WebRtcAudioSinkAdapter>::iterator it = 77 sink_adapters_.begin(); 78 it != sink_adapters_.end(); ++it) { 79 if ((*it)->IsEqual(sink)) { 80 owner_->RemoveSink(*it); 81 sink_adapters_.erase(it); 82 return; 83 } 84 } 85 } 86 87 bool WebRtcLocalAudioTrackAdapter::GetSignalLevel(int* level) { 88 base::AutoLock auto_lock(lock_); 89 // It is required to provide the signal level after audio processing. In 90 // case the audio processing is not enabled for the track, we return 91 // false here in order not to overwrite the value from WebRTC. 92 // TODO(xians): Remove this after we turn on the APM in Chrome by default. 93 // http://crbug/365672 . 94 if (!MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()) 95 return false; 96 97 *level = signal_level_; 98 return true; 99 } 100 101 talk_base::scoped_refptr<webrtc::AudioProcessorInterface> 102 WebRtcLocalAudioTrackAdapter::GetAudioProcessor() { 103 base::AutoLock auto_lock(lock_); 104 return audio_processor_.get(); 105 } 106 107 std::vector<int> WebRtcLocalAudioTrackAdapter::VoeChannels() const { 108 base::AutoLock auto_lock(lock_); 109 return voe_channels_; 110 } 111 112 void WebRtcLocalAudioTrackAdapter::SetSignalLevel(int signal_level) { 113 base::AutoLock auto_lock(lock_); 114 signal_level_ = signal_level; 115 } 116 117 void WebRtcLocalAudioTrackAdapter::AddChannel(int channel_id) { 118 DVLOG(1) << "WebRtcLocalAudioTrack::AddChannel(channel_id=" 119 << channel_id << ")"; 120 base::AutoLock auto_lock(lock_); 121 if (std::find(voe_channels_.begin(), voe_channels_.end(), channel_id) != 122 voe_channels_.end()) { 123 // We need to handle the case when the same channel is connected to the 124 // track more than once. 125 return; 126 } 127 128 voe_channels_.push_back(channel_id); 129 } 130 131 void WebRtcLocalAudioTrackAdapter::RemoveChannel(int channel_id) { 132 DVLOG(1) << "WebRtcLocalAudioTrack::RemoveChannel(channel_id=" 133 << channel_id << ")"; 134 base::AutoLock auto_lock(lock_); 135 std::vector<int>::iterator iter = 136 std::find(voe_channels_.begin(), voe_channels_.end(), channel_id); 137 DCHECK(iter != voe_channels_.end()); 138 voe_channels_.erase(iter); 139 } 140 141 webrtc::AudioSourceInterface* WebRtcLocalAudioTrackAdapter::GetSource() const { 142 return track_source_; 143 } 144 145 cricket::AudioRenderer* WebRtcLocalAudioTrackAdapter::GetRenderer() { 146 // When the audio track processing is enabled, return a NULL so that capture 147 // data goes through Libjingle LocalAudioTrackHandler::LocalAudioSinkAdapter 148 // ==> WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer ==> WebRTC. 149 // When the audio track processing is disabled, WebRtcLocalAudioTrackAdapter 150 // is used to pass the channel ids to WebRtcAudioDeviceImpl, the data flow 151 // becomes WebRtcAudioDeviceImpl ==> WebRTC. 152 // TODO(xians): Only return NULL after the APM in WebRTC is deprecated. 153 // See See http://crbug/365672 for details. 154 return MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()? 155 NULL : this; 156 } 157 158 } // namespace content 159