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 |