Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Unified Diff: content/browser/media/audio_debug_recording_impl.cc

Issue 1246283003: Split out audio debug recording from RenderProcessHostImpl. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/media/audio_debug_recording_impl.cc
diff --git a/content/browser/media/audio_debug_recording_impl.cc b/content/browser/media/audio_debug_recording_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..89f4c081297311e3a96ffa7d63d0aac35da6319c
--- /dev/null
+++ b/content/browser/media/audio_debug_recording_impl.cc
@@ -0,0 +1,217 @@
+// 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/browser/media/audio_debug_recording_impl.h"
+
+#include "base/bind.h"
+#include "base/files/file.h"
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/browser/media/webrtc_internals.h"
+#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/child_process_host.h"
+#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
+#include "third_party/mojo/src/mojo/public/cpp/system/handle.h"
+
+namespace content {
+
+namespace {
+
+const base::FilePath::CharType kAudioDebugRecordingFileNameAddition[] =
Henrik Grunell 2015/10/15 12:17:03 kAecDumpFileNameAddition
Anand Mistry (off Chromium) 2015/10/21 03:58:23 Done.
+ FILE_PATH_LITERAL("aec_dump");
+
+// Creates a file used for diagnostic echo canceller recordings for handing
+// over to the renderer.
+mojo::ScopedHandle CreateAudioDebugRecordingFile(base::FilePath file_path) {
Henrik Grunell 2015/10/15 12:17:03 CreateAecDumpFile()
Anand Mistry (off Chromium) 2015/10/21 03:58:23 Done.
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ base::File dump_file(file_path,
+ base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
+ if (!dump_file.IsValid()) {
+ VLOG(1) << "Could not open AEC dump file, error="
+ << dump_file.error_details();
+ return mojo::ScopedHandle();
+ }
+
+ mojo::embedder::PlatformHandle platform_handle_wrapper(
+ dump_file.TakePlatformFile());
+ mojo::embedder::ScopedPlatformHandle scoped_platform_handle(
+ platform_handle_wrapper);
+ MojoHandle mojo_handle = MOJO_HANDLE_INVALID;
+ MojoResult create_result = mojo::embedder::CreatePlatformHandleWrapper(
+ scoped_platform_handle.Pass(), &mojo_handle);
+ if (create_result != MOJO_RESULT_OK)
+ return mojo::ScopedHandle();
+
+ return MakeScopedHandle(mojo::Handle(mojo_handle));
+}
+
+// Does nothing. Just to avoid races between enable and disable.
+void DisableAudioDebugRecordingOnFileThread() {
Henrik Grunell 2015/10/15 12:17:02 Would be great if you could remove this and replac
Anand Mistry (off Chromium) 2015/10/21 03:58:23 Done.
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+}
+
+} // namespace
+
+class AudioDebugRecordingImpl::DumpObserver {
+ public:
+ DumpObserver(AudioDebugRecordingImpl* dump_impl,
+ int32_t id,
+ AudioDebugRecordingObserverPtr service)
+ : dump_impl_(dump_impl),
+ id_(id),
+ observer_service_(service.Pass()),
+ weak_factory_(this) {
+ observer_service_.set_connection_error_handler(
+ base::Bind(&DumpObserver::OnConnectionError, base::Unretained(this)));
+ }
+
+ void Enable(const base::FilePath& file);
+
+ void Disable() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // Posting on the FILE thread and then replying back on the UI thread is
+ // only for avoiding races between enable and disable. Nothing is done on
+ // the FILE thread.
+ BrowserThread::PostTaskAndReply(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DisableAudioDebugRecordingOnFileThread),
+ base::Bind(&DumpObserver::SendDisable, weak_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void OnConnectionError() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // Deletes |this|.
+ dump_impl_->RemoveObserver(this);
+ }
+
+ void SendEnable(mojo::ScopedHandle handle) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!handle.is_valid())
+ return;
+ observer_service_->Enable(handle.Pass());
+ }
+
+ void SendDisable() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ observer_service_->Disable();
+ }
+
+ AudioDebugRecordingImpl* dump_impl_;
Henrik Grunell 2015/10/15 12:17:02 Rename to audio_debug_recording_impl_
Anand Mistry (off Chromium) 2015/10/21 03:58:23 Done.
+ const int32_t id_;
+ AudioDebugRecordingObserverPtr observer_service_;
+ base::ThreadChecker thread_checker_;
+
+ base::WeakPtrFactory<DumpObserver> weak_factory_;
+};
+
+#if defined(OS_WIN)
+#define IntToStringType base::IntToString16
+#else
+#define IntToStringType base::IntToString
+#endif
+
+void AudioDebugRecordingImpl::DumpObserver::Enable(const base::FilePath& file) {
Henrik Grunell 2015/10/15 12:17:03 You might as well put the definition with the decl
Anand Mistry (off Chromium) 2015/10/21 03:58:23 Done.
+ DCHECK(thread_checker_.CalledOnValidThread());
+ RenderProcessHost* rph =
+ RenderProcessHost::FromID(dump_impl_->render_host_id_);
+
+ // Process is dead. We're likely to receive a connection error soon.
+ if (!rph)
+ return;
+
+ base::FilePath unique_file =
+ file.AddExtension(IntToStringType(base::GetProcId(rph->GetHandle())))
+ .AddExtension(kAudioDebugRecordingFileNameAddition)
+ .AddExtension(IntToStringType(id_));
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&CreateAudioDebugRecordingFile, unique_file),
+ base::Bind(&DumpObserver::SendEnable, weak_factory_.GetWeakPtr()));
+}
+
+#undef IntToStringType
+
+AudioDebugRecordingImpl::AudioDebugRecordingImpl(
+ int render_host_id,
+ const scoped_refptr<AudioInputRendererHost>& audio_input_renderer_host,
+ const DisconnectCallback& disconnect_cb,
+ mojo::InterfaceRequest<AudioDebugRecording> request)
+ : render_host_id_(render_host_id),
+ audio_input_renderer_host_(audio_input_renderer_host),
+ disconnect_cb_(disconnect_cb),
+ binding_(this) {
+ DCHECK_NE(render_host_id_, ChildProcessHost::kInvalidUniqueID);
+ DCHECK(!disconnect_cb_.is_null());
+ binding_.Bind(request.Pass());
+ binding_.set_connection_error_handler(base::Bind(
+ &AudioDebugRecordingImpl::OnConnectionError, base::Unretained(this)));
+}
+
+AudioDebugRecordingImpl::~AudioDebugRecordingImpl() {
+ STLDeleteContainerPointers(observers_.begin(), observers_.end());
+}
+
+void AudioDebugRecordingImpl::EnableAudioDebugRecording(
+ const base::FilePath& file) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ for (auto& observer : observers_)
Henrik Grunell 2015/10/15 12:17:02 Add comment that this enables AEC dump.
Anand Mistry (off Chromium) 2015/10/21 03:58:23 Done.
+ observer->Enable(file);
+
+ // Enable mic input recording. AudioInputRendererHost is reference counted, so
+ // its lifetime is guarantueed during the lifetime of the closure.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioInputRendererHost::EnableDebugRecording,
+ audio_input_renderer_host_, file));
+}
+
+void AudioDebugRecordingImpl::DisableAudioDebugRecording() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ for (auto& observer : observers_)
+ observer->Disable();
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioInputRendererHost::DisableDebugRecording,
+ audio_input_renderer_host_));
+}
+
+void AudioDebugRecordingImpl::RegisterObserver(
+ int32_t id,
+ AudioDebugRecordingObserverPtr observer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ DumpObserver* dump_observer = new DumpObserver(this, id, observer.Pass());
+ bool inserted = observers_.insert(dump_observer).second;
+ DCHECK(inserted);
+
+ if (WebRTCInternals::GetInstance()->IsAudioDebugRecordingsEnabled()) {
+ dump_observer->Enable(
+ WebRTCInternals::GetInstance()->GetAudioDebugRecordingsFilePath());
+ }
+}
+
+void AudioDebugRecordingImpl::OnConnectionError() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // May delete |this|.
+ disconnect_cb_.Run(this);
+}
+
+void AudioDebugRecordingImpl::RemoveObserver(
+ AudioDebugRecordingImpl::DumpObserver* observer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ auto it = observers_.find(observer);
+ DCHECK(it != observers_.end());
+ observers_.erase(it);
+ delete observer;
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698