osxaudio: Always expose max amount of channels with no positions

For outputs with a high number of channels, macOS has a bug where
initially CoreAudio will report incorrect positions for all channels,
but after you run Audio MIDI Setup and configure the speaker layout
there, macOS will always report those few as positioned, with no option
to revert that (other than deleting some internal files).

In such scenario our code would just ignore all the unpositioned
channels. Since you can only position max. 16 channels in macOS, if you
had more on your output device, those would be unusable.

This commit makes sure that in addition to the usual positioned layout
(if there is one), we will expose caps for a no-positions layout that
always has the maximum amount of channels available.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8311>
This commit is contained in:
Piotr Brzeziński 2025-01-27 16:38:38 +01:00 committed by GStreamer Marge Bot
parent c5c5327df6
commit a88eda66d2

View file

@ -866,7 +866,7 @@ gst_core_audio_get_channel_layout (GstCoreAudio * core_audio, gboolean outer)
GstCaps * GstCaps *
gst_core_audio_probe_caps (GstCoreAudio * core_audio, GstCaps * in_caps) gst_core_audio_probe_caps (GstCoreAudio * core_audio, GstCaps * in_caps)
{ {
guint i, channels; guint i, channels, channels_max = 0;
gboolean spdif_allowed; gboolean spdif_allowed;
AudioChannelLayout *layout; AudioChannelLayout *layout;
AudioStreamBasicDescription outer_asbd; AudioStreamBasicDescription outer_asbd;
@ -898,6 +898,17 @@ gst_core_audio_probe_caps (GstCoreAudio * core_audio, GstCaps * in_caps)
channel_mask = 0; channel_mask = 0;
} }
if (channel_mask != 0 && channels > 2 &&
layout->mChannelLayoutTag ==
kAudioChannelLayoutTag_UseChannelDescriptions) {
/* CoreAudio gave us a positioned layout, which might mean we're ignoring some unpositioned channels.
* For example, with a 64ch output, macOS only allows assigning positions to 16 channels at most.
* Let's make sure we also expose the actual maximum amount of channels in our caps,
* without any positions assigned. */
channels_max =
MIN (layout->mNumberChannelDescriptions, GST_OSX_AUDIO_MAX_CHANNEL);
}
/* If available, start with the preferred caps. */ /* If available, start with the preferred caps. */
if (got_outer_asbd) if (got_outer_asbd)
caps = gst_core_audio_asbd_to_caps (&outer_asbd, layout); caps = gst_core_audio_asbd_to_caps (&outer_asbd, layout);
@ -982,7 +993,17 @@ gst_core_audio_probe_caps (GstCoreAudio * core_audio, GstCaps * in_caps)
gst_caps_append_structure (caps, out_s); gst_caps_append_structure (caps, out_s);
gst_caps_append_structure (caps, mono); gst_caps_append_structure (caps, mono);
} else { } else {
/* Otherwise just add the caps */ /* Otherwise, if needed, add an unpositioned max-channels variant ... */
if (channels_max > 0) {
GstStructure *unpos_s = gst_structure_copy (in_s);
gst_structure_set (unpos_s, "channels", G_TYPE_INT, channels_max,
NULL);
gst_structure_set (unpos_s, "channel-mask", GST_TYPE_BITMASK, 0,
NULL);
gst_caps_append_structure (caps, unpos_s);
}
/* ... and just add the caps */
gst_caps_append_structure (caps, out_s); gst_caps_append_structure (caps, out_s);
} }
} }