-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hi,
I'm one of the developers of NMM (thanks for your link to use on your Website). We are using libmad to decode MPEG Audio Layer 2 as received by Digital Video Broadcast (DVB) via satelite. After remuxing the received MPEG transport stream to a MPEG 2 PES stream (first part: DVBReadNode) it is demultiplexed into its audio and video parts by our MPEG Demultiplexer Node (= demuxer unit). The resulting MPEG Audio part is MPEG Audio layer 2 with 48000 Hz sample rate (at least we did not found any other one yet) and one ore 2 channels. It is decoded by the MPEGAudioDecodeNode based on libmad version 0.14.2b. The code was inspired by the minimad example from your distribution although we had do make many changes, e.g. unlooping the while loop to process the incoming buffers or computing timestamps for the decoded audio buffers for later syncronisation with the video frames.
Now back to my problem. I discovered, that some few times, the mad_pcm struct seems to contain invalid values for samplerate and number of channels. Although the mad_header struct in the mad_frame says, that the frame has 48000 Hz and 1 channel, in the mad_pcm struct, the values are 24000 Hz and 2 channels (see: the total number of samples is 96000 in both cases). I already tried the newer version 0.15 of the mad library, but I get the same effects. We also have mad a "simulation", where we use a recorded DVB-Stream. The effect apears here also indeterministically. Also playing the demulitplexed audio stream is affected. The "accident" occures not so often and most times, it is not reproduceable directly after it occured, except if the application is left running. When the app is left running we can reproduce it a few times and after 4-5 tries, the decoder gets it right.
We also tried not to use the values from the mad_pcm struct but the ones from the mad_header struct, but as we heard, the decoded audio data was also affected (or wrong interleaved).
Can you give me some hints where I can search for the error or do you think, this is a bug in the library perhaps?
I would like to test it also with the current development library. Do you have something like anonymous CVS access?
CU/all
P.S.: If you want to see our implementation, you can download the latest NMM release. The Code in this release is (at least for the MPEGAudioDecodeNode) nearly identical with our current CVS head! - -- Patrick Cernko | mailto:errror@errror.de | http://www.errror.de Quote of the Week: "Is net scheen, das Bild, awwer einmalisch!" (Markus Sand)
On Thursday, July 10, 2003, at 11:07 AM, Patrick Cernko wrote:
Can you give me some hints where I can search for the error or do you think, this is a bug in the library perhaps?
Looking briefly at your CVS code, a few things come to mind.
I would guess most probably the error results from this:
if ( stream->error == MAD_ERROR_BUFLEN ) {
/* calculate the size of the data that could not be decoded */ rest_length = cur_buffer_end - stream->this_frame;
Since the decoding of the frame failed, there is in effect no "this_frame" -- the pointer you want is actually stream->next_frame.
Likewise you should use stream->next_frame here:
memcpy( tmpbuffer, stream->this_frame, rest_length );
and furthermore, technically, this should probably instead be memmove() since it's possible (although unlikely) the memory areas may overlap.
My guess is that on a few occasions this bitstream mismanipulation is causing some frames to be decoded incorrectly.
The only other thing that jumps out at me is that, while unlikely to be related to your problem, I noticed you are maintaining a struct mad_decoder when there is no reason to do so. That structure is only used in the high-level API. Since you are now using the low-level API, there is no need for it.
This will simplify some of your code. You don't need to allocate memory for, initialize, or deinitialize the decoder struct. The initMadDecoderSync.[ch] files are unnecessary. Allocate memory for the stream, frame, and synth structs directly (i.e. include the actual structs instead of pointers in your class.) And you don't need to bother with setting the stream options unless you actually want/need something specific.
Hope this helps.