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

Reply via email to