GNOME Bugzilla – Bug 755543
wavparse: plain PCM wav wrongly treated as DTS
Last modified: 2015-09-25 23:50:43 UTC
Created attachment 312059 [details] A 5 second wav that won't play properly in Gstreamer I have an 8kHz mono wav (relevant section attached) that happens to contain the magic bytes 'fe 7f 01 80' near the start: 000008d0 ab fb 10 fb 43 fc 30 fe c2 fd 60 fc f2 fe 7f 01 |....C.0...`.....| 000008e0 80 02 c3 02 c7 03 23 02 dd 00 29 02 a0 01 fe fe |......#...).....| This causes wavparse to treat it as DTS, and use the next few bytes as some kind of accursed header. In turn it happens to survive this check: num_blocks = (hdr[2] >> 2) & 0x7F; *frame_size = (((hdr[2] & 0x03) << 12) | (hdr[3] >> 4)) + 1; chans = ((hdr[3] & 0x0F) << 2) | (hdr[4] >> 14); *sample_rate = sample_rates[(hdr[4] >> 10) & 0x0F]; lfe = (hdr[5] >> 9) & 0x03; if (num_blocks < 5 || *frame_size < 96 || *sample_rate == 0) return FALSE; That's all in -base/gst/typefind, and in wavparse plugin itself there is this: /* for maybe, check for at least a valid-looking rate and channels */ if (!gst_structure_has_field (s, "channels")) return FALSE; /* and for extra assurance we could also check the rate from the DTS frame * against the one in the wav header, but for now let's not do that */ return gst_structure_has_field (s, "rate"); I'm guessing I want to do that last bit, right? As GST_DEBUG puts it: LOG typefindfunctions gsttypefindfunctions.c:1733:dts_parse_frame_header: dts sync marker 0xfe7f0180 at offset 2225 LOG typefindfunctions gsttypefindfunctions.c:1754:dts_parse_frame_header: frame header: c302c7022303dd02 ... LOG wavparse gstwavparse.c:1835:gst_wavparse_add_src_pad: typefind caps = audio/x-dts, rate=(int)44100, channels=(int)5, depth=(int)16, endianness=(int)1234, framed=(boolean)false, P=50 ... and that doesn't want to link. The caps ought to be something like "audio/x-raw, format=(string)S16LE, layout=(string)interleaved, channels=(int)1, rate=(int)8000". Nobody else seems to get this wrong. gst123 plays a short little squirting sound and offers a few of these: ERROR: block code look-up failed Didn't get subframe DSYNC I believe this is the opposite of https://bugzilla.gnome.org/show_bug.cgi?id=636234, whose incomplete fix caused this. It might be useful to have a wavparse flag property that meant "trust me, believe the RIFF header", which would avoid this always and save all that time spent looking for magic brokenness.
Some comments on the likeliness of this: There are four different 32 bit signatures, so assuming vaguely random wavs, there is ~1 chance in a billion of a collision per candidate slot. But there are roughly 20000 places it could be, which reduces the chances to 1 in 50 thousand. I am working on something that listens to in the order of 3000 1-minute wavs, so this will happen to 1 out of 17 people like me -- not, of course, taking into account the second wave of checks which is harder to calculate.
On closer inspection, it seems this has been fixed in master, here: commit c3bb399fd3e238da77aa3242557eedf3f42d1167 Author: David Schleef <ds@schleef.org> Date: Thu Mar 26 12:21:25 2015 -0700 wavparse: be more strict about typefinding DTS Code now matches comments. [...] /* DTS at non-0 offsets and without second sync may yield POSSIBLE .. */ - if (prob < GST_TYPE_FIND_POSSIBLE) + if (prob <= GST_TYPE_FIND_POSSIBLE) return FALSE; So I'll close this.
Thanks, nothing like bugs that resolve themselves :)