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
This commit is contained in:
Antonio Ospite 2013-10-31 17:16:14 +01:00 committed by Thiago Santos
parent f02e7a2439
commit c4fbff50df

View file

@ -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);
}
}