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

Side by Side Diff: chrome/browser/media/webrtc/audio_debug_recordings_handler.cc

Issue 2582703003: Audio output debug recording. (Closed)
Patch Set: Code review. Created 3 years, 9 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/media/audio_debug_recordings_handler.h" 5 #include "chrome/browser/media/audio_debug_recordings_handler.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "base/time/time.h" 14 #include "base/time/time.h"
15 #include "chrome/browser/media/webrtc/webrtc_log_list.h" 15 #include "chrome/browser/media/webrtc/webrtc_log_list.h"
16 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/common/chrome_switches.h" 17 #include "chrome/common/chrome_switches.h"
18 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/render_process_host.h" 19 #include "content/public/browser/render_process_host.h"
20 #include "media/audio/audio_manager.h"
20 21
21 using content::BrowserThread; 22 using content::BrowserThread;
22 23
23 // Keys used to attach handler to the RenderProcessHost 24 // Keys used to attach handler to the RenderProcessHost
24 const char AudioDebugRecordingsHandler::kAudioDebugRecordingsHandlerKey[] = 25 const char AudioDebugRecordingsHandler::kAudioDebugRecordingsHandlerKey[] =
25 "kAudioDebugRecordingsHandlerKey"; 26 "kAudioDebugRecordingsHandlerKey";
26 27
27 namespace { 28 namespace {
28 29
29 // Returns a path name to be used as prefix for audio debug recordings files. 30 // Returns a path name to be used as prefix for audio debug recordings files.
30 base::FilePath GetAudioDebugRecordingsPrefixPath( 31 base::FilePath GetAudioDebugRecordingsPrefixPath(
31 const base::FilePath& directory, 32 const base::FilePath& directory,
32 uint64_t audio_debug_recordings_id) { 33 uint64_t audio_debug_recordings_id) {
33 static const char kAudioDebugRecordingsFilePrefix[] = "AudioDebugRecordings."; 34 static const char kAudioDebugRecordingsFilePrefix[] = "AudioDebugRecordings.";
34 return directory.AppendASCII(kAudioDebugRecordingsFilePrefix + 35 return directory.AppendASCII(kAudioDebugRecordingsFilePrefix +
35 base::Int64ToString(audio_debug_recordings_id)); 36 base::Int64ToString(audio_debug_recordings_id));
36 } 37 }
37 38
38 } // namespace 39 } // namespace
39 40
40 AudioDebugRecordingsHandler::AudioDebugRecordingsHandler(Profile* profile) 41 AudioDebugRecordingsHandler::AudioDebugRecordingsHandler(
42 Profile* profile,
43 media::AudioManager* audio_manager)
41 : profile_(profile), 44 : profile_(profile),
42 is_audio_debug_recordings_in_progress_(false), 45 is_audio_debug_recordings_in_progress_(false),
43 current_audio_debug_recordings_id_(0) { 46 current_audio_debug_recordings_id_(0),
47 audio_manager_(audio_manager) {
48 DCHECK_CURRENTLY_ON(BrowserThread::UI);
44 DCHECK(profile_); 49 DCHECK(profile_);
50 DCHECK(audio_manager_);
45 } 51 }
46 52
47 AudioDebugRecordingsHandler::~AudioDebugRecordingsHandler() {} 53 AudioDebugRecordingsHandler::~AudioDebugRecordingsHandler() {}
48 54
49 void AudioDebugRecordingsHandler::StartAudioDebugRecordings( 55 void AudioDebugRecordingsHandler::StartAudioDebugRecordings(
50 content::RenderProcessHost* host, 56 content::RenderProcessHost* host,
51 base::TimeDelta delay, 57 base::TimeDelta delay,
52 const RecordingDoneCallback& callback, 58 const RecordingDoneCallback& callback,
53 const RecordingErrorCallback& error_callback) { 59 const RecordingErrorCallback& error_callback) {
54 DCHECK(thread_checker_.CalledOnValidThread()); 60 DCHECK_CURRENTLY_ON(BrowserThread::UI);
55 61
56 BrowserThread::PostTaskAndReplyWithResult( 62 BrowserThread::PostTaskAndReplyWithResult(
57 BrowserThread::FILE, FROM_HERE, 63 BrowserThread::FILE, FROM_HERE,
58 base::Bind(&AudioDebugRecordingsHandler::GetLogDirectoryAndEnsureExists, 64 base::Bind(&AudioDebugRecordingsHandler::GetLogDirectoryAndEnsureExists,
59 this), 65 this),
60 base::Bind(&AudioDebugRecordingsHandler::DoStartAudioDebugRecordings, 66 base::Bind(&AudioDebugRecordingsHandler::DoStartAudioDebugRecordings,
61 this, host, delay, callback, error_callback)); 67 this, host, delay, callback, error_callback));
62 } 68 }
63 69
64 void AudioDebugRecordingsHandler::StopAudioDebugRecordings( 70 void AudioDebugRecordingsHandler::StopAudioDebugRecordings(
65 content::RenderProcessHost* host, 71 content::RenderProcessHost* host,
66 const RecordingDoneCallback& callback, 72 const RecordingDoneCallback& callback,
67 const RecordingErrorCallback& error_callback) { 73 const RecordingErrorCallback& error_callback) {
68 DCHECK(thread_checker_.CalledOnValidThread()); 74 DCHECK_CURRENTLY_ON(BrowserThread::UI);
69 const bool is_manual_stop = true; 75 const bool is_manual_stop = true;
70 BrowserThread::PostTaskAndReplyWithResult( 76 BrowserThread::PostTaskAndReplyWithResult(
71 BrowserThread::FILE, FROM_HERE, 77 BrowserThread::FILE, FROM_HERE,
72 base::Bind(&AudioDebugRecordingsHandler::GetLogDirectoryAndEnsureExists, 78 base::Bind(&AudioDebugRecordingsHandler::GetLogDirectoryAndEnsureExists,
73 this), 79 this),
74 base::Bind(&AudioDebugRecordingsHandler::DoStopAudioDebugRecordings, this, 80 base::Bind(&AudioDebugRecordingsHandler::DoStopAudioDebugRecordings, this,
75 host, is_manual_stop, current_audio_debug_recordings_id_, 81 host, is_manual_stop, current_audio_debug_recordings_id_,
76 callback, error_callback)); 82 callback, error_callback));
77 } 83 }
78 84
79 base::FilePath AudioDebugRecordingsHandler::GetLogDirectoryAndEnsureExists() { 85 base::FilePath AudioDebugRecordingsHandler::GetLogDirectoryAndEnsureExists() {
80 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 86 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
81 base::FilePath log_dir_path = 87 base::FilePath log_dir_path =
82 WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath()); 88 WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath());
83 base::File::Error error; 89 base::File::Error error;
84 if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) { 90 if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) {
85 DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error; 91 DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error;
86 return base::FilePath(); 92 return base::FilePath();
87 } 93 }
88 return log_dir_path; 94 return log_dir_path;
89 } 95 }
90 96
91 void AudioDebugRecordingsHandler::DoStartAudioDebugRecordings( 97 void AudioDebugRecordingsHandler::DoStartAudioDebugRecordings(
92 content::RenderProcessHost* host, 98 content::RenderProcessHost* host,
93 base::TimeDelta delay, 99 base::TimeDelta delay,
94 const RecordingDoneCallback& callback, 100 const RecordingDoneCallback& callback,
95 const RecordingErrorCallback& error_callback, 101 const RecordingErrorCallback& error_callback,
96 const base::FilePath& log_directory) { 102 const base::FilePath& log_directory) {
97 DCHECK(thread_checker_.CalledOnValidThread()); 103 DCHECK_CURRENTLY_ON(BrowserThread::UI);
98 104
99 if (is_audio_debug_recordings_in_progress_) { 105 if (is_audio_debug_recordings_in_progress_) {
100 error_callback.Run("Audio debug recordings already in progress"); 106 error_callback.Run("Audio debug recordings already in progress");
101 return; 107 return;
102 } 108 }
103 109
104 is_audio_debug_recordings_in_progress_ = true; 110 is_audio_debug_recordings_in_progress_ = true;
105 base::FilePath prefix_path = GetAudioDebugRecordingsPrefixPath( 111 base::FilePath prefix_path = GetAudioDebugRecordingsPrefixPath(
106 log_directory, ++current_audio_debug_recordings_id_); 112 log_directory, ++current_audio_debug_recordings_id_);
107 host->EnableAudioDebugRecordings(prefix_path); 113 host->EnableAudioDebugRecordings(prefix_path);
108 114
115 // AudioManager is deleted on the audio thread, and the AudioManager outlives
116 // this object, which is owned by content::RenderProcessHost, so it's safe to
117 // post unretained.
118 audio_manager_->GetTaskRunner()->PostTask(
119 FROM_HERE, base::Bind(&media::AudioManager::EnableOutputDebugRecording,
120 base::Unretained(audio_manager_), prefix_path));
121
109 if (delay.is_zero()) { 122 if (delay.is_zero()) {
110 const bool is_stopped = false, is_manual_stop = false; 123 const bool is_stopped = false, is_manual_stop = false;
111 callback.Run(prefix_path.AsUTF8Unsafe(), is_stopped, is_manual_stop); 124 callback.Run(prefix_path.AsUTF8Unsafe(), is_stopped, is_manual_stop);
112 return; 125 return;
113 } 126 }
114 127
115 const bool is_manual_stop = false; 128 const bool is_manual_stop = false;
116 BrowserThread::PostDelayedTask( 129 BrowserThread::PostDelayedTask(
117 BrowserThread::UI, FROM_HERE, 130 BrowserThread::UI, FROM_HERE,
118 base::Bind(&AudioDebugRecordingsHandler::DoStopAudioDebugRecordings, this, 131 base::Bind(&AudioDebugRecordingsHandler::DoStopAudioDebugRecordings, this,
119 host, is_manual_stop, current_audio_debug_recordings_id_, 132 host, is_manual_stop, current_audio_debug_recordings_id_,
120 callback, error_callback, log_directory), 133 callback, error_callback, log_directory),
121 delay); 134 delay);
122 } 135 }
123 136
124 void AudioDebugRecordingsHandler::DoStopAudioDebugRecordings( 137 void AudioDebugRecordingsHandler::DoStopAudioDebugRecordings(
125 content::RenderProcessHost* host, 138 content::RenderProcessHost* host,
126 bool is_manual_stop, 139 bool is_manual_stop,
127 uint64_t audio_debug_recordings_id, 140 uint64_t audio_debug_recordings_id,
128 const RecordingDoneCallback& callback, 141 const RecordingDoneCallback& callback,
129 const RecordingErrorCallback& error_callback, 142 const RecordingErrorCallback& error_callback,
130 const base::FilePath& log_directory) { 143 const base::FilePath& log_directory) {
131 DCHECK(thread_checker_.CalledOnValidThread()); 144 DCHECK_CURRENTLY_ON(BrowserThread::UI);
132 DCHECK_LE(audio_debug_recordings_id, current_audio_debug_recordings_id_); 145 DCHECK_LE(audio_debug_recordings_id, current_audio_debug_recordings_id_);
133 146
134 base::FilePath prefix_path = GetAudioDebugRecordingsPrefixPath( 147 base::FilePath prefix_path = GetAudioDebugRecordingsPrefixPath(
135 log_directory, audio_debug_recordings_id); 148 log_directory, audio_debug_recordings_id);
136 // Prevent an old posted StopAudioDebugRecordings() call to stop a newer dump. 149 // Prevent an old posted StopAudioDebugRecordings() call to stop a newer dump.
137 // This could happen in a sequence like: 150 // This could happen in a sequence like:
138 // Start(10); // Start dump 1. Post Stop() to run after 10 seconds. 151 // Start(10); // Start dump 1. Post Stop() to run after 10 seconds.
139 // Stop(); // Manually stop dump 1 before 10 seconds; 152 // Stop(); // Manually stop dump 1 before 10 seconds;
140 // Start(20); // Start dump 2. Posted Stop() for 1 should not stop dump 2. 153 // Start(20); // Start dump 2. Posted Stop() for 1 should not stop dump 2.
141 if (audio_debug_recordings_id < current_audio_debug_recordings_id_) { 154 if (audio_debug_recordings_id < current_audio_debug_recordings_id_) {
142 const bool is_stopped = false; 155 const bool is_stopped = false;
143 callback.Run(prefix_path.AsUTF8Unsafe(), is_stopped, is_manual_stop); 156 callback.Run(prefix_path.AsUTF8Unsafe(), is_stopped, is_manual_stop);
144 return; 157 return;
145 } 158 }
146 159
147 if (!is_audio_debug_recordings_in_progress_) { 160 if (!is_audio_debug_recordings_in_progress_) {
148 error_callback.Run("No audio debug recording in progress"); 161 error_callback.Run("No audio debug recording in progress");
149 return; 162 return;
150 } 163 }
151 164
165 // AudioManager is deleted on the audio thread, and the AudioManager outlives
166 // this object, which is owned by content::RenderProcessHost, so it's safe to
167 // post unretained.
168 audio_manager_->GetTaskRunner()->PostTask(
169 FROM_HERE, base::Bind(&media::AudioManager::DisableOutputDebugRecording,
170 base::Unretained(audio_manager_)));
171
152 host->DisableAudioDebugRecordings(); 172 host->DisableAudioDebugRecordings();
173
153 is_audio_debug_recordings_in_progress_ = false; 174 is_audio_debug_recordings_in_progress_ = false;
154 const bool is_stopped = true; 175 const bool is_stopped = true;
155 callback.Run(prefix_path.AsUTF8Unsafe(), is_stopped, is_manual_stop); 176 callback.Run(prefix_path.AsUTF8Unsafe(), is_stopped, is_manual_stop);
156 } 177 }
OLDNEW
« no previous file with comments | « chrome/browser/media/audio_debug_recordings_handler.h ('k') | content/browser/browser_main_loop.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698