| 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/mac/audio_manager_mac.h" | 5 #include "media/audio/mac/audio_manager_mac.h" |
| 6 | 6 |
| 7 #include <CoreAudio/AudioHardware.h> | 7 #include <CoreAudio/AudioHardware.h> |
| 8 #include <string> | 8 #include <string> |
| 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/mac/mac_logging.h" | 12 #include "base/mac/mac_logging.h" |
| 13 #include "base/mac/scoped_cftyperef.h" | 13 #include "base/mac/scoped_cftyperef.h" |
| 14 #include "base/power_monitor/power_monitor.h" | 14 #include "base/power_monitor/power_monitor.h" |
| 15 #include "base/power_monitor/power_observer.h" | 15 #include "base/power_monitor/power_observer.h" |
| 16 #include "base/strings/sys_string_conversions.h" | 16 #include "base/strings/sys_string_conversions.h" |
| 17 #include "base/threading/thread_checker.h" | 17 #include "base/threading/thread_checker.h" |
| 18 #include "media/audio/audio_parameters.h" | 18 #include "media/audio/audio_parameters.h" |
| 19 #include "media/audio/mac/audio_auhal_mac.h" | 19 #include "media/audio/mac/audio_auhal_mac.h" |
| 20 #include "media/audio/mac/audio_input_mac.h" | 20 #include "media/audio/mac/audio_input_mac.h" |
| 21 #include "media/audio/mac/audio_low_latency_input_mac.h" | 21 #include "media/audio/mac/audio_low_latency_input_mac.h" |
| 22 #include "media/audio/mac/audio_low_latency_output_mac.h" | 22 #include "media/audio/mac/audio_low_latency_output_mac.h" |
| 23 #include "media/audio/mac/audio_synchronized_mac.h" | |
| 24 #include "media/audio/mac/audio_unified_mac.h" | |
| 25 #include "media/base/bind_to_current_loop.h" | 23 #include "media/base/bind_to_current_loop.h" |
| 26 #include "media/base/channel_layout.h" | 24 #include "media/base/channel_layout.h" |
| 27 #include "media/base/limits.h" | 25 #include "media/base/limits.h" |
| 28 #include "media/base/media_switches.h" | 26 #include "media/base/media_switches.h" |
| 29 | 27 |
| 30 namespace media { | 28 namespace media { |
| 31 | 29 |
| 32 // Maximum number of output streams that can be open simultaneously. | 30 // Maximum number of output streams that can be open simultaneously. |
| 33 static const int kMaxOutputStreams = 50; | 31 static const int kMaxOutputStreams = 50; |
| 34 | 32 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 49 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, | 47 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, |
| 50 &property_address, | 48 &property_address, |
| 51 0, // inQualifierDataSize | 49 0, // inQualifierDataSize |
| 52 NULL, // inQualifierData | 50 NULL, // inQualifierData |
| 53 &output_device_id_size, | 51 &output_device_id_size, |
| 54 &output_device_id); | 52 &output_device_id); |
| 55 return err == kAudioHardwareNoError && | 53 return err == kAudioHardwareNoError && |
| 56 output_device_id != kAudioObjectUnknown; | 54 output_device_id != kAudioObjectUnknown; |
| 57 } | 55 } |
| 58 | 56 |
| 59 // Returns true if the default input device is the same as | |
| 60 // the default output device. | |
| 61 bool AudioManagerMac::HasUnifiedDefaultIO() { | |
| 62 AudioDeviceID input_id, output_id; | |
| 63 if (!GetDefaultInputDevice(&input_id) || !GetDefaultOutputDevice(&output_id)) | |
| 64 return false; | |
| 65 | |
| 66 return input_id == output_id; | |
| 67 } | |
| 68 | |
| 69 // Retrieves information on audio devices, and prepends the default | 57 // Retrieves information on audio devices, and prepends the default |
| 70 // device to the list if the list is non-empty. | 58 // device to the list if the list is non-empty. |
| 71 static void GetAudioDeviceInfo(bool is_input, | 59 static void GetAudioDeviceInfo(bool is_input, |
| 72 media::AudioDeviceNames* device_names) { | 60 media::AudioDeviceNames* device_names) { |
| 73 // Query the number of total devices. | 61 // Query the number of total devices. |
| 74 AudioObjectPropertyAddress property_address = { | 62 AudioObjectPropertyAddress property_address = { |
| 75 kAudioHardwarePropertyDevices, | 63 kAudioHardwarePropertyDevices, |
| 76 kAudioObjectPropertyScopeGlobal, | 64 kAudioObjectPropertyScopeGlobal, |
| 77 kAudioObjectPropertyElementMaster | 65 kAudioObjectPropertyElementMaster |
| 78 }; | 66 }; |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 if (default_device == *iter) | 547 if (default_device == *iter) |
| 560 return *iter; | 548 return *iter; |
| 561 } | 549 } |
| 562 | 550 |
| 563 // Failed to figure out which is the matching device, return an emtpy string. | 551 // Failed to figure out which is the matching device, return an emtpy string. |
| 564 return std::string(); | 552 return std::string(); |
| 565 } | 553 } |
| 566 | 554 |
| 567 AudioOutputStream* AudioManagerMac::MakeLinearOutputStream( | 555 AudioOutputStream* AudioManagerMac::MakeLinearOutputStream( |
| 568 const AudioParameters& params) { | 556 const AudioParameters& params) { |
| 569 return MakeLowLatencyOutputStream(params, std::string(), std::string()); | 557 return MakeLowLatencyOutputStream(params, std::string()); |
| 570 } | 558 } |
| 571 | 559 |
| 572 AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream( | 560 AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream( |
| 573 const AudioParameters& params, | 561 const AudioParameters& params, |
| 574 const std::string& device_id, | 562 const std::string& device_id) { |
| 575 const std::string& input_device_id) { | 563 AudioDeviceID device = GetAudioDeviceIdByUId(false, device_id); |
| 576 // Handle basic output with no input channels. | 564 if (device == kAudioObjectUnknown) { |
| 577 if (params.input_channels() == 0) { | 565 DLOG(ERROR) << "Failed to open output device: " << device_id; |
| 578 AudioDeviceID device = GetAudioDeviceIdByUId(false, device_id); | |
| 579 if (device == kAudioObjectUnknown) { | |
| 580 DLOG(ERROR) << "Failed to open output device: " << device_id; | |
| 581 return NULL; | |
| 582 } | |
| 583 return new AUHALStream(this, params, device); | |
| 584 } | |
| 585 | |
| 586 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; | |
| 587 | |
| 588 // TODO(xians): support more than stereo input. | |
| 589 if (params.input_channels() != 2) { | |
| 590 // WebAudio is currently hard-coded to 2 channels so we should not | |
| 591 // see this case. | |
| 592 NOTREACHED() << "Only stereo input is currently supported!"; | |
| 593 return NULL; | 566 return NULL; |
| 594 } | 567 } |
| 595 | 568 return new AUHALStream(this, params, device); |
| 596 AudioDeviceID device = kAudioObjectUnknown; | |
| 597 if (HasUnifiedDefaultIO()) { | |
| 598 // For I/O, the simplest case is when the default input and output | |
| 599 // devices are the same. | |
| 600 GetDefaultOutputDevice(&device); | |
| 601 VLOG(0) << "UNIFIED: default input and output devices are identical"; | |
| 602 } else { | |
| 603 // Some audio hardware is presented as separate input and output devices | |
| 604 // even though they are really the same physical hardware and | |
| 605 // share the same "clock domain" at the lowest levels of the driver. | |
| 606 // A common of example of this is the "built-in" audio hardware: | |
| 607 // "Built-in Line Input" | |
| 608 // "Built-in Output" | |
| 609 // We would like to use an "aggregate" device for these situations, since | |
| 610 // CoreAudio will make the most efficient use of the shared "clock domain" | |
| 611 // so we get the lowest latency and use fewer threads. | |
| 612 device = aggregate_device_manager_.GetDefaultAggregateDevice(); | |
| 613 if (device != kAudioObjectUnknown) | |
| 614 VLOG(0) << "Using AGGREGATE audio device"; | |
| 615 } | |
| 616 | |
| 617 if (device != kAudioObjectUnknown && | |
| 618 input_device_id == AudioManagerBase::kDefaultDeviceId) | |
| 619 return new AUHALStream(this, params, device); | |
| 620 | |
| 621 // Fallback to AudioSynchronizedStream which will handle completely | |
| 622 // different and arbitrary combinations of input and output devices | |
| 623 // even running at different sample-rates. | |
| 624 // kAudioDeviceUnknown translates to "use default" here. | |
| 625 // TODO(xians): consider tracking UMA stats on AUHALStream | |
| 626 // versus AudioSynchronizedStream. | |
| 627 AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, input_device_id); | |
| 628 if (audio_device_id == kAudioObjectUnknown) | |
| 629 return NULL; | |
| 630 | |
| 631 return new AudioSynchronizedStream(this, | |
| 632 params, | |
| 633 audio_device_id, | |
| 634 kAudioDeviceUnknown); | |
| 635 } | 569 } |
| 636 | 570 |
| 637 std::string AudioManagerMac::GetDefaultOutputDeviceID() { | 571 std::string AudioManagerMac::GetDefaultOutputDeviceID() { |
| 638 AudioDeviceID device_id = kAudioObjectUnknown; | 572 AudioDeviceID device_id = kAudioObjectUnknown; |
| 639 if (!GetDefaultOutputDevice(&device_id)) | 573 if (!GetDefaultOutputDevice(&device_id)) |
| 640 return std::string(); | 574 return std::string(); |
| 641 | 575 |
| 642 const AudioObjectPropertyAddress property_address = { | 576 const AudioObjectPropertyAddress property_address = { |
| 643 kAudioDevicePropertyDeviceUID, | 577 kAudioDevicePropertyDeviceUID, |
| 644 kAudioObjectPropertyScopeGlobal, | 578 kAudioObjectPropertyScopeGlobal, |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 bool AudioManagerMac::ShouldDeferOutputStreamStart() { | 735 bool AudioManagerMac::ShouldDeferOutputStreamStart() { |
| 802 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 736 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 803 return power_observer_->ShouldDeferOutputStreamStart(); | 737 return power_observer_->ShouldDeferOutputStreamStart(); |
| 804 } | 738 } |
| 805 | 739 |
| 806 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { | 740 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { |
| 807 return new AudioManagerMac(audio_log_factory); | 741 return new AudioManagerMac(audio_log_factory); |
| 808 } | 742 } |
| 809 | 743 |
| 810 } // namespace media | 744 } // namespace media |
| OLD | NEW |