Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / renderer / media / webrtc_local_audio_track.cc
blobd499233a4b2950cbe14f129beee56c53ed68e5bd
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
3 // found in the LICENSE file.
5 #include "content/renderer/media/webrtc_local_audio_track.h"
7 #include "content/public/renderer/media_stream_audio_sink.h"
8 #include "content/renderer/media/media_stream_audio_level_calculator.h"
9 #include "content/renderer/media/media_stream_audio_processor.h"
10 #include "content/renderer/media/media_stream_audio_sink_owner.h"
11 #include "content/renderer/media/media_stream_audio_track_sink.h"
12 #include "content/renderer/media/peer_connection_audio_sink_owner.h"
13 #include "content/renderer/media/webaudio_capturer_source.h"
14 #include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
15 #include "content/renderer/media/webrtc_audio_capturer.h"
17 namespace content {
19 WebRtcLocalAudioTrack::WebRtcLocalAudioTrack(
20 WebRtcLocalAudioTrackAdapter* adapter,
21 const scoped_refptr<WebRtcAudioCapturer>& capturer,
22 WebAudioCapturerSource* webaudio_source)
23 : MediaStreamTrack(adapter, true),
24 adapter_(adapter),
25 capturer_(capturer),
26 webaudio_source_(webaudio_source) {
27 DCHECK(capturer.get() || webaudio_source);
29 adapter_->Initialize(this);
31 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
34 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() {
35 DCHECK(main_render_thread_checker_.CalledOnValidThread());
36 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()";
37 // Users might not call Stop() on the track.
38 Stop();
41 void WebRtcLocalAudioTrack::Capture(const int16* audio_data,
42 base::TimeDelta delay,
43 int volume,
44 bool key_pressed,
45 bool need_audio_processing) {
46 DCHECK(capture_thread_checker_.CalledOnValidThread());
48 // Calculate the signal level regardless if the track is disabled or enabled.
49 int signal_level = level_calculator_->Calculate(
50 audio_data, audio_parameters_.channels(),
51 audio_parameters_.frames_per_buffer());
52 adapter_->SetSignalLevel(signal_level);
54 scoped_refptr<WebRtcAudioCapturer> capturer;
55 SinkList::ItemList sinks;
56 SinkList::ItemList sinks_to_notify_format;
58 base::AutoLock auto_lock(lock_);
59 capturer = capturer_;
60 sinks = sinks_.Items();
61 sinks_.RetrieveAndClearTags(&sinks_to_notify_format);
64 // Notify the tracks on when the format changes. This will do nothing if
65 // |sinks_to_notify_format| is empty.
66 for (SinkList::ItemList::const_iterator it = sinks_to_notify_format.begin();
67 it != sinks_to_notify_format.end(); ++it) {
68 (*it)->OnSetFormat(audio_parameters_);
71 // Feed the data to the sinks.
72 // TODO(jiayl): we should not pass the real audio data down if the track is
73 // disabled. This is currently done so to feed input to WebRTC typing
74 // detection and should be changed when audio processing is moved from
75 // WebRTC to the track.
76 std::vector<int> voe_channels = adapter_->VoeChannels();
77 for (SinkList::ItemList::const_iterator it = sinks.begin();
78 it != sinks.end();
79 ++it) {
80 int new_volume = (*it)->OnData(audio_data,
81 audio_parameters_.sample_rate(),
82 audio_parameters_.channels(),
83 audio_parameters_.frames_per_buffer(),
84 voe_channels,
85 delay.InMilliseconds(),
86 volume,
87 need_audio_processing,
88 key_pressed);
89 if (new_volume != 0 && capturer.get() && !webaudio_source_.get()) {
90 // Feed the new volume to WebRtc while changing the volume on the
91 // browser.
92 capturer->SetVolume(new_volume);
97 void WebRtcLocalAudioTrack::OnSetFormat(
98 const media::AudioParameters& params) {
99 DVLOG(1) << "WebRtcLocalAudioTrack::OnSetFormat()";
100 // If the source is restarted, we might have changed to another capture
101 // thread.
102 capture_thread_checker_.DetachFromThread();
103 DCHECK(capture_thread_checker_.CalledOnValidThread());
105 audio_parameters_ = params;
106 level_calculator_.reset(new MediaStreamAudioLevelCalculator());
108 base::AutoLock auto_lock(lock_);
109 // Remember to notify all sinks of the new format.
110 sinks_.TagAll();
113 void WebRtcLocalAudioTrack::SetAudioProcessor(
114 const scoped_refptr<MediaStreamAudioProcessor>& processor) {
115 // if the |processor| does not have audio processing, which can happen if
116 // kDisableAudioTrackProcessing is set set or all the constraints in
117 // the |processor| are turned off. In such case, we pass NULL to the
118 // adapter to indicate that no stats can be gotten from the processor.
119 adapter_->SetAudioProcessor(processor->has_audio_processing() ?
120 processor : NULL);
123 void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) {
124 DCHECK(main_render_thread_checker_.CalledOnValidThread());
125 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
126 base::AutoLock auto_lock(lock_);
128 // Verify that |sink| is not already added to the list.
129 DCHECK(!sinks_.Contains(
130 MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink)));
132 // Create (and add to the list) a new MediaStreamAudioTrackSink
133 // which owns the |sink| and delagates all calls to the
134 // MediaStreamAudioSink interface. It will be tagged in the list, so
135 // we remember to call OnSetFormat() on the new sink.
136 scoped_refptr<MediaStreamAudioTrackSink> sink_owner(
137 new MediaStreamAudioSinkOwner(sink));
138 sinks_.AddAndTag(sink_owner.get());
141 void WebRtcLocalAudioTrack::RemoveSink(MediaStreamAudioSink* sink) {
142 DCHECK(main_render_thread_checker_.CalledOnValidThread());
143 DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()";
145 base::AutoLock auto_lock(lock_);
147 scoped_refptr<MediaStreamAudioTrackSink> removed_item = sinks_.Remove(
148 MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink));
150 // Clear the delegate to ensure that no more capture callbacks will
151 // be sent to this sink. Also avoids a possible crash which can happen
152 // if this method is called while capturing is active.
153 if (removed_item.get())
154 removed_item->Reset();
157 void WebRtcLocalAudioTrack::AddSink(PeerConnectionAudioSink* sink) {
158 DCHECK(main_render_thread_checker_.CalledOnValidThread());
159 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
160 base::AutoLock auto_lock(lock_);
162 // Verify that |sink| is not already added to the list.
163 DCHECK(!sinks_.Contains(
164 MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink)));
166 // Create (and add to the list) a new MediaStreamAudioTrackSink
167 // which owns the |sink| and delagates all calls to the
168 // MediaStreamAudioSink interface. It will be tagged in the list, so
169 // we remember to call OnSetFormat() on the new sink.
170 scoped_refptr<MediaStreamAudioTrackSink> sink_owner(
171 new PeerConnectionAudioSinkOwner(sink));
172 sinks_.AddAndTag(sink_owner.get());
175 void WebRtcLocalAudioTrack::RemoveSink(PeerConnectionAudioSink* sink) {
176 DCHECK(main_render_thread_checker_.CalledOnValidThread());
177 DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()";
179 base::AutoLock auto_lock(lock_);
181 scoped_refptr<MediaStreamAudioTrackSink> removed_item = sinks_.Remove(
182 MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink));
183 // Clear the delegate to ensure that no more capture callbacks will
184 // be sent to this sink. Also avoids a possible crash which can happen
185 // if this method is called while capturing is active.
186 if (removed_item.get())
187 removed_item->Reset();
190 void WebRtcLocalAudioTrack::Start() {
191 DCHECK(main_render_thread_checker_.CalledOnValidThread());
192 DVLOG(1) << "WebRtcLocalAudioTrack::Start()";
193 if (webaudio_source_.get()) {
194 // If the track is hooking up with WebAudio, do NOT add the track to the
195 // capturer as its sink otherwise two streams in different clock will be
196 // pushed through the same track.
197 webaudio_source_->Start(this, capturer_.get());
198 } else if (capturer_.get()) {
199 capturer_->AddTrack(this);
202 SinkList::ItemList sinks;
204 base::AutoLock auto_lock(lock_);
205 sinks = sinks_.Items();
207 for (SinkList::ItemList::const_iterator it = sinks.begin();
208 it != sinks.end();
209 ++it) {
210 (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateLive);
214 void WebRtcLocalAudioTrack::Stop() {
215 DCHECK(main_render_thread_checker_.CalledOnValidThread());
216 DVLOG(1) << "WebRtcLocalAudioTrack::Stop()";
217 if (!capturer_.get() && !webaudio_source_.get())
218 return;
220 if (webaudio_source_.get()) {
221 // Called Stop() on the |webaudio_source_| explicitly so that
222 // |webaudio_source_| won't push more data to the track anymore.
223 // Also note that the track is not registered as a sink to the |capturer_|
224 // in such case and no need to call RemoveTrack().
225 webaudio_source_->Stop();
226 } else {
227 // It is necessary to call RemoveTrack on the |capturer_| to avoid getting
228 // audio callback after Stop().
229 capturer_->RemoveTrack(this);
232 // Protect the pointers using the lock when accessing |sinks_| and
233 // setting the |capturer_| to NULL.
234 SinkList::ItemList sinks;
236 base::AutoLock auto_lock(lock_);
237 sinks = sinks_.Items();
238 sinks_.Clear();
239 webaudio_source_ = NULL;
240 capturer_ = NULL;
243 for (SinkList::ItemList::const_iterator it = sinks.begin();
244 it != sinks.end();
245 ++it){
246 (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded);
247 (*it)->Reset();
251 } // namespace content