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

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: addressed Tommi's comments and added unittest 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 kMaxNumberOfBuffersInFifo = 2;
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) {
62 DCHECK(params.IsValid());
63 params_ = params;
64
65 // Use 10ms as the sink buffer size since that is the native packet size
66 // WebRtc is running on.
67 sink_buffer_size_ = params.sample_rate() / 100;
68 audio_wrapper_ =
69 media::AudioBus::Create(params.channels(),sink_buffer_size_);
tommi (sloooow) - chröme 2013/09/10 16:00:38 space after ,
no longer working on chromium 2013/09/11 10:22:07 Done.
70 buffer_.reset(new int16[params.frames_per_buffer() * params.channels()]);
71
72 // The size of the FIFO should be at least twice of the source buffer size
73 // or twice of the sink buffer size.
74 int buffer_size = std::max(
75 kMaxNumberOfBuffersInFifo * params.frames_per_buffer(),
76 kMaxNumberOfBuffersInFifo * sink_buffer_size_);
77 fifo_.reset(new media::AudioFifo(params.channels(), buffer_size));
78 }
79
80 void Push(media::AudioBus* audio_source) {
81 DCHECK(fifo_->frames() + audio_source->frames() <= fifo_->max_frames());
82 fifo_->Push(audio_source);
83 }
84
85 bool Consume() {
86 if (fifo_->frames() < audio_wrapper_->frames())
87 return false;
88
89 fifo_->Consume(audio_wrapper_.get(), 0, audio_wrapper_->frames());
90 audio_wrapper_->ToInterleaved(audio_wrapper_->frames(),
91 params_.bits_per_sample() / 8,
92 buffer());
93 return true;
94 }
95
96 int16* buffer() const { return buffer_.get(); }
97 const media::AudioParameters& params() const { return params_; }
98 int sink_buffer_size() const { return sink_buffer_size_; }
99
100 private:
101 ~ConfiguredBuffer() {}
102 friend class base::RefCounted<WebRtcLocalAudioTrack::ConfiguredBuffer>;
103
104 media::AudioParameters params_;
105 scoped_ptr<media::AudioBus> audio_wrapper_;
106 scoped_ptr<media::AudioFifo> fifo_;
107 scoped_ptr<int16[]> buffer_;
108 int sink_buffer_size_;
109 };
110
50 scoped_refptr<WebRtcLocalAudioTrack> WebRtcLocalAudioTrack::Create( 111 scoped_refptr<WebRtcLocalAudioTrack> WebRtcLocalAudioTrack::Create(
51 const std::string& id, 112 const std::string& id,
52 const scoped_refptr<WebRtcAudioCapturer>& capturer, 113 const scoped_refptr<WebRtcAudioCapturer>& capturer,
114 WebAudioCapturerSource* webaudio_source,
53 webrtc::AudioSourceInterface* track_source, 115 webrtc::AudioSourceInterface* track_source,
54 const webrtc::MediaConstraintsInterface* constraints) { 116 const webrtc::MediaConstraintsInterface* constraints) {
55 talk_base::RefCountedObject<WebRtcLocalAudioTrack>* track = 117 talk_base::RefCountedObject<WebRtcLocalAudioTrack>* track =
56 new talk_base::RefCountedObject<WebRtcLocalAudioTrack>( 118 new talk_base::RefCountedObject<WebRtcLocalAudioTrack>(
57 id, capturer, track_source, constraints); 119 id, capturer, webaudio_source, track_source, constraints);
58 return track; 120 return track;
59 } 121 }
60 122
61 WebRtcLocalAudioTrack::WebRtcLocalAudioTrack( 123 WebRtcLocalAudioTrack::WebRtcLocalAudioTrack(
62 const std::string& label, 124 const std::string& label,
63 const scoped_refptr<WebRtcAudioCapturer>& capturer, 125 const scoped_refptr<WebRtcAudioCapturer>& capturer,
126 WebAudioCapturerSource* webaudio_source,
64 webrtc::AudioSourceInterface* track_source, 127 webrtc::AudioSourceInterface* track_source,
65 const webrtc::MediaConstraintsInterface* constraints) 128 const webrtc::MediaConstraintsInterface* constraints)
66 : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label), 129 : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label),
67 capturer_(capturer), 130 capturer_(capturer),
131 webaudio_source_(webaudio_source),
68 track_source_(track_source), 132 track_source_(track_source),
69 need_audio_processing_(NeedsAudioProcessing(constraints)) { 133 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()); 134 DCHECK(capturer.get());
73 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()"; 135 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
74 } 136 }
75 137
76 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() { 138 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() {
77 DCHECK(thread_checker_.CalledOnValidThread()); 139 DCHECK(thread_checker_.CalledOnValidThread());
78 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()"; 140 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()";
79 // Users might not call Stop() on the track. 141 // Users might not call Stop() on the track.
80 Stop(); 142 Stop();
81 } 143 }
82 144
83 void WebRtcLocalAudioTrack::CaptureData(const int16* audio_data, 145 void WebRtcLocalAudioTrack::Capture(media::AudioBus* audio_source,
84 int number_of_channels, 146 int audio_delay_milliseconds,
85 int number_of_frames, 147 int volume,
86 int audio_delay_milliseconds, 148 bool key_pressed) {
87 int volume,
88 bool key_pressed) {
89 scoped_refptr<WebRtcAudioCapturer> capturer; 149 scoped_refptr<WebRtcAudioCapturer> capturer;
90 std::vector<int> voe_channels; 150 std::vector<int> voe_channels;
91 int sample_rate = 0; 151 int sample_rate = 0;
152 int number_of_channels = 0;
153 int number_of_frames = 0;
92 SinkList sinks; 154 SinkList sinks;
155 scoped_refptr<ConfiguredBuffer> current_buffer;
93 { 156 {
94 base::AutoLock auto_lock(lock_); 157 base::AutoLock auto_lock(lock_);
95 // When the track is diabled, we simply return here. 158 // When the track is disabled, we simply return here.
96 // TODO(xians): Figure out if we should feed zero to sinks instead, in 159 // TODO(xians): Figure out if we should feed zero to sinks instead, in
97 // order to inject VAD data in such case. 160 // order to inject VAD data in such case.
98 if (!enabled()) 161 if (!enabled())
99 return; 162 return;
100 163
101 capturer = capturer_; 164 capturer = capturer_;
102 voe_channels = voe_channels_; 165 voe_channels = voe_channels_;
103 sample_rate = params_.sample_rate(), 166 current_buffer = buffer_;
167 sample_rate = current_buffer->params().sample_rate();
168 number_of_channels = current_buffer->params().channels();
169 number_of_frames = current_buffer->sink_buffer_size();
104 sinks = sinks_; 170 sinks = sinks_;
105 } 171 }
106 172
107 // Feed the data to the sinks. 173 // Push the data to the fifo.
108 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) { 174 current_buffer->Push(audio_source);
109 int new_volume = (*it)->CaptureData(voe_channels, 175 // Only turn off the audio processing when the constrain is set to false as
110 audio_data, 176 // well as there is no correct delay value.
111 sample_rate, 177 bool need_audio_processing = need_audio_processing_?
tommi (sloooow) - chröme 2013/09/10 16:00:38 space before ?
no longer working on chromium 2013/09/11 10:22:07 Done.
112 number_of_channels, 178 need_audio_processing_ : (audio_delay_milliseconds != 0);
113 number_of_frames, 179 int current_volume = volume;
114 audio_delay_milliseconds, 180 while (current_buffer->Consume()) {
115 volume, 181 // Feed the data to the sinks.
116 need_audio_processing_, 182 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) {
117 key_pressed); 183 int new_volume = (*it)->CaptureData(voe_channels,
118 if (new_volume != 0 && capturer.get()) 184 current_buffer->buffer(),
119 capturer->SetVolume(new_volume); 185 sample_rate,
186 number_of_channels,
187 number_of_frames,
188 audio_delay_milliseconds,
189 current_volume,
190 need_audio_processing,
191 key_pressed);
192 if (new_volume != 0 && capturer.get()) {
193 // Feed the new volume to WebRtc while changing the volume on the
194 // browser.
195 capturer->SetVolume(new_volume);
196 current_volume = new_volume;
197 }
198 }
120 } 199 }
121 } 200 }
122 201
123 void WebRtcLocalAudioTrack::SetCaptureFormat( 202 void WebRtcLocalAudioTrack::SetCaptureFormat(
124 const media::AudioParameters& params) { 203 const media::AudioParameters& params) {
125 base::AutoLock auto_lock(lock_); 204 if (!params.IsValid())
126 params_ = params; 205 return;
206
207 scoped_refptr<ConfiguredBuffer> new_buffer(new ConfiguredBuffer());
208 new_buffer->Initialize(params);
209
210 SinkList sinks;
211 {
212 base::AutoLock auto_lock(lock_);
213 buffer_ = new_buffer;
214 sinks = sinks_;
215 }
127 216
128 // Update all the existing sinks with the new format. 217 // Update all the existing sinks with the new format.
129 for (SinkList::const_iterator it = sinks_.begin(); 218 for (SinkList::const_iterator it = sinks.begin();
130 it != sinks_.end(); ++it) 219 it != sinks.end(); ++it)
tommi (sloooow) - chröme 2013/09/10 16:00:38 {}
no longer working on chromium 2013/09/11 10:22:07 Done.
131 (*it)->SetCaptureFormat(params); 220 (*it)->SetCaptureFormat(params);
132 } 221 }
133 222
134 void WebRtcLocalAudioTrack::AddChannel(int channel_id) { 223 void WebRtcLocalAudioTrack::AddChannel(int channel_id) {
135 DVLOG(1) << "WebRtcLocalAudioTrack::AddChannel(channel_id=" 224 DVLOG(1) << "WebRtcLocalAudioTrack::AddChannel(channel_id="
136 << channel_id << ")"; 225 << channel_id << ")";
137 base::AutoLock auto_lock(lock_); 226 base::AutoLock auto_lock(lock_);
138 if (std::find(voe_channels_.begin(), voe_channels_.end(), channel_id) != 227 if (std::find(voe_channels_.begin(), voe_channels_.end(), channel_id) !=
139 voe_channels_.end()) { 228 voe_channels_.end()) {
140 // We need to handle the case when the same channel is connected to the 229 // We need to handle the case when the same channel is connected to the
(...skipping 24 matching lines...) Expand all
165 } 254 }
166 255
167 std::string WebRtcLocalAudioTrack::kind() const { 256 std::string WebRtcLocalAudioTrack::kind() const {
168 return kAudioTrackKind; 257 return kAudioTrackKind;
169 } 258 }
170 259
171 void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) { 260 void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) {
172 DCHECK(thread_checker_.CalledOnValidThread()); 261 DCHECK(thread_checker_.CalledOnValidThread());
173 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; 262 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
174 base::AutoLock auto_lock(lock_); 263 base::AutoLock auto_lock(lock_);
175 sink->SetCaptureFormat(params_); 264 if (buffer_.get())
265 sink->SetCaptureFormat(buffer_->params());
176 266
177 // Verify that |sink| is not already added to the list. 267 // Verify that |sink| is not already added to the list.
178 DCHECK(std::find_if( 268 DCHECK(std::find_if(
179 sinks_.begin(), sinks_.end(), 269 sinks_.begin(), sinks_.end(),
180 WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end()); 270 WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end());
181 271
182 // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns 272 // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns
183 // the |sink| and delagates all calls to the WebRtcAudioCapturerSink 273 // the |sink| and delagates all calls to the WebRtcAudioCapturerSink
184 // interface. 274 // interface.
185 sinks_.push_back(new WebRtcAudioCapturerSinkOwner(sink)); 275 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 290 // be sent to this sink. Also avoids a possible crash which can happen
201 // if this method is called while capturing is active. 291 // if this method is called while capturing is active.
202 (*it)->Reset(); 292 (*it)->Reset();
203 sinks_.erase(it); 293 sinks_.erase(it);
204 } 294 }
205 } 295 }
206 296
207 void WebRtcLocalAudioTrack::Start() { 297 void WebRtcLocalAudioTrack::Start() {
208 DCHECK(thread_checker_.CalledOnValidThread()); 298 DCHECK(thread_checker_.CalledOnValidThread());
209 DVLOG(1) << "WebRtcLocalAudioTrack::Start()"; 299 DVLOG(1) << "WebRtcLocalAudioTrack::Start()";
210 if (capturer_.get()) 300 DCHECK(capturer_.get());
211 capturer_->AddTrack(this); 301 if (webaudio_source_.get()) {
302 // If the track is hooking up with WebAudio, do NOT add the track to the
303 // capturer as its sink otherwise two streams in different clock will be
304 // pushed through the same track.
305 WebRtcLocalAudioSourceProvider* source_provider =
306 static_cast<WebRtcLocalAudioSourceProvider*>(
307 capturer_->audio_source_provider());
308 webaudio_source_->Start(this, source_provider);
309 return;
310 }
311
312 capturer_->AddTrack(this);
212 } 313 }
213 314
214 void WebRtcLocalAudioTrack::Stop() { 315 void WebRtcLocalAudioTrack::Stop() {
215 DCHECK(thread_checker_.CalledOnValidThread()); 316 DCHECK(thread_checker_.CalledOnValidThread());
216 DVLOG(1) << "WebRtcLocalAudioTrack::Stop()"; 317 DVLOG(1) << "WebRtcLocalAudioTrack::Stop()";
217 if (!capturer_.get()) 318 if (!capturer_.get())
218 return; 319 return;
219 320
220 capturer_->RemoveTrack(this); 321 if (webaudio_source_.get()) {
322 // Called Stop() on the |webaudio_source_| explicitly so that
323 // |webaudio_source_| won't push more data to the track anymore.
324 // Also note that the track is not registered as a sink to the |capturer_|
325 // in such case and no need to call RemoveTrack().
326 webaudio_source_->Stop();
327 } else {
328 capturer_->RemoveTrack(this);
329 }
221 330
222 // Protect the pointers using the lock when accessing |sinks_| and 331 // Protect the pointers using the lock when accessing |sinks_| and
223 // setting the |capturer_| to NULL. 332 // setting the |capturer_| to NULL.
224 SinkList sinks; 333 SinkList sinks;
225 { 334 {
226 base::AutoLock auto_lock(lock_); 335 base::AutoLock auto_lock(lock_);
227 sinks = sinks_; 336 sinks = sinks_;
337 webaudio_source_ = NULL;
228 capturer_ = NULL; 338 capturer_ = NULL;
229 } 339 }
230 340
231 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) 341 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it)
232 (*it)->Reset(); 342 (*it)->Reset();
233 } 343 }
234 344
235 } // namespace content 345 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698