From c4fbff50dfa99e0f725a8690b0d0ff8509300a95 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Thu, 31 Oct 2013 17:16:14 +0100 Subject: [PATCH] mssdemux: fix setting codec_data when using WaveFormatEx When using WaveFormatEx the actual codec private data is at the end of the wav header structure, after the cbSize field, see for example the notes at http://wiki.multimedia.cx/index.php?title=WAVEFORMATEX The previous code was erroneously passing the whole WAVEFORMATEX structure as codec_data. The smoothstreaming specifications[1,2,3] always mention WAVEFORMATEX and never smaller structures like WAVEFORMAT or PCMWAVEFORMAT, so the buffer can assumed to be at least 18 bytes and always consuming the wav header gives the (possibly empty) codec private data. [1] http://web.archive.org/web/20120907004742/http://www.iis.net/community/files/media/smoothspecs/%5BMS-SMTH%5D.pdf [2] http://download.microsoft.com/download/B/0/B/B0B199DB-41E6-400F-90CD-C350D0C14A53/%5BMS-SSTR%5D.pdf [3] http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-SSTR%5D.pdf https://bugzilla.gnome.org/show_bug.cgi?id=699924 --- ext/smoothstreaming/gstmssmanifest.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c index e882437..85f3da2 100644 --- a/ext/smoothstreaming/gstmssmanifest.c +++ b/ext/smoothstreaming/gstmssmanifest.c @@ -597,23 +597,34 @@ _gst_mss_stream_audio_caps_from_qualitylevel_xml (GstMssStreamQuality * q) block_align = (int) g_ascii_strtoull (block_align_str, NULL, 10); if (!codec_data) { - GstMapInfo mapinfo; + gint codec_data_len; codec_data_str = (gchar *) xmlGetProp (node, (xmlChar *) "WaveFormatEx"); - if (codec_data_str && strlen (codec_data_str)) { + codec_data_len = strlen (codec_data_str) / 2; + + /* a WAVEFORMATEX structure is 18 bytes */ + if (codec_data_str && codec_data_len >= 18) { + GstMapInfo mapinfo; codec_data = gst_buffer_from_hex_string ((gchar *) codec_data_str); - /* since this is a waveformatex, try to get the block_align and rate */ + /* since this is a WAVEFORMATEX, try to get the block_align and rate */ gst_buffer_map (codec_data, &mapinfo, GST_MAP_READ); - if (mapinfo.size >= 14) { - if (!channels_str) { - channels = GST_READ_UINT16_LE (mapinfo.data + 2); - } - if (!rate_str) { - rate = GST_READ_UINT32_LE (mapinfo.data + 4); - } + if (!channels_str) { + channels = GST_READ_UINT16_LE (mapinfo.data + 2); + } + if (!rate_str) { + rate = GST_READ_UINT32_LE (mapinfo.data + 4); + } + if (!block_align) { block_align = GST_READ_UINT16_LE (mapinfo.data + 12); } gst_buffer_unmap (codec_data, &mapinfo); + + /* Consume all the WAVEFORMATEX structure, and pass only the rest of + * the data as the codec private data */ + gst_buffer_resize (codec_data, 18, -1); + } else { + GST_WARNING ("Dropping WaveFormatEx: data is %d bytes, " + "but at least 18 bytes are expected", codec_data_len); } } -- 2.7.4