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

Side by Side Diff: media/audio/pulse/pulse_util.cc

Issue 1711823004: Let default device in PulseAudio be the system default device (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix issues Created 4 years, 10 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
« no previous file with comments | « media/audio/pulse/pulse_util.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "media/audio/pulse/pulse_util.h" 5 #include "media/audio/pulse/pulse_util.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/macros.h" 10 #include "base/macros.h"
11 #include "base/time/time.h" 11 #include "base/time/time.h"
12 #include "media/audio/audio_manager_base.h" 12 #include "media/audio/audio_manager_base.h"
13 #include "media/audio/audio_parameters.h" 13 #include "media/audio/audio_parameters.h"
14 #include "media/audio/pulse/pulse_input.h"
15 #include "media/base/limits.h"
14 16
15 namespace media { 17 namespace media {
16 18
17 namespace pulse { 19 namespace pulse {
18 20
19 namespace { 21 namespace {
20 22
21 #if defined(GOOGLE_CHROME_BUILD) 23 #if defined(GOOGLE_CHROME_BUILD)
22 static const char kBrowserDisplayName[] = "google-chrome"; 24 static const char kBrowserDisplayName[] = "google-chrome";
23 #else 25 #else
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 156
155 // Helper macro for CreateInput/OutputStream() to avoid code spam and 157 // Helper macro for CreateInput/OutputStream() to avoid code spam and
156 // string bloat. 158 // string bloat.
157 #define RETURN_ON_FAILURE(expression, message) do { \ 159 #define RETURN_ON_FAILURE(expression, message) do { \
158 if (!(expression)) { \ 160 if (!(expression)) { \
159 DLOG(ERROR) << message; \ 161 DLOG(ERROR) << message; \
160 return false; \ 162 return false; \
161 } \ 163 } \
162 } while (0) 164 } while (0)
163 165
166 void SystemDefaultInputDeviceCallback(pa_context* context,
167 const pa_server_info* info,
168 void* user_data) {
169 PulseAudioInputStream* stream =
170 reinterpret_cast<PulseAudioInputStream*>(user_data);
171 stream->device_name_ = info->default_source_name;
Henrik Grunell 2016/02/24 15:54:53 This will overwrite the device name provided in th
rchtara 2016/02/25 17:17:26 Done.
172 pa_threaded_mainloop* pa_mainloop =
173 static_cast<pa_threaded_mainloop*>(stream->pa_mainloop_);
174 pa_threaded_mainloop_signal(pa_mainloop, 0);
175 }
176
177 std::string GetSystemDefaultInputDevice(pa_threaded_mainloop* mainloop,
178 pa_context* context) {
179 DCHECK(mainloop);
180 DCHECK(context);
181 AudioParameters params(AudioParameters::Format::AUDIO_PCM_LINEAR,
182 ChannelLayout::CHANNEL_LAYOUT_MONO,
183 limits::kMinSampleRate, limits::kMaxBitsPerSample,
184 limits::kMaxSamplesPerPacket);
185
186 PulseAudioInputStream stream(NULL, "", params, mainloop, context);
187
188 pa_operation* operation = pa_context_get_server_info(
189 context, SystemDefaultInputDeviceCallback, &stream);
190 WaitForOperationCompletion(mainloop, operation);
191 return stream.device_name_;
192 }
193
164 bool CreateInputStream(pa_threaded_mainloop* mainloop, 194 bool CreateInputStream(pa_threaded_mainloop* mainloop,
165 pa_context* context, 195 pa_context* context,
166 pa_stream** stream, 196 pa_stream** stream,
167 const AudioParameters& params, 197 const AudioParameters& params,
168 const std::string& device_id, 198 const std::string& device_id,
169 pa_stream_notify_cb_t stream_callback, 199 pa_stream_notify_cb_t stream_callback,
170 void* user_data) { 200 void* user_data) {
171 DCHECK(mainloop); 201 DCHECK(mainloop);
172 DCHECK(context); 202 DCHECK(context);
173 203
(...skipping 25 matching lines...) Expand all
199 // Set server-side capture buffer metrics. Detailed documentation on what 229 // Set server-side capture buffer metrics. Detailed documentation on what
200 // values should be chosen can be found at 230 // values should be chosen can be found at
201 // freedesktop.org/software/pulseaudio/doxygen/structpa__buffer__attr.html. 231 // freedesktop.org/software/pulseaudio/doxygen/structpa__buffer__attr.html.
202 pa_buffer_attr buffer_attributes; 232 pa_buffer_attr buffer_attributes;
203 const unsigned int buffer_size = params.GetBytesPerBuffer(); 233 const unsigned int buffer_size = params.GetBytesPerBuffer();
204 buffer_attributes.maxlength = static_cast<uint32_t>(-1); 234 buffer_attributes.maxlength = static_cast<uint32_t>(-1);
205 buffer_attributes.tlength = buffer_size; 235 buffer_attributes.tlength = buffer_size;
206 buffer_attributes.minreq = buffer_size; 236 buffer_attributes.minreq = buffer_size;
207 buffer_attributes.prebuf = static_cast<uint32_t>(-1); 237 buffer_attributes.prebuf = static_cast<uint32_t>(-1);
208 buffer_attributes.fragsize = buffer_size; 238 buffer_attributes.fragsize = buffer_size;
239
209 int flags = PA_STREAM_AUTO_TIMING_UPDATE | 240 int flags = PA_STREAM_AUTO_TIMING_UPDATE |
210 PA_STREAM_INTERPOLATE_TIMING | 241 PA_STREAM_INTERPOLATE_TIMING |
211 PA_STREAM_ADJUST_LATENCY | 242 PA_STREAM_ADJUST_LATENCY |
212 PA_STREAM_START_CORKED; 243 PA_STREAM_START_CORKED;
244
245 std::string system_default_input_device =
246 GetSystemDefaultInputDevice(mainloop, context);
247
213 RETURN_ON_FAILURE( 248 RETURN_ON_FAILURE(
214 pa_stream_connect_record( 249 pa_stream_connect_record(
215 *stream, 250 *stream, device_id == AudioManagerBase::kDefaultDeviceId
Henrik Grunell 2016/02/24 15:54:52 Then here, always use |device_id|. And below for
rchtara 2016/02/25 17:17:26 Done.
rchtara 2016/02/25 17:17:26 Done.
216 device_id == AudioManagerBase::kDefaultDeviceId ? 251 ? system_default_input_device.c_str()
217 NULL : device_id.c_str(), 252 : device_id.c_str(),
218 &buffer_attributes, 253 &buffer_attributes, static_cast<pa_stream_flags_t>(flags)) == 0,
219 static_cast<pa_stream_flags_t>(flags)) == 0,
220 "pa_stream_connect_record FAILED "); 254 "pa_stream_connect_record FAILED ");
221 255
222 // Wait for the stream to be ready. 256 // Wait for the stream to be ready.
223 while (true) { 257 while (true) {
224 pa_stream_state_t stream_state = pa_stream_get_state(*stream); 258 pa_stream_state_t stream_state = pa_stream_get_state(*stream);
225 RETURN_ON_FAILURE( 259 RETURN_ON_FAILURE(
226 PA_STREAM_IS_GOOD(stream_state), "Invalid PulseAudio stream state"); 260 PA_STREAM_IS_GOOD(stream_state), "Invalid PulseAudio stream state");
227 if (stream_state == PA_STREAM_READY) 261 if (stream_state == PA_STREAM_READY)
228 break; 262 break;
229 pa_threaded_mainloop_wait(mainloop); 263 pa_threaded_mainloop_wait(mainloop);
230 } 264 }
231 265
232 return true; 266 return true;
233 } 267 }
234 268
269 void SystemDefaultOutputDeviceCallback(pa_context* context,
270 const pa_server_info* info,
271 void* user_data) {
272 PulseAudioInputStream* stream =
273 reinterpret_cast<PulseAudioInputStream*>(user_data);
274 stream->device_name_ = info->default_sink_name;
275 pa_threaded_mainloop* pa_mainloop =
276 static_cast<pa_threaded_mainloop*>(stream->pa_mainloop_);
277 pa_threaded_mainloop_signal(pa_mainloop, 0);
278 }
279
280 std::string GetSystemDefaultOutputDevice(pa_threaded_mainloop* mainloop,
281 pa_context* context) {
282 DCHECK(mainloop);
283 DCHECK(context);
284 AudioParameters params(AudioParameters::Format::AUDIO_PCM_LINEAR,
285 ChannelLayout::CHANNEL_LAYOUT_MONO,
286 limits::kMinSampleRate, limits::kMaxBitsPerSample,
287 limits::kMaxSamplesPerPacket);
288
289 PulseAudioInputStream stream(NULL, "", params, mainloop, context);
290
291 pa_operation* operation = pa_context_get_server_info(
292 context, SystemDefaultOutputDeviceCallback, &stream);
293 WaitForOperationCompletion(mainloop, operation);
294 DLOG(WARNING) << "Operation is NU" << stream.device_name_;
295 return stream.device_name_;
296 }
297
235 bool CreateOutputStream(pa_threaded_mainloop** mainloop, 298 bool CreateOutputStream(pa_threaded_mainloop** mainloop,
236 pa_context** context, 299 pa_context** context,
237 pa_stream** stream, 300 pa_stream** stream,
238 const AudioParameters& params, 301 const AudioParameters& params,
239 const std::string& device_id, 302 const std::string& device_id,
240 const std::string& app_name, 303 const std::string& app_name,
241 pa_stream_notify_cb_t stream_callback, 304 pa_stream_notify_cb_t stream_callback,
242 pa_stream_request_cb_t write_callback, 305 pa_stream_request_cb_t write_callback,
243 void* user_data) { 306 void* user_data) {
244 DCHECK(!*mainloop); 307 DCHECK(!*mainloop);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 // Setting |minreq| to the exact buffer size leads to more callbacks than 383 // Setting |minreq| to the exact buffer size leads to more callbacks than
321 // necessary, so we've clipped it to half the buffer size. Regardless of the 384 // necessary, so we've clipped it to half the buffer size. Regardless of the
322 // requested amount, we'll always fill |params.GetBytesPerBuffer()| though. 385 // requested amount, we'll always fill |params.GetBytesPerBuffer()| though.
323 pa_buffer_attr pa_buffer_attributes; 386 pa_buffer_attr pa_buffer_attributes;
324 pa_buffer_attributes.maxlength = static_cast<uint32_t>(-1); 387 pa_buffer_attributes.maxlength = static_cast<uint32_t>(-1);
325 pa_buffer_attributes.minreq = params.GetBytesPerBuffer() / 2; 388 pa_buffer_attributes.minreq = params.GetBytesPerBuffer() / 2;
326 pa_buffer_attributes.prebuf = static_cast<uint32_t>(-1); 389 pa_buffer_attributes.prebuf = static_cast<uint32_t>(-1);
327 pa_buffer_attributes.tlength = params.GetBytesPerBuffer() * 3; 390 pa_buffer_attributes.tlength = params.GetBytesPerBuffer() * 3;
328 pa_buffer_attributes.fragsize = static_cast<uint32_t>(-1); 391 pa_buffer_attributes.fragsize = static_cast<uint32_t>(-1);
329 392
393 std::string system_default_output_device =
394 GetSystemDefaultOutputDevice(*mainloop, *context);
395
330 // Connect playback stream. Like pa_buffer_attr, the pa_stream_flags have a 396 // Connect playback stream. Like pa_buffer_attr, the pa_stream_flags have a
331 // huge impact on the performance of the stream and were chosen through trial 397 // huge impact on the performance of the stream and were chosen through trial
332 // and error. 398 // and error.
333 RETURN_ON_FAILURE( 399 RETURN_ON_FAILURE(
334 pa_stream_connect_playback( 400 pa_stream_connect_playback(
335 *stream, 401 *stream, device_id == AudioManagerBase::kDefaultDeviceId
336 device_id == AudioManagerBase::kDefaultDeviceId ? 402 ? system_default_output_device.c_str()
337 NULL : device_id.c_str(), 403 : device_id.c_str(),
338 &pa_buffer_attributes, 404 &pa_buffer_attributes,
339 static_cast<pa_stream_flags_t>( 405 static_cast<pa_stream_flags_t>(
340 PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | 406 PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY |
341 PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_NOT_MONOTONIC | 407 PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_NOT_MONOTONIC |
342 PA_STREAM_START_CORKED), 408 PA_STREAM_START_CORKED),
343 NULL, 409 NULL, NULL) == 0,
344 NULL) == 0,
345 "pa_stream_connect_playback FAILED "); 410 "pa_stream_connect_playback FAILED ");
346 411
347 // Wait for the stream to be ready. 412 // Wait for the stream to be ready.
348 while (true) { 413 while (true) {
349 pa_stream_state_t stream_state = pa_stream_get_state(*stream); 414 pa_stream_state_t stream_state = pa_stream_get_state(*stream);
350 RETURN_ON_FAILURE( 415 RETURN_ON_FAILURE(
351 PA_STREAM_IS_GOOD(stream_state), "Invalid PulseAudio stream state"); 416 PA_STREAM_IS_GOOD(stream_state), "Invalid PulseAudio stream state");
352 if (stream_state == PA_STREAM_READY) 417 if (stream_state == PA_STREAM_READY)
353 break; 418 break;
354 pa_threaded_mainloop_wait(*mainloop); 419 pa_threaded_mainloop_wait(*mainloop);
355 } 420 }
356 421
357 return true; 422 return true;
358 } 423 }
359 424
360 #undef RETURN_ON_FAILURE 425 #undef RETURN_ON_FAILURE
361 426
362 } // namespace pulse 427 } // namespace pulse
363 428
364 } // namespace media 429 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/pulse/pulse_util.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698