diff options
author | wm4 <wm4@nowhere> | 2015-05-05 01:07:57 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-05-05 01:11:16 +0200 |
commit | 8121529a6cc01a0d036c0a228e240c87994f1340 (patch) | |
tree | 856463a2649b80a47664de42eac80764fa90ac8d | |
parent | 305a85cc9aa169a75317acb55e539f49d420f629 (diff) | |
download | mpv-8121529a6cc01a0d036c0a228e240c87994f1340.tar.bz2 mpv-8121529a6cc01a0d036c0a228e240c87994f1340.tar.xz |
ao_coreaudio: add an option for changing the physical format
ao_coreaudio uses AudioUnit - the OSX software mixer. In theory, it
supports multichannel audio just fine. But in practice, this might be
disabled by default, and the user is supposed to select a multichannel
base format in the "Audio MIDI Setup" utility.
This option attempts to change this setting automatically. Some possible
disadvantages and caveats are listed in the manpage additions. It is off
by default, since changing this might be rather bad behavior for a
normal application.
-rw-r--r-- | DOCS/man/ao.rst | 8 | ||||
-rw-r--r-- | audio/out/ao_coreaudio.c | 55 |
2 files changed, 63 insertions, 0 deletions
diff --git a/DOCS/man/ao.rst b/DOCS/man/ao.rst index 5103997e76..e02a5886ff 100644 --- a/DOCS/man/ao.rst +++ b/DOCS/man/ao.rst @@ -162,6 +162,14 @@ Available audio output drivers are: Automatically redirects to ``coreaudio_exclusive`` when playing compressed formats. + ``change-physical-format=<yes|no>`` + Change the physical format to one similar to the requested audio format + (default: no). This has the advantage that multichannel audio output + will actually work. The disadvantage is that it will change the + system-wide audio settings. This is equivalent to change the ``Format`` + setting in the ``Audio Devices`` dialog in the ``Audio MIDI Setup`` + utility. Note that this does not effect the selected speaker setup. + ``coreaudio_exclusive`` (Mac OS X only) Native Mac OS X audio output driver using direct device access and exclusive mode (bypasses the sound server). diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index 65f7a070fd..85057bee67 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -33,6 +33,8 @@ struct priv { AudioUnit audio_unit; uint64_t hw_latency_us; + + int change_physical_format; }; bool ca_layout_to_mp_chmap(struct ao *ao, AudioChannelLayout *layout, @@ -260,12 +262,61 @@ coreaudio_error: return false; } +static void init_physical_format(struct ao *ao, AudioStreamBasicDescription asbd) +{ + struct priv *p = ao->priv; + OSErr err; + + AudioStreamID *streams; + size_t n_streams; + + err = CA_GET_ARY_O(p->device, kAudioDevicePropertyStreams, + &streams, &n_streams); + CHECK_CA_ERROR("could not get number of streams"); + + for (int i = 0; i < n_streams; i++) { + AudioStreamRangedDescription *formats; + size_t n_formats; + + err = CA_GET_ARY(streams[i], + kAudioStreamPropertyAvailablePhysicalFormats, + &formats, &n_formats); + + if (!CHECK_CA_WARN("could not get number of stream formats")) + continue; // try next one + + AudioStreamBasicDescription best_asbd = {0}; + + for (int j = 0; j < n_formats; j++) { + AudioStreamBasicDescription *stream_asbd = &formats[j].mFormat; + + if (!best_asbd.mFormatID || ca_asbd_is_better(&asbd, &best_asbd, + stream_asbd)) + best_asbd = *stream_asbd; + } + + if (best_asbd.mFormatID) { + ca_print_asbd(ao, "Trying to set physical format:", &best_asbd); + err = CA_SET(streams[i], kAudioStreamPropertyPhysicalFormat, + &best_asbd); + CHECK_CA_ERROR("could not set physical format"); + break; + } + } + +coreaudio_error: + return; +} + static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd) { OSStatus err; uint32_t size; struct priv *p = ao->priv; + if (p->change_physical_format) + init_physical_format(ao, asbd); + AudioComponentDescription desc = (AudioComponentDescription) { .componentType = kAudioUnitType_Output, .componentSubType = (ao->device) ? @@ -583,4 +634,8 @@ const struct ao_driver audio_out_coreaudio = { .hotplug_uninit = hotplug_uninit, .list_devs = ca_get_device_list, .priv_size = sizeof(struct priv), + .options = (const struct m_option[]){ + OPT_FLAG("change-physical-format", change_physical_format, 0), + {0} + }, }; |