summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_coreaudio_chmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/out/ao_coreaudio_chmap.c')
-rw-r--r--audio/out/ao_coreaudio_chmap.c232
1 files changed, 206 insertions, 26 deletions
diff --git a/audio/out/ao_coreaudio_chmap.c b/audio/out/ao_coreaudio_chmap.c
index 13ac87e2ba..b45cf7799c 100644
--- a/audio/out/ao_coreaudio_chmap.c
+++ b/audio/out/ao_coreaudio_chmap.c
@@ -15,11 +15,14 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <Availability.h>
+
#include "common/common.h"
#include "ao_coreaudio_utils.h"
#include "ao_coreaudio_chmap.h"
+#include <CoreAudioTypes/CoreAudioTypes.h>
static const int speaker_map[][2] = {
{ kAudioChannelLabel_Left, MP_SPEAKER_ID_FL },
@@ -47,6 +50,13 @@ static const int speaker_map[][2] = {
{ kAudioChannelLabel_LeftWide, MP_SPEAKER_ID_WL },
{ kAudioChannelLabel_RightWide, MP_SPEAKER_ID_WR },
{ kAudioChannelLabel_LFE2, MP_SPEAKER_ID_LFE2 },
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 130000
+ { kAudioChannelLabel_LeftTopSurround, MP_SPEAKER_ID_TSL },
+ { kAudioChannelLabel_RightTopSurround, MP_SPEAKER_ID_TSR },
+ { kAudioChannelLabel_CenterBottom, MP_SPEAKER_ID_BFC },
+ { kAudioChannelLabel_LeftBottom, MP_SPEAKER_ID_BFL },
+ { kAudioChannelLabel_RightBottom, MP_SPEAKER_ID_BFR },
+#endif
{ kAudioChannelLabel_HeadphonesLeft, MP_SPEAKER_ID_DL },
{ kAudioChannelLabel_HeadphonesRight, MP_SPEAKER_ID_DR },
@@ -56,6 +66,119 @@ static const int speaker_map[][2] = {
{ 0, -1 },
};
+static const AudioChannelLayoutTag std_layouts[] = {
+ (100U<<16) | 1, // kAudioChannelLayoutTag_Mono
+ (101U<<16) | 2, // kAudioChannelLayoutTag_Stereo
+ (102U<<16) | 2, // kAudioChannelLayoutTag_StereoHeadphones
+ (103U<<16) | 2, // kAudioChannelLayoutTag_MatrixStereo
+ (104U<<16) | 2, // kAudioChannelLayoutTag_MidSide
+ (105U<<16) | 2, // kAudioChannelLayoutTag_XY
+ (106U<<16) | 2, // kAudioChannelLayoutTag_Binaural
+ (107U<<16) | 4, // kAudioChannelLayoutTag_Ambisonic_B_Format
+ (108U<<16) | 4, // kAudioChannelLayoutTag_Quadraphonic
+ (109U<<16) | 5, // kAudioChannelLayoutTag_Pentagonal
+ (110U<<16) | 6, // kAudioChannelLayoutTag_Hexagonal
+ (111U<<16) | 8, // kAudioChannelLayoutTag_Octagonal
+ (112U<<16) | 8, // kAudioChannelLayoutTag_Cube
+ (113U<<16) | 3, // kAudioChannelLayoutTag_MPEG_3_0_A
+ (114U<<16) | 3, // kAudioChannelLayoutTag_MPEG_3_0_B
+ (115U<<16) | 4, // kAudioChannelLayoutTag_MPEG_4_0_A
+ (116U<<16) | 4, // kAudioChannelLayoutTag_MPEG_4_0_B
+ (117U<<16) | 5, // kAudioChannelLayoutTag_MPEG_5_0_A
+ (118U<<16) | 5, // kAudioChannelLayoutTag_MPEG_5_0_B
+ (119U<<16) | 5, // kAudioChannelLayoutTag_MPEG_5_0_C
+ (120U<<16) | 5, // kAudioChannelLayoutTag_MPEG_5_0_D
+ (121U<<16) | 6, // kAudioChannelLayoutTag_MPEG_5_1_A
+ (122U<<16) | 6, // kAudioChannelLayoutTag_MPEG_5_1_B
+ (123U<<16) | 6, // kAudioChannelLayoutTag_MPEG_5_1_C
+ (124U<<16) | 6, // kAudioChannelLayoutTag_MPEG_5_1_D
+ (125U<<16) | 7, // kAudioChannelLayoutTag_MPEG_6_1_A
+ (126U<<16) | 8, // kAudioChannelLayoutTag_MPEG_7_1_A
+ (127U<<16) | 8, // kAudioChannelLayoutTag_MPEG_7_1_B
+ (128U<<16) | 8, // kAudioChannelLayoutTag_MPEG_7_1_C
+ (129U<<16) | 8, // kAudioChannelLayoutTag_Emagic_Default_7_1
+ (130U<<16) | 8, // kAudioChannelLayoutTag_SMPTE_DTV
+ (131U<<16) | 3, // kAudioChannelLayoutTag_ITU_2_1
+ (132U<<16) | 4, // kAudioChannelLayoutTag_ITU_2_2
+ (133U<<16) | 3, // kAudioChannelLayoutTag_DVD_4
+ (134U<<16) | 4, // kAudioChannelLayoutTag_DVD_5
+ (135U<<16) | 5, // kAudioChannelLayoutTag_DVD_6
+ (136U<<16) | 4, // kAudioChannelLayoutTag_DVD_10
+ (137U<<16) | 5, // kAudioChannelLayoutTag_DVD_11
+ (138U<<16) | 5, // kAudioChannelLayoutTag_DVD_18
+ (139U<<16) | 6, // kAudioChannelLayoutTag_AudioUnit_6_0
+ (140U<<16) | 7, // kAudioChannelLayoutTag_AudioUnit_7_0
+ (148U<<16) | 7, // kAudioChannelLayoutTag_AudioUnit_7_0_Front
+ (141U<<16) | 6, // kAudioChannelLayoutTag_AAC_6_0
+ (142U<<16) | 7, // kAudioChannelLayoutTag_AAC_6_1
+ (143U<<16) | 7, // kAudioChannelLayoutTag_AAC_7_0
+ (183U<<16) | 8, // kAudioChannelLayoutTag_AAC_7_1_B
+ (184U<<16) | 8, // kAudioChannelLayoutTag_AAC_7_1_C
+ (144U<<16) | 8, // kAudioChannelLayoutTag_AAC_Octagonal
+ (145U<<16) | 16, // kAudioChannelLayoutTag_TMH_10_2_std
+ (146U<<16) | 21, // kAudioChannelLayoutTag_TMH_10_2_full
+ (149U<<16) | 2, // kAudioChannelLayoutTag_AC3_1_0_1
+ (150U<<16) | 3, // kAudioChannelLayoutTag_AC3_3_0
+ (151U<<16) | 4, // kAudioChannelLayoutTag_AC3_3_1
+ (152U<<16) | 4, // kAudioChannelLayoutTag_AC3_3_0_1
+ (153U<<16) | 4, // kAudioChannelLayoutTag_AC3_2_1_1
+ (154U<<16) | 5, // kAudioChannelLayoutTag_AC3_3_1_1
+ (155U<<16) | 6, // kAudioChannelLayoutTag_EAC_6_0_A
+ (156U<<16) | 7, // kAudioChannelLayoutTag_EAC_7_0_A
+ (157U<<16) | 7, // kAudioChannelLayoutTag_EAC3_6_1_A
+ (158U<<16) | 7, // kAudioChannelLayoutTag_EAC3_6_1_B
+ (159U<<16) | 7, // kAudioChannelLayoutTag_EAC3_6_1_C
+ (160U<<16) | 8, // kAudioChannelLayoutTag_EAC3_7_1_A
+ (161U<<16) | 8, // kAudioChannelLayoutTag_EAC3_7_1_B
+ (162U<<16) | 8, // kAudioChannelLayoutTag_EAC3_7_1_C
+ (163U<<16) | 8, // kAudioChannelLayoutTag_EAC3_7_1_D
+ (164U<<16) | 8, // kAudioChannelLayoutTag_EAC3_7_1_E
+ (165U<<16) | 8, // kAudioChannelLayoutTag_EAC3_7_1_F
+ (166U<<16) | 8, // kAudioChannelLayoutTag_EAC3_7_1_G
+ (167U<<16) | 8, // kAudioChannelLayoutTag_EAC3_7_1_H
+ (168U<<16) | 4, // kAudioChannelLayoutTag_DTS_3_1
+ (169U<<16) | 5, // kAudioChannelLayoutTag_DTS_4_1
+ (170U<<16) | 6, // kAudioChannelLayoutTag_DTS_6_0_A
+ (171U<<16) | 6, // kAudioChannelLayoutTag_DTS_6_0_B
+ (172U<<16) | 6, // kAudioChannelLayoutTag_DTS_6_0_C
+ (173U<<16) | 7, // kAudioChannelLayoutTag_DTS_6_1_A
+ (174U<<16) | 7, // kAudioChannelLayoutTag_DTS_6_1_B
+ (175U<<16) | 7, // kAudioChannelLayoutTag_DTS_6_1_C
+ (176U<<16) | 7, // kAudioChannelLayoutTag_DTS_7_0
+ (177U<<16) | 8, // kAudioChannelLayoutTag_DTS_7_1
+ (178U<<16) | 8, // kAudioChannelLayoutTag_DTS_8_0_A
+ (179U<<16) | 8, // kAudioChannelLayoutTag_DTS_8_0_B
+ (180U<<16) | 9, // kAudioChannelLayoutTag_DTS_8_1_A
+ (181U<<16) | 9, // kAudioChannelLayoutTag_DTS_8_1_B
+ (182U<<16) | 7, // kAudioChannelLayoutTag_DTS_6_1_D
+ (185U<<16) | 4, // kAudioChannelLayoutTag_WAVE_4_0_B
+ (186U<<16) | 5, // kAudioChannelLayoutTag_WAVE_5_0_B
+ (187U<<16) | 6, // kAudioChannelLayoutTag_WAVE_5_1_B
+ (188U<<16) | 7, // kAudioChannelLayoutTag_WAVE_6_1
+ (189U<<16) | 8, // kAudioChannelLayoutTag_WAVE_7_1
+ (194U<<16) | 8, // kAudioChannelLayoutTag_Atmos_5_1_2
+ (195U<<16) | 10, // kAudioChannelLayoutTag_Atmos_5_1_4
+ (196U<<16) | 10, // kAudioChannelLayoutTag_Atmos_7_1_2
+ (192U<<16) | 12, // kAudioChannelLayoutTag_Atmos_7_1_4
+ (193U<<16) | 16, // kAudioChannelLayoutTag_Atmos_9_1_6
+ (197U<<16) | 4, // kAudioChannelLayoutTag_Logic_4_0_C
+ (198U<<16) | 6, // kAudioChannelLayoutTag_Logic_6_0_B
+ (199U<<16) | 7, // kAudioChannelLayoutTag_Logic_6_1_B
+ (200U<<16) | 7, // kAudioChannelLayoutTag_Logic_6_1_D
+ (201U<<16) | 8, // kAudioChannelLayoutTag_Logic_7_1_B
+ (202U<<16) | 12, // kAudioChannelLayoutTag_Logic_Atmos_7_1_4_B
+ (203U<<16) | 14, // kAudioChannelLayoutTag_Logic_Atmos_7_1_6
+ (204U<<16) | 24, // kAudioChannelLayoutTag_CICP_13
+ (205U<<16) | 8, // kAudioChannelLayoutTag_CICP_14
+ (206U<<16) | 12, // kAudioChannelLayoutTag_CICP_15
+ (207U<<16) | 10, // kAudioChannelLayoutTag_CICP_16
+ (208U<<16) | 12, // kAudioChannelLayoutTag_CICP_17
+ (209U<<16) | 14, // kAudioChannelLayoutTag_CICP_18
+ (210U<<16) | 12, // kAudioChannelLayoutTag_CICP_19
+ (211U<<16) | 14, // kAudioChannelLayoutTag_CICP_20
+ kAudioChannelLayoutTag_Unknown
+};
+
int ca_label_to_mp_speaker_id(AudioChannelLabel label)
{
for (int i = 0; speaker_map[i][1] >= 0; i++)
@@ -64,30 +187,48 @@ int ca_label_to_mp_speaker_id(AudioChannelLabel label)
return -1;
}
-#if HAVE_COREAUDIO
-static void ca_log_layout(struct ao *ao, int l, AudioChannelLayout *layout)
+AudioChannelLabel mp_speaker_id_to_ca_label(int speaker_id)
+{
+ for (int i = 0; speaker_map[i][1] >= 0; i++)
+ if (speaker_map[i][1] == speaker_id)
+ return speaker_map[i][0];
+ return -1; // kAudioChannelLabel_Unknown
+}
+
+#if HAVE_COREAUDIO || HAVE_AVFOUNDATION
+void ca_log_layout(struct ao *ao, int l, AudioChannelLayout *layout)
{
if (!mp_msg_test(ao->log, l))
return;
- AudioChannelDescription *descs = layout->mChannelDescriptions;
-
- mp_msg(ao->log, l, "layout: tag: <%u>, bitmap: <%u>, "
- "descriptions <%u>\n",
- (unsigned) layout->mChannelLayoutTag,
- (unsigned) layout->mChannelBitmap,
- (unsigned) layout->mNumberChannelDescriptions);
-
- for (int i = 0; i < layout->mNumberChannelDescriptions; i++) {
- AudioChannelDescription d = descs[i];
- mp_msg(ao->log, l, " - description %d: label <%u, %u>, "
- " flags: <%u>, coords: <%f, %f, %f>\n", i,
- (unsigned) d.mChannelLabel,
- (unsigned) ca_label_to_mp_speaker_id(d.mChannelLabel),
- (unsigned) d.mChannelFlags,
- d.mCoordinates[0],
- d.mCoordinates[1],
- d.mCoordinates[2]);
+ AudioChannelLayoutTag tag = layout->mChannelLayoutTag;
+ mp_msg(ao->log, l, "audio channel layout: tag: <%u>", tag);
+
+ if (tag == kAudioChannelLayoutTag_UseChannelDescriptions) {
+ AudioChannelDescription *descs = layout->mChannelDescriptions;
+ mp_msg(ao->log, l, ", descriptions <%u>\n",
+ (unsigned) layout->mNumberChannelDescriptions);
+
+ for (int i = 0; i < layout->mNumberChannelDescriptions; i++) {
+ AudioChannelDescription d = descs[i];
+ mp_msg(ao->log, l, " - description %d: label <%u, %u>, flags: <%u>",
+ i,
+ (unsigned) d.mChannelLabel,
+ (unsigned) ca_label_to_mp_speaker_id(d.mChannelLabel),
+ (unsigned) d.mChannelFlags);
+ if (d.mChannelFlags != kAudioChannelFlags_AllOff) {
+ mp_msg(ao->log, l, ", coords: <%f, %f, %f>\n",
+ d.mCoordinates[0],
+ d.mCoordinates[1],
+ d.mCoordinates[2]);
+ } else {
+ mp_msg(ao->log, l, "\n");
+ }
+ }
+ } else if (tag == kAudioChannelLayoutTag_UseChannelBitmap) {
+ mp_msg(ao->log, l, ", bitmap <%u>\n", layout->mChannelBitmap);
+ } else {
+ mp_msg(ao->log, l, "\n");
}
}
@@ -108,7 +249,7 @@ static AudioChannelLayout *ca_layout_to_custom_layout(struct ao *ao,
kAudioFormatProperty_ChannelLayoutForBitmap,
sizeof(uint32_t), &l->mChannelBitmap, &psize);
CHECK_CA_ERROR("failed to convert channel bitmap to descriptions (info)");
- r = talloc_size(NULL, psize);
+ r = talloc_size(talloc_ctx, psize);
err = AudioFormatGetProperty(
kAudioFormatProperty_ChannelLayoutForBitmap,
sizeof(uint32_t), &l->mChannelBitmap, &psize, r);
@@ -118,7 +259,7 @@ static AudioChannelLayout *ca_layout_to_custom_layout(struct ao *ao,
err = AudioFormatGetPropertyInfo(
kAudioFormatProperty_ChannelLayoutForTag,
sizeof(AudioChannelLayoutTag), &l->mChannelLayoutTag, &psize);
- r = talloc_size(NULL, psize);
+ r = talloc_size(talloc_ctx, psize);
CHECK_CA_ERROR("failed to convert channel tag to descriptions (info)");
err = AudioFormatGetProperty(
kAudioFormatProperty_ChannelLayoutForTag,
@@ -126,14 +267,53 @@ static AudioChannelLayout *ca_layout_to_custom_layout(struct ao *ao,
CHECK_CA_ERROR("failed to convert channel tag to descriptions (get)");
}
- MP_VERBOSE(ao, "converted input channel layout:\n");
- ca_log_layout(ao, MSGL_V, l);
+ if (ao) {
+ MP_VERBOSE(ao, "converted input channel layout:\n");
+ ca_log_layout(ao, MSGL_V, l);
+ }
return r;
coreaudio_error:
return NULL;
}
+AudioChannelLayout *ca_find_standard_layout(void *talloc_ctx, AudioChannelLayout *l)
+{
+ if (l->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions)
+ return l;
+
+ AudioChannelLayout *s = talloc_size(talloc_ctx, sizeof(AudioChannelLayout));
+
+ for (int i = 0; ; ++i) {
+ if ((s->mChannelLayoutTag = std_layouts[i]) == kAudioChannelLayoutTag_Unknown) {
+ s = NULL;
+ break;
+ }
+
+ AudioChannelLayout *r = ca_layout_to_custom_layout(NULL, talloc_ctx, s);
+
+ if (!r)
+ goto mismatch;
+ if (l->mNumberChannelDescriptions != r->mNumberChannelDescriptions)
+ goto mismatch;
+
+ for (int i = 0; i < l->mNumberChannelDescriptions; ++i) {
+ AudioChannelDescription *ld = l->mChannelDescriptions + i;
+ AudioChannelDescription *rd = r->mChannelDescriptions + i;
+ if (ld->mChannelLabel == rd->mChannelLabel)
+ continue;
+ // XXX: we cannot handle channels with coordinates
+ goto mismatch;
+ }
+
+ break;
+
+mismatch:;
+ }
+
+ return s ? s : l;
+}
+
#define CHMAP(n, ...) &(struct mp_chmap) MP_CONCAT(MP_CHMAP, n) (__VA_ARGS__)
@@ -232,8 +412,8 @@ static AudioChannelLayout* ca_query_stereo_layout(struct ao *ao,
void *talloc_ctx)
{
OSStatus err;
- const int nch = 2;
- uint32_t channels[nch];
+ uint32_t channels[2];
+ const int nch = MP_ARRAY_SIZE(channels);
AudioChannelLayout *r = NULL;
AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) {