mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
305a85cc9a
commit
8121529a6c
|
@ -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).
|
||||
|
|
|
@ -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}
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue