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

Side by Side Diff: media/audio/win/audio_manager_win.cc

Issue 23523023: Add GetOutputStreamParameters, GetAssociatedOutputDeviceID to AudioManager. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Address comments Created 7 years, 3 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/win/audio_manager_win.h ('k') | media/audio/win/core_audio_util_win.h » ('j') | 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/audio_io.h" 5 #include "media/audio/audio_io.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <objbase.h> // This has to be before initguid.h 8 #include <objbase.h> // This has to be before initguid.h
9 #include <initguid.h> 9 #include <initguid.h>
10 #include <mmsystem.h> 10 #include <mmsystem.h>
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 WASAPIAudioInputStream::HardwareChannelCount(device_id) == 1 ? 274 WASAPIAudioInputStream::HardwareChannelCount(device_id) == 1 ?
275 CHANNEL_LAYOUT_MONO : CHANNEL_LAYOUT_STEREO; 275 CHANNEL_LAYOUT_MONO : CHANNEL_LAYOUT_STEREO;
276 } 276 }
277 277
278 // TODO(Henrika): improve the default buffer size value for input stream. 278 // TODO(Henrika): improve the default buffer size value for input stream.
279 return AudioParameters( 279 return AudioParameters(
280 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 280 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
281 sample_rate, 16, kFallbackBufferSize); 281 sample_rate, 16, kFallbackBufferSize);
282 } 282 }
283 283
284 std::string AudioManagerWin::GetAssociatedOutputDeviceID(
285 const std::string& input_device_id) {
286 return CoreAudioUtil::GetMatchingOutputDeviceID(input_device_id);
287 }
288
284 // Factory for the implementations of AudioOutputStream for AUDIO_PCM_LINEAR 289 // Factory for the implementations of AudioOutputStream for AUDIO_PCM_LINEAR
285 // mode. 290 // mode.
286 // - PCMWaveOutAudioOutputStream: Based on the waveOut API. 291 // - PCMWaveOutAudioOutputStream: Based on the waveOut API.
287 AudioOutputStream* AudioManagerWin::MakeLinearOutputStream( 292 AudioOutputStream* AudioManagerWin::MakeLinearOutputStream(
288 const AudioParameters& params) { 293 const AudioParameters& params) {
289 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); 294 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
290 if (params.channels() > kWinMaxChannels) 295 if (params.channels() > kWinMaxChannels)
291 return NULL; 296 return NULL;
292 297
293 return new PCMWaveOutAudioOutputStream(this, 298 return new PCMWaveOutAudioOutputStream(this,
(...skipping 16 matching lines...) Expand all
310 if (params.channels() > kWinMaxChannels) 315 if (params.channels() > kWinMaxChannels)
311 return NULL; 316 return NULL;
312 317
313 if (!CoreAudioUtil::IsSupported()) { 318 if (!CoreAudioUtil::IsSupported()) {
314 // Fall back to Windows Wave implementation on Windows XP or lower. 319 // Fall back to Windows Wave implementation on Windows XP or lower.
315 DVLOG(1) << "Using WaveOut since WASAPI requires at least Vista."; 320 DVLOG(1) << "Using WaveOut since WASAPI requires at least Vista.";
316 return new PCMWaveOutAudioOutputStream( 321 return new PCMWaveOutAudioOutputStream(
317 this, params, media::NumberOfWaveOutBuffers(), WAVE_MAPPER); 322 this, params, media::NumberOfWaveOutBuffers(), WAVE_MAPPER);
318 } 323 }
319 324
320 // TODO(crogers): support more than stereo input. 325 // TODO(rtoy): support more than stereo input.
321 if (params.input_channels() > 0) { 326 if (params.input_channels() > 0) {
322 DVLOG(1) << "WASAPIUnifiedStream is created."; 327 DVLOG(1) << "WASAPIUnifiedStream is created.";
323 return new WASAPIUnifiedStream(this, params, input_device_id); 328 return new WASAPIUnifiedStream(this, params, input_device_id);
324 } 329 }
325 330
326 return new WASAPIAudioOutputStream(this, params, eConsole); 331 return new WASAPIAudioOutputStream(this, params, eConsole);
327 } 332 }
328 333
329 // Factory for the implementations of AudioInputStream for AUDIO_PCM_LINEAR 334 // Factory for the implementations of AudioInputStream for AUDIO_PCM_LINEAR
330 // mode. 335 // mode.
(...skipping 13 matching lines...) Expand all
344 // Fall back to Windows Wave implementation on Windows XP or lower. 349 // Fall back to Windows Wave implementation on Windows XP or lower.
345 DVLOG(1) << "Using WaveIn since WASAPI requires at least Vista."; 350 DVLOG(1) << "Using WaveIn since WASAPI requires at least Vista.";
346 stream = CreatePCMWaveInAudioInputStream(params, device_id); 351 stream = CreatePCMWaveInAudioInputStream(params, device_id);
347 } else { 352 } else {
348 stream = new WASAPIAudioInputStream(this, params, device_id); 353 stream = new WASAPIAudioInputStream(this, params, device_id);
349 } 354 }
350 355
351 return stream; 356 return stream;
352 } 357 }
353 358
359 std::string AudioManagerWin::GetDefaultOutputDeviceID() {
360 if (!CoreAudioUtil::IsSupported())
361 return std::string();
362 return CoreAudioUtil::GetDefaultOutputDeviceID();
363 }
364
354 AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters( 365 AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters(
355 const std::string& output_device_id, 366 const std::string& output_device_id,
356 const AudioParameters& input_params) { 367 const AudioParameters& input_params) {
357 // TODO(tommi): Support |output_device_id|. 368 // TODO(tommi): Support |output_device_id|.
358 DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!"; 369 DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
370
371 const bool core_audio_supported = CoreAudioUtil::IsSupported();
372 DLOG_IF(ERROR, !core_audio_supported && !output_device_id.empty())
373 << "CoreAudio is required to open non-default devices.";
374
359 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 375 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
360 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; 376 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
361 int sample_rate = 48000; 377 int sample_rate = 48000;
362 int buffer_size = kFallbackBufferSize; 378 int buffer_size = kFallbackBufferSize;
363 int bits_per_sample = 16; 379 int bits_per_sample = 16;
364 int input_channels = 0; 380 int input_channels = 0;
365 bool use_input_params = !CoreAudioUtil::IsSupported(); 381 bool use_input_params = !core_audio_supported;
366 if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) { 382 if (core_audio_supported) {
367 // TODO(crogers): tune these values for best possible WebAudio performance. 383 if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) {
368 // WebRTC works well at 48kHz and a buffer size of 480 samples will be used 384 // TODO(rtoy): tune these values for best possible WebAudio
369 // for this case. Note that exclusive mode is experimental. 385 // performance. WebRTC works well at 48kHz and a buffer size of 480
370 // This sample rate will be combined with a buffer size of 256 samples, 386 // samples will be used for this case. Note that exclusive mode is
371 // which corresponds to an output delay of ~5.33ms. 387 // experimental. This sample rate will be combined with a buffer size of
372 sample_rate = 48000; 388 // 256 samples, which corresponds to an output delay of ~5.33ms.
373 buffer_size = 256; 389 sample_rate = 48000;
374 if (input_params.IsValid()) 390 buffer_size = 256;
375 channel_layout = input_params.channel_layout(); 391 if (input_params.IsValid())
376 } else if (!use_input_params) { 392 channel_layout = input_params.channel_layout();
377 // Hardware sample-rate on Windows can be configured, so we must query.
378 // TODO(henrika): improve possibility to specify an audio endpoint.
379 // Use the default device (same as for Wave) for now to be compatible.
380 int hw_sample_rate = WASAPIAudioOutputStream::HardwareSampleRate();
381
382 AudioParameters params;
383 HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(eRender, eConsole,
384 &params);
385 int hw_buffer_size =
386 FAILED(hr) ? kFallbackBufferSize : params.frames_per_buffer();
387 channel_layout = WASAPIAudioOutputStream::HardwareChannelLayout();
388
389 // TODO(henrika): Figure out the right thing to do here.
390 if (hw_sample_rate && hw_buffer_size) {
391 sample_rate = hw_sample_rate;
392 buffer_size = hw_buffer_size;
393 } else { 393 } else {
394 use_input_params = true; 394 AudioParameters params;
395 HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(output_device_id,
396 &params);
397 if (SUCCEEDED(hr)) {
398 bits_per_sample = params.bits_per_sample();
399 buffer_size = params.frames_per_buffer();
400 channel_layout = params.channel_layout();
401 sample_rate = params.sample_rate();
402 } else {
403 use_input_params = true;
404 }
395 } 405 }
396 } 406 }
397 407
398 if (input_params.IsValid()) { 408 if (input_params.IsValid()) {
399 if (cmd_line->HasSwitch(switches::kTrySupportedChannelLayouts) && 409 if (core_audio_supported &&
400 CoreAudioUtil::IsSupported()) { 410 cmd_line->HasSwitch(switches::kTrySupportedChannelLayouts)) {
401 // Check if it is possible to open up at the specified input channel 411 // Check if it is possible to open up at the specified input channel
402 // layout but avoid checking if the specified layout is the same as the 412 // layout but avoid checking if the specified layout is the same as the
403 // hardware (preferred) layout. We do this extra check to avoid the 413 // hardware (preferred) layout. We do this extra check to avoid the
404 // CoreAudioUtil::IsChannelLayoutSupported() overhead in most cases. 414 // CoreAudioUtil::IsChannelLayoutSupported() overhead in most cases.
405 if (input_params.channel_layout() != channel_layout) { 415 if (input_params.channel_layout() != channel_layout) {
416 // TODO(henrika): Use |output_device_id| here.
417 // Internally, IsChannelLayoutSupported does many of the operations
418 // that have already been done such as opening up a client and fetching
419 // the WAVEFORMATPCMEX format. Ideally we should only do that once and
420 // do it for the requested device. Then here, we can check the layout
421 // from the data we already hold.
406 if (CoreAudioUtil::IsChannelLayoutSupported( 422 if (CoreAudioUtil::IsChannelLayoutSupported(
407 eRender, eConsole, input_params.channel_layout())) { 423 eRender, eConsole, input_params.channel_layout())) {
408 // Open up using the same channel layout as the source if it is 424 // Open up using the same channel layout as the source if it is
409 // supported by the hardware. 425 // supported by the hardware.
410 channel_layout = input_params.channel_layout(); 426 channel_layout = input_params.channel_layout();
411 VLOG(1) << "Hardware channel layout is not used; using same layout" 427 VLOG(1) << "Hardware channel layout is not used; using same layout"
412 << " as the source instead (" << channel_layout << ")"; 428 << " as the source instead (" << channel_layout << ")";
413 } 429 }
414 } 430 }
415 } 431 }
416 input_channels = input_params.input_channels(); 432 input_channels = input_params.input_channels();
417 if (use_input_params) { 433 if (use_input_params) {
418 // If WASAPI isn't supported we'll fallback to WaveOut, which will take 434 // If WASAPI isn't supported we'll fallback to WaveOut, which will take
419 // care of resampling and bits per sample changes. By setting these 435 // care of resampling and bits per sample changes. By setting these
420 // equal to the input values, AudioOutputResampler will skip resampling 436 // equal to the input values, AudioOutputResampler will skip resampling
421 // and bit per sample differences (since the input parameters will match 437 // and bit per sample differences (since the input parameters will match
422 // the output parameters). 438 // the output parameters).
439 bits_per_sample = input_params.bits_per_sample();
440 buffer_size = input_params.frames_per_buffer();
441 channel_layout = input_params.channel_layout();
423 sample_rate = input_params.sample_rate(); 442 sample_rate = input_params.sample_rate();
424 bits_per_sample = input_params.bits_per_sample();
425 channel_layout = input_params.channel_layout();
426 buffer_size = input_params.frames_per_buffer();
427 } 443 }
428 } 444 }
429 445
430 int user_buffer_size = GetUserBufferSize(); 446 int user_buffer_size = GetUserBufferSize();
431 if (user_buffer_size) 447 if (user_buffer_size)
432 buffer_size = user_buffer_size; 448 buffer_size = user_buffer_size;
433 449
434 return AudioParameters( 450 return AudioParameters(
435 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, 451 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
436 sample_rate, bits_per_sample, buffer_size); 452 sample_rate, bits_per_sample, buffer_size);
(...skipping 16 matching lines...) Expand all
453 return new PCMWaveInAudioInputStream(this, params, kNumInputBuffers, 469 return new PCMWaveInAudioInputStream(this, params, kNumInputBuffers,
454 xp_device_id); 470 xp_device_id);
455 } 471 }
456 472
457 /// static 473 /// static
458 AudioManager* CreateAudioManager() { 474 AudioManager* CreateAudioManager() {
459 return new AudioManagerWin(); 475 return new AudioManagerWin();
460 } 476 }
461 477
462 } // namespace media 478 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/win/audio_manager_win.h ('k') | media/audio/win/core_audio_util_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698