gst-libs/gst/riff/riff-media.c: Use the ALSA channel layout as default for wav files without channel layout informati...

Original commit message from CVS:
* gst-libs/gst/riff/riff-media.c:
(gst_riff_wavext_add_channel_layout),
(gst_riff_wave_add_default_channel_layout),
(gst_riff_wavext_get_default_channel_mask),
(gst_riff_create_audio_caps):
Use the ALSA channel layout as default for wav files without channel
layout information. This fixes playback of chan-id.wav on 5.1 systems
for example. Also refactor the channel layout setting a bit and add
more default channel orders. Fixes #489010.
This commit is contained in:
Sebastian Dröge 2007-10-28 11:53:36 +00:00
parent c3d94683d9
commit a81de45df3
2 changed files with 122 additions and 89 deletions

View file

@ -1,5 +1,6 @@
2007-10-28 Sebastian Dröge <slomo@circular-chaos.org>
* gst-libs/gst/riff/riff-media.c:
(gst_riff_wavext_add_channel_layout),
(gst_riff_wave_add_default_channel_layout),
(gst_riff_wavext_get_default_channel_mask),

View file

@ -707,7 +707,10 @@ gst_riff_wavext_add_channel_layout (GstCaps * caps, guint32 layout)
if (!gst_structure_get_int (s, "channels", &num_channels))
g_return_val_if_reached (FALSE);
if (num_channels < 2 || num_channels > MAX_CHANNEL_POSITIONS) {
/* In theory this should be done for 1 and 2 channels too but
* apparently breaks too many things currently.
*/
if (num_channels <= 2 || num_channels > MAX_CHANNEL_POSITIONS) {
GST_DEBUG ("invalid number of channels: %d", num_channels);
return FALSE;
}
@ -741,6 +744,93 @@ gst_riff_wavext_add_channel_layout (GstCaps * caps, guint32 layout)
return TRUE;
}
static gboolean
gst_riff_wave_add_default_channel_layout (GstCaps * caps)
{
GstAudioChannelPosition pos[8] = { GST_AUDIO_CHANNEL_POSITION_NONE, };
GstStructure *s;
gint nchannels;
s = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (s, "channels", &nchannels))
g_return_val_if_reached (FALSE);
if (nchannels > 8) {
GST_DEBUG ("invalid number of channels: %d", nchannels);
return FALSE;
}
/* This uses the default channel mapping from ALSA which
* is used in quite a few surround test files and seems to be
* the defacto standard. The channel mapping from
* WAVE_FORMAT_EXTENSIBLE doesn't seem to be used in normal
* wav files like chan-id.wav.
* http://bugzilla.gnome.org/show_bug.cgi?id=489010
*/
switch (nchannels) {
case 1:
pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
break;
case 8:
pos[7] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
pos[6] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
/* fall through */
case 6:
pos[5] = GST_AUDIO_CHANNEL_POSITION_LFE;
/* fall through */
case 5:
pos[4] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
/* fall through */
case 4:
pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
pos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
/* fall through */
case 2:
pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
break;
default:
return FALSE;
}
gst_audio_set_channel_positions (s, pos);
return TRUE;
}
static guint32
gst_riff_wavext_get_default_channel_mask (guint nchannels)
{
guint32 channel_mask = 0;
/* Set the default channel mask for the given number of channels.
* http://www.microsoft.com/whdc/device/audio/multichaud.mspx
*/
switch (nchannels) {
case 11:
channel_mask |= 0x00400;
channel_mask |= 0x00200;
case 9:
channel_mask |= 0x00100;
case 8:
channel_mask |= 0x00080;
channel_mask |= 0x00040;
case 6:
channel_mask |= 0x00020;
channel_mask |= 0x00010;
case 4:
channel_mask |= 0x00008;
case 3:
channel_mask |= 0x00004;
case 2:
channel_mask |= 0x00002;
channel_mask |= 0x00001;
break;
}
return channel_mask;
}
GstCaps *
gst_riff_create_audio_caps (guint16 codec_id,
gst_riff_strh * strh, gst_riff_strf_auds * strf,
@ -778,36 +868,17 @@ gst_riff_create_audio_caps (guint16 codec_id,
"width", G_TYPE_INT, wd,
"depth", G_TYPE_INT, ws, "signed", G_TYPE_BOOLEAN, wd != 8, NULL);
/* Add default MS channel layout if we have more than 2 channels,
* but the layout isn't specified like with WAVEEXT below. Not sure
* if this is right, but at least it makes sound output work at all
* in those cases. Somebody with a a 5.1 setup should double-check
* with chan-id.wav */
/* 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
* 8 channels. */
if (ch > 2) {
guint32 channel_mask;
switch (ch) {
case 4:
channel_mask = 0x33;
break;
case 6:
channel_mask = 0x3f;
break;
case 8:
channel_mask = 0xff;
break;
default:
GST_WARNING ("don't know default layout for %d channels", ch);
channel_mask = 0;
break;
}
if (channel_mask) {
if (ch > 8)
GST_WARNING ("don't know default layout for %d channels", ch);
else if (gst_riff_wave_add_default_channel_layout (caps))
GST_DEBUG ("using default channel layout for %d channels", ch);
if (!gst_riff_wavext_add_channel_layout (caps, channel_mask)) {
GST_WARNING ("failed to add channel layout");
}
}
else
GST_WARNING ("failed to add channel layout");
}
} else {
/* FIXME: this is pretty useless - we need fixed caps */
@ -841,36 +912,17 @@ gst_riff_create_audio_caps (guint16 codec_id,
"endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
"channels", G_TYPE_INT, ch, "width", G_TYPE_INT, wd, NULL);
/* Add default MS channel layout if we have more than 2 channels,
* but the layout isn't specified like with WAVEEXT below. Not sure
* if this is right, but at least it makes sound output work at all
* in those cases. Somebody with a a 5.1 setup should double-check
* with chan-id.wav */
/* 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
* 8 channels. */
if (ch > 2) {
guint32 channel_mask;
switch (ch) {
case 4:
channel_mask = 0x33;
break;
case 6:
channel_mask = 0x3f;
break;
case 8:
channel_mask = 0xff;
break;
default:
GST_WARNING ("don't know default layout for %d channels", ch);
channel_mask = 0;
break;
}
if (channel_mask) {
if (ch > 8)
GST_WARNING ("don't know default layout for %d channels", ch);
else if (gst_riff_wave_add_default_channel_layout (caps))
GST_DEBUG ("using default channel layout for %d channels", ch);
if (!gst_riff_wavext_add_channel_layout (caps, channel_mask)) {
GST_WARNING ("failed to add channel layout");
}
}
else
GST_WARNING ("failed to add channel layout");
}
} else {
/* FIXME: this is pretty useless - we need fixed caps */
@ -1108,23 +1160,13 @@ gst_riff_create_audio_caps (guint16 codec_id,
"rate", G_TYPE_INT, strf->rate,
"signed", G_TYPE_BOOLEAN, wd != 8, NULL);
/* If channel_mask == 0 and channels <= 2, 4, 6 or 8 let's
/* If channel_mask == 0 and channels > 2 let's
* assume default layout as some wav files don't have the
* channel mask set */
if (channel_mask == 0) {
switch (strf->channels) {
case 4:
channel_mask = 0x33;
break;
case 6:
channel_mask = 0x3f;
break;
case 8:
channel_mask = 0xff;
break;
}
}
* 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 =
gst_riff_wavext_get_default_channel_mask (strf->channels);
if ((channel_mask != 0 || strf->channels > 2) &&
!gst_riff_wavext_add_channel_layout (caps, channel_mask)) {
@ -1154,23 +1196,13 @@ gst_riff_create_audio_caps (guint16 codec_id,
"channels", G_TYPE_INT, strf->channels,
"width", G_TYPE_INT, wd, "rate", G_TYPE_INT, strf->rate, NULL);
/* If channel_mask == 0 and channels <= 2, 4, 6 or 8 let's
/* If channel_mask == 0 and channels > 2 let's
* assume default layout as some wav files don't have the
* channel mask set */
if (channel_mask == 0) {
switch (strf->channels) {
case 4:
channel_mask = 0x33;
break;
case 6:
channel_mask = 0x3f;
break;
case 8:
channel_mask = 0xff;
break;
}
}
* 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 =
gst_riff_wavext_get_default_channel_mask (strf->channels);
if ((channel_mask != 0 || strf->channels > 2) &&
!gst_riff_wavext_add_channel_layout (caps, channel_mask)) {