riff: Return a channel reorder map for raw audio when creating the caps

This commit is contained in:
Sebastian Dröge 2011-12-31 14:15:41 +01:00
parent 7cd0659032
commit c52b50a517
2 changed files with 70 additions and 39 deletions

View file

@ -964,17 +964,19 @@ static const struct
#define MAX_CHANNEL_POSITIONS G_N_ELEMENTS (layout_mapping)
static gboolean
gst_riff_wavext_add_channel_mask (GstCaps * caps, guint32 layout)
gst_riff_wavext_add_channel_mask (GstCaps * caps, guint32 layout,
gint channel_reorder_map[18])
{
GstStructure *s;
gint num_channels, i, p;
guint64 channel_mask = 0;
GstAudioChannelPosition from[18], to[18];
s = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (s, "channels", &num_channels))
g_return_val_if_reached (FALSE);
if (num_channels < 2 || num_channels > MAX_CHANNEL_POSITIONS) {
if (num_channels < 1 || num_channels > MAX_CHANNEL_POSITIONS) {
GST_DEBUG ("invalid number of channels: %d", num_channels);
return FALSE;
}
@ -994,6 +996,7 @@ gst_riff_wavext_add_channel_mask (GstCaps * caps, guint32 layout)
* layout that has INVALID positions in it for now ... */
}
channel_mask |= G_GUINT64_CONSTANT (1) << layout_mapping[i].gst_pos;
from[p] = layout_mapping[i].gst_pos;
++p;
}
}
@ -1004,6 +1007,15 @@ gst_riff_wavext_add_channel_mask (GstCaps * caps, guint32 layout)
return FALSE;
}
if (channel_reorder_map) {
memcpy (to, from, sizeof (from[0]) * num_channels);
if (!gst_audio_channel_positions_to_valid_order (to, num_channels))
return FALSE;
if (!gst_audio_get_channel_reorder_map (num_channels, from, to,
channel_reorder_map))
return FALSE;
}
gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask,
NULL);
@ -1011,11 +1023,22 @@ gst_riff_wavext_add_channel_mask (GstCaps * caps, guint32 layout)
}
static gboolean
gst_riff_wave_add_default_channel_mask (GstCaps * caps)
gst_riff_wave_add_default_channel_mask (GstCaps * caps,
gint channel_reorder_map[18])
{
GstStructure *s;
gint nchannels;
guint64 channel_mask = 0;
static const gint reorder_maps[8][11] = {
{0,},
{0, 1},
{-1, -1, -1},
{0, 1, 2, 3},
{0, 1, 3, 4, 2},
{0, 1, 4, 5, 2, 3},
{-1, -1, -1, -1, -1, -1, -1},
{0, 1, 4, 5, 2, 3, 6, 7}
};
s = gst_caps_get_structure (caps, 0);
@ -1037,6 +1060,8 @@ gst_riff_wave_add_default_channel_mask (GstCaps * caps)
switch (nchannels) {
case 1:
/* Mono => nothing */
if (channel_reorder_map)
channel_reorder_map[0] = 0;
return TRUE;
case 8:
channel_mask |=
@ -1067,6 +1092,10 @@ gst_riff_wave_add_default_channel_mask (GstCaps * caps)
return FALSE;
}
if (channel_reorder_map)
memcpy (channel_reorder_map, reorder_maps[nchannels],
sizeof (gint) * nchannels);
gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask,
NULL);
@ -1109,12 +1138,17 @@ gst_riff_wavext_get_default_channel_mask (guint nchannels)
GstCaps *
gst_riff_create_audio_caps (guint16 codec_id,
gst_riff_strh * strh, gst_riff_strf_auds * strf,
GstBuffer * strf_data, GstBuffer * strd_data, char **codec_name)
GstBuffer * strf_data, GstBuffer * strd_data, char **codec_name,
gint channel_reorder_map[18])
{
gboolean block_align = FALSE, rate_chan = TRUE;
GstCaps *caps = NULL;
gint rate_min = 1000, rate_max = 96000;
gint channels_max = 2;
gint i;
for (i = 0; i < 18; i++)
channel_reorder_map[i] = -1;
switch (codec_id) {
case GST_RIFF_WAVE_FORMAT_PCM: /* PCM */
@ -1154,18 +1188,15 @@ gst_riff_create_audio_caps (guint16 codec_id,
"layout", G_TYPE_STRING, "interleaved",
"channels", G_TYPE_INT, ch, NULL);
/* Add default channel layout. In theory this should be done
* for 1 and 2 channels too but apparently breaks too many
* things currently. Also we know no default layout for more than
/* Add default channel layout. We know no default layout for more than
* 8 channels. */
if (ch > 2) {
if (ch > 8)
GST_WARNING ("don't know default layout for %d channels", ch);
else if (gst_riff_wave_add_default_channel_mask (caps))
GST_DEBUG ("using default channel layout for %d channels", ch);
else
GST_WARNING ("failed to add channel layout");
}
if (ch > 8)
GST_WARNING ("don't know default layout for %d channels", ch);
else if (gst_riff_wave_add_default_channel_mask (caps,
channel_reorder_map))
GST_DEBUG ("using default channel layout for %d channels", ch);
else
GST_WARNING ("failed to add channel layout");
} else {
/* FIXME: this is pretty useless - we need fixed caps */
caps = gst_caps_from_string ("audio/x-raw, "
@ -1199,18 +1230,15 @@ gst_riff_create_audio_caps (guint16 codec_id,
"layout", G_TYPE_STRING, "interleaved",
"channels", G_TYPE_INT, ch, NULL);
/* Add default channel layout. In theory this should be done
* for 1 and 2 channels too but apparently breaks too many
* things currently. Also we know no default layout for more than
/* Add default channel layout. We know no default layout for more than
* 8 channels. */
if (ch > 2) {
if (ch > 8)
GST_WARNING ("don't know default layout for %d channels", ch);
else if (gst_riff_wave_add_default_channel_mask (caps))
GST_DEBUG ("using default channel layout for %d channels", ch);
else
GST_WARNING ("failed to add channel layout");
}
if (ch > 8)
GST_WARNING ("don't know default layout for %d channels", ch);
else if (gst_riff_wave_add_default_channel_mask (caps,
channel_reorder_map))
GST_DEBUG ("using default channel layout for %d channels", ch);
else
GST_WARNING ("failed to add channel layout");
} else {
/* FIXME: this is pretty useless - we need fixed caps */
caps = gst_caps_from_string ("audio/x-raw, "
@ -1524,14 +1552,14 @@ gst_riff_create_audio_caps (guint16 codec_id,
/* If channel_mask == 0 and channels > 2 let's
* assume default layout as some wav files don't have the
* channel mask set. Don't set the layout for 1 or 2
* channels as it apparently breaks too many things currently. */
if (channel_mask == 0 && strf->channels > 2)
* channel mask set. Don't set the layout for 1 channel. */
if (channel_mask == 0 && strf->channels > 1)
channel_mask =
gst_riff_wavext_get_default_channel_mask (strf->channels);
if ((channel_mask != 0 || strf->channels > 2) &&
!gst_riff_wavext_add_channel_mask (caps, channel_mask)) {
if ((channel_mask != 0 || strf->channels > 1) &&
!gst_riff_wavext_add_channel_mask (caps, channel_mask,
channel_reorder_map)) {
GST_WARNING ("failed to add channel layout");
gst_caps_unref (caps);
caps = NULL;
@ -1555,16 +1583,16 @@ gst_riff_create_audio_caps (guint16 codec_id,
"channels", G_TYPE_INT, strf->channels,
"rate", G_TYPE_INT, strf->rate, NULL);
/* If channel_mask == 0 and channels > 2 let's
/* If channel_mask == 0 and channels > 1 let's
* assume default layout as some wav files don't have the
* channel mask set. Don't set the layout for 1 or 2
* channels as it apparently breaks too many things currently. */
if (channel_mask == 0 && strf->channels > 2)
* channel mask set. Don't set the layout for 1 channel. */
if (channel_mask == 0 && strf->channels > 1)
channel_mask =
gst_riff_wavext_get_default_channel_mask (strf->channels);
if ((channel_mask != 0 || strf->channels > 2) &&
!gst_riff_wavext_add_channel_mask (caps, channel_mask)) {
if ((channel_mask != 0 || strf->channels > 1) &&
!gst_riff_wavext_add_channel_mask (caps, channel_mask,
channel_reorder_map)) {
GST_WARNING ("failed to add channel layout");
gst_caps_unref (caps);
caps = NULL;
@ -1885,7 +1913,9 @@ gst_riff_create_audio_template_caps (void)
caps = gst_caps_new_empty ();
for (i = 0; i < G_N_ELEMENTS (tags); i++) {
one = gst_riff_create_audio_caps (tags[i], NULL, NULL, NULL, NULL, NULL);
one =
gst_riff_create_audio_caps (tags[i], NULL, NULL, NULL, NULL, NULL,
NULL);
if (one)
gst_caps_append (caps, one);
}

View file

@ -44,7 +44,8 @@ GstCaps * gst_riff_create_audio_caps (guint16 codec_id,
gst_riff_strf_auds * strf,
GstBuffer * strf_data,
GstBuffer * strd_data,
char ** codec_name);
char ** codec_name,
gint channel_reorder_map[18]);
GstCaps * gst_riff_create_iavs_caps (guint32 codec_fcc,
gst_riff_strh * strh,