Hi Lionel,
If I put aside the licensing issues ( :-) ), my biggest problem is to really understand how the low-level MAD interface is working. After looking at the WinAMP plug-in source, I somewhat understood how it works (except for the timers, where I am completely lost). My understanding for now is :
- read some data from the stream
- call mad_stream_buffer
These steps:
- call mad_frame_decode
- call mad_synth_frame
- send the data to the sound device
should be repeated until MAD returns the error MAD_ERROR_BUFLEN.
- copy the data remaining in the buffer (ie the 'next_frame' pointer) to the start of my input buffer
For a stand-alone player, this works wonderfully. The problem comes when I try to incorporate this in my AVI player. Indeed, when I added some printfs to my small player, I saw that MAD always :
- output the same amount of data (0.006 seconds of sound)
- always 'progressed' of the same amount of data in my stream
Each MPEG audio frame generally contains the same number of PCM samples, and (in the case of constant bitrate streams) will usually consume the same amount of data from the stream. Each call to mad_frame_decode() and mad_synth_frame() will decode only a single frame.
On the other hand, in my AVI stream, for each video frame, the amount of MP3 data is not AT ALL constant.... Moreover, it is sometimes smaller than the amount of data read by MAD => I get (as soon as the first video frame) a decode error from MAD (I did not check exactly what error it was).
You will have to demultiplex the MPEG audio data from the video data and stream this independently to MAD.
I could do 'buffering' (ie concatenate some sound AVI chunks) but then I would completely lose my synchro (and I do not want to rely on timers or to retrieve the synchro, it would start to get bad with long films).
You will probably have to deal with the synchronization somehow. MAD's timers can help you keep track of how much audio data has been decoded. They might seem intimidating but they're really quite simple to use. I'll post some details in a follow-up message.
PS: I hope this is the right mailing list, I did not know if I should send this to the devel list or the user list :-)
I think mad-dev is probably more appropriate; I've adjusted the Reply-To header but you might need to subscribe before you can reply.
Cheers, -rob
Hi members of the Dev list :-)
These steps:
- call mad_frame_decode
- call mad_synth_frame
- send the data to the sound device
should be repeated until MAD returns the error MAD_ERROR_BUFLEN.
Ok.
You will have to demultiplex the MPEG audio data from the video data and stream this independently to MAD.
Yeah, now I realize this... But I really wonder why all the AVI streams I have tested with have 'sound' frames that are NOT a multiple of the size of the MP3 frame.
Anyway, I have another question now about the timers :-) (now that I may use them to do the synchronisation). When I decode the MP3 stream I saved on disk from an AVI, I get this (it's my program debug output) :
109 - 00:00:00.024 - 1152 - 288 | | | | MP3 frame length | | | Sound output frame length | | Frame length (frame.header.duration) | Frame number
But the header of the AVI gives me this :
STREAMHEADER : - DataType : auds (...) - DataRate : 12000 (...) WAVEFORMATEX : - wFormatTag : 85 ( MPEG Layer3 ) - nChannels : 2 - nSamplesPerSec : 48000 - nAvgBytesPerSec : 12000
We have clearly here a 'fixed' frame MP3 stream with output being a stereo 48 kHz.
But when I look at the the time the frame will take to play : 1152 / 2 (stereo) / 2 (16 bit per sample) / 48000 = 0.006 ms
So why does MAD say that this frame is 0.024 ms long ? Is there some bug in the stream in the AVI file (but well, I have this on ALL the streams I have, generated on at least 3 different encoders).
By the way, out of curiosity, is the MP3 frame always the same size or can it be variable from stream to stream or even in a stream ? Is it possible to get the frame size without decoding a frame ?
You will probably have to deal with the synchronization somehow. MAD's timers can help you keep track of how much audio data has been decoded. They might seem intimidating but they're really quite simple to use. I'll post some details in a follow-up message.
Thanks for your explanation on the timers... I think you should add your post somewhere in the docs section of the source tree :-)
Lionel
PS: I am sure I will have other questions before my player is done :-)
Lionel Ulmer wrote:
But when I look at the the time the frame will take to play : 1152 / 2 (stereo) / 2 (16 bit per sample) / 48000 = 0.006 ms
1152 is the number of samples from the frame, regardless of the number of channels or your output resolution. So, your calculation should be:
1152 / 48000 = 0.024 seconds
which agrees with your frame.header.duration. Incidentally, you should also find the sampling frequency (48000) in frame.header.samplerate (or synth.pcm.samplerate after synthesis).
By the way, out of curiosity, is the MP3 frame always the same size or can it be variable from stream to stream or even in a stream ? Is it possible to get the frame size without decoding a frame ?
If by frame size you mean number of bytes, it is not always the same size. It depends on the sampling frequency, the bitrate (which may be variable, i.e. change from frame to frame), and whether a "padding" slot is necessary to maintain a particular bitrate.
After calling mad_header_decode(), you can determine the frame size from:
stream.next_frame - stream.this_frame
Thanks for your explanation on the timers... I think you should add your post somewhere in the docs section of the source tree :-)
Yes, eventually I will have more complete documentation, but at least now the information is online in the mad-dev archive which was part of my purpose in posting it. :-)
Cheers, -rob