GNOME Bugzilla – Bug 433119
wavparse causes skipping for MPEG-encoded RIFF Wav files with incorrect headers
Last modified: 2007-04-26 08:40:09 UTC
Please describe the problem: I have some MP3s that cause synchronization problems in almost all gstreamer-based player I've used. Audacious, mplayer, Totem, and Xine can all play them fine. Gnome-sound-recorder and Rhythmbox cannot play them without skipping about once a second. Examining the header differences between good and bad mp3s from the same collection made it apparent that all mp3s that skipped while playing had RIFF Wave headers. Further experimentation with adding RIFF headers to valid mp3s demonstrated that an invalid 'dwAvgBytesPerSec' value is what causes synchronization issues that result in skipping every second or so, with the following messages: WARNING: from element /pipeline0/gconfaudiosink0/bin0/alsasink0: Compensating for audio synchronisation problems Additional debug info: gstbaseaudiosink.c(860): gst_base_audio_sink_render (): /pipeline0/gconfaudiosink0/bin0/alsasink0: Unexpected discontinuity in audio timestamps of more than half a second (0:00:00.553333333), resyncing WARNING: from element /pipeline0/gconfaudiosink0/bin0/alsasink0: Compensating for audio synchronisation problems Additional debug info: gstbaseaudiosink.c(860): gst_base_audio_sink_render (): /pipeline0/gconfaudiosink0/bin0/alsasink0: Unexpected discontinuity in audio timestamps of more than half a second (0:00:00.553287981), resyncing Steps to reproduce: 1. Choose any invalid RIFF-encoded mp3 file; to create your own invalid mp3 file for testing: 1a. Take mp3 file. 1b. Add RIFF header 1c. Alter header so that 'dwAvgBytesPerSec' actually specifies the samplerate. 2. Play the file using a gstreamer-based application. Actual results: Audio skips about once a second or so Expected results: Audio plays fine Does this happen every time? Yes Other information: I tried to emulate 'playbin' in gst-launch to find exactly what in the gstreamer pipeline was causing these issues... This plays the file perfectly fine: >> gst-launch-0.10 filesrc location=BrokenFile.mp3 ! mad ! audioconvert ! audioresample ! volume ! gconfaudiosink Changing 'mad' to 'decodebin' reintroduces the skipping >> gst-launch-0.10 filesrc location=BrokenFile.mp3 ! decodebin ! audioconvert ! audioresample ! volume ! gconfaudiosink Viewing verbose output shows that gstreamer uses 'id3demux' and 'wavparse' before sending data to 'mad' when using 'decodebin', so I stripped the ID3 data and tried: >> gst-launch-0.10 filesrc location=BrokenFile.mp3 ! wavparse ! mad ! audioconvert ! audioresample ! volume ! gconfaudiosink and the skipping was back. Using verbose debug output from mplayer I tried to find what discrepancies in header data caused the problem. >>mplayer -v BrokenFile.mp3 lists the following in the output: ======= WAVE Format ======= Format Tag: 85 (0x55) Channels: 1 Samplerate: 22050 avg byte/sec: 44100 Block align: 2 bits/sample: 16 cbSize: 0 ... MPEG 1.0, Layer III, 44100 Hz 128 kbit Joint-Stereo, BPF: 417 Channels: 2, copyright: No, original: Yes, CRC: No, emphasis: 0 AUDIO: 44100 Hz, 2 ch, s16le, 128.0 kbit/9.07% (ratio: 16000->176400) Selected audio codec: [mp3] afm: mp3lib (mp3lib MPEG layer-2, layer-3) After noting the discrepancies in the WAVE header, I managed to reproduce the problem on every mp3 file I have by adding a RIFF wave header and setting the 'dwAvgBytesPerSec' field to the # of samples per second.
Created attachment 86957 [details] Example of MP3 that plays incorrectly (CC-licensed) I've 'produced' a CC-licensed MP3 file that exemplifies this bug from an abridged version of 'Code Monkey' (Jonathan Coulton's Thing A Week series: http://www.jonathancoulton.com/2006/04/14/thing-a-week-29-code-monkey/) by 1. Stripping the ID3v2 tag via 'id3v2 -D' (because I can't get id3demux to pass audio data to wavparse via gst-launch) 2. Run 'riffmp3 -l 0 -b 352.8 -o BrokenFile.mp3' on the valid mp3 file to add a broken header (352.8 = 44100 * 8 bits/byte / 1000, which matches the broken mp3 files I have. This number isn't magic; I would imagine any number significantly larger than the 'correct' 160 kbits/s would cause the same issues) As a side note, does anybody know of a program for Linux that is able to remove the RIFF header between ID3 data and the mp3 data so I can just get rid of this annoying problem (and save a couple kilobytes of disk space too)?
* gst/wavparse/gstwavparse.c: (gst_wavparse_perform_seek), (gst_wavparse_stream_headers), (gst_wavparse_stream_data): * gst/wavparse/gstwavparse.h: Apply DISCONT to buffers. Only apply timestamp to the first sample after a DISCONT, too many VBR files cause random jitter in the timestamps. Fixes #433119.