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

Side by Side Diff: media/audio/mac/audio_manager_mac.cc

Issue 2718903003: Add play test.
Patch Set: updated.. 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
« no previous file with comments | « media/audio/mac/audio_low_latency_input_mac_unittest.cc ('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/mac/audio_manager_mac.h" 5 #include "media/audio/mac/audio_manager_mac.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 CHECK(channels); 303 CHECK(channels);
304 304
305 // Get the stream configuration of the device in an AudioBufferList (with the 305 // Get the stream configuration of the device in an AudioBufferList (with the
306 // buffer pointers set to nullptr) which describes the list of streams and the 306 // buffer pointers set to nullptr) which describes the list of streams and the
307 // number of channels in each stream. 307 // number of channels in each stream.
308 AudioObjectPropertyAddress pa = {kAudioDevicePropertyStreamConfiguration, 308 AudioObjectPropertyAddress pa = {kAudioDevicePropertyStreamConfiguration,
309 scope, kAudioObjectPropertyElementMaster}; 309 scope, kAudioObjectPropertyElementMaster};
310 310
311 UInt32 size; 311 UInt32 size;
312 OSStatus result = AudioObjectGetPropertyDataSize(device, &pa, 0, 0, &size); 312 OSStatus result = AudioObjectGetPropertyDataSize(device, &pa, 0, 0, &size);
313 if (result != noErr || !size) 313 if (result != noErr || !size) {
314 OSSTATUS_LOG(ERROR, result) << "Failed to get property size... " << size;
314 return false; 315 return false;
316 }
315 317
316 std::unique_ptr<uint8_t[]> list_storage(new uint8_t[size]); 318 std::unique_ptr<uint8_t[]> list_storage(new uint8_t[size]);
317 AudioBufferList* buffer_list = 319 AudioBufferList* buffer_list =
318 reinterpret_cast<AudioBufferList*>(list_storage.get()); 320 reinterpret_cast<AudioBufferList*>(list_storage.get());
319 321
320 result = AudioObjectGetPropertyData(device, &pa, 0, 0, &size, buffer_list); 322 result = AudioObjectGetPropertyData(device, &pa, 0, 0, &size, buffer_list);
321 if (result != noErr) 323 if (result != noErr) {
324 OSSTATUS_LOG(ERROR, result) << "Failed to get property...";
322 return false; 325 return false;
326 }
323 327
324 // Determine number of channels based on the AudioBufferList. 328 // Determine number of channels based on the AudioBufferList.
325 // |mNumberBuffers] is the number of interleaved channels in the buffer. 329 // |mNumberBuffers] is the number of interleaved channels in the buffer.
326 // If the number is 1, the buffer is noninterleaved. 330 // If the number is 1, the buffer is noninterleaved.
327 *channels = 0; 331 *channels = 0;
328 for (UInt32 i = 0; i < buffer_list->mNumberBuffers; ++i) 332 for (UInt32 i = 0; i < buffer_list->mNumberBuffers; ++i)
329 *channels += buffer_list->mBuffers[i].mNumberChannels; 333 *channels += buffer_list->mBuffers[i].mNumberChannels;
330 334
331 DVLOG(1) << (scope == kAudioDevicePropertyScopeInput ? "Input" : "Output") 335 LOG(ERROR) << (scope == kAudioDevicePropertyScopeInput ? "Input" : "Output")
332 << " total channels: " << *channels; 336 << " total channels: " << *channels;
333 return true; 337 return true;
334 } 338 }
335 339
336 class AudioManagerMac::AudioPowerObserver : public base::PowerObserver { 340 class AudioManagerMac::AudioPowerObserver : public base::PowerObserver {
337 public: 341 public:
338 AudioPowerObserver() 342 AudioPowerObserver()
339 : is_suspending_(false), 343 : is_suspending_(false),
340 is_monitoring_(base::PowerMonitor::Get()), 344 is_monitoring_(base::PowerMonitor::Get()),
341 num_resume_notifications_(0) { 345 num_resume_notifications_(0) {
342 // The PowerMonitor requires significant setup (a CFRunLoop and preallocated 346 // The PowerMonitor requires significant setup (a CFRunLoop and preallocated
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 448
445 // If the device has more channels than possible for layouts to express, use 449 // If the device has more channels than possible for layouts to express, use
446 // the total count of channels on the device; as of this writing, macOS will 450 // the total count of channels on the device; as of this writing, macOS will
447 // only return up to 8 channels in any layout. To allow WebAudio to work with 451 // only return up to 8 channels in any layout. To allow WebAudio to work with
448 // > 8 channel devices, we must use the total channel count instead of the 452 // > 8 channel devices, we must use the total channel count instead of the
449 // channel count of the preferred layout. 453 // channel count of the preferred layout.
450 int total_channel_count = 0; 454 int total_channel_count = 0;
451 if (GetDeviceTotalChannelCount(device, scope, &total_channel_count) && 455 if (GetDeviceTotalChannelCount(device, scope, &total_channel_count) &&
452 total_channel_count > kMaxConcurrentChannels) { 456 total_channel_count > kMaxConcurrentChannels) {
453 *channels = total_channel_count; 457 *channels = total_channel_count;
458 LOG(ERROR) << "Total count exceeds 8 channels, preferring total count.";
454 return true; 459 return true;
455 } 460 }
456 461
457 AudioObjectPropertyAddress pa = {kAudioDevicePropertyPreferredChannelLayout, 462 AudioObjectPropertyAddress pa = {kAudioDevicePropertyPreferredChannelLayout,
458 scope, kAudioObjectPropertyElementMaster}; 463 scope, kAudioObjectPropertyElementMaster};
459 UInt32 size; 464 UInt32 size;
460 OSStatus result = AudioObjectGetPropertyDataSize(device, &pa, 0, 0, &size); 465 OSStatus result = AudioObjectGetPropertyDataSize(device, &pa, 0, 0, &size);
461 if (result != noErr || !size) 466 if (result != noErr || !size) {
467 OSSTATUS_LOG(ERROR, result)
468 << "Failed to get property (2) size... " << size;
462 return false; 469 return false;
470 }
463 471
464 std::unique_ptr<uint8_t[]> layout_storage(new uint8_t[size]); 472 std::unique_ptr<uint8_t[]> layout_storage(new uint8_t[size]);
465 AudioChannelLayout* layout = 473 AudioChannelLayout* layout =
466 reinterpret_cast<AudioChannelLayout*>(layout_storage.get()); 474 reinterpret_cast<AudioChannelLayout*>(layout_storage.get());
467 result = AudioObjectGetPropertyData(device, &pa, 0, 0, &size, layout); 475 result = AudioObjectGetPropertyData(device, &pa, 0, 0, &size, layout);
468 if (result != noErr) 476 if (result != noErr) {
477 OSSTATUS_LOG(ERROR, result) << "Failed to get property (2)... ";
469 return false; 478 return false;
479 }
470 480
471 // We don't want to have to know about all channel layout tags, so force OSX 481 // We don't want to have to know about all channel layout tags, so force OSX
472 // to give us the channel descriptions from the bitmap or tag if necessary. 482 // to give us the channel descriptions from the bitmap or tag if necessary.
473 const AudioChannelLayoutTag tag = layout->mChannelLayoutTag; 483 const AudioChannelLayoutTag tag = layout->mChannelLayoutTag;
474 if (tag != kAudioChannelLayoutTag_UseChannelDescriptions) { 484 if (tag != kAudioChannelLayoutTag_UseChannelDescriptions) {
475 const bool is_bitmap = tag == kAudioChannelLayoutTag_UseChannelBitmap; 485 const bool is_bitmap = tag == kAudioChannelLayoutTag_UseChannelBitmap;
476 const AudioFormatPropertyID fa = 486 const AudioFormatPropertyID fa =
477 is_bitmap ? kAudioFormatProperty_ChannelLayoutForBitmap 487 is_bitmap ? kAudioFormatProperty_ChannelLayoutForBitmap
478 : kAudioFormatProperty_ChannelLayoutForTag; 488 : kAudioFormatProperty_ChannelLayoutForTag;
479 489
480 if (is_bitmap) { 490 if (is_bitmap) {
481 result = AudioFormatGetPropertyInfo(fa, sizeof(UInt32), 491 result = AudioFormatGetPropertyInfo(fa, sizeof(UInt32),
482 &layout->mChannelBitmap, &size); 492 &layout->mChannelBitmap, &size);
483 } else { 493 } else {
484 result = AudioFormatGetPropertyInfo(fa, sizeof(AudioChannelLayoutTag), 494 result = AudioFormatGetPropertyInfo(fa, sizeof(AudioChannelLayoutTag),
485 &tag, &size); 495 &tag, &size);
486 } 496 }
487 if (result != noErr || !size) 497 if (result != noErr || !size) {
498 OSSTATUS_LOG(ERROR, result) << "Failed to get af info... " << size;
488 return false; 499 return false;
500 }
489 501
490 layout_storage.reset(new uint8_t[size]); 502 layout_storage.reset(new uint8_t[size]);
491 layout = reinterpret_cast<AudioChannelLayout*>(layout_storage.get()); 503 layout = reinterpret_cast<AudioChannelLayout*>(layout_storage.get());
492 if (is_bitmap) { 504 if (is_bitmap) {
493 result = AudioFormatGetProperty(fa, sizeof(UInt32), 505 result = AudioFormatGetProperty(fa, sizeof(UInt32),
494 &layout->mChannelBitmap, &size, layout); 506 &layout->mChannelBitmap, &size, layout);
495 } else { 507 } else {
496 result = AudioFormatGetProperty(fa, sizeof(AudioChannelLayoutTag), &tag, 508 result = AudioFormatGetProperty(fa, sizeof(AudioChannelLayoutTag), &tag,
497 &size, layout); 509 &size, layout);
498 } 510 }
499 if (result != noErr) 511 if (result != noErr) {
512 OSSTATUS_LOG(ERROR, result) << "Failed to get af structure... ";
500 return false; 513 return false;
501 }
502
503 // There is no channel info for stereo, assume so for mono as well.
504 if (layout->mNumberChannelDescriptions <= 2) {
505 *channels = layout->mNumberChannelDescriptions;
506 } else {
507 *channels = 0;
508 for (UInt32 i = 0; i < layout->mNumberChannelDescriptions; ++i) {
509 if (layout->mChannelDescriptions[i].mChannelLabel !=
510 kAudioChannelLabel_Unknown)
511 (*channels)++;
512 } 514 }
513 } 515 }
514 516
515 // If we still don't have a channel count, fall back to total channel count. 517 bool is_au_based_retry = false;
516 if (*channels == 0) { 518 do {
517 DLOG(WARNING) << "Unable to use channel layout for channel count."; 519 // There is no channel info for stereo, assume so for mono as well.
518 *channels = total_channel_count; 520 if (layout->mNumberChannelDescriptions <= 2) {
519 } 521 *channels = layout->mNumberChannelDescriptions;
522 } else {
523 *channels = 0;
524 for (UInt32 i = 0; i < layout->mNumberChannelDescriptions; ++i) {
525 if (layout->mChannelDescriptions[i].mChannelLabel !=
526 kAudioChannelLabel_Unknown)
527 (*channels)++;
528 }
529 }
520 530
521 DVLOG(1) << (scope == kAudioDevicePropertyScopeInput ? "Input" : "Output") 531 // If we still don't have a channel count, fall back to total channel count.
522 << " channels: " << *channels; 532 if (*channels == 0 && !is_au_based_retry) {
533 is_au_based_retry = true;
534
535 const AudioUnitScope au_scope =
536 scope == kAudioDevicePropertyScopeOutput ? 0 : 1;
537
538 LOG(ERROR)
539 << "Unable to use channel layout for channel count, trying AU.";
540
541 AudioComponentDescription desc = {kAudioUnitType_Output,
542 kAudioUnitSubType_HALOutput,
543 kAudioUnitManufacturer_Apple, 0, 0};
544 AudioComponent comp = AudioComponentFindNext(0, &desc);
545 if (!comp) {
546 LOG(ERROR) << "Failed to find component.";
547 return false;
548 }
549
550 AudioUnit audio_unit;
551 result = AudioComponentInstanceNew(comp, &audio_unit);
552 if (result != noErr) {
553 OSSTATUS_LOG(ERROR, result) << "AudioComponentInstanceNew() failed.";
554 return false;
555 }
556
557 Boolean writable;
558 result = AudioUnitGetPropertyInfo(
559 audio_unit, kAudioUnitProperty_AudioChannelLayout,
560 kAudioUnitScope_Output, au_scope, &size, &writable);
561 if (result != noErr) {
562 OSSTATUS_LOG(ERROR, result) << "AudioUnitGetPropertyInfo() failed.";
563 return false;
564 }
565
566 layout_storage.reset(new uint8_t[size]);
567 layout = reinterpret_cast<AudioChannelLayout*>(layout_storage.get());
568
569 result = AudioUnitGetProperty(
570 audio_unit, kAudioUnitProperty_AudioChannelLayout,
571 kAudioUnitScope_Output, au_scope, layout, &size);
572 if (result != noErr) {
573 OSSTATUS_LOG(ERROR, result) << "AudioUnitGetProperty() failed.";
574 return false;
575 }
576
577 result = AudioUnitUninitialize(audio_unit);
578 OSSTATUS_LOG_IF(ERROR, result != noErr, result)
579 << "AudioUnitUninitialize() failed.";
580 result = AudioComponentInstanceDispose(audio_unit);
581 OSSTATUS_LOG_IF(ERROR, result != noErr, result)
582 << "AudioComponentInstanceDispose() failed.";
583 }
584 } while (*channels == 0 && is_au_based_retry);
585
586 LOG(ERROR) << (scope == kAudioDevicePropertyScopeInput ? "Input" : "Output")
587 << " channels: " << *channels;
523 return true; 588 return true;
524 } 589 }
525 590
526 // static 591 // static
527 int AudioManagerMac::HardwareSampleRateForDevice(AudioDeviceID device_id) { 592 int AudioManagerMac::HardwareSampleRateForDevice(AudioDeviceID device_id) {
528 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 593 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
529 Float64 nominal_sample_rate; 594 Float64 nominal_sample_rate;
530 UInt32 info_size = sizeof(nominal_sample_rate); 595 UInt32 info_size = sizeof(nominal_sample_rate);
531 596
532 static const AudioObjectPropertyAddress kNominalSampleRateAddress = { 597 static const AudioObjectPropertyAddress kNominalSampleRateAddress = {
(...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after
1168 ScopedAudioManagerPtr CreateAudioManager( 1233 ScopedAudioManagerPtr CreateAudioManager(
1169 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 1234 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
1170 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, 1235 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
1171 AudioLogFactory* audio_log_factory) { 1236 AudioLogFactory* audio_log_factory) {
1172 return ScopedAudioManagerPtr( 1237 return ScopedAudioManagerPtr(
1173 new AudioManagerMac(std::move(task_runner), std::move(worker_task_runner), 1238 new AudioManagerMac(std::move(task_runner), std::move(worker_task_runner),
1174 audio_log_factory)); 1239 audio_log_factory));
1175 } 1240 }
1176 1241
1177 } // namespace media 1242 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/mac/audio_low_latency_input_mac_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698