Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: content/renderer/media/webrtc_local_audio_track.cc

Issue 23691038: Switch LiveAudio to source provider solution. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased and fixed some unittests Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/renderer/media/webaudio_capturer_source.h"
7 #include "content/renderer/media/webrtc_audio_capturer.h" 8 #include "content/renderer/media/webrtc_audio_capturer.h"
8 #include "content/renderer/media/webrtc_audio_capturer_sink_owner.h" 9 #include "content/renderer/media/webrtc_audio_capturer_sink_owner.h"
10 #include "content/renderer/media/webrtc_local_audio_source_provider.h"
11 #include "media/base/audio_fifo.h"
9 #include "third_party/libjingle/source/talk/media/base/audiorenderer.h" 12 #include "third_party/libjingle/source/talk/media/base/audiorenderer.h"
10 13
11 namespace content { 14 namespace content {
12 15
16 static const size_t kMaxNumberOfBufferInFifo = 2;
tommi (sloooow) - chröme 2013/09/06 11:20:30 kMaxNumberOfBuffersInFifo (plural)
no longer working on chromium 2013/09/10 12:43:15 Done.
13 static const char kAudioTrackKind[] = "audio"; 17 static const char kAudioTrackKind[] = "audio";
14 18
15 namespace { 19 namespace {
16 20
17 using webrtc::MediaConstraintsInterface; 21 using webrtc::MediaConstraintsInterface;
18 22
19 // This helper function checks if any audio constraints are set that require 23 // This helper function checks if any audio constraints are set that require
20 // audio processing to be applied. Right now this is a big, single switch for 24 // audio processing to be applied. Right now this is a big, single switch for
21 // all of the properties, but in the future they'll be handled one by one. 25 // all of the properties, but in the future they'll be handled one by one.
22 bool NeedsAudioProcessing( 26 bool NeedsAudioProcessing(
(...skipping 17 matching lines...) Expand all
40 value) { 44 value) {
41 return true; 45 return true;
42 } 46 }
43 } 47 }
44 48
45 return false; 49 return false;
46 } 50 }
47 51
48 } // namespace. 52 } // namespace.
49 53
54 // This is a temporary audio buffer with parameters used to send data to
55 // callbacks.
56 class WebRtcLocalAudioTrack::ConfiguredBuffer :
57 public base::RefCounted<WebRtcLocalAudioTrack::ConfiguredBuffer> {
58 public:
59 ConfiguredBuffer() : sink_buffer_size_(0) {}
60
61 void Initialize(const media::AudioParameters& params) {
tommi (sloooow) - chröme 2013/09/06 11:20:30 Since Initialize() returns void and it's not a vir
no longer working on chromium 2013/09/10 12:43:15 The main reason for existing code is that we will
62 DCHECK(params.IsValid());
63 params_ = params;
64 sink_buffer_size_ = params.sample_rate() / 100;
tommi (sloooow) - chröme 2013/09/06 11:20:30 document why 10ms
no longer working on chromium 2013/09/10 12:43:15 Done.
65 audio_wrapper_ =
66 media::AudioBus::Create(params.channels(),sink_buffer_size_);
67 buffer_.reset(new int16[params.frames_per_buffer() * params.channels()]);
68
69 // The size of the FIFO should be at least twice of the source buffer size
70 // or twice of the sink buffer size.
71 int buffer_size = std::max(
72 2 * params.frames_per_buffer(), 2 * sink_buffer_size_);
73 fifo_.reset(new media::AudioFifo(params.channels(), buffer_size));
74 }
75
76 void Push(media::AudioBus* audio_source) {
77 DCHECK(fifo_.get());
tommi (sloooow) - chröme 2013/09/06 11:20:30 this isn't necessary since you dereference the poi
78 CHECK(fifo_->frames() + audio_source->frames() <= fifo_->max_frames());
tommi (sloooow) - chröme 2013/09/06 11:20:30 DCHECK?
no longer working on chromium 2013/09/10 12:43:15 Done.
79 fifo_->Push(audio_source);
80 }
81
82 bool Consume() {
83 DCHECK(audio_wrapper_.get());
tommi (sloooow) - chröme 2013/09/06 11:20:30 unnecessary
no longer working on chromium 2013/09/10 12:43:15 Done.
84 if (fifo_->frames() < audio_wrapper_->frames())
85 return false;
86
87 fifo_->Consume(audio_wrapper_.get(), 0, audio_wrapper_->frames());
88 audio_wrapper_->ToInterleaved(audio_wrapper_->frames(),
89 params_.bits_per_sample() / 8,
90 buffer());
91 return true;
92 }
93
94 int16* buffer() const { return buffer_.get(); }
95 const media::AudioParameters& params() const { return params_; }
96 int sink_buffer_size() const { return sink_buffer_size_; }
97
98 private:
99 ~ConfiguredBuffer() {}
100 friend class base::RefCounted<WebRtcLocalAudioTrack::ConfiguredBuffer>;
101
102 media::AudioParameters params_;
103 scoped_ptr<media::AudioBus> audio_wrapper_;
104 scoped_ptr<media::AudioFifo> fifo_;
105 scoped_ptr<int16[]> buffer_;
106 int sink_buffer_size_;
107 };
108
50 scoped_refptr<WebRtcLocalAudioTrack> WebRtcLocalAudioTrack::Create( 109 scoped_refptr<WebRtcLocalAudioTrack> WebRtcLocalAudioTrack::Create(
51 const std::string& id, 110 const std::string& id,
52 const scoped_refptr<WebRtcAudioCapturer>& capturer, 111 const scoped_refptr<WebRtcAudioCapturer>& capturer,
112 WebAudioCapturerSource* webaudio_source,
53 webrtc::AudioSourceInterface* track_source, 113 webrtc::AudioSourceInterface* track_source,
54 const webrtc::MediaConstraintsInterface* constraints) { 114 const webrtc::MediaConstraintsInterface* constraints) {
55 talk_base::RefCountedObject<WebRtcLocalAudioTrack>* track = 115 talk_base::RefCountedObject<WebRtcLocalAudioTrack>* track =
56 new talk_base::RefCountedObject<WebRtcLocalAudioTrack>( 116 new talk_base::RefCountedObject<WebRtcLocalAudioTrack>(
57 id, capturer, track_source, constraints); 117 id, capturer, webaudio_source, track_source, constraints);
58 return track; 118 return track;
59 } 119 }
60 120
61 WebRtcLocalAudioTrack::WebRtcLocalAudioTrack( 121 WebRtcLocalAudioTrack::WebRtcLocalAudioTrack(
62 const std::string& label, 122 const std::string& label,
63 const scoped_refptr<WebRtcAudioCapturer>& capturer, 123 const scoped_refptr<WebRtcAudioCapturer>& capturer,
124 WebAudioCapturerSource* webaudio_source,
64 webrtc::AudioSourceInterface* track_source, 125 webrtc::AudioSourceInterface* track_source,
65 const webrtc::MediaConstraintsInterface* constraints) 126 const webrtc::MediaConstraintsInterface* constraints)
66 : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label), 127 : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label),
67 capturer_(capturer), 128 capturer_(capturer),
129 webaudio_source_(webaudio_source),
68 track_source_(track_source), 130 track_source_(track_source),
69 need_audio_processing_(NeedsAudioProcessing(constraints)) { 131 need_audio_processing_(NeedsAudioProcessing(constraints)) {
70 // The capturer with a valid device id is using microphone as source,
71 // and APM (AudioProcessingModule) is turned on only for microphone data.
72 DCHECK(capturer.get()); 132 DCHECK(capturer.get());
73 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()"; 133 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
74 } 134 }
75 135
76 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() { 136 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() {
77 DCHECK(thread_checker_.CalledOnValidThread()); 137 DCHECK(thread_checker_.CalledOnValidThread());
78 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()"; 138 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()";
79 // Users might not call Stop() on the track. 139 // Users might not call Stop() on the track.
80 Stop(); 140 Stop();
81 } 141 }
82 142
83 void WebRtcLocalAudioTrack::CaptureData(const int16* audio_data, 143 void WebRtcLocalAudioTrack::Capture(media::AudioBus* audio_source,
84 int number_of_channels, 144 int audio_delay_milliseconds,
85 int number_of_frames, 145 int volume,
86 int audio_delay_milliseconds, 146 bool key_pressed) {
87 int volume,
88 bool key_pressed) {
89 scoped_refptr<WebRtcAudioCapturer> capturer; 147 scoped_refptr<WebRtcAudioCapturer> capturer;
90 std::vector<int> voe_channels; 148 std::vector<int> voe_channels;
91 int sample_rate = 0; 149 int sample_rate = 0;
150 int number_of_channels = 0;
151 int number_of_frames = 0;
92 SinkList sinks; 152 SinkList sinks;
153 scoped_refptr<ConfiguredBuffer> current_buffer;
93 { 154 {
94 base::AutoLock auto_lock(lock_); 155 base::AutoLock auto_lock(lock_);
95 // When the track is diabled, we simply return here. 156 // When the track is disabled, we simply return here.
96 // TODO(xians): Figure out if we should feed zero to sinks instead, in 157 // TODO(xians): Figure out if we should feed zero to sinks instead, in
97 // order to inject VAD data in such case. 158 // order to inject VAD data in such case.
98 if (!enabled()) 159 if (!enabled())
99 return; 160 return;
100 161
101 capturer = capturer_; 162 capturer = capturer_;
102 voe_channels = voe_channels_; 163 voe_channels = voe_channels_;
103 sample_rate = params_.sample_rate(), 164 current_buffer = buffer_;
165 sample_rate = current_buffer->params().sample_rate();
166 number_of_channels = current_buffer->params().channels();
167 number_of_frames = current_buffer->sink_buffer_size();
104 sinks = sinks_; 168 sinks = sinks_;
105 } 169 }
106 170
107 // Feed the data to the sinks. 171 // Push the data to the fifo.
108 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) { 172 current_buffer->Push(audio_source);
109 int new_volume = (*it)->CaptureData(voe_channels, 173 // Only turn off the audio processing when the constrain is set to false as
110 audio_data, 174 // well as there is no correct delay value.
111 sample_rate, 175 bool need_audio_processing = need_audio_processing_?
112 number_of_channels, 176 need_audio_processing_ : (audio_delay_milliseconds != 0);
113 number_of_frames, 177 int current_volume = volume;
114 audio_delay_milliseconds, 178 while (current_buffer->Consume()) {
115 volume, 179 // Feed the data to the sinks.
116 need_audio_processing_, 180 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) {
117 key_pressed); 181 int new_volume = (*it)->CaptureData(voe_channels,
118 if (new_volume != 0 && capturer.get()) 182 current_buffer->buffer(),
119 capturer->SetVolume(new_volume); 183 sample_rate,
184 number_of_channels,
185 number_of_frames,
186 audio_delay_milliseconds,
187 current_volume,
188 need_audio_processing,
189 key_pressed);
190 if (new_volume != 0 && capturer.get()) {
191 // Feed the new volume to WebRtc while changing the volume on the
192 // browser.
193 capturer->SetVolume(new_volume);
194 current_volume = new_volume;
195 }
196 }
120 } 197 }
121 } 198 }
122 199
123 void WebRtcLocalAudioTrack::SetCaptureFormat( 200 void WebRtcLocalAudioTrack::SetCaptureFormat(
124 const media::AudioParameters& params) { 201 const media::AudioParameters& params) {
125 base::AutoLock auto_lock(lock_); 202 if (!params.IsValid())
126 params_ = params; 203 return;
204
205 scoped_refptr<ConfiguredBuffer> new_buffer(new ConfiguredBuffer());
206 new_buffer->Initialize(params);
207
208 SinkList sinks;
209 {
210 base::AutoLock auto_lock(lock_);
211 buffer_ = new_buffer;
212 sinks = sinks_;
213 }
127 214
128 // Update all the existing sinks with the new format. 215 // Update all the existing sinks with the new format.
129 for (SinkList::const_iterator it = sinks_.begin(); 216 for (SinkList::const_iterator it = sinks.begin();
130 it != sinks_.end(); ++it) 217 it != sinks.end(); ++it)
131 (*it)->SetCaptureFormat(params); 218 (*it)->SetCaptureFormat(params);
132 } 219 }
133 220
134 void WebRtcLocalAudioTrack::AddChannel(int channel_id) { 221 void WebRtcLocalAudioTrack::AddChannel(int channel_id) {
135 DVLOG(1) << "WebRtcLocalAudioTrack::AddChannel(channel_id=" 222 DVLOG(1) << "WebRtcLocalAudioTrack::AddChannel(channel_id="
136 << channel_id << ")"; 223 << channel_id << ")";
137 base::AutoLock auto_lock(lock_); 224 base::AutoLock auto_lock(lock_);
138 if (std::find(voe_channels_.begin(), voe_channels_.end(), channel_id) != 225 if (std::find(voe_channels_.begin(), voe_channels_.end(), channel_id) !=
139 voe_channels_.end()) { 226 voe_channels_.end()) {
140 // We need to handle the case when the same channel is connected to the 227 // We need to handle the case when the same channel is connected to the
(...skipping 24 matching lines...) Expand all
165 } 252 }
166 253
167 std::string WebRtcLocalAudioTrack::kind() const { 254 std::string WebRtcLocalAudioTrack::kind() const {
168 return kAudioTrackKind; 255 return kAudioTrackKind;
169 } 256 }
170 257
171 void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) { 258 void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) {
172 DCHECK(thread_checker_.CalledOnValidThread()); 259 DCHECK(thread_checker_.CalledOnValidThread());
173 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; 260 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
174 base::AutoLock auto_lock(lock_); 261 base::AutoLock auto_lock(lock_);
175 sink->SetCaptureFormat(params_); 262 if (buffer_.get())
263 sink->SetCaptureFormat(buffer_->params());
176 264
177 // Verify that |sink| is not already added to the list. 265 // Verify that |sink| is not already added to the list.
178 DCHECK(std::find_if( 266 DCHECK(std::find_if(
179 sinks_.begin(), sinks_.end(), 267 sinks_.begin(), sinks_.end(),
180 WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end()); 268 WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end());
181 269
182 // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns 270 // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns
183 // the |sink| and delagates all calls to the WebRtcAudioCapturerSink 271 // the |sink| and delagates all calls to the WebRtcAudioCapturerSink
184 // interface. 272 // interface.
185 sinks_.push_back(new WebRtcAudioCapturerSinkOwner(sink)); 273 sinks_.push_back(new WebRtcAudioCapturerSinkOwner(sink));
(...skipping 14 matching lines...) Expand all
200 // be sent to this sink. Also avoids a possible crash which can happen 288 // be sent to this sink. Also avoids a possible crash which can happen
201 // if this method is called while capturing is active. 289 // if this method is called while capturing is active.
202 (*it)->Reset(); 290 (*it)->Reset();
203 sinks_.erase(it); 291 sinks_.erase(it);
204 } 292 }
205 } 293 }
206 294
207 void WebRtcLocalAudioTrack::Start() { 295 void WebRtcLocalAudioTrack::Start() {
208 DCHECK(thread_checker_.CalledOnValidThread()); 296 DCHECK(thread_checker_.CalledOnValidThread());
209 DVLOG(1) << "WebRtcLocalAudioTrack::Start()"; 297 DVLOG(1) << "WebRtcLocalAudioTrack::Start()";
210 if (capturer_.get()) 298 DCHECK(capturer_.get());
211 capturer_->AddTrack(this); 299 if (webaudio_source_.get()) {
300 // If the track is hooking up with WebAudio, do NOT add the track to the
301 // capturer as its sink.
tommi (sloooow) - chröme 2013/09/06 11:20:30 document why not. The "what" can usually be under
no longer working on chromium 2013/09/10 12:43:15 Done.
302 WebRtcLocalAudioSourceProvider* source_provider =
303 static_cast<WebRtcLocalAudioSourceProvider*>(
304 capturer_->AudioSourceProvider());
305 webaudio_source_->Start(this, source_provider);
306 return;
307 }
308
309 capturer_->AddTrack(this);
212 } 310 }
213 311
214 void WebRtcLocalAudioTrack::Stop() { 312 void WebRtcLocalAudioTrack::Stop() {
215 DCHECK(thread_checker_.CalledOnValidThread()); 313 DCHECK(thread_checker_.CalledOnValidThread());
216 DVLOG(1) << "WebRtcLocalAudioTrack::Stop()"; 314 DVLOG(1) << "WebRtcLocalAudioTrack::Stop()";
217 if (!capturer_.get()) 315 if (!capturer_.get())
218 return; 316 return;
219 317
220 capturer_->RemoveTrack(this); 318 if (webaudio_source_.get())
319 webaudio_source_->Stop();
320 else
321 capturer_->RemoveTrack(this);
tommi (sloooow) - chröme 2013/09/06 11:20:30 why do we not want to call RemoveTrack if webaudio
no longer working on chromium 2013/09/10 12:43:15 Added a comment to explain the track is not a sink
221 322
222 // Protect the pointers using the lock when accessing |sinks_| and 323 // Protect the pointers using the lock when accessing |sinks_| and
223 // setting the |capturer_| to NULL. 324 // setting the |capturer_| to NULL.
224 SinkList sinks; 325 SinkList sinks;
225 { 326 {
226 base::AutoLock auto_lock(lock_); 327 base::AutoLock auto_lock(lock_);
227 sinks = sinks_; 328 sinks = sinks_;
329 webaudio_source_ = NULL;
228 capturer_ = NULL; 330 capturer_ = NULL;
229 } 331 }
230 332
231 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) 333 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it)
232 (*it)->Reset(); 334 (*it)->Reset();
233 } 335 }
234 336
235 } // namespace content 337 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698