Hello,
im trying to stream an mp3, although im finding it quite difficult, since there is no Documentation (or i could not find any) :)
i looked at minimad .. although that is for non-streaming, what would i need to do for streaming?
i have set my write and read callbacks... when are they called? how do i know how many bytes need to be called in the read callback? do i still need to call mad_decoder_run()? what do the synth functions do? do i need them? should i call mad_frame_decode .. and when? ... what does it return?
i am just completely lost...
btw, even the mildest documentation can be somewhat helpful...
thankyou, Nehal
Hmm, I'm assuming you are talking about shoutcast streaming; if that's the case, then just do some google searching for it and you'll find stuff. Basically, it's like downloading an mp3 file wich has "meta" information embedded in it. When you establish a connection, it'll tell you how often to expect the meta information -- extract that from the stream, and send everything else to the rio. You can check out my code for RRR for an example -- these files should containt the crux of it...
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/grrr/rrr/shoutcast.c?rev=1.1&... http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/grrr/rrr/glue.c?rev=1.15&...
Reza
Nehal wrote:
Hello,
im trying to stream an mp3, although im finding it quite difficult, since there is no Documentation (or i could not find any) :)
i looked at minimad .. although that is for non-streaming, what would i need to do for streaming?
i have set my write and read callbacks... when are they called? how do i know how many bytes need to be called in the read callback? do i still need to call mad_decoder_run()? what do the synth functions do? do i need them? should i call mad_frame_decode .. and when? ... what does it return?
i am just completely lost...
btw, even the mildest documentation can be somewhat helpful...
thankyou, Nehal
no i was talking about streaming a local file, but i will take a look anyways...
Nehal
Hmm, I'm assuming you are talking about shoutcast streaming; if that's the case, then just do some google searching for it and you'll find stuff. Basically, it's like downloading an mp3 file wich has "meta" information embedded in it. When you establish a connection, it'll tell you how often to expect the meta information -- extract that from the stream, and send everything else to the rio. You can check out my code for RRR for an example -- these files should containt the crux of it...
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/grrr/rrr/shoutcast.c?rev=1.1&... http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/grrr/rrr/glue.c?rev=1.15&...
Reza
Nehal wrote:
Hello,
im trying to stream an mp3, although im finding it quite difficult, since there is no Documentation (or i could not find any) :)
i looked at minimad .. although that is for non-streaming, what would i need to do for streaming?
i have set my write and read callbacks... when are they called? how do i know how many bytes need to be called in the read callback? do i still need to call mad_decoder_run()? what do the synth functions do? do i need them? should i call mad_frame_decode .. and when? ... what does it return?
i am just completely lost...
btw, even the mildest documentation can be somewhat helpful...
thankyou, Nehal
On Saturday, April 19, 2003, at 11:35 AM, Nehal wrote:
im trying to stream an mp3, although im finding it quite difficult, since there is no Documentation (or i could not find any) :)
i looked at minimad .. although that is for non-streaming, what would i need to do for streaming?
Joe Drew has written some useful information about MAD's high-level API:
http://www.mars.org/mailman/public/mad-dev/2001-October/000369.html
You might also have a look at Bertrand Petit's MAD low-level demonstration:
http://www.bsd-dk.dk/%7Eelrond/audio/madlld/
It shows how to use the low-level API and may fill in some gaps in understanding how the decoder works, especially because the high-level API (minimad) is implemented in terms of the low-level one.
You could implement streaming using either the high- or low-level API. Timing will be critical, though, and I'm guessing it would be helpful to use multiple threads -- one to buffer data from the network, and another to do the decoding work.
i have set my write and read callbacks... when are they called?
Your input callback is called whenever the decoder's stream buffer lacks enough data to decode a complete frame. You should refill the buffer from your data source, taking care to place the unconsumed data from the end of the old buffer (starting from stream->next_frame) at the beginning of your new buffer.
Your output callback is called once per decoded frame. You are expected to consume all of the PCM samples as they will be overwritten with the next decoded frame.
how do i know how many bytes need to be called in the read callback?
Fill as many bytes as you have available. The more bytes you give the decoder at a time, the less often the decoder will ask for more. In principle it doesn't matter how many bytes you give, because the decoder will just ask for more if it doesn't have enough. The only constraint on the maximum number of bytes is the amount of memory you're willing to allocate.
In practice for the decoder to do any work you'll need to provide at least enough bytes to decode a single frame, but how many that is depends on the stream you're decoding. To give you an idea though, the largest possible frame size for MPEG audio is 2881 bytes.
One key to deciding buffer sizes is to consider the rate of data consumption. The stream bitrate tells you pretty accurately how fast the stream will be consumed; e.g. 128 kbps equates to 16000 bytes/second. You can find the instantaneous bitrate in frame->header.bitrate, in bits per second. (To see frames from the high-level API, use the header or filter callbacks.)
do i still need to call mad_decoder_run()?
This is the workhorse routine for the high-level API. If you're using the low-level API, don't use this routine.
what do the synth functions do? do i need them?
You only need to call the synth functions directly if you're using the low-level API. They do PCM synthesis on the decoded frame subband samples (after mad_frame_decode()). The high-level API does this for you and calls your output callback with the result.
should i call mad_frame_decode .. and when? ... what does it return?
Same here: low-level API only. You would call this to decode the next frame from the stream (followed by mad_synth_frame()). It returns 0 if a frame was successfully decoded, and -1 if there was an error. The error is described by stream->error -- for example, MAD_ERROR_BUFLEN means more data is needed to continue decoding; the high-level API would call your input callback at this point.
Hope this helps.