summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrunell@chromium.org <grunell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-18 19:39:04 +0000
committergrunell@chromium.org <grunell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-18 19:39:04 +0000
commitda9f30ae881fe63b37b17197d6a18b305d2154f8 (patch)
tree67f2679ee38e5c002b57a83dcdc2f3350cb1c099
parentfe2962f4b16746d1d26b9bb7ba078b136ed5ce6d (diff)
downloadchromium_src-da9f30ae881fe63b37b17197d6a18b305d2154f8.zip
chromium_src-da9f30ae881fe63b37b17197d6a18b305d2154f8.tar.gz
chromium_src-da9f30ae881fe63b37b17197d6a18b305d2154f8.tar.bz2
Support multiple files for AEC dump.
* This adds support for AEC dump files in multiple tabs and if multiple getUserMedia calls are made in one tab. * Each AEC dump consumer registers with the browser to recieve a file handle when AEC dump is enabled. * Add dedicated aec dump message filter an messages file. * Works with and without track-processing. NOTRY=true BUG=350347 Review URL: https://codereview.chromium.org/334743006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278148 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/media/webrtc_browsertest.cc21
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc85
-rw-r--r--content/browser/renderer_host/render_process_host_impl.h11
-rw-r--r--content/common/content_message_generator.h1
-rw-r--r--content/common/media/aec_dump_messages.h36
-rw-r--r--content/common/media/media_stream_messages.h9
-rw-r--r--content/content_common.gypi1
-rw-r--r--content/content_renderer.gypi2
-rw-r--r--content/renderer/media/aec_dump_message_filter.cc191
-rw-r--r--content/renderer/media/aec_dump_message_filter.h108
-rw-r--r--content/renderer/media/media_stream_audio_processor.cc34
-rw-r--r--content/renderer/media/media_stream_audio_processor.h16
-rw-r--r--content/renderer/media/webrtc/peer_connection_dependency_factory.cc71
-rw-r--r--content/renderer/media/webrtc/peer_connection_dependency_factory.h26
-rw-r--r--content/renderer/media/webrtc_audio_capturer.cc14
-rw-r--r--content/renderer/media/webrtc_audio_capturer.h3
-rw-r--r--content/renderer/media/webrtc_audio_device_impl.cc51
-rw-r--r--content/renderer/media/webrtc_audio_device_impl.h15
-rw-r--r--content/renderer/render_thread_impl.cc7
-rw-r--r--content/renderer/render_thread_impl.h7
-rw-r--r--ipc/ipc_message_start.h1
21 files changed, 545 insertions, 165 deletions
diff --git a/content/browser/media/webrtc_browsertest.cc b/content/browser/media/webrtc_browsertest.cc
index e26510b..f5bb216 100644
--- a/content/browser/media/webrtc_browsertest.cc
+++ b/content/browser/media/webrtc_browsertest.cc
@@ -4,6 +4,7 @@
#include "base/command_line.h"
#include "base/file_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/threading/platform_thread.h"
#include "base/values.h"
@@ -367,6 +368,12 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CallAndVerifyVideoMutingWorks) {
MakeTypicalPeerConnectionCall("callAndEnsureVideoTrackMutingWorks();");
}
+#if defined(OS_WIN)
+#define IntToStringType base::IntToString16
+#else
+#define IntToStringType base::IntToString
+#endif
+
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
// Timing out on ARM linux bot: http://crbug.com/238490
#define MAYBE_CallWithAecDump DISABLED_CallWithAecDump
@@ -398,6 +405,17 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CallWithAecDump) {
DisableOpusIfOnAndroid();
ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
+ // Get the ID for the render process host. There should only be one.
+ RenderProcessHost::iterator it(
+ content::RenderProcessHost::AllHostsIterator());
+ int render_process_host_id = it.GetCurrentValue()->GetID();
+ EXPECT_GE(render_process_host_id, 0);
+
+ // Add file extensions that we expect to be added.
+ static const int kExpectedConsumerId = 0;
+ dump_file = dump_file.AddExtension(IntToStringType(render_process_host_id))
+ .AddExtension(IntToStringType(kExpectedConsumerId));
+
EXPECT_TRUE(base::PathExists(dump_file));
int64 file_size = 0;
EXPECT_TRUE(base::GetFileSize(dump_file, &file_size));
@@ -406,6 +424,9 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CallWithAecDump) {
base::DeleteFile(dump_file, false);
}
+// TODO(grunell): Add test for multiple dumps when re-use of
+// MediaStreamAudioProcessor in AudioCapturer has been removed.
+
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
// Timing out on ARM linux bot: http://crbug.com/238490
#define MAYBE_CallWithAecDumpEnabledThenDisabled DISABLED_CallWithAecDumpEnabledThenDisabled
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 890c390..efe852b 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -30,6 +30,7 @@
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/supports_user_data.h"
#include "base/sys_info.h"
@@ -173,6 +174,7 @@
#include "content/browser/media/webrtc_internals.h"
#include "content/browser/renderer_host/media/media_stream_track_metrics_host.h"
#include "content/browser/renderer_host/media/webrtc_identity_service_host.h"
+#include "content/common/media/aec_dump_messages.h"
#include "content/common/media/media_stream_messages.h"
#endif
@@ -1368,6 +1370,12 @@ bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
OnAllocateGpuMemoryBuffer)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close_ACK, OnCloseACK)
+#if defined(ENABLE_WEBRTC)
+ IPC_MESSAGE_HANDLER(AecDumpMsg_RegisterAecDumpConsumer,
+ OnRegisterAecDumpConsumer)
+ IPC_MESSAGE_HANDLER(AecDumpMsg_UnregisterAecDumpConsumer,
+ OnUnregisterAecDumpConsumer)
+#endif
// Adding single handlers for your service here is fine, but once your
// service needs more than one handler, please extract them into a new
// message filter and add that filter to CreateMessageFilters().
@@ -1538,11 +1546,11 @@ void RenderProcessHostImpl::FilterURL(bool empty_allowed, GURL* url) {
#if defined(ENABLE_WEBRTC)
void RenderProcessHostImpl::EnableAecDump(const base::FilePath& file) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&CreateAecDumpFileForProcess, file, GetHandle()),
- base::Bind(&RenderProcessHostImpl::SendAecDumpFileToRenderer,
- weak_factory_.GetWeakPtr()));
+ // Enable AEC dump for each registered consumer.
+ for (std::vector<int>::iterator it = aec_dump_consumers_.begin();
+ it != aec_dump_consumers_.end(); ++it) {
+ EnableAecDumpForId(file, *it);
+ }
}
void RenderProcessHostImpl::DisableAecDump() {
@@ -2154,15 +2162,78 @@ void RenderProcessHostImpl::OnGpuSwitching() {
}
#if defined(ENABLE_WEBRTC)
+void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread,
+ weak_factory_.GetWeakPtr(),
+ id));
+}
+
+void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread,
+ weak_factory_.GetWeakPtr(),
+ id));
+}
+
+void RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread(int id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ aec_dump_consumers_.push_back(id);
+ if (WebRTCInternals::GetInstance()->aec_dump_enabled()) {
+ EnableAecDumpForId(WebRTCInternals::GetInstance()->aec_dump_file_path(),
+ id);
+ }
+}
+
+void RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread(int id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ for (std::vector<int>::iterator it = aec_dump_consumers_.begin();
+ it != aec_dump_consumers_.end(); ++it) {
+ if (*it == id) {
+ aec_dump_consumers_.erase(it);
+ break;
+ }
+ }
+}
+
+#if defined(OS_WIN)
+#define IntToStringType base::IntToString16
+#else
+#define IntToStringType base::IntToString
+#endif
+
+void RenderProcessHostImpl::EnableAecDumpForId(const base::FilePath& file,
+ int id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ base::FilePath unique_file =
+ file.AddExtension(IntToStringType(GetID()))
+ .AddExtension(IntToStringType(id));
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&CreateAecDumpFileForProcess, unique_file, GetHandle()),
+ base::Bind(&RenderProcessHostImpl::SendAecDumpFileToRenderer,
+ weak_factory_.GetWeakPtr(),
+ id));
+}
+
+#undef IntToStringType
+
void RenderProcessHostImpl::SendAecDumpFileToRenderer(
+ int id,
IPC::PlatformFileForTransit file_for_transit) {
if (file_for_transit == IPC::InvalidPlatformFileForTransit())
return;
- Send(new MediaStreamMsg_EnableAecDump(file_for_transit));
+ Send(new AecDumpMsg_EnableAecDump(id, file_for_transit));
}
void RenderProcessHostImpl::SendDisableAecDumpToRenderer() {
- Send(new MediaStreamMsg_DisableAecDump());
+ Send(new AecDumpMsg_DisableAecDump());
}
#endif
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 32e342d..2728626 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -324,8 +324,14 @@ class CONTENT_EXPORT RenderProcessHostImpl
virtual void OnGpuSwitching() OVERRIDE;
#if defined(ENABLE_WEBRTC)
+ void OnRegisterAecDumpConsumer(int id);
+ void OnUnregisterAecDumpConsumer(int id);
+ void RegisterAecDumpConsumerOnUIThread(int id);
+ void UnregisterAecDumpConsumerOnUIThread(int id);
+ void EnableAecDumpForId(const base::FilePath& file, int id);
// Sends |file_for_transit| to the render process.
- void SendAecDumpFileToRenderer(IPC::PlatformFileForTransit file_for_transit);
+ void SendAecDumpFileToRenderer(int id,
+ IPC::PlatformFileForTransit file_for_transit);
void SendDisableAecDumpToRenderer();
#endif
@@ -444,6 +450,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
scoped_refptr<P2PSocketDispatcherHost> p2p_socket_dispatcher_host_;
+ // Must be accessed on UI thread.
+ std::vector<int> aec_dump_consumers_;
+
WebRtcStopRtpDumpCallback stop_rtp_dump_callback_;
#endif
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index dd0f096..e18ddfe 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -31,6 +31,7 @@
#include "content/common/indexed_db/indexed_db_messages.h"
#include "content/common/input_messages.h"
#include "content/common/java_bridge_messages.h"
+#include "content/common/media/aec_dump_messages.h"
#include "content/common/media/audio_messages.h"
// TODO(xhwang): Move this to a new ifdef block.
#include "content/common/media/cdm_messages.h"
diff --git a/content/common/media/aec_dump_messages.h b/content/common/media/aec_dump_messages.h
new file mode 100644
index 0000000..0f98f27
--- /dev/null
+++ b/content/common/media/aec_dump_messages.h
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// IPC messages for the AEC dump.
+// Multiply-included message file, hence no include guard.
+
+#include "content/common/content_export.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_platform_file.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+#define IPC_MESSAGE_START AecDumpMsgStart
+
+// Messages sent from the browser to the renderer.
+
+// The browser hands over a file handle to the consumer in the renderer
+// identified by |id| to use for AEC dump.
+IPC_MESSAGE_CONTROL2(AecDumpMsg_EnableAecDump,
+ int /* id */,
+ IPC::PlatformFileForTransit /* file_handle */)
+
+// Tell the renderer to disable AEC dump in all consumers.
+IPC_MESSAGE_CONTROL0(AecDumpMsg_DisableAecDump)
+
+// Messages sent from the renderer to the browser.
+
+// Registers a consumer with the browser. The consumer will then get a file
+// handle when the dump is enabled.
+IPC_MESSAGE_CONTROL1(AecDumpMsg_RegisterAecDumpConsumer,
+ int /* id */)
+
+// Unregisters a consumer with the browser.
+IPC_MESSAGE_CONTROL1(AecDumpMsg_UnregisterAecDumpConsumer,
+ int /* id */)
diff --git a/content/common/media/media_stream_messages.h b/content/common/media/media_stream_messages.h
index 0afa9ec..695776c 100644
--- a/content/common/media/media_stream_messages.h
+++ b/content/common/media/media_stream_messages.h
@@ -101,15 +101,6 @@ IPC_MESSAGE_CONTROL2(MediaStreamMsg_GetSourcesACK,
int /* request id */,
content::StreamDeviceInfoArray /* device_list */)
-// The browser hands over a file handle to the renderer to use for AEC dump.
-// TODO(grunell): This should not belong to media stream. Change when
-// refactoring MediaStreamDependencyFactory.
-IPC_MESSAGE_CONTROL1(MediaStreamMsg_EnableAecDump,
- IPC::PlatformFileForTransit /* file_handle */)
-
-// Tell the renderer to disable AEC dump.
-IPC_MESSAGE_CONTROL0(MediaStreamMsg_DisableAecDump)
-
// Messages sent from the renderer to the browser.
// Request a new media stream.
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 2c54e77..240c001 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -348,6 +348,7 @@
'common/mac/font_descriptor.mm',
'common/mac/font_loader.h',
'common/mac/font_loader.mm',
+ 'common/media/aec_dump_messages.h',
'common/media/audio_messages.h',
'common/media/cdm_messages.h',
'common/media/cdm_messages_enums.h',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 67dd628..444a665 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -249,6 +249,8 @@
'renderer/java/java_bridge_dispatcher.h',
'renderer/media/active_loader.cc',
'renderer/media/active_loader.h',
+ 'renderer/media/aec_dump_message_filter.cc',
+ 'renderer/media/aec_dump_message_filter.h',
'renderer/media/android/audio_decoder_android.cc',
'renderer/media/android/audio_decoder_android.h',
'renderer/media/android/media_info_loader.cc',
diff --git a/content/renderer/media/aec_dump_message_filter.cc b/content/renderer/media/aec_dump_message_filter.cc
new file mode 100644
index 0000000..ed6aa4a
--- /dev/null
+++ b/content/renderer/media/aec_dump_message_filter.cc
@@ -0,0 +1,191 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/aec_dump_message_filter.h"
+
+#include "base/message_loop/message_loop_proxy.h"
+#include "content/common/media/aec_dump_messages.h"
+#include "content/renderer/media/webrtc_logging.h"
+#include "ipc/ipc_logging.h"
+#include "ipc/ipc_sender.h"
+
+namespace {
+const int kInvalidDelegateId = -1;
+}
+
+namespace content {
+
+AecDumpMessageFilter* AecDumpMessageFilter::g_filter = NULL;
+
+AecDumpMessageFilter::AecDumpMessageFilter(
+ const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
+ const scoped_refptr<base::MessageLoopProxy>& main_message_loop)
+ : sender_(NULL),
+ delegate_id_counter_(0),
+ io_message_loop_(io_message_loop),
+ main_message_loop_(main_message_loop) {
+ DCHECK(!g_filter);
+ g_filter = this;
+}
+
+AecDumpMessageFilter::~AecDumpMessageFilter() {
+ DCHECK_EQ(g_filter, this);
+ g_filter = NULL;
+}
+
+// static
+scoped_refptr<AecDumpMessageFilter> AecDumpMessageFilter::Get() {
+ return g_filter;
+}
+
+void AecDumpMessageFilter::AddDelegate(
+ AecDumpMessageFilter::AecDumpDelegate* delegate) {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ DCHECK(delegate);
+ DCHECK_EQ(kInvalidDelegateId, GetIdForDelegate(delegate));
+
+ int id = delegate_id_counter_++;
+ delegates_[id] = delegate;
+
+ io_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &AecDumpMessageFilter::RegisterAecDumpConsumer,
+ this,
+ id));
+}
+
+void AecDumpMessageFilter::RemoveDelegate(
+ AecDumpMessageFilter::AecDumpDelegate* delegate) {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ DCHECK(delegate);
+
+ int id = GetIdForDelegate(delegate);
+ DCHECK_NE(kInvalidDelegateId, id);
+ delegates_.erase(id);
+
+ io_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &AecDumpMessageFilter::UnregisterAecDumpConsumer,
+ this,
+ id));
+}
+
+void AecDumpMessageFilter::Send(IPC::Message* message) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ if (sender_)
+ sender_->Send(message);
+ else
+ delete message;
+}
+
+void AecDumpMessageFilter::RegisterAecDumpConsumer(int id) {
+ Send(new AecDumpMsg_RegisterAecDumpConsumer(id));
+}
+
+void AecDumpMessageFilter::UnregisterAecDumpConsumer(int id) {
+ Send(new AecDumpMsg_UnregisterAecDumpConsumer(id));
+}
+
+bool AecDumpMessageFilter::OnMessageReceived(const IPC::Message& message) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(AecDumpMessageFilter, message)
+ IPC_MESSAGE_HANDLER(AecDumpMsg_EnableAecDump, OnEnableAecDump)
+ IPC_MESSAGE_HANDLER(AecDumpMsg_DisableAecDump, OnDisableAecDump)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void AecDumpMessageFilter::OnFilterAdded(IPC::Sender* sender) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ sender_ = sender;
+}
+
+void AecDumpMessageFilter::OnFilterRemoved() {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+
+ // Once removed, a filter will not be used again. At this time the
+ // observer must be notified so it releases its reference.
+ OnChannelClosing();
+}
+
+void AecDumpMessageFilter::OnChannelClosing() {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ sender_ = NULL;
+ main_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &AecDumpMessageFilter::DoChannelClosingOnDelegates,
+ this));
+}
+
+void AecDumpMessageFilter::OnEnableAecDump(
+ int id,
+ IPC::PlatformFileForTransit file_handle) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ main_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &AecDumpMessageFilter::DoEnableAecDump,
+ this,
+ id,
+ file_handle));
+}
+
+void AecDumpMessageFilter::OnDisableAecDump() {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ main_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &AecDumpMessageFilter::DoDisableAecDump,
+ this));
+}
+
+void AecDumpMessageFilter::DoEnableAecDump(
+ int id,
+ IPC::PlatformFileForTransit file_handle) {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ DelegateMap::iterator it = delegates_.find(id);
+ if (it != delegates_.end()) {
+ it->second->OnAecDumpFile(file_handle);
+ } else {
+ // Delegate has been removed, we must close the file.
+ base::File file = IPC::PlatformFileForTransitToFile(file_handle);
+ DCHECK(file.IsValid());
+ file.Close();
+ }
+}
+
+void AecDumpMessageFilter::DoDisableAecDump() {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ for (DelegateMap::iterator it = delegates_.begin();
+ it != delegates_.end(); ++it) {
+ it->second->OnDisableAecDump();
+ }
+}
+
+void AecDumpMessageFilter::DoChannelClosingOnDelegates() {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ for (DelegateMap::iterator it = delegates_.begin();
+ it != delegates_.end(); ++it) {
+ it->second->OnIpcClosing();
+ }
+ delegates_.clear();
+}
+
+int AecDumpMessageFilter::GetIdForDelegate(
+ AecDumpMessageFilter::AecDumpDelegate* delegate) {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ for (DelegateMap::iterator it = delegates_.begin();
+ it != delegates_.end(); ++it) {
+ if (it->second == delegate)
+ return it->first;
+ }
+ return kInvalidDelegateId;
+}
+
+} // namespace content
diff --git a/content/renderer/media/aec_dump_message_filter.h b/content/renderer/media/aec_dump_message_filter.h
new file mode 100644
index 0000000..7268132
--- /dev/null
+++ b/content/renderer/media/aec_dump_message_filter.h
@@ -0,0 +1,108 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_AEC_DUMP_MESSAGE_FILTER_H_
+#define CONTENT_RENDERER_MEDIA_AEC_DUMP_MESSAGE_FILTER_H_
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "content/renderer/render_thread_impl.h"
+#include "ipc/ipc_platform_file.h"
+#include "ipc/message_filter.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace content {
+
+// MessageFilter that handles AEC dump messages and forwards them to an
+// observer.
+class CONTENT_EXPORT AecDumpMessageFilter : public IPC::MessageFilter {
+ public:
+ class AecDumpDelegate {
+ public:
+ virtual void OnAecDumpFile(
+ const IPC::PlatformFileForTransit& file_handle) = 0;
+ virtual void OnDisableAecDump() = 0;
+ virtual void OnIpcClosing() = 0;
+ };
+
+ AecDumpMessageFilter(
+ const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
+ const scoped_refptr<base::MessageLoopProxy>& main_message_loop);
+
+ // Getter for the one AecDumpMessageFilter object.
+ static scoped_refptr<AecDumpMessageFilter> Get();
+
+ // Adds a delegate that receives the enable and disable notifications.
+ void AddDelegate(AecDumpMessageFilter::AecDumpDelegate* delegate);
+
+ // Removes a delegate.
+ void RemoveDelegate(AecDumpMessageFilter::AecDumpDelegate* delegate);
+
+ // IO message loop associated with this message filter.
+ scoped_refptr<base::MessageLoopProxy> io_message_loop() const {
+ return io_message_loop_;
+ }
+
+ protected:
+ virtual ~AecDumpMessageFilter();
+
+ private:
+ // Sends an IPC message using |sender_|.
+ void Send(IPC::Message* message);
+
+ // Registers a consumer of AEC dump in the browser process. This consumer will
+ // get a file handle when the AEC dump is enabled and a notification when it
+ // is disabled.
+ void RegisterAecDumpConsumer(int id);
+
+ // Unregisters a consumer of AEC dump in the browser process.
+ void UnregisterAecDumpConsumer(int id);
+
+ // IPC::MessageFilter override. Called on |io_message_loop|.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
+ virtual void OnFilterRemoved() OVERRIDE;
+ virtual void OnChannelClosing() OVERRIDE;
+
+ // Accessed on |io_message_loop|.
+ void OnEnableAecDump(int id, IPC::PlatformFileForTransit file_handle);
+ void OnDisableAecDump();
+
+ // Accessed on |main_message_loop_|.
+ void DoEnableAecDump(int id, IPC::PlatformFileForTransit file_handle);
+ void DoDisableAecDump();
+ void DoChannelClosingOnDelegates();
+ int GetIdForDelegate(AecDumpMessageFilter::AecDumpDelegate* delegate);
+
+ // Accessed on |io_message_loop_|.
+ IPC::Sender* sender_;
+
+ // The delgates for this filter. Must only be accessed on
+ // |main_message_loop_|.
+ typedef std::map<int, AecDumpMessageFilter::AecDumpDelegate*> DelegateMap;
+ DelegateMap delegates_;
+
+ // Counter for generating unique IDs to delegates. Accessed on
+ // |main_message_loop_|.
+ int delegate_id_counter_;
+
+ // Message loop on which IPC calls are driven.
+ const scoped_refptr<base::MessageLoopProxy> io_message_loop_;
+
+ // Main message loop.
+ const scoped_refptr<base::MessageLoopProxy> main_message_loop_;
+
+ // The singleton instance for this filter.
+ static AecDumpMessageFilter* g_filter;
+
+ DISALLOW_COPY_AND_ASSIGN(AecDumpMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_AEC_DUMP_MESSAGE_FILTER_H_
diff --git a/content/renderer/media/media_stream_audio_processor.cc b/content/renderer/media/media_stream_audio_processor.cc
index f929b14..12e8d34 100644
--- a/content/renderer/media/media_stream_audio_processor.cc
+++ b/content/renderer/media/media_stream_audio_processor.cc
@@ -177,10 +177,22 @@ MediaStreamAudioProcessor::MediaStreamAudioProcessor(
capture_thread_checker_.DetachFromThread();
render_thread_checker_.DetachFromThread();
InitializeAudioProcessingModule(constraints, effects);
+ if (IsAudioTrackProcessingEnabled()) {
+ aec_dump_message_filter_ = AecDumpMessageFilter::Get();
+ // In unit tests not creating a message filter, |aec_dump_message_filter_|
+ // will be NULL. We can just ignore that. Other unit tests and browser tests
+ // ensure that we do get the filter when we should.
+ if (aec_dump_message_filter_)
+ aec_dump_message_filter_->AddDelegate(this);
+ }
}
MediaStreamAudioProcessor::~MediaStreamAudioProcessor() {
DCHECK(main_thread_checker_.CalledOnValidThread());
+ if (aec_dump_message_filter_) {
+ aec_dump_message_filter_->RemoveDelegate(this);
+ aec_dump_message_filter_ = NULL;
+ }
StopAudioProcessing();
}
@@ -238,16 +250,30 @@ const media::AudioParameters& MediaStreamAudioProcessor::OutputFormat() const {
return capture_converter_->sink_parameters();
}
-void MediaStreamAudioProcessor::StartAecDump(base::File aec_dump_file) {
+void MediaStreamAudioProcessor::OnAecDumpFile(
+ const IPC::PlatformFileForTransit& file_handle) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+
+ base::File file = IPC::PlatformFileForTransitToFile(file_handle);
+ DCHECK(file.IsValid());
+
if (audio_processing_)
- StartEchoCancellationDump(audio_processing_.get(), aec_dump_file.Pass());
+ StartEchoCancellationDump(audio_processing_.get(), file.Pass());
+ else
+ file.Close();
}
-void MediaStreamAudioProcessor::StopAecDump() {
+void MediaStreamAudioProcessor::OnDisableAecDump() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
if (audio_processing_)
StopEchoCancellationDump(audio_processing_.get());
}
+void MediaStreamAudioProcessor::OnIpcClosing() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ aec_dump_message_filter_ = NULL;
+}
+
void MediaStreamAudioProcessor::OnPlayoutData(media::AudioBus* audio_bus,
int sample_rate,
int audio_delay_milliseconds) {
@@ -494,7 +520,7 @@ void MediaStreamAudioProcessor::StopAudioProcessing() {
if (!audio_processing_.get())
return;
- StopAecDump();
+ StopEchoCancellationDump(audio_processing_.get());
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 b97cb395..2dddff5 100644
--- a/content/renderer/media/media_stream_audio_processor.h
+++ b/content/renderer/media/media_stream_audio_processor.h
@@ -11,6 +11,7 @@
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
+#include "content/renderer/media/aec_dump_message_filter.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
#include "media/base/audio_converter.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
@@ -44,7 +45,8 @@ using webrtc::AudioProcessorInterface;
// of 10 ms data chunk.
class CONTENT_EXPORT MediaStreamAudioProcessor :
NON_EXPORTED_BASE(public WebRtcPlayoutDataSource::Sink),
- NON_EXPORTED_BASE(public AudioProcessorInterface) {
+ NON_EXPORTED_BASE(public AudioProcessorInterface),
+ NON_EXPORTED_BASE(public AecDumpMessageFilter::AecDumpDelegate) {
public:
// Returns false if |kDisableAudioTrackProcessing| is set to true, otherwise
// returns true.
@@ -96,11 +98,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_|.
+ // AecDumpMessageFilter::AecDumpDelegate implementation.
// Called on the main render thread.
- // This method takes the ownership of |aec_dump_file|.
- void StartAecDump(base::File aec_dump_file);
- void StopAecDump();
+ virtual void OnAecDumpFile(
+ const IPC::PlatformFileForTransit& file_handle) OVERRIDE;
+ virtual void OnDisableAecDump() OVERRIDE;
+ virtual void OnIpcClosing() OVERRIDE;
protected:
friend class base::RefCountedThreadSafe<MediaStreamAudioProcessor>;
@@ -191,6 +194,9 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// It can be accessed by the capture audio thread and by the libjingle thread
// which calls GetStats().
base::subtle::Atomic32 typing_detected_;
+
+ // Communication with browser for AEC dump.
+ scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_;
};
} // namespace content
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index a9652e7..f2f7f1d1 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -172,6 +172,8 @@ PeerConnectionDependencyFactory::PeerConnectionDependencyFactory(
PeerConnectionDependencyFactory::~PeerConnectionDependencyFactory() {
CleanupPeerConnectionFactory();
+ if (aec_dump_message_filter_)
+ aec_dump_message_filter_->RemoveDelegate(this);
}
blink::WebRTCPeerConnectionHandler*
@@ -347,9 +349,16 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
cmd_line->HasSwitch(switches::kDisableWebRtcEncryption);
pc_factory_->SetOptions(factory_options);
- // |aec_dump_file| will be invalid when dump is not enabled.
- if (aec_dump_file_.IsValid())
- StartAecDump(aec_dump_file_.Pass());
+ // TODO(xians): Remove the following code after kDisableAudioTrackProcessing
+ // is removed.
+ if (!MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()) {
+ aec_dump_message_filter_ = AecDumpMessageFilter::Get();
+ // In unit tests not creating a message filter, |aec_dump_message_filter_|
+ // will be NULL. We can just ignore that. Other unit tests and browser tests
+ // ensure that we do get the filter when we should.
+ if (aec_dump_message_filter_)
+ aec_dump_message_filter_->AddDelegate(this);
+ }
}
bool PeerConnectionDependencyFactory::PeerConnectionFactoryCreated() {
@@ -612,56 +621,30 @@ PeerConnectionDependencyFactory::GetWebRtcWorkerThread() const {
return chrome_worker_thread_.message_loop_proxy();
}
-bool PeerConnectionDependencyFactory::OnControlMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PeerConnectionDependencyFactory, message)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_EnableAecDump, OnAecDumpFile)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_DisableAecDump, OnDisableAecDump)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
void PeerConnectionDependencyFactory::OnAecDumpFile(
- IPC::PlatformFileForTransit file_handle) {
- DCHECK(!aec_dump_file_.IsValid());
+ const IPC::PlatformFileForTransit& file_handle) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled());
+ DCHECK(PeerConnectionFactoryCreated());
+
base::File file = IPC::PlatformFileForTransitToFile(file_handle);
DCHECK(file.IsValid());
- if (MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()) {
- EnsureWebRtcAudioDeviceImpl();
- GetWebRtcAudioDevice()->EnableAecDump(file.Pass());
- return;
- }
-
- // TODO(xians): Remove the following code after kDisableAudioTrackProcessing
- // is removed.
- if (PeerConnectionFactoryCreated())
- StartAecDump(file.Pass());
- else
- aec_dump_file_ = file.Pass();
+ // |pc_factory_| always takes ownership of |aec_dump_file|. If StartAecDump()
+ // fails, |aec_dump_file| will be closed.
+ if (!GetPcFactory()->StartAecDump(file.TakePlatformFile()))
+ VLOG(1) << "Could not start AEC dump.";
}
void PeerConnectionDependencyFactory::OnDisableAecDump() {
- if (MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()) {
- // Do nothing if OnAecDumpFile() has never been called.
- if (GetWebRtcAudioDevice())
- GetWebRtcAudioDevice()->DisableAecDump();
- return;
- }
-
- // TODO(xians): Remove the following code after kDisableAudioTrackProcessing
- // is removed.
- if (aec_dump_file_.IsValid())
- aec_dump_file_.Close();
+ DCHECK(CalledOnValidThread());
+ DCHECK(!MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled());
+ // Do nothing. We never disable AEC dump for non-track-processing case.
}
-void PeerConnectionDependencyFactory::StartAecDump(base::File aec_dump_file) {
- // |pc_factory_| always takes ownership of |aec_dump_file|. If StartAecDump()
- // fails, |aec_dump_file| will be closed.
- if (!GetPcFactory()->StartAecDump(aec_dump_file.TakePlatformFile()))
- VLOG(1) << "Could not start AEC dump.";
+void PeerConnectionDependencyFactory::OnIpcClosing() {
+ DCHECK(CalledOnValidThread());
+ aec_dump_message_filter_ = NULL;
}
void PeerConnectionDependencyFactory::EnsureWebRtcAudioDeviceImpl() {
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/content/renderer/media/webrtc/peer_connection_dependency_factory.h
index 969fb6b..5169935 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.h
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.h
@@ -12,6 +12,7 @@
#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "content/public/renderer/render_process_observer.h"
+#include "content/renderer/media/aec_dump_message_filter.h"
#include "content/renderer/p2p/socket_dispatcher.h"
#include "ipc/ipc_platform_file.h"
#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
@@ -55,7 +56,7 @@ struct StreamDeviceInfo;
// Object factory for RTC PeerConnections.
class CONTENT_EXPORT PeerConnectionDependencyFactory
: NON_EXPORTED_BASE(public base::NonThreadSafe),
- public RenderProcessObserver {
+ NON_EXPORTED_BASE(public AecDumpMessageFilter::AecDumpDelegate) {
public:
PeerConnectionDependencyFactory(
P2PSocketDispatcher* p2p_socket_dispatcher);
@@ -129,6 +130,14 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
scoped_refptr<base::MessageLoopProxy> GetWebRtcWorkerThread() const;
+ // AecDumpMessageFilter::AecDumpDelegate implementation.
+ // TODO(xians): Remove when option to disable audio track processing is
+ // removed.
+ virtual void OnAecDumpFile(
+ const IPC::PlatformFileForTransit& file_handle) OVERRIDE;
+ virtual void OnDisableAecDump() OVERRIDE;
+ virtual void OnIpcClosing() OVERRIDE;
+
protected:
// Asks the PeerConnection factory to create a Local Audio Source.
virtual scoped_refptr<webrtc::AudioSourceInterface>
@@ -177,14 +186,6 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
void DeleteIpcNetworkManager();
void CleanupPeerConnectionFactory();
- // RenderProcessObserver implementation.
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
-
- void OnAecDumpFile(IPC::PlatformFileForTransit file_handle);
- void OnDisableAecDump();
-
- void StartAecDump(base::File aec_dump_file);
-
// Helper method to create a WebRtcAudioDeviceImpl.
void EnsureWebRtcAudioDeviceImpl();
@@ -198,14 +199,17 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
scoped_refptr<P2PSocketDispatcher> p2p_socket_dispatcher_;
scoped_refptr<WebRtcAudioDeviceImpl> audio_device_;
+ // This is only used if audio track processing is disabled.
+ // TODO(xians): Remove when option to disable audio track processing is
+ // removed.
+ scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_;
+
// PeerConnection threads. signaling_thread_ is created from the
// "current" chrome thread.
talk_base::Thread* signaling_thread_;
talk_base::Thread* worker_thread_;
base::Thread chrome_worker_thread_;
- base::File aec_dump_file_;
-
DISALLOW_COPY_AND_ASSIGN(PeerConnectionDependencyFactory);
};
diff --git a/content/renderer/media/webrtc_audio_capturer.cc b/content/renderer/media/webrtc_audio_capturer.cc
index 2ff0d43..6212a8e 100644
--- a/content/renderer/media/webrtc_audio_capturer.cc
+++ b/content/renderer/media/webrtc_audio_capturer.cc
@@ -417,9 +417,6 @@ 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) {
@@ -615,15 +612,4 @@ void WebRtcAudioCapturer::SetCapturerSourceForTesting(
static_cast<float>(params.sample_rate()));
}
-void WebRtcAudioCapturer::StartAecDump(base::File aec_dump_file) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(aec_dump_file.IsValid());
- audio_processor_->StartAecDump(aec_dump_file.Pass());
-}
-
-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 f433a1a..89ac7a9 100644
--- a/content/renderer/media/webrtc_audio_capturer.h
+++ b/content/renderer/media/webrtc_audio_capturer.h
@@ -117,9 +117,6 @@ class CONTENT_EXPORT WebRtcAudioCapturer
const scoped_refptr<media::AudioCapturerSource>& source,
media::AudioParameters params);
- void StartAecDump(base::File aec_dump_file);
- void StopAecDump();
-
protected:
friend class base::RefCountedThreadSafe<WebRtcAudioCapturer>;
virtual ~WebRtcAudioCapturer();
diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc
index 293ff36..1339a6f 100644
--- a/content/renderer/media/webrtc_audio_device_impl.cc
+++ b/content/renderer/media/webrtc_audio_device_impl.cc
@@ -249,8 +249,6 @@ int32_t WebRtcAudioDeviceImpl::Terminate() {
DCHECK(!renderer_.get() || !renderer_->IsStarted())
<< "The shared audio renderer shouldn't be running";
- DisableAecDump();
-
// Stop all the capturers to ensure no further OnData() and
// RemoveAudioCapturer() callback.
// Cache the capturers in a local list since WebRtcAudioCapturer::Stop()
@@ -477,11 +475,6 @@ void WebRtcAudioDeviceImpl::AddAudioCapturer(
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_.IsValid())
- MaybeStartAecDump();
}
void WebRtcAudioDeviceImpl::RemoveAudioCapturer(
@@ -533,48 +526,4 @@ bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer(
session_id, output_sample_rate, output_frames_per_buffer);
}
-void WebRtcAudioDeviceImpl::EnableAecDump(base::File aec_dump_file) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(aec_dump_file.IsValid());
-
- // Close the previous AEC dump file description if it has not been consumed.
- // This can happen if no getUserMedia has been made yet.
- // TODO(xians): DCHECK(!aec_dump_file_.IsValid()) after the browser
- // guarantees it won't call EnableAecDump() more than once in a row.
- if (aec_dump_file_.IsValid())
- aec_dump_file_.Close();
-
- aec_dump_file_ = aec_dump_file.Pass();
- 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_.IsValid()) {
- aec_dump_file_.Close();
- 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(aec_dump_file_.IsValid());
-
- // 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_.Pass());
-}
-
} // namespace content
diff --git a/content/renderer/media/webrtc_audio_device_impl.h b/content/renderer/media/webrtc_audio_device_impl.h
index d182acf..e53125d 100644
--- a/content/renderer/media/webrtc_audio_device_impl.h
+++ b/content/renderer/media/webrtc_audio_device_impl.h
@@ -353,15 +353,6 @@ 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(base::File 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;
@@ -401,9 +392,6 @@ 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_;
@@ -452,9 +440,6 @@ 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::File aec_dump_file_;
-
// Flag to tell if audio processing is enabled in MediaStreamAudioProcessor.
const bool is_audio_track_processing_enabled_;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 2fcaab4..8934a31 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -74,6 +74,7 @@
#include "content/renderer/gpu/gpu_benchmarking_extension.h"
#include "content/renderer/input/input_event_filter.h"
#include "content/renderer/input/input_handler_manager.h"
+#include "content/renderer/media/aec_dump_message_filter.h"
#include "content/renderer/media/audio_input_message_filter.h"
#include "content/renderer/media/audio_message_filter.h"
#include "content/renderer/media/audio_renderer_mixer_manager.h"
@@ -381,9 +382,13 @@ void RenderThreadImpl::Init() {
webrtc_identity_service_.reset(new WebRTCIdentityService());
+ aec_dump_message_filter_ =
+ new AecDumpMessageFilter(GetIOMessageLoopProxy(),
+ message_loop()->message_loop_proxy());
+ AddFilter(aec_dump_message_filter_.get());
+
peer_connection_factory_.reset(new PeerConnectionDependencyFactory(
p2p_socket_dispatcher_.get()));
- AddObserver(peer_connection_factory_.get());
#endif // defined(ENABLE_WEBRTC)
audio_input_message_filter_ =
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 3659394..4afe3ed 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -74,6 +74,7 @@ class GrContextForWebGraphicsContext3D;
namespace content {
class AppCacheDispatcher;
+class AecDumpMessageFilter;
class AudioInputMessageFilter;
class AudioMessageFilter;
class AudioRendererMixerManager;
@@ -489,6 +490,12 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
// Used on the render thread.
scoped_ptr<VideoCaptureImplManager> vc_manager_;
+ // Used for communicating registering AEC dump consumers with the browser and
+ // receving AEC dump file handles when AEC dump is enabled. An AEC dump is
+ // diagnostic audio data for WebRTC stored locally when enabled by the user in
+ // chrome://webrtc-internals.
+ scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_;
+
// The count of RenderWidgets running through this thread.
int widget_count_;
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index 74d7463..8d813a2 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -106,6 +106,7 @@ enum IPCMessageStart {
GinJavaBridgeMsgStart,
BatteryStatusMsgStart,
UtilityPrintingMsgStart,
+ AecDumpMsgStart,
LastIPCMsgStart // Must come last.
};