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