Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |