OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/media_stream_audio_processor.h" | 5 #include "content/renderer/media/media_stream_audio_processor.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
9 #include "content/public/common/content_switches.h" | 9 #include "content/public/common/content_switches.h" |
10 #include "content/renderer/media/media_stream_audio_processor_options.h" | 10 #include "content/renderer/media/media_stream_audio_processor_options.h" |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 // TODO(xians): consider using SincResampler to save some memcpy. | 134 // TODO(xians): consider using SincResampler to save some memcpy. |
135 // Handles mixing and resampling between input and output parameters. | 135 // Handles mixing and resampling between input and output parameters. |
136 media::AudioConverter audio_converter_; | 136 media::AudioConverter audio_converter_; |
137 scoped_ptr<media::AudioBus> audio_wrapper_; | 137 scoped_ptr<media::AudioBus> audio_wrapper_; |
138 scoped_ptr<media::AudioFifo> fifo_; | 138 scoped_ptr<media::AudioFifo> fifo_; |
139 }; | 139 }; |
140 | 140 |
141 MediaStreamAudioProcessor::MediaStreamAudioProcessor( | 141 MediaStreamAudioProcessor::MediaStreamAudioProcessor( |
142 const media::AudioParameters& source_params, | 142 const media::AudioParameters& source_params, |
143 const blink::WebMediaConstraints& constraints, | 143 const blink::WebMediaConstraints& constraints, |
144 int effects) | 144 int effects, |
| 145 WebRtcPlayoutDataSource* playout_data_source) |
145 : render_delay_ms_(0), | 146 : render_delay_ms_(0), |
| 147 playout_data_source_(playout_data_source), |
146 audio_mirroring_(false) { | 148 audio_mirroring_(false) { |
147 capture_thread_checker_.DetachFromThread(); | 149 capture_thread_checker_.DetachFromThread(); |
148 render_thread_checker_.DetachFromThread(); | 150 render_thread_checker_.DetachFromThread(); |
149 InitializeAudioProcessingModule(constraints, effects); | 151 InitializeAudioProcessingModule(constraints, effects); |
150 InitializeCaptureConverter(source_params); | 152 InitializeCaptureConverter(source_params); |
151 } | 153 } |
152 | 154 |
153 MediaStreamAudioProcessor::~MediaStreamAudioProcessor() { | 155 MediaStreamAudioProcessor::~MediaStreamAudioProcessor() { |
154 DCHECK(main_thread_checker_.CalledOnValidThread()); | 156 DCHECK(main_thread_checker_.CalledOnValidThread()); |
155 StopAudioProcessing(); | 157 StopAudioProcessing(); |
156 } | 158 } |
157 | 159 |
158 void MediaStreamAudioProcessor::PushCaptureData(media::AudioBus* audio_source) { | 160 void MediaStreamAudioProcessor::PushCaptureData(media::AudioBus* audio_source) { |
159 DCHECK(capture_thread_checker_.CalledOnValidThread()); | 161 DCHECK(capture_thread_checker_.CalledOnValidThread()); |
160 capture_converter_->Push(audio_source); | 162 capture_converter_->Push(audio_source); |
161 } | 163 } |
162 | 164 |
163 void MediaStreamAudioProcessor::PushRenderData( | |
164 const int16* render_audio, int sample_rate, int number_of_channels, | |
165 int number_of_frames, base::TimeDelta render_delay) { | |
166 DCHECK(render_thread_checker_.CalledOnValidThread()); | |
167 | |
168 // Return immediately if the echo cancellation is off. | |
169 if (!audio_processing_ || | |
170 !audio_processing_->echo_cancellation()->is_enabled()) { | |
171 return; | |
172 } | |
173 | |
174 TRACE_EVENT0("audio", | |
175 "MediaStreamAudioProcessor::FeedRenderDataToAudioProcessing"); | |
176 int64 new_render_delay_ms = render_delay.InMilliseconds(); | |
177 DCHECK_LT(new_render_delay_ms, | |
178 std::numeric_limits<base::subtle::Atomic32>::max()); | |
179 base::subtle::Release_Store(&render_delay_ms_, new_render_delay_ms); | |
180 | |
181 InitializeRenderConverterIfNeeded(sample_rate, number_of_channels, | |
182 number_of_frames); | |
183 | |
184 // TODO(xians): Avoid this extra interleave/deinterleave. | |
185 render_data_bus_->FromInterleaved(render_audio, | |
186 render_data_bus_->frames(), | |
187 sizeof(render_audio[0])); | |
188 render_converter_->Push(render_data_bus_.get()); | |
189 while (render_converter_->Convert(&render_frame_)) | |
190 audio_processing_->AnalyzeReverseStream(&render_frame_); | |
191 } | |
192 | |
193 bool MediaStreamAudioProcessor::ProcessAndConsumeData( | 165 bool MediaStreamAudioProcessor::ProcessAndConsumeData( |
194 base::TimeDelta capture_delay, int volume, bool key_pressed, | 166 base::TimeDelta capture_delay, int volume, bool key_pressed, |
195 int* new_volume, int16** out) { | 167 int* new_volume, int16** out) { |
196 DCHECK(capture_thread_checker_.CalledOnValidThread()); | 168 DCHECK(capture_thread_checker_.CalledOnValidThread()); |
197 TRACE_EVENT0("audio", | 169 TRACE_EVENT0("audio", "MediaStreamAudioProcessor::ProcessAndConsumeData"); |
198 "MediaStreamAudioProcessor::ProcessAndConsumeData"); | |
199 | 170 |
200 if (!capture_converter_->Convert(&capture_frame_)) | 171 if (!capture_converter_->Convert(&capture_frame_)) |
201 return false; | 172 return false; |
202 | 173 |
203 *new_volume = ProcessData(&capture_frame_, capture_delay, volume, | 174 *new_volume = ProcessData(&capture_frame_, capture_delay, volume, |
204 key_pressed); | 175 key_pressed); |
205 *out = capture_frame_.data_; | 176 *out = capture_frame_.data_; |
206 | 177 |
207 return true; | 178 return true; |
208 } | 179 } |
209 | 180 |
210 const media::AudioParameters& MediaStreamAudioProcessor::InputFormat() const { | 181 const media::AudioParameters& MediaStreamAudioProcessor::InputFormat() const { |
211 return capture_converter_->source_parameters(); | 182 return capture_converter_->source_parameters(); |
212 } | 183 } |
213 | 184 |
214 const media::AudioParameters& MediaStreamAudioProcessor::OutputFormat() const { | 185 const media::AudioParameters& MediaStreamAudioProcessor::OutputFormat() const { |
215 return capture_converter_->sink_parameters(); | 186 return capture_converter_->sink_parameters(); |
216 } | 187 } |
217 | 188 |
| 189 void MediaStreamAudioProcessor::OnPlayoutData(media::AudioBus* audio_bus, |
| 190 int sample_rate, |
| 191 int audio_delay_milliseconds) { |
| 192 DCHECK(render_thread_checker_.CalledOnValidThread()); |
| 193 DCHECK(audio_processing_->echo_cancellation()->is_enabled()); |
| 194 |
| 195 TRACE_EVENT0("audio", "MediaStreamAudioProcessor::OnPlayoutData"); |
| 196 DCHECK_LT(audio_delay_milliseconds, |
| 197 std::numeric_limits<base::subtle::Atomic32>::max()); |
| 198 base::subtle::Release_Store(&render_delay_ms_, audio_delay_milliseconds); |
| 199 |
| 200 InitializeRenderConverterIfNeeded(sample_rate, audio_bus->channels(), |
| 201 audio_bus->frames()); |
| 202 |
| 203 render_converter_->Push(audio_bus); |
| 204 while (render_converter_->Convert(&render_frame_)) |
| 205 audio_processing_->AnalyzeReverseStream(&render_frame_); |
| 206 } |
| 207 |
218 void MediaStreamAudioProcessor::InitializeAudioProcessingModule( | 208 void MediaStreamAudioProcessor::InitializeAudioProcessingModule( |
219 const blink::WebMediaConstraints& constraints, int effects) { | 209 const blink::WebMediaConstraints& constraints, int effects) { |
220 DCHECK(!audio_processing_); | 210 DCHECK(!audio_processing_); |
221 if (!CommandLine::ForCurrentProcess()->HasSwitch( | 211 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
222 switches::kEnableAudioTrackProcessing)) { | 212 switches::kEnableAudioTrackProcessing)) { |
223 return; | 213 return; |
224 } | 214 } |
225 | 215 |
226 RTCMediaConstraints native_constraints(constraints); | 216 RTCMediaConstraints native_constraints(constraints); |
227 ApplyFixedAudioConstraints(&native_constraints); | 217 ApplyFixedAudioConstraints(&native_constraints); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 } | 259 } |
270 | 260 |
271 // Create and configure the webrtc::AudioProcessing. | 261 // Create and configure the webrtc::AudioProcessing. |
272 audio_processing_.reset(webrtc::AudioProcessing::Create(0)); | 262 audio_processing_.reset(webrtc::AudioProcessing::Create(0)); |
273 | 263 |
274 // Enable the audio processing components. | 264 // Enable the audio processing components. |
275 if (enable_aec) { | 265 if (enable_aec) { |
276 EnableEchoCancellation(audio_processing_.get()); | 266 EnableEchoCancellation(audio_processing_.get()); |
277 if (enable_experimental_aec) | 267 if (enable_experimental_aec) |
278 EnableExperimentalEchoCancellation(audio_processing_.get()); | 268 EnableExperimentalEchoCancellation(audio_processing_.get()); |
| 269 |
| 270 if (playout_data_source_) |
| 271 playout_data_source_->AddPlayoutSink(this); |
279 } | 272 } |
280 | 273 |
281 if (enable_ns) | 274 if (enable_ns) |
282 EnableNoiseSuppression(audio_processing_.get()); | 275 EnableNoiseSuppression(audio_processing_.get()); |
283 | 276 |
284 if (enable_high_pass_filter) | 277 if (enable_high_pass_filter) |
285 EnableHighPassFilter(audio_processing_.get()); | 278 EnableHighPassFilter(audio_processing_.get()); |
286 | 279 |
287 if (enable_typing_detection) | 280 if (enable_typing_detection) |
288 EnableTypingDetection(audio_processing_.get()); | 281 EnableTypingDetection(audio_processing_.get()); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 // Return 0 if the volume has not been changed, otherwise return the new | 394 // Return 0 if the volume has not been changed, otherwise return the new |
402 // volume. | 395 // volume. |
403 return (agc->stream_analog_level() == volume) ? | 396 return (agc->stream_analog_level() == volume) ? |
404 0 : agc->stream_analog_level(); | 397 0 : agc->stream_analog_level(); |
405 } | 398 } |
406 | 399 |
407 void MediaStreamAudioProcessor::StopAudioProcessing() { | 400 void MediaStreamAudioProcessor::StopAudioProcessing() { |
408 if (!audio_processing_.get()) | 401 if (!audio_processing_.get()) |
409 return; | 402 return; |
410 | 403 |
| 404 if (playout_data_source_) |
| 405 playout_data_source_->RemovePlayoutSink(this); |
| 406 |
411 audio_processing_.reset(); | 407 audio_processing_.reset(); |
412 } | 408 } |
413 | 409 |
414 } // namespace content | 410 } // namespace content |
OLD | NEW |