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/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 }; | 272 }; |
273 | 273 |
274 MediaStreamAudioProcessor::MediaStreamAudioProcessor( | 274 MediaStreamAudioProcessor::MediaStreamAudioProcessor( |
275 const blink::WebMediaConstraints& constraints, | 275 const blink::WebMediaConstraints& constraints, |
276 const MediaStreamDevice::AudioDeviceParameters& input_params, | 276 const MediaStreamDevice::AudioDeviceParameters& input_params, |
277 WebRtcPlayoutDataSource* playout_data_source) | 277 WebRtcPlayoutDataSource* playout_data_source) |
278 : render_delay_ms_(0), | 278 : render_delay_ms_(0), |
279 playout_data_source_(playout_data_source), | 279 playout_data_source_(playout_data_source), |
280 audio_mirroring_(false), | 280 audio_mirroring_(false), |
281 typing_detected_(false), | 281 typing_detected_(false), |
282 stopped_(false) { | 282 stopped_(false), |
| 283 skipped_output_frames_(0) { |
283 capture_thread_checker_.DetachFromThread(); | 284 capture_thread_checker_.DetachFromThread(); |
284 render_thread_checker_.DetachFromThread(); | 285 render_thread_checker_.DetachFromThread(); |
285 InitializeAudioProcessingModule(constraints, input_params); | 286 InitializeAudioProcessingModule(constraints, input_params); |
286 | 287 |
287 aec_dump_message_filter_ = AecDumpMessageFilter::Get(); | 288 aec_dump_message_filter_ = AecDumpMessageFilter::Get(); |
288 // In unit tests not creating a message filter, |aec_dump_message_filter_| | 289 // In unit tests not creating a message filter, |aec_dump_message_filter_| |
289 // will be NULL. We can just ignore that. Other unit tests and browser tests | 290 // will be NULL. We can just ignore that. Other unit tests and browser tests |
290 // ensure that we do get the filter when we should. | 291 // ensure that we do get the filter when we should. |
291 if (aec_dump_message_filter_.get()) | 292 if (aec_dump_message_filter_.get()) |
292 aec_dump_message_filter_->AddDelegate(this); | 293 aec_dump_message_filter_->AddDelegate(this); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 StopEchoCancellationDump(audio_processing_.get()); | 426 StopEchoCancellationDump(audio_processing_.get()); |
426 } | 427 } |
427 | 428 |
428 void MediaStreamAudioProcessor::OnIpcClosing() { | 429 void MediaStreamAudioProcessor::OnIpcClosing() { |
429 DCHECK(main_thread_checker_.CalledOnValidThread()); | 430 DCHECK(main_thread_checker_.CalledOnValidThread()); |
430 aec_dump_message_filter_ = NULL; | 431 aec_dump_message_filter_ = NULL; |
431 } | 432 } |
432 | 433 |
433 void MediaStreamAudioProcessor::OnPlayoutData(media::AudioBus* audio_bus, | 434 void MediaStreamAudioProcessor::OnPlayoutData(media::AudioBus* audio_bus, |
434 int sample_rate, | 435 int sample_rate, |
435 int audio_delay_milliseconds) { | 436 int audio_delay_milliseconds, |
| 437 uint32_t skipped_frames) { |
436 DCHECK(render_thread_checker_.CalledOnValidThread()); | 438 DCHECK(render_thread_checker_.CalledOnValidThread()); |
437 DCHECK(audio_processing_->echo_control_mobile()->is_enabled() ^ | 439 DCHECK(audio_processing_->echo_control_mobile()->is_enabled() ^ |
438 audio_processing_->echo_cancellation()->is_enabled()); | 440 audio_processing_->echo_cancellation()->is_enabled()); |
439 | 441 |
440 TRACE_EVENT0("audio", "MediaStreamAudioProcessor::OnPlayoutData"); | 442 TRACE_EVENT0("audio", "MediaStreamAudioProcessor::OnPlayoutData"); |
441 DCHECK_LT(audio_delay_milliseconds, | 443 DCHECK_LT(audio_delay_milliseconds, |
442 std::numeric_limits<base::subtle::Atomic32>::max()); | 444 std::numeric_limits<base::subtle::Atomic32>::max()); |
443 base::subtle::Release_Store(&render_delay_ms_, audio_delay_milliseconds); | 445 base::subtle::Release_Store(&render_delay_ms_, audio_delay_milliseconds); |
444 | 446 |
445 InitializeRenderFifoIfNeeded(sample_rate, audio_bus->channels(), | 447 InitializeRenderFifoIfNeeded(sample_rate, audio_bus->channels(), |
446 audio_bus->frames()); | 448 audio_bus->frames()); |
447 | 449 |
448 render_fifo_->Push( | 450 render_fifo_->Push( |
449 *audio_bus, base::TimeDelta::FromMilliseconds(audio_delay_milliseconds)); | 451 *audio_bus, base::TimeDelta::FromMilliseconds(audio_delay_milliseconds)); |
| 452 |
| 453 // Feed the APM with empty frames if frames have been skipped. The APM only |
| 454 // accepts 10 ms chunks. |
| 455 skipped_output_frames_ += skipped_frames; |
| 456 uint32_t frames_per_10ms = static_cast<uint32_t>(sample_rate / 100); |
| 457 if (skipped_output_frames_ > frames_per_10ms) { |
| 458 MediaStreamAudioBus empty_bus(audio_bus->channels(), frames_per_10ms); |
| 459 empty_bus.bus()->Zero(); |
| 460 while (skipped_output_frames_ > frames_per_10ms) { |
| 461 audio_processing_->AnalyzeReverseStream( |
| 462 empty_bus.channel_ptrs(), |
| 463 empty_bus.bus()->frames(), |
| 464 sample_rate, |
| 465 ChannelsToLayout(empty_bus.bus()->channels())); |
| 466 skipped_output_frames_ -= frames_per_10ms; |
| 467 } |
| 468 } |
| 469 |
| 470 // Pull data from the fifo and feed the APM. |
450 MediaStreamAudioBus* analysis_bus; | 471 MediaStreamAudioBus* analysis_bus; |
451 base::TimeDelta audio_delay; | 472 base::TimeDelta audio_delay; |
452 while (render_fifo_->Consume(&analysis_bus, &audio_delay)) { | 473 while (render_fifo_->Consume(&analysis_bus, &audio_delay)) { |
453 // TODO(ajm): Should AnalyzeReverseStream() account for the |audio_delay|? | 474 // TODO(ajm): Should AnalyzeReverseStream() account for the |audio_delay|? |
454 audio_processing_->AnalyzeReverseStream( | 475 audio_processing_->AnalyzeReverseStream( |
455 analysis_bus->channel_ptrs(), | 476 analysis_bus->channel_ptrs(), |
456 analysis_bus->bus()->frames(), | 477 analysis_bus->bus()->frames(), |
457 sample_rate, | 478 sample_rate, |
458 ChannelsToLayout(audio_bus->channels())); | 479 ChannelsToLayout(analysis_bus->bus()->channels())); |
459 } | 480 } |
460 } | 481 } |
461 | 482 |
462 void MediaStreamAudioProcessor::OnPlayoutDataSourceChanged() { | 483 void MediaStreamAudioProcessor::OnPlayoutDataSourceChanged() { |
463 DCHECK(main_thread_checker_.CalledOnValidThread()); | 484 DCHECK(main_thread_checker_.CalledOnValidThread()); |
464 // There is no need to hold a lock here since the caller guarantees that | 485 // There is no need to hold a lock here since the caller guarantees that |
465 // there is no more OnPlayoutData() callback on the render thread. | 486 // there is no more OnPlayoutData() callback on the render thread. |
466 render_thread_checker_.DetachFromThread(); | 487 render_thread_checker_.DetachFromThread(); |
467 render_fifo_.reset(); | 488 render_fifo_.reset(); |
468 } | 489 } |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 if (echo_information_) { | 765 if (echo_information_) { |
745 echo_information_.get()->UpdateAecDelayStats(ap->echo_cancellation()); | 766 echo_information_.get()->UpdateAecDelayStats(ap->echo_cancellation()); |
746 } | 767 } |
747 | 768 |
748 // Return 0 if the volume hasn't been changed, and otherwise the new volume. | 769 // Return 0 if the volume hasn't been changed, and otherwise the new volume. |
749 return (agc->stream_analog_level() == volume) ? | 770 return (agc->stream_analog_level() == volume) ? |
750 0 : agc->stream_analog_level(); | 771 0 : agc->stream_analog_level(); |
751 } | 772 } |
752 | 773 |
753 } // namespace content | 774 } // namespace content |
OLD | NEW |