mirror of
https://code.videolan.org/videolan/vlc
synced 2024-10-11 06:21:30 +02:00
263 lines
9.4 KiB
Plaintext
263 lines
9.4 KiB
Plaintext
|
MAD API documentation collected from e-mails of Joe Drew and Rob Leslie.
|
||
|
The original e-mails can be found in the docs directory. They contain the
|
||
|
same information as is presented below.
|
||
|
|
||
|
INDEX
|
||
|
======
|
||
|
1. I/O Synchronous Mode
|
||
|
2. Low-level API
|
||
|
|
||
|
|
||
|
|
||
|
1. I/O SYNCHRONOUS MODE (extract from Joe Drew)
|
||
|
===============================================
|
||
|
MAD operates with callbacks for functions. Each of these functions is
|
||
|
expected to return type enum mad_flow; this allows you to control the
|
||
|
decoding process.
|
||
|
|
||
|
MAD always outputs 32-bit (well, mad_fixed_t) little-endian data. Take
|
||
|
this into account when outputting samples to the sound card.
|
||
|
Related to the above, since MAD outputs type mad_fixed_t, unless you can
|
||
|
output with 32-bit accuracy (most sound cards can't), you will have to
|
||
|
quantize, round, dither, etc these samples to 16-bit (or whatever you
|
||
|
need.) While there is a sample routine in minimad.c, if you want good
|
||
|
quality you'll either want to roll your own or take a look in madplay's
|
||
|
sources.
|
||
|
|
||
|
Integral to understanding MAD: MAD is a decoding library only. You
|
||
|
handle input and output; you're responsible for fast-forwarding and
|
||
|
rewinding, if you want that type of functionality. All that MAD will do
|
||
|
is take input from you, decode the MPEG frames, give you some
|
||
|
information about them, and give you the decoded PCM data.
|
||
|
|
||
|
Now, the nitty-gritty information.
|
||
|
|
||
|
First, you need a mad_decoder struct. This holds all information about
|
||
|
how you want your stream decoded, such as input/output functions, error
|
||
|
handling functions, etc.
|
||
|
|
||
|
mad_decoder_init() sets this structure up for you.
|
||
|
|
||
|
struct mad_decoder decoder;
|
||
|
struct my_playbuf playbuf;
|
||
|
|
||
|
mad_decoder_init(&decoder, &playbuf, input_func, header_func, /*filter*/
|
||
|
0, output_func, /*error*/ 0, /* message */ 0);
|
||
|
|
||
|
In this example, the function called to get more data is set to
|
||
|
input_func, the function called after MPEG headers have been decoded is
|
||
|
header_func, the function called after all sound data has been decoded
|
||
|
to PCM (for output) is output_func, and the filter, error, and message
|
||
|
functions are unset.
|
||
|
|
||
|
Now, MAD runs in a constant decoding loop. It runs something along the
|
||
|
following lines:
|
||
|
|
||
|
if I'm out of data
|
||
|
call input_func
|
||
|
if input_func says there's no more data,
|
||
|
quit
|
||
|
decode the header and call header_func
|
||
|
decode the mpeg audio data
|
||
|
call the filter function
|
||
|
call the output function
|
||
|
loop
|
||
|
|
||
|
Now, this is an oversimplification obviously. The important thing to
|
||
|
realise is that at every step of the process you can tell MAD what to
|
||
|
do.
|
||
|
|
||
|
Since all of these functions return enum mad_flow, you can tell MAD to
|
||
|
do any of the following:
|
||
|
|
||
|
enum mad_flow {
|
||
|
MAD_FLOW_CONTINUE = 0x0000, /* Keep decoding this stream */
|
||
|
MAD_FLOW_STOP = 0x0010, /* Stop decoding this stream, but exit
|
||
|
normally */
|
||
|
MAD_FLOW_BREAK = 0x0011, /* Stop decoding this stream, and exit
|
||
|
with an error */
|
||
|
MAD_FLOW_IGNORE = 0x0020 /* Don't decode this frame,
|
||
|
but continue afterwards */
|
||
|
};
|
||
|
|
||
|
Most of the time you'll probably want to return MAD_FLOW_CONTINUE. In
|
||
|
every case, you'll have to return one of these values from the functions
|
||
|
you define.
|
||
|
|
||
|
This is the definition of each of the functions:
|
||
|
|
||
|
enum mad_flow (*input_func)(void *, struct mad_stream *);
|
||
|
enum mad_flow (*header_func)(void *, struct mad_header const *);
|
||
|
enum mad_flow (*filter_func)(void *, struct mad_stream const *, struct
|
||
|
mad_frame *);
|
||
|
enum mad_flow (*output_func)(void *, struct mad_header const *, struct
|
||
|
mad_pcm *);
|
||
|
enum mad_flow (*error_func)(void *, struct mad_stream *, struct
|
||
|
mad_frame *);
|
||
|
enum mad_flow (*message_func)(void *, void *, unsigned int *);
|
||
|
|
||
|
In each of these functions the void* pointer passed to the function is
|
||
|
your "playbuf" structure. This can hold whatever you want - for example,
|
||
|
song title, length, number of frames - just remember to re-cast it to
|
||
|
the type you've defined.
|
||
|
|
||
|
input_func takes a mad_stream pointer. Most of the time what you'll want
|
||
|
to do is something along the lines of the following:
|
||
|
|
||
|
if (more_data_available)
|
||
|
buffer = refill_buffer();
|
||
|
mad_stream_buffer(stream, buffer, length_of_buffer);
|
||
|
return MAD_FLOW_CONTINUE;
|
||
|
else
|
||
|
return MAD_FLOW_STOP;
|
||
|
|
||
|
(On many systems you'll want to use mmap() for this.)
|
||
|
|
||
|
header_func takes a mad_header pointer. This contains most of the
|
||
|
important information about a given frame; in constant bitrate files, it
|
||
|
can contain most of the important information about the stream. It will
|
||
|
give you the length of that frame, using mad_timer_t; the audio layer;
|
||
|
extension; bitrate... the list is long. Read frame.h or mad.h in the
|
||
|
frame.h area for more information.
|
||
|
Again, return MAD_FLOW_{CONTINUE,STOP,BREAK} depending on outside
|
||
|
conditions.
|
||
|
|
||
|
The only other function I have firsthand information on is output_func;
|
||
|
in this case, you are given a pointer to struct mad_pcm. This gives you
|
||
|
the sampling rate, number of channels, and number of samples per
|
||
|
channel; doing something like the following should work:
|
||
|
|
||
|
mad_fixed_t *left_channel = pcm->samples[0], *right_channel =
|
||
|
pcm->samples[1];
|
||
|
int nsamples = pcm->length;
|
||
|
signed int sample;
|
||
|
unsigned char * buffer = some_buffer;
|
||
|
unsigned char * ptr = buffer;
|
||
|
|
||
|
while (nsamples--)
|
||
|
{
|
||
|
sample = (signed int) do_downsample(*left_ch++)
|
||
|
|
||
|
*ptr++ = (unsigned char) (sample >> 0);
|
||
|
*ptr++ = (unsigned char) (sample >> 8);
|
||
|
|
||
|
sample = (signed int) do_downsample(*right_ch++)
|
||
|
|
||
|
*ptr++ = (unsigned char) (sample >> 0);
|
||
|
*ptr++ = (unsigned char) (sample >> 8);
|
||
|
}
|
||
|
|
||
|
output buffer to device.
|
||
|
|
||
|
Be sure to handle the big-endian case (autoconf can test for this), and
|
||
|
also the mono (1 channel) case. See mad.c in mpg321, at the end of the
|
||
|
file, for an example.
|
||
|
|
||
|
Information on the other (error, filter, message) functions would be
|
||
|
appreciated, though I think in knowing this information anyone should be
|
||
|
able to puzzle it out.
|
||
|
|
||
|
Now that the decoder is set up with all these callback functions, you
|
||
|
call
|
||
|
|
||
|
mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
|
||
|
|
||
|
and then
|
||
|
|
||
|
mad_decoder_finish(&decoder);
|
||
|
|
||
|
Once you've called mad_decoder_finish, you can re-use the decoder
|
||
|
struct, if you're, for example, within a playlist. Incidentally, all MAD
|
||
|
structures have similar mad_(whatever)_init and mad_(whatever)_finish
|
||
|
functions.
|
||
|
|
||
|
I hope this helps people get their feet wet with MAD. Read the source,
|
||
|
and particularly mad.h - there are a lot of things there you might not
|
||
|
expect. Rob has done a good job in making MAD a complete solution. :)
|
||
|
|
||
|
|
||
|
2. LOW-LEVEL API (extract from Rob Leslie)
|
||
|
==========================================
|
||
|
|
||
|
By way of clarification, MAD also has a low-level API which does not use
|
||
|
callbacks. You can control the entire decoding process yourself more or less
|
||
|
as follows:
|
||
|
|
||
|
/* load buffer with your MPEG audio data */
|
||
|
|
||
|
mad_stream_buffer(&stream, buffer, buflen);
|
||
|
|
||
|
while (1) {
|
||
|
mad_frame_decode(&frame, &stream);
|
||
|
mad_synth_frame(&synth, &frame);
|
||
|
|
||
|
/* output PCM samples in synth.pcm */
|
||
|
}
|
||
|
|
||
|
This is vastly simplified, but it shows the general idea. mad_frame_decode()
|
||
|
decodes the next frame's header and subband samples. mad_synth_frame() takes
|
||
|
those subband samples and synthesizes PCM samples.
|
||
|
|
||
|
It is also possible to call mad_header_decode() before mad_frame_decode().
|
||
|
This just gives you the frame's header info, in case that's all you want, or
|
||
|
perhaps to help you decide whether you want to decode the rest of the frame.
|
||
|
|
||
|
As Joe mentions, each of the stream, frame, and synth structs needs to be
|
||
|
initialized and "finished" before and after use:
|
||
|
|
||
|
struct mad_stream stream;
|
||
|
struct mad_frame frame;
|
||
|
struct mad_synth synth;
|
||
|
|
||
|
mad_stream_init(&stream);
|
||
|
mad_frame_init(&frame);
|
||
|
mad_synth_init(&synth);
|
||
|
|
||
|
/* ... */
|
||
|
|
||
|
mad_synth_finish(&synth);
|
||
|
mad_frame_finish(&frame);
|
||
|
mad_stream_finish(&stream);
|
||
|
|
||
|
You can work with just a struct mad_header instead of a struct mad_frame if
|
||
|
you only want to decode frame headers.
|
||
|
|
||
|
Joe writes:
|
||
|
> MAD always outputs 32-bit (well, mad_fixed_t) little-endian data. Take
|
||
|
> this into account when outputting samples to the sound card.
|
||
|
|
||
|
This isn't quite right: the mad_fixed_t type is not necessarily little-endian.
|
||
|
It's the same endianness as the native integer types. Also, it's only
|
||
|
guaranteed to be *at least* 32 bits wide.
|
||
|
|
||
|
The fixed-point sample format is important to understand, and I recommend
|
||
|
reading the comments in libmad/fixed.h. The thing to remember when converting
|
||
|
MAD's fixed-point integer samples to 16-bit PCM (or whatever) is that MAD
|
||
|
encodes samples as numbers in the full-scale range [-1.0, +1.0) where the
|
||
|
binary point is placed 28 (MAD_F_FRACBITS) bits to the left of the integer.
|
||
|
However, you need to be prepared to handle clipping as some numbers may be
|
||
|
less than -1.0 (-MAD_F_ONE) or greater than or equal to +1.0 (MAD_F_ONE, aka
|
||
|
1 << MAD_F_FRACBITS).
|
||
|
|
||
|
> Information on the other (error, filter, message) functions would be
|
||
|
> appreciated, though I think in knowing this information anyone should be
|
||
|
> able to puzzle it out.
|
||
|
|
||
|
In the high-level API, the error callback function is called whenever a
|
||
|
decoding error occurs. The error number is in stream->error.
|
||
|
|
||
|
The filter callback function is called after decoding a frame, but before
|
||
|
synthesis. Here it is possible to modify the frame's subband samples, for
|
||
|
example to perform a uniform attenuation/amplification, or to do other special
|
||
|
processing in the frequency domain.
|
||
|
|
||
|
The message callback function is only used with MAD_DECODER_MODE_ASYNC, and is
|
||
|
called whenever the parent process sends a message via mad_decoder_message().
|
||
|
This callback can generate a reply by overwriting the message buffer that is
|
||
|
passed to it. (The size of the reply must be the same or smaller than the
|
||
|
message.)
|
||
|
|
||
|
|
||
|
|
||
|
|