Hi!
Lame used mpglib for decoding, mpglib is part of mpg123 and way behind the
development of mpg123 itself. So I plan to spend part of the summer semester
rewriting the mpglib part. Hence, I think of a new interface for mpglib.
I enclose the draft of the new interface of mpglib below for public
discussion. Especially the writers of the lame interface to mpglib are
asked for some feedback. Is the new interface better/worse?
What are foreseeable problems? What should be changed?
Please comment!
Martin
--------- a draft of mpglib.h---------
#include <stdlib.h>
/* mpglib.h (draft) a new mpglib interface (draft)
*/
typedef int mpg_id;
/* A handle to a mpg stream.
Values are created with mpg_open, used with mpg_read,
and destroyed with mpg_close.
Several mp3 streams might be open for decoding at the same time,
representing e.g. several tracks of a mixing application. mpg_open
will always return the smallest non-negative number that is not yet
associated with an open stream. E.g opening five streams will return
the numbers 0,1,2,3,4 in this order; then after closing stream 2,
the next call to mpg_open will return 2. Handles can be used by an
application as an index into an array containing application specific
supplemental information.
*/
/* Information on streams is provided in a mpg_info structure */
typedef struct mpg_info {
mpg_id self; /* the stream that provides the information */
/* MPG format parameters */
int version; /* can be one of */
#define MPG_V2_5 0x00 /* MPEG Version 2.5 (later extension of MPEG 2) */
#define MPG_V2_0 0x02 /* MPEG Version 2 (ISO/IEC 13818-3) */
#define MPG_V1_0 0x03 /* MPEG Version 1 (ISO/IEC 11172-3) */
int layer; /* can be 1 2 or 3 */
int crc_protected; /* can be TRUE or FALSE */
int bitrate; /* the frame's bitrate */
int framesize; /* the byte size of this frame */
int mode; /* can be one of the following */
#define MPG_MD_STEREO 0x00
#define MPG_MD_JOINT_STEREO 0x01
#define MPG_MD_DUAL_CHANNEL 0x02
#define MPG_MD_MONO 0x03
int mode_extension; /* can be 0,1,2, or 2 */
int private; /* can be TRUE or FALSE */
int copyright; /* can be TRUE or FALSE */
int original; /* can be TRUE or FALSE */
int emphasis; /* can be 0,1,2, or 2 */
/* PCM format parameters */
int sample_frequency; /* the frequency in Hz */
int channels; /* the number of channels 1=mono 2=stereo */
} mpg_info;
/* Streams can be opened with options specified in a
mpg_options structure.
*/
typedef struct mpg_options {
/* To be populated with all kinds of parameters. */
int (*info)(mpg_info *p); /* If != NULL, called when an mp3 frame
is found, depending on the enable bits.
return 0 to decode the frame.
return 1 to skip this frame. */
int enable_info_callback; /* The following values can be ORed together:
*/
#define MPG_INFO_ALWAYS 0x01 /* call info for each frame, */
#define MPG_INFO_ONCE 0x02 /* call info once at the very beginning */
#define MPG_INFO_READ 0x04 /* ... for each mpg_read */
#define MPG_INFO_PCM 0x08 /* ... pcm parameters change, */
#define MPG_INFO_MPG 0x10 /* ... mpg parameters change, */
#define MPG_CRC_VIOLATION 0x20 /* ... wrong crc field. */
int break_read; /* The following values can be ORed together:
*/
#define MPG_BREAK_FRAME 0x01 /* return form read after decoding each frame
*/
#define MPG_BREAK_TAG 0x02 /* return from read before calling a
tag_handler */
#define MPG_BREAK_PCM 0x04 /* ... before a change in pcm format occurs */
#define MPG_BREAK_MPG 0x08 /* ... before a change in mpg format occurs */
#define MPG_BREAK_CRC 0x10 /* ... before a crc error */
int resync; /* The following values can be ORed together:
*/
#define MPG_SYNC_ONCE 0x01 /* synchronize the stream at the very
beginning */
#define MPG_SYNC_UNKNOWN 0x02 /* ... after each unknown tag (garbage)*/
#define MPG_SYNC_READ 0x04 /* ... at the beginning of each mpg_read */
#define MPG_SYNC_SIZE 0x08 /* ... after each tag of unknown size */
#define MPG_SYNC_TAG 0x10 /* ... after each tag */
#define MPG_SYNC_2 0x20 /* ... with at least two frames */
#define MPG_SYNC_3 0x40 /* ... with at least three frames */
#define MPG_SYNC_4 0x80 /* ... with at least four frames */
} mpg_options;
extern mpg_id mpg_open(int next_byte(mpg_id self),
int tag_handler(mpg_id self,
int tag,
int next_byte(mpg_id self),
size_t size),
mpg_options *p);
/* Opens an mpg decoding stream.
On failure it returns -1.
The return value can be used in successive mpg_read and
mpg_close calls.
The parameters:
next_byte is a function that will deliver the next unsigned char
(0-255) cast to an int from the mp3 stream. It may return -1 on end
of file or error. The parameter self can be used to identify the
stream in case there are multiple open streams at the same time.
In the simplest case this might, for example, be the
function int next_byte(mpg_id self) { return getchar(); }.
tag_handler is a function, that will be called if the decoding
engine detects data in the stream that presents additional
information (tags).
tag_handler might be NULL, in this case tags are just skipped.
The tag_handler gets four parameters:
self, the stream that found the tag. This parameter can be used to
identify the stream that called the tag handler.
tag, this might be one of the following:
*/
#define MPG_TAG_UNKNOWN 0 /* the decoding engine has no idea */
#define MPG_TAG_RIFF 1
#define MPG_TAG_ID3V1 2
#define MPG_TAG_ID3V2 3
#define MPG_TAG_LYRICS 4
#define MPG_TAG_AID 5
#define MPG_TAG_XING 6
#define MPG_TAG_LAME 7
/*
The tag is a guess of mpglib of what follows. An unknown tag is
often just garbage in the stream. Analyzing the tags and
extracting information is a different problem from decoding mpg
streams. Even buffering them is a problem since id3v2 tags can
be quite large. We do not deal with that right now but may
provide some separate utility code for the most common cases (an
interface to the id3lib might be good).
next_byte is a function that can be used by the tag_handler to
read the next unsigned char (0-255) cast to an int from the mp3
stream. It may return -1 on end of file or error.
size is an lower estimate of the size of the tag. It might be
used by the handler. size is always positive but it might be far
to small. Especially if the size of a tag is not determined by
some number embedded in the tag, but by some kind of end-marker,
the decoding engine may not search for the end of the tag and
size may be just 1. Then the tag handler should use next_byte and
read whatever is in the stream until the end-marker is found and
finally end with returning 0.
The tag_handler will return the additional number of bytes to be
skipped in the stream before continuing with decoding mp3 frames.
Additional means that each call of next_byte by the tag handler
already removes one byte from the stream. That is, calling
next_byte k times and returning i has the same effect as calling
next_byte k+i times and returning 0 or not calling next_byte at
all and returning i+k. You can return a negative value i > -16
with the effect of pushing back i bytes into the stream as long
as you did read the bytes beforehand. This gives the tag_handler
a 15 byte look ahead. In case of error or end of input, the tag
handler should return -16 or less.
A simple tag_handler could be
int tag_handler(mpg_id s, int tag, int nb(), int size) {return size;}
this is equivalent to supplying NULL instead of a tag_handler.
p is a pointer to an mpg_options structure. It can be NULL, and then
the decoding engine will use reasonable default values. Otherwise,
the structure contains the options that influence the decoding
process. The structure can be deallocated after the mpg_open call.
*/
extern int mpg_read(mpg_id s, unsigned char* buffer, size_t count);
/* Attempts to read count decoded bytes from the stream s to the buffer.
On success, it will return the number of bytes read. Zero indicates
the end of file and a negative value indicates an error. It is not an
error if the number returned is smaller than count. The buffer will
be filled with 16 bit PCM data. The sample frequency and the number
of channels can be obtained by the info callback function. A change
in the output format or other events given by the break_read option,
will cause the function to return with a partly filled buffer, such
that no buffer will contain data sets belonging to different output
formats, or to keep tags strictly in sync with decoded data.
If parameter count is zero, the function will analyse the header(s)
of the stream and invoke the appropriate call-back functions, but no
attempt is made to decode the data inside an mp3 frame. buffer might
be NULL in this case. As usual, the callback functions can advance
the stream by calling the next_byte function or by returning an
appropriate value.
This feature can be used at the beginning of a stream to extract
information from the first frame without decoding and without
advancing the stream. If you advance the stream and then start
decoding, the output of mpg_read will be exactly the same as when
calling mpg_read with count > 0 and discarding the data it produces.
*/
extern int mpg_close(mpg_id s);
/*
Will close the stream s. It returns 0 on success and a negative
value if an error occurred. It will free all data associated with the
stream. After closing it, the stream id's might not longer be used
in a call to mpg_read() or mpg_info(). A later call of mpg_open
might return again the same id for a new stream.
*/
_______________________________________________
mp3encoder mailing list
[EMAIL PROTECTED]
http://minnie.tuhs.org/mailman/listinfo/mp3encoder