From a3019ffb63b1213cbad10abafa4e0ee9cd53c66b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 7 Jan 2016 18:26:26 +0000 Subject: [PATCH] aiffparse: fix negotiation errors with multi-channel files Set fallback channel layout on files with more than two channels. Not clear where to retrieve the real layout from or what the default layout is for AIFF files, the spec only seems to specify some layout for up to 6 channels and the file in question doesn't have a CHAN chunk. https://bugzilla.gnome.org/show_bug.cgi?id=676425 --- gst/aiff/aiffparse.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/gst/aiff/aiffparse.c b/gst/aiff/aiffparse.c index 7ca19c6eae..5600a7eb8c 100644 --- a/gst/aiff/aiffparse.c +++ b/gst/aiff/aiffparse.c @@ -816,11 +816,14 @@ too_small: } +#define _P(pos) (G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_ ##pos) + static GstCaps * gst_aiff_parse_create_caps (GstAiffParse * aiff) { GstCaps *caps = NULL; const gchar *format = NULL; + guint64 channel_mask; if (aiff->floating_point) { if (aiff->endianness == G_BIG_ENDIAN) { @@ -858,6 +861,44 @@ gst_aiff_parse_create_caps (GstAiffParse * aiff) "rate", G_TYPE_INT, aiff->rate, NULL); } + if (aiff->channels > 2) { + GST_FIXME_OBJECT (aiff, "using fallback channel layout for %d channels", + aiff->channels); + + /* based on AIFF-1.3.pdf */ + switch (aiff->channels) { + case 1: + channel_mask = 0; + break; + case 2: + channel_mask = _P (FRONT_LEFT) | _P (FRONT_RIGHT); + break; + case 3: + channel_mask = _P (FRONT_LEFT) | _P (FRONT_RIGHT) | _P (FRONT_CENTER); + break; + case 4: + /* lists both this and 'quad' but doesn't say how to distinguish the two */ + channel_mask = + _P (FRONT_LEFT) | _P (FRONT_RIGHT) | _P (REAR_LEFT) | + _P (REAR_RIGHT); + break; + case 6: + channel_mask = + _P (FRONT_LEFT) | _P (FRONT_LEFT_OF_CENTER) | _P (FRONT_CENTER) | + _P (FRONT_RIGHT) | _P (FRONT_RIGHT_OF_CENTER) | _P (LFE1); + break; + default: + channel_mask = gst_audio_channel_get_fallback_mask (aiff->channels); + break; + } + + + if (channel_mask != 0) { + gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask, + NULL); + } + } + GST_DEBUG_OBJECT (aiff, "Created caps: %" GST_PTR_FORMAT, caps); return caps; @@ -1050,6 +1091,11 @@ gst_aiff_parse_stream_headers (GstAiffParse * aiff) } break; } + case GST_MAKE_FOURCC ('C', 'H', 'A', 'N'):{ + GST_FIXME_OBJECT (aiff, "Handle CHAN chunk with channel layouts"); + gst_aiff_parse_ignore_chunk (aiff, tag, size); + break; + } default: gst_aiff_parse_ignore_chunk (aiff, tag, size); }