| 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 |