]> git.sesse.net Git - vlc/blobdiff - doc/mad/joe_drew.txt
* ./modules/*: moved plugins to the new tree. Yet untested builds include
[vlc] / doc / mad / joe_drew.txt
diff --git a/doc/mad/joe_drew.txt b/doc/mad/joe_drew.txt
new file mode 100644 (file)
index 0000000..97dbab9
--- /dev/null
@@ -0,0 +1,174 @@
+Subject: [mad-dev] Some information about programming with MAD (in synchronous mode)
+
+As the author of mpg321, I too faced the problem of MAD not being
+documented. However, in looking at minimad.c, and re-writing mpg321 to
+use MAD, I came to understand it better. Here's some information which
+will help anybody start out with MAD:
+
+First, some basic information.
+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. :)
+
+-- 
+Joe Drew <hoserhead@woot.net> <drew@debian.org>
+
+Please encrypt email sent to me.