summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-08 13:09:35 +0000
committerxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-08 13:09:35 +0000
commit69eafc14a642e9cd26d663dad63f726c55e55d5b (patch)
treed1942fa30fa1107ade73b20bd8700ba85dc2344d /content
parent2c98b8f08f079862baec265690ab65133cc83d80 (diff)
downloadchromium_src-69eafc14a642e9cd26d663dad63f726c55e55d5b.zip
chromium_src-69eafc14a642e9cd26d663dad63f726c55e55d5b.tar.gz
chromium_src-69eafc14a642e9cd26d663dad63f726c55e55d5b.tar.bz2
Support the Aec dump for the APM in chrome.
The code will run behind the kEnableAudioTrackProcessor flag and the behaviour will be compatible with the existing behaviours. Since AEC dump can be started only once, so we can't re-create a new instance of MediaStreamAudioProcessor when the format changes. This CL will create the MediaStreamAudioProcessor in the constructor of WebRtcAudioCapturer and call OnCaptureFormatChanged() to the MediaStreamAudioProcessor when the format changes. BUG=264611 TEST=manual enable aec dump in chrome://webrtc-internals and verify the aec dump audio files. Review URL: https://codereview.chromium.org/187913002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@255769 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/renderer/media/media_stream_audio_processor.cc34
-rw-r--r--content/renderer/media/media_stream_audio_processor.h18
-rw-r--r--content/renderer/media/media_stream_audio_processor_options.cc30
-rw-r--r--content/renderer/media/media_stream_audio_processor_options.h8
-rw-r--r--content/renderer/media/media_stream_audio_processor_unittest.cc6
-rw-r--r--content/renderer/media/media_stream_dependency_factory.cc32
-rw-r--r--content/renderer/media/webrtc_audio_capturer.cc67
-rw-r--r--content/renderer/media/webrtc_audio_capturer.h10
-rw-r--r--content/renderer/media/webrtc_audio_device_impl.cc64
-rw-r--r--content/renderer/media/webrtc_audio_device_impl.h16
10 files changed, 212 insertions, 73 deletions
diff --git a/content/renderer/media/media_stream_audio_processor.cc b/content/renderer/media/media_stream_audio_processor.cc
index b055dcc..a80207a 100644
--- a/content/renderer/media/media_stream_audio_processor.cc
+++ b/content/renderer/media/media_stream_audio_processor.cc
@@ -140,7 +140,6 @@ class MediaStreamAudioProcessor::MediaStreamAudioConverter
};
MediaStreamAudioProcessor::MediaStreamAudioProcessor(
- const media::AudioParameters& source_params,
const blink::WebMediaConstraints& constraints,
int effects,
WebRtcPlayoutDataSource* playout_data_source)
@@ -151,7 +150,6 @@ MediaStreamAudioProcessor::MediaStreamAudioProcessor(
capture_thread_checker_.DetachFromThread();
render_thread_checker_.DetachFromThread();
InitializeAudioProcessingModule(constraints, effects);
- InitializeCaptureConverter(source_params);
}
MediaStreamAudioProcessor::~MediaStreamAudioProcessor() {
@@ -159,8 +157,26 @@ MediaStreamAudioProcessor::~MediaStreamAudioProcessor() {
StopAudioProcessing();
}
+void MediaStreamAudioProcessor::OnCaptureFormatChanged(
+ const media::AudioParameters& source_params) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ // There is no need to hold a lock here since the caller guarantees that
+ // there is no more PushCaptureData() and ProcessAndConsumeData() callbacks
+ // on the capture thread.
+ InitializeCaptureConverter(source_params);
+
+ // Reset the |capture_thread_checker_| since the capture data will come from
+ // a new capture thread.
+ capture_thread_checker_.DetachFromThread();
+}
+
void MediaStreamAudioProcessor::PushCaptureData(media::AudioBus* audio_source) {
DCHECK(capture_thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(audio_source->channels(),
+ capture_converter_->source_parameters().channels());
+ DCHECK_EQ(audio_source->frames(),
+ capture_converter_->source_parameters().frames_per_buffer());
+
if (audio_mirroring_ &&
capture_converter_->source_parameters().channel_layout() ==
media::CHANNEL_LAYOUT_STEREO) {
@@ -195,6 +211,17 @@ const media::AudioParameters& MediaStreamAudioProcessor::OutputFormat() const {
return capture_converter_->sink_parameters();
}
+void MediaStreamAudioProcessor::StartAecDump(
+ const base::PlatformFile& aec_dump_file) {
+ if (audio_processing_)
+ StartEchoCancellationDump(audio_processing_.get(), aec_dump_file);
+}
+
+void MediaStreamAudioProcessor::StopAecDump() {
+ if (audio_processing_)
+ StopEchoCancellationDump(audio_processing_.get());
+}
+
void MediaStreamAudioProcessor::OnPlayoutData(media::AudioBus* audio_bus,
int sample_rate,
int audio_delay_milliseconds) {
@@ -332,6 +359,7 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
void MediaStreamAudioProcessor::InitializeCaptureConverter(
const media::AudioParameters& source_params) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(source_params.IsValid());
// Create and initialize audio converter for the source data.
@@ -445,6 +473,8 @@ void MediaStreamAudioProcessor::StopAudioProcessing() {
if (!audio_processing_.get())
return;
+ StopAecDump();
+
if (playout_data_source_)
playout_data_source_->RemovePlayoutSink(this);
diff --git a/content/renderer/media/media_stream_audio_processor.h b/content/renderer/media/media_stream_audio_processor.h
index 58e322b..4364f3c 100644
--- a/content/renderer/media/media_stream_audio_processor.h
+++ b/content/renderer/media/media_stream_audio_processor.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_H_
#include "base/atomicops.h"
+#include "base/platform_file.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
@@ -48,11 +49,17 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// |playout_data_source| is used to register this class as a sink to the
// WebRtc playout data for processing AEC. If clients do not enable AEC,
// |playout_data_source| won't be used.
- MediaStreamAudioProcessor(const media::AudioParameters& source_params,
- const blink::WebMediaConstraints& constraints,
+ MediaStreamAudioProcessor(const blink::WebMediaConstraints& constraints,
int effects,
WebRtcPlayoutDataSource* playout_data_source);
+ // Called when format of the capture data has changed.
+ // Called on the main render thread. The caller is responsible for stopping
+ // the capture thread before calling this method.
+ // After this method, the capture thread will be changed to a new capture
+ // thread.
+ void OnCaptureFormatChanged(const media::AudioParameters& source_params);
+
// Pushes capture data in |audio_source| to the internal FIFO.
// Called on the capture audio thread.
void PushCaptureData(media::AudioBus* audio_source);
@@ -76,7 +83,6 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
int* new_volume,
int16** out);
-
// The audio format of the input to the processor.
const media::AudioParameters& InputFormat() const;
@@ -86,6 +92,12 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// Accessor to check if the audio processing is enabled or not.
bool has_audio_processing() const { return audio_processing_ != NULL; }
+ // Starts/Stops the Aec dump on the |audio_processing_|.
+ // Called on the main render thread.
+ // This method takes the ownership of |aec_dump_file|.
+ void StartAecDump(const base::PlatformFile& aec_dump_file);
+ void StopAecDump();
+
protected:
friend class base::RefCountedThreadSafe<MediaStreamAudioProcessor>;
virtual ~MediaStreamAudioProcessor();
diff --git a/content/renderer/media/media_stream_audio_processor_options.cc b/content/renderer/media/media_stream_audio_processor_options.cc
index 0fcf8f7..12338e2 100644
--- a/content/renderer/media/media_stream_audio_processor_options.cc
+++ b/content/renderer/media/media_stream_audio_processor_options.cc
@@ -144,29 +144,21 @@ void EnableExperimentalEchoCancellation(AudioProcessing* audio_processing) {
audio_processing->SetExtraOptions(config);
}
-void StartAecDump(AudioProcessing* audio_processing) {
- // TODO(grunell): Figure out a more suitable directory for the audio dump
- // data.
- base::FilePath path;
-#if defined(CHROMEOS)
- PathService::Get(base::DIR_TEMP, &path);
-#elif defined(ANDROID)
- path = base::FilePath(FILE_PATH_LITERAL("sdcard"));
-#else
- PathService::Get(base::DIR_EXE, &path);
-#endif
- base::FilePath file = path.Append(FILE_PATH_LITERAL("audio.aecdump"));
+void StartEchoCancellationDump(AudioProcessing* audio_processing,
+ const base::PlatformFile& aec_dump_file) {
+ DCHECK_NE(aec_dump_file, base::kInvalidPlatformFileValue);
-#if defined(OS_WIN)
- const std::string file_name = base::WideToUTF8(file.value());
-#else
- const std::string file_name = file.value();
-#endif
- if (audio_processing->StartDebugRecording(file_name.c_str()))
+ FILE* stream = base::FdopenPlatformFile(aec_dump_file, "w");
+ if (!stream) {
+ LOG(ERROR) << "Failed to open AEC dump file";
+ return;
+ }
+
+ if (audio_processing->StartDebugRecording(stream))
DLOG(ERROR) << "Fail to start AEC debug recording";
}
-void StopAecDump(AudioProcessing* audio_processing) {
+void StopEchoCancellationDump(AudioProcessing* audio_processing) {
if (audio_processing->StopDebugRecording())
DLOG(ERROR) << "Fail to stop AEC debug recording";
}
diff --git a/content/renderer/media/media_stream_audio_processor_options.h b/content/renderer/media/media_stream_audio_processor_options.h
index 0e3b882..3ad4110 100644
--- a/content/renderer/media/media_stream_audio_processor_options.h
+++ b/content/renderer/media/media_stream_audio_processor_options.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/platform_file.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
namespace blink {
@@ -70,10 +71,13 @@ void EnableTypingDetection(AudioProcessing* audio_processing,
void EnableExperimentalEchoCancellation(AudioProcessing* audio_processing);
// Starts the echo cancellation dump in |audio_processing|.
-void StartAecDump(AudioProcessing* audio_processing);
+void StartEchoCancellationDump(AudioProcessing* audio_processing,
+ const base::PlatformFile& aec_dump_file);
// Stops the echo cancellation dump in |audio_processing|.
-void StopAecDump(AudioProcessing* audio_processing);
+// This method has no impact if echo cancellation dump has not been started on
+// |audio_processing|.
+void StopEchoCancellationDump(AudioProcessing* audio_processing);
void EnableAutomaticGainControl(AudioProcessing* audio_processing);
diff --git a/content/renderer/media/media_stream_audio_processor_unittest.cc b/content/renderer/media/media_stream_audio_processor_unittest.cc
index fb2f0ab..6262c43 100644
--- a/content/renderer/media/media_stream_audio_processor_unittest.cc
+++ b/content/renderer/media/media_stream_audio_processor_unittest.cc
@@ -156,8 +156,9 @@ TEST_F(MediaStreamAudioProcessorTest, WithoutAudioProcessing) {
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
- params_, constraints, 0, webrtc_audio_device.get()));
+ constraints, 0, webrtc_audio_device.get()));
EXPECT_FALSE(audio_processor->has_audio_processing());
+ audio_processor->OnCaptureFormatChanged(params_);
ProcessDataAndVerifyFormat(audio_processor,
params_.sample_rate(),
@@ -177,8 +178,9 @@ TEST_F(MediaStreamAudioProcessorTest, WithAudioProcessing) {
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
- params_, constraints, 0, webrtc_audio_device.get()));
+ constraints, 0, webrtc_audio_device.get()));
EXPECT_TRUE(audio_processor->has_audio_processing());
+ audio_processor->OnCaptureFormatChanged(params_);
VerifyDefaultComponents(audio_processor);
ProcessDataAndVerifyFormat(audio_processor,
diff --git a/content/renderer/media/media_stream_dependency_factory.cc b/content/renderer/media/media_stream_dependency_factory.cc
index be33d64..d7b2793 100644
--- a/content/renderer/media/media_stream_dependency_factory.cc
+++ b/content/renderer/media/media_stream_dependency_factory.cc
@@ -753,18 +753,34 @@ bool MediaStreamDependencyFactory::OnControlMessageReceived(
void MediaStreamDependencyFactory::OnAecDumpFile(
IPC::PlatformFileForTransit file_handle) {
DCHECK_EQ(aec_dump_file_, base::kInvalidPlatformFileValue);
- if (PeerConnectionFactoryCreated()) {
- base::PlatformFile file =
- IPC::PlatformFileForTransitToPlatformFile(file_handle);
- DCHECK_NE(file, base::kInvalidPlatformFileValue);
- StartAecDump(file);
- } else {
- aec_dump_file_ = IPC::PlatformFileForTransitToPlatformFile(file_handle);
- DCHECK_NE(aec_dump_file_, base::kInvalidPlatformFileValue);
+ base::PlatformFile file =
+ IPC::PlatformFileForTransitToPlatformFile(file_handle);
+ DCHECK_NE(file, base::kInvalidPlatformFileValue);
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableAudioTrackProcessing)) {
+ EnsureWebRtcAudioDeviceImpl();
+ GetWebRtcAudioDevice()->EnableAecDump(file);
+ return;
}
+
+ // TODO(xians): Remove the following code after kEnableAudioTrackProcessing
+ // is removed.
+ if (PeerConnectionFactoryCreated())
+ StartAecDump(file);
+ else
+ aec_dump_file_ = file;
}
void MediaStreamDependencyFactory::OnDisableAecDump() {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableAudioTrackProcessing)) {
+ GetWebRtcAudioDevice()->DisableAecDump();
+ return;
+ }
+
+ // TODO(xians): Remove the following code after kEnableAudioTrackProcessing
+ // is removed.
if (aec_dump_file_ != base::kInvalidPlatformFileValue)
base::ClosePlatformFile(aec_dump_file_);
aec_dump_file_ = base::kInvalidPlatformFileValue;
diff --git a/content/renderer/media/webrtc_audio_capturer.cc b/content/renderer/media/webrtc_audio_capturer.cc
index f396813..3339a21 100644
--- a/content/renderer/media/webrtc_audio_capturer.cc
+++ b/content/renderer/media/webrtc_audio_capturer.cc
@@ -194,9 +194,7 @@ bool WebRtcAudioCapturer::Initialize() {
// Create and configure the default audio capturing source.
SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id_),
channel_layout,
- static_cast<float>(device_info_.device.input.sample_rate),
- device_info_.device.input.effects,
- constraints_);
+ static_cast<float>(device_info_.device.input.sample_rate));
// Add the capturer to the WebRtcAudioDeviceImpl since it needs some hardware
// information from the capturer.
@@ -212,6 +210,9 @@ WebRtcAudioCapturer::WebRtcAudioCapturer(
const blink::WebMediaConstraints& constraints,
WebRtcAudioDeviceImpl* audio_device)
: constraints_(constraints),
+ audio_processor_(
+ new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
+ constraints, device_info.device.input.effects, audio_device)),
running_(false),
render_view_id_(render_view_id),
device_info_(device_info),
@@ -268,9 +269,7 @@ void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) {
void WebRtcAudioCapturer::SetCapturerSource(
const scoped_refptr<media::AudioCapturerSource>& source,
media::ChannelLayout channel_layout,
- float sample_rate,
- int effects,
- const blink::WebMediaConstraints& constraints) {
+ float sample_rate) {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << ","
<< "sample_rate=" << sample_rate << ")";
@@ -301,15 +300,16 @@ void WebRtcAudioCapturer::SetCapturerSource(
int buffer_size = GetBufferSize(sample_rate);
media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
channel_layout, 0, sample_rate,
- 16, buffer_size, effects);
- scoped_refptr<MediaStreamAudioProcessor> new_audio_processor(
- new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
- params, constraints, effects, audio_device_));
+ 16, buffer_size,
+ device_info_.device.input.effects);
+
{
base::AutoLock auto_lock(lock_);
- audio_processor_ = new_audio_processor;
- need_audio_processing_ = NeedsAudioProcessing(constraints, effects);
+ // Notify the |audio_processor_| of the new format.
+ audio_processor_->OnCaptureFormatChanged(params);
+ need_audio_processing_ = NeedsAudioProcessing(
+ constraints_, device_info_.device.input.effects);
// Notify all tracks about the new format.
tracks_.TagAll();
}
@@ -352,12 +352,11 @@ void WebRtcAudioCapturer::EnablePeerConnectionMode() {
// WebRtc native buffer size.
SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
input_params.channel_layout(),
- static_cast<float>(input_params.sample_rate()),
- input_params.effects(),
- constraints_);
+ static_cast<float>(input_params.sample_rate()));
}
void WebRtcAudioCapturer::Start() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioCapturer::Start()";
base::AutoLock auto_lock(lock_);
if (running_ || !source_)
@@ -371,6 +370,7 @@ void WebRtcAudioCapturer::Start() {
}
void WebRtcAudioCapturer::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioCapturer::Stop()";
scoped_refptr<media::AudioCapturerSource> source;
TrackList::ItemList tracks;
@@ -389,6 +389,9 @@ void WebRtcAudioCapturer::Stop() {
if (audio_device_)
audio_device_->RemoveAudioCapturer(this);
+ // Stop the Aec dump.
+ StopAecDump();
+
for (TrackList::ItemList::const_iterator it = tracks.begin();
it != tracks.end();
++it) {
@@ -439,7 +442,6 @@ void WebRtcAudioCapturer::Capture(media::AudioBus* audio_source,
TrackList::ItemList tracks_to_notify_format;
int current_volume = 0;
base::TimeDelta audio_delay;
- scoped_refptr<MediaStreamAudioProcessor> audio_processor;
bool need_audio_processing = true;
{
base::AutoLock auto_lock(lock_);
@@ -456,38 +458,37 @@ void WebRtcAudioCapturer::Capture(media::AudioBus* audio_source,
key_pressed_ = key_pressed;
tracks = tracks_.Items();
tracks_.RetrieveAndClearTags(&tracks_to_notify_format);
- audio_processor = audio_processor_;
// Set the flag to turn on the audio processing in PeerConnection level.
// Note that, we turn off the audio processing in PeerConnection if the
// processor has already processed the data.
need_audio_processing = need_audio_processing_ ?
- !audio_processor->has_audio_processing() : false;
+ !audio_processor_->has_audio_processing() : false;
}
- DCHECK(audio_processor->InputFormat().IsValid());
+ DCHECK(audio_processor_->InputFormat().IsValid());
DCHECK_EQ(audio_source->channels(),
- audio_processor->InputFormat().channels());
+ audio_processor_->InputFormat().channels());
DCHECK_EQ(audio_source->frames(),
- audio_processor->InputFormat().frames_per_buffer());
+ audio_processor_->InputFormat().frames_per_buffer());
// Notify the tracks on when the format changes. This will do nothing if
// |tracks_to_notify_format| is empty.
- media::AudioParameters output_params = audio_processor->OutputFormat();
+ media::AudioParameters output_params = audio_processor_->OutputFormat();
for (TrackList::ItemList::const_iterator it = tracks_to_notify_format.begin();
it != tracks_to_notify_format.end(); ++it) {
(*it)->OnSetFormat(output_params);
- (*it)->SetAudioProcessor(audio_processor);
+ (*it)->SetAudioProcessor(audio_processor_);
}
// Push the data to the processor for processing.
- audio_processor->PushCaptureData(audio_source);
+ audio_processor_->PushCaptureData(audio_source);
// Process and consume the data in the processor until there is not enough
// data in the processor.
int16* output = NULL;
int new_volume = 0;
- while (audio_processor->ProcessAndConsumeData(
+ while (audio_processor_->ProcessAndConsumeData(
audio_delay, current_volume, key_pressed, &new_volume, &output)) {
// Feed the post-processed data to the tracks.
for (TrackList::ItemList::const_iterator it = tracks.begin();
@@ -569,9 +570,19 @@ void WebRtcAudioCapturer::SetCapturerSourceForTesting(
media::AudioParameters params) {
// Create a new audio stream as source which uses the new source.
SetCapturerSource(source, params.channel_layout(),
- static_cast<float>(params.sample_rate()),
- params.effects(),
- constraints_);
+ static_cast<float>(params.sample_rate()));
+}
+
+void WebRtcAudioCapturer::StartAecDump(
+ const base::PlatformFile& aec_dump_file) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_NE(aec_dump_file, base::kInvalidPlatformFileValue);
+ audio_processor_->StartAecDump(aec_dump_file);
+}
+
+void WebRtcAudioCapturer::StopAecDump() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ audio_processor_->StopAecDump();
}
} // namespace content
diff --git a/content/renderer/media/webrtc_audio_capturer.h b/content/renderer/media/webrtc_audio_capturer.h
index 7f198ea..78a21811 100644
--- a/content/renderer/media/webrtc_audio_capturer.h
+++ b/content/renderer/media/webrtc_audio_capturer.h
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
+#include "base/platform_file.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
@@ -108,11 +109,14 @@ class CONTENT_EXPORT WebRtcAudioCapturer
void GetAudioProcessingParams(base::TimeDelta* delay, int* volume,
bool* key_pressed);
- // Use by the unittests to inject their own source to the capturer.
+ // Used by the unittests to inject their own source to the capturer.
void SetCapturerSourceForTesting(
const scoped_refptr<media::AudioCapturerSource>& source,
media::AudioParameters params);
+ void StartAecDump(const base::PlatformFile& aec_dump_file);
+ void StopAecDump();
+
protected:
friend class base::RefCountedThreadSafe<WebRtcAudioCapturer>;
virtual ~WebRtcAudioCapturer();
@@ -145,9 +149,7 @@ class CONTENT_EXPORT WebRtcAudioCapturer
void SetCapturerSource(
const scoped_refptr<media::AudioCapturerSource>& source,
media::ChannelLayout channel_layout,
- float sample_rate,
- int effects,
- const blink::WebMediaConstraints& constraints);
+ float sample_rate);
// Starts recording audio.
// Triggered by AddSink() on the main render thread or a Libjingle working
diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc
index 7e27af1..48dbdc6 100644
--- a/content/renderer/media/webrtc_audio_device_impl.cc
+++ b/content/renderer/media/webrtc_audio_device_impl.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/metrics/histogram.h"
+#include "base/platform_file.h"
#include "base/strings/string_util.h"
#include "base/win/windows_version.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
@@ -27,7 +28,8 @@ WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
initialized_(false),
playing_(false),
recording_(false),
- microphone_volume_(0) {
+ microphone_volume_(0),
+ aec_dump_file_(base::kInvalidPlatformFileValue) {
DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()";
}
@@ -220,6 +222,8 @@ int32_t WebRtcAudioDeviceImpl::Terminate() {
DCHECK(!renderer_.get() || !renderer_->IsStarted())
<< "The shared audio renderer shouldn't be running";
+ DisableAecDump();
+
capturers_.clear();
initialized_ = false;
@@ -431,10 +435,17 @@ void WebRtcAudioDeviceImpl::AddAudioCapturer(
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(capturer.get());
DCHECK(!capturer->device_id().empty());
- base::AutoLock auto_lock(lock_);
- DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) ==
- capturers_.end());
- capturers_.push_back(capturer);
+ {
+ base::AutoLock auto_lock(lock_);
+ DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) ==
+ capturers_.end());
+ capturers_.push_back(capturer);
+ }
+
+ // Start the Aec dump if the Aec dump has been enabled and has not been
+ // started.
+ if (aec_dump_file_ != base::kInvalidPlatformFileValue)
+ MaybeStartAecDump();
}
void WebRtcAudioDeviceImpl::RemoveAudioCapturer(
@@ -491,4 +502,47 @@ bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer(
session_id, output_sample_rate, output_frames_per_buffer);
}
+void WebRtcAudioDeviceImpl::EnableAecDump(
+ const base::PlatformFile& aec_dump_file) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_NE(aec_dump_file, base::kInvalidPlatformFileValue);
+ DCHECK_EQ(aec_dump_file_, base::kInvalidPlatformFileValue);
+ aec_dump_file_ = aec_dump_file;
+ MaybeStartAecDump();
+}
+
+void WebRtcAudioDeviceImpl::DisableAecDump() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // Simply invalidate the |aec_dump_file_| if we have not pass the ownership
+ // to WebRtc.
+ if (aec_dump_file_ != base::kInvalidPlatformFileValue) {
+ base::ClosePlatformFile(aec_dump_file_);
+ aec_dump_file_ = base::kInvalidPlatformFileValue;
+ return;
+ }
+
+ // We might have call StartAecDump() on one of the capturer. Loop
+ // through all the capturers and call StopAecDump() on each of them.
+ for (CapturerList::const_iterator iter = capturers_.begin();
+ iter != capturers_.end(); ++iter) {
+ (*iter)->StopAecDump();
+ }
+}
+
+void WebRtcAudioDeviceImpl::MaybeStartAecDump() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_NE(aec_dump_file_, base::kInvalidPlatformFileValue);
+
+ // Start the Aec dump on the current default capturer.
+ scoped_refptr<WebRtcAudioCapturer> default_capturer(GetDefaultCapturer());
+ if (!default_capturer)
+ return;
+
+ default_capturer->StartAecDump(aec_dump_file_);
+
+ // Invalidate the |aec_dump_file_| since the ownership of the file has been
+ // passed to WebRtc.
+ aec_dump_file_ = base::kInvalidPlatformFileValue;
+}
+
} // namespace content
diff --git a/content/renderer/media/webrtc_audio_device_impl.h b/content/renderer/media/webrtc_audio_device_impl.h
index 80b0cd5..bf67f236 100644
--- a/content/renderer/media/webrtc_audio_device_impl.h
+++ b/content/renderer/media/webrtc_audio_device_impl.h
@@ -18,6 +18,7 @@
#include "content/renderer/media/webrtc_audio_capturer.h"
#include "content/renderer/media/webrtc_audio_device_not_impl.h"
#include "content/renderer/media/webrtc_audio_renderer.h"
+#include "ipc/ipc_platform_file.h"
#include "media/base/audio_capturer_source.h"
#include "media/base/audio_renderer_sink.h"
@@ -351,6 +352,15 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
return renderer_;
}
+ // Enables the Aec dump. If the default capturer exists, it will call
+ // StartAecDump() on the capturer and pass the ownership of the file to
+ // WebRtc. Otherwise it will hold the file until a capturer is added.
+ void EnableAecDump(const base::PlatformFile& aec_dump_file);
+
+ // Disables the Aec dump. When this method is called, the ongoing Aec dump
+ // on WebRtc will be stopped.
+ void DisableAecDump();
+
private:
typedef std::list<scoped_refptr<WebRtcAudioCapturer> > CapturerList;
typedef std::list<WebRtcPlayoutDataSource::Sink*> PlayoutDataSinkList;
@@ -389,6 +399,9 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
virtual void AddPlayoutSink(WebRtcPlayoutDataSource::Sink* sink) OVERRIDE;
virtual void RemovePlayoutSink(WebRtcPlayoutDataSource::Sink* sink) OVERRIDE;
+ // Helper to start the Aec dump if the default capturer exists.
+ void MaybeStartAecDump();
+
// Used to DCHECK that we are called on the correct thread.
base::ThreadChecker thread_checker_;
@@ -437,6 +450,9 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
// It is only accessed by the audio render thread.
std::vector<int16> render_buffer_;
+ // Used for start the Aec dump on the default capturer.
+ base::PlatformFile aec_dump_file_;
+
DISALLOW_COPY_AND_ASSIGN(WebRtcAudioDeviceImpl);
};