From 3effb4d23eaf9ce1b9f778e99e8482e2691f72f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 17 Apr 2007 01:56:07 +0000 Subject: [PATCH] gst-libs/gst/riff/riff-media.c: Correctly support 4, 6 and 8 channels with normal PCM and float wav files. Original commit message from CVS: * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): Correctly support 4, 6 and 8 channels with normal PCM and float wav files. Fix the depth and signedness calculation in extensible wav files and also handle 1, 2, 4, 6, 8 channels here when a file without channel mask is found. Add support for float, alaw and mulaw in extensible wav files. This allows correct playback of all but 5 files from http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples.html (gst_riff_create_audio_template_caps): Add voxware and float formats to the template caps. --- ChangeLog | 18 +++++ gst-libs/gst/riff/riff-media.c | 139 +++++++++++++++++++++++++++++++-- 2 files changed, 149 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4c0e8c9d4d..e0d7f8b358 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2007-04-17 Sebastian Dröge + + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Correctly support 4, 6 and 8 channels with normal PCM and float + wav files. + + Fix the depth and signedness calculation in extensible wav files and + also handle 1, 2, 4, 6, 8 channels here when a file without channel + mask is found. + + Add support for float, alaw and mulaw in extensible wav files. + + This allows correct playback of all but 5 files from + http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples.html + + (gst_riff_create_audio_template_caps): + Add voxware and float formats to the template caps. + 2007-04-17 Sebastian Dröge Patch by: Vincent Torri diff --git a/gst-libs/gst/riff/riff-media.c b/gst-libs/gst/riff/riff-media.c index d765a3f3ce..2db3e63be0 100644 --- a/gst-libs/gst/riff/riff-media.c +++ b/gst-libs/gst/riff/riff-media.c @@ -759,6 +759,8 @@ gst_riff_create_audio_caps (guint16 codec_id, gint wd = ba * 8 / ch; gint ws; + channels_max = 8; + if (strf->size > 32) { GST_WARNING ("invalid depth (%d) of pcm audio, overwriting.", strf->size); @@ -787,6 +789,9 @@ gst_riff_create_audio_caps (guint16 codec_id, 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; @@ -827,6 +832,8 @@ gst_riff_create_audio_caps (guint16 codec_id, gint ch = strf->channels; gint wd = ba * 8 / ch; + channels_max = 8; + caps = gst_caps_new_simple ("audio/x-raw-float", "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, "channels", G_TYPE_INT, ch, "width", G_TYPE_INT, wd, NULL); @@ -846,6 +853,9 @@ gst_riff_create_audio_caps (guint16 codec_id, 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; @@ -1043,6 +1053,8 @@ gst_riff_create_audio_caps (guint16 codec_id, guint32 subformat_guid[4]; const guint8 *data; + channels_max = 8; + /* should be at least 22 bytes */ if (strf_data == NULL || GST_BUFFER_SIZE (strf_data) < 22) { GST_WARNING ("WAVE_FORMAT_EXTENSIBLE data size is %d (expected: 22)", @@ -1071,20 +1083,39 @@ gst_riff_create_audio_caps (guint16 codec_id, if (strf != NULL) { gint ba = strf->blockalign; gint ws = strf->size; - gint depth = ws; + gint wd = ba * 8 / strf->channels; if (valid_bits_per_sample != 0) - depth = valid_bits_per_sample; + ws = valid_bits_per_sample; caps = gst_caps_new_simple ("audio/x-raw-int", "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, "channels", G_TYPE_INT, strf->channels, - "width", G_TYPE_INT, (int) (ba * 8 / strf->channels), - "depth", G_TYPE_INT, depth, + "width", G_TYPE_INT, wd, + "depth", G_TYPE_INT, ws, "rate", G_TYPE_INT, strf->rate, - "signed", G_TYPE_BOOLEAN, (depth > 8) ? TRUE : FALSE, NULL); + "signed", G_TYPE_BOOLEAN, wd != 8, NULL); - if (!gst_riff_wavext_add_channel_layout (caps, channel_mask)) { + /* If channel_mask == 0 and channels <= 2, 4, 6 or 8 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; + } + } + + if ((channel_mask != 0 || strf->channels > 2) && + !gst_riff_wavext_add_channel_layout (caps, channel_mask)) { GST_WARNING ("failed to add channel layout"); gst_caps_unref (caps); caps = NULL; @@ -1097,7 +1128,97 @@ gst_riff_create_audio_caps (guint16 codec_id, } } } else if (subformat_guid[0] == 0x00000003) { - GST_DEBUG ("FIXME: handle IEEE float format"); + GST_DEBUG ("FLOAT"); + if (strf != NULL) { + gint ba = strf->blockalign; + gint ws = strf->size; + gint wd = ba * 8 / strf->channels; + + if (valid_bits_per_sample != 0) + ws = valid_bits_per_sample; + + caps = gst_caps_new_simple ("audio/x-raw-float", + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "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 + * 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; + } + } + + if ((channel_mask != 0 || strf->channels > 2) && + !gst_riff_wavext_add_channel_layout (caps, channel_mask)) { + GST_WARNING ("failed to add channel layout"); + gst_caps_unref (caps); + caps = NULL; + } + rate_chan = FALSE; + + if (codec_name) { + *codec_name = + g_strdup_printf ("Uncompressed %d-bit IEEE float audio", + strf->size); + } + } + } else if (subformat_guid[0] == 00000006) { + GST_DEBUG ("ALAW"); + if (strf != NULL) { + if (strf->size != 8) { + GST_WARNING ("invalid depth (%d) of alaw audio, overwriting.", + strf->size); + strf->size = 8; + strf->av_bps = 8; + strf->blockalign = strf->av_bps * strf->channels; + } + if (strf->av_bps == 0 || strf->blockalign == 0) { + GST_WARNING + ("fixing av_bps (%d) and blockalign (%d) of alaw audio", + strf->av_bps, strf->blockalign); + strf->av_bps = strf->size; + strf->blockalign = strf->av_bps * strf->channels; + } + } + rate_max = 48000; + caps = gst_caps_new_simple ("audio/x-alaw", NULL); + + if (codec_name) + *codec_name = g_strdup ("A-law audio"); + } else if (subformat_guid[0] == 0x00000007) { + GST_DEBUG ("MULAW"); + if (strf != NULL) { + if (strf->size != 8) { + GST_WARNING ("invalid depth (%d) of mulaw audio, overwriting.", + strf->size); + strf->size = 8; + strf->av_bps = 8; + strf->blockalign = strf->av_bps * strf->channels; + } + if (strf->av_bps == 0 || strf->blockalign == 0) { + GST_WARNING + ("fixing av_bps (%d) and blockalign (%d) of mulaw audio", + strf->av_bps, strf->blockalign); + strf->av_bps = strf->size; + strf->blockalign = strf->av_bps * strf->channels; + } + } + rate_max = 48000; + caps = gst_caps_new_simple ("audio/x-mulaw", NULL); + if (codec_name) + *codec_name = g_strdup ("Mu-law audio"); } else if (subformat_guid[0] == 0x00000092) { GST_DEBUG ("FIXME: handle DOLBY AC3 SPDIF format"); } @@ -1316,7 +1437,9 @@ gst_riff_create_audio_template_caps (void) GST_RIFF_WAVE_FORMAT_WMAV1, GST_RIFF_WAVE_FORMAT_WMAV2, GST_RIFF_WAVE_FORMAT_WMAV3, - GST_RIFF_WAVE_FORMAT_SONY_ATRAC3 + GST_RIFF_WAVE_FORMAT_SONY_ATRAC3, + GST_RIFF_WAVE_FORMAT_IEEE_FLOAT, + GST_RIFF_WAVE_FORMAT_VOXWARE /* FILL ME */ }; guint i;