summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-05-05 01:07:57 +0200
committerwm4 <wm4@nowhere>2015-05-05 01:11:16 +0200
commit8121529a6cc01a0d036c0a228e240c87994f1340 (patch)
tree856463a2649b80a47664de42eac80764fa90ac8d
parent305a85cc9aa169a75317acb55e539f49d420f629 (diff)
downloadmpv-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.rst8
-rw-r--r--audio/out/ao_coreaudio.c55
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}
+ },
};