Index: content/renderer/media/audio_debug_recorder.cc |
diff --git a/content/renderer/media/audio_debug_recorder.cc b/content/renderer/media/audio_debug_recorder.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4fed79f029c8fe2f563f2aecf1eea391de3855a7 |
--- /dev/null |
+++ b/content/renderer/media/audio_debug_recorder.cc |
@@ -0,0 +1,151 @@ |
+// Copyright 2015 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/audio_debug_recorder.h" |
+ |
+#include <utility> |
+ |
+#include "base/files/file.h" |
+#include "content/common/media/audio_debug_recording.mojom.h" |
+#include "content/public/common/service_registry.h" |
+#include "content/renderer/media/webrtc_logging.h" |
+#include "mojo/public/cpp/bindings/binding.h" |
+#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" |
+ |
+namespace { |
+const int kInvalidDelegateId = -1; |
+} |
+ |
+namespace content { |
+ |
+AudioDebugRecorder* AudioDebugRecorder::g_filter = nullptr; |
+ |
+class AudioDebugRecorder::Observer : public AudioDebugRecordingObserver { |
+ public: |
+ Observer(int id, mojo::InterfaceRequest<AudioDebugRecordingObserver> request) |
+ : id_(id), binding_(this, std::move(request)) {} |
+ ~Observer() override = default; |
+ |
+ // AudioDebugRecordingObserver implementation. |
+ void Enable(mojo::ScopedHandle file_handle) override { |
+ mojo::embedder::ScopedPlatformHandle scoped_platform_handle; |
+ MojoResult result = mojo::embedder::PassWrappedPlatformHandle( |
+ file_handle.release().value(), &scoped_platform_handle); |
+ if (result != MOJO_RESULT_OK) |
+ return; |
+ |
+ DCHECK(scoped_platform_handle.is_valid()); |
+ base::PlatformFile platform_handle; |
+#if defined(OS_POSIX) |
+ platform_handle = scoped_platform_handle.release().fd; |
+#elif defined(OS_WIN) |
+ platform_handle = scoped_platform_handle.release().handle; |
+#else |
+#error "Platform not yet supported." |
+#endif |
+ |
+ AudioDebugRecorder::Get()->DoEnableAecDump(id_, platform_handle); |
+ } |
+ |
+ void Disable() override { |
+ AudioDebugRecorder::Get()->DoDisableAecDump(id_); |
+ } |
+ |
+ private: |
+ const int id_; |
+ mojo::Binding<AudioDebugRecordingObserver> binding_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Observer); |
+}; |
+ |
+AudioDebugRecorder::AudioDebugRecorder(ServiceRegistry* service_registry) |
+ : delegate_id_counter_(1) { |
+ DCHECK(!g_filter); |
+ g_filter = this; |
+ |
+ service_registry->ConnectToRemoteService(mojo::GetProxy(&service_)); |
+ service_.set_connection_error_handler(base::Bind( |
+ &AudioDebugRecorder::OnConnectionError, base::Unretained(this))); |
+} |
+ |
+AudioDebugRecorder::~AudioDebugRecorder() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK_EQ(g_filter, this); |
+ g_filter = nullptr; |
+} |
+ |
+// static |
+scoped_refptr<AudioDebugRecorder> AudioDebugRecorder::Get() { |
+ return g_filter; |
+} |
+ |
+void AudioDebugRecorder::OnConnectionError() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ for (DelegateMap::iterator it = delegates_.begin(); it != delegates_.end(); |
+ ++it) { |
+ it->second->OnIpcClosing(); |
+ } |
+ delegates_.clear(); |
+ observers_.clear(); |
+} |
+ |
+void AudioDebugRecorder::AddDelegate( |
+ AudioDebugRecorder::AecDumpDelegate* delegate) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(delegate); |
+ DCHECK_EQ(kInvalidDelegateId, GetIdForDelegate(delegate)); |
+ |
+ int id = delegate_id_counter_++; |
+ delegates_[id] = delegate; |
+ |
+ AudioDebugRecordingObserverPtr observer; |
+ bool inserted = observers_.insert( |
+ std::make_pair(id, make_scoped_ptr( |
+ new Observer(id, mojo::GetProxy(&observer))))).second; |
+ DCHECK(inserted); |
+ |
+ service_->RegisterObserver(id, std::move(observer)); |
+} |
+ |
+void AudioDebugRecorder::RemoveDelegate( |
+ AudioDebugRecorder::AecDumpDelegate* delegate) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(delegate); |
+ |
+ int id = GetIdForDelegate(delegate); |
+ DCHECK_NE(kInvalidDelegateId, id); |
+ delegates_.erase(id); |
+ |
+ auto it = observers_.find(id); |
+ DCHECK(it != observers_.end()); |
+ observers_.erase(it); |
+} |
+ |
+void AudioDebugRecorder::DoEnableAecDump(int id, |
+ base::PlatformFile file_handle) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DelegateMap::iterator it = delegates_.find(id); |
+ DCHECK(it != delegates_.end()); |
+ it->second->OnAecDumpFile(file_handle); |
+} |
+ |
+void AudioDebugRecorder::DoDisableAecDump(int id) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DelegateMap::iterator it = delegates_.find(id); |
+ DCHECK(it != delegates_.end()); |
+ it->second->OnDisableAecDump(); |
+} |
+ |
+int AudioDebugRecorder::GetIdForDelegate( |
+ AudioDebugRecorder::AecDumpDelegate* delegate) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ for (DelegateMap::iterator it = delegates_.begin(); it != delegates_.end(); |
+ ++it) { |
+ if (it->second == delegate) |
+ return it->first; |
+ } |
+ return kInvalidDelegateId; |
+} |
+ |
+} // namespace content |