File: API

package info (click to toggle)
vlc 0.2.92-8
  • links: PTS
  • area: main
  • in suites: woody
  • size: 7,076 kB
  • ctags: 7,147
  • sloc: ansic: 62,829; cpp: 5,824; sh: 2,469; xml: 2,351; makefile: 1,291; python: 503; perl: 19
file content (262 lines) | stat: -rw-r--r-- 9,655 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
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.)