Cleaned up parse_xing, added support for Info magic, and added a parse_extension_headers function for when LAME tag support is added

git-svn-id: https://svn.musicpd.org/mpd/trunk@4398 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
J. Alexander Treuman 2006-07-18 18:18:02 +00:00
parent e7566b9643
commit 6ea0ba392a

View File

@ -402,16 +402,24 @@ static int decodeNextFrame(mp3DecodeData * data) {
return DECODE_OK; return DECODE_OK;
} }
/* xing stuff stolen from alsaplayer */ /* xing stuff stolen from alsaplayer, and heavily modified by jat */
#define XI_MAGIC (('X' << 8) | 'i') #define XI_MAGIC (('X' << 8) | 'i')
#define NG_MAGIC (('n' << 8) | 'g') #define NG_MAGIC (('n' << 8) | 'g')
#define IN_MAGIC (('I' << 8) | 'n')
#define FO_MAGIC (('f' << 8) | 'o')
enum xing_magic {
XING_MAGIC_XING, /* VBR */
XING_MAGIC_INFO, /* CBR */
};
struct xing { struct xing {
long flags; /* valid fields (see below) */ long flags; /* valid fields (see below) */
unsigned long frames; /* total number of frames */ unsigned long frames; /* total number of frames */
unsigned long bytes; /* total number of bytes */ unsigned long bytes; /* total number of bytes */
unsigned char toc[100]; /* 100-point seek table */ unsigned char toc[100]; /* 100-point seek table */
long scale; /* ?? */ long scale; /* VBR quality */
enum xing_magic magic; /* header magic */
}; };
enum { enum {
@ -421,54 +429,84 @@ enum {
XING_SCALE = 0x00000008L XING_SCALE = 0x00000008L
}; };
static int parse_xing(struct xing *xing, struct mad_bitptr ptr, unsigned int bitlen) static int parse_xing(struct xing *xing, struct mad_bitptr *ptr, int bitlen)
{ {
unsigned long bits; unsigned long bits;
int oldbitlen;
int bitsleft;
int i;
oldbitlen = bitlen;
if (bitlen < 16) goto fail; if (bitlen < 16) goto fail;
bits = mad_bit_read(&ptr, 16); bits = mad_bit_read(ptr, 16);
bitlen -= 16; bitlen -= 16;
if (bits == XI_MAGIC) { if (bits == XI_MAGIC) {
if (bitlen < 16) goto fail; if (bitlen < 16) goto fail;
if (mad_bit_read(&ptr, 16) != NG_MAGIC) goto fail; if (mad_bit_read(ptr, 16) != NG_MAGIC) goto fail;
bitlen -= 16; bitlen -= 16;
xing->magic = XING_MAGIC_XING;
} else if (bits == IN_MAGIC) {
if (bitlen < 16) goto fail;
if (mad_bit_read(ptr, 16) != FO_MAGIC) goto fail;
bitlen -= 16;
xing->magic = XING_MAGIC_INFO;
} }
else if (bits != NG_MAGIC) goto fail; else if (bits == NG_MAGIC) xing->magic = XING_MAGIC_XING;
else if (bits == FO_MAGIC) xing->magic = XING_MAGIC_INFO;
else goto fail;
if (bitlen < 32) goto fail; if (bitlen < 32) goto fail;
xing->flags = mad_bit_read(&ptr, 32); xing->flags = mad_bit_read(ptr, 32);
bitlen -= 32; bitlen -= 32;
if (xing->flags & XING_FRAMES) { if (xing->flags & XING_FRAMES) {
if (bitlen < 32) goto fail; if (bitlen < 32) goto fail;
xing->frames = mad_bit_read(&ptr, 32); xing->frames = mad_bit_read(ptr, 32);
bitlen -= 32; bitlen -= 32;
} }
if (xing->flags & XING_BYTES) { if (xing->flags & XING_BYTES) {
if (bitlen < 32) goto fail; if (bitlen < 32) goto fail;
xing->bytes = mad_bit_read(&ptr, 32); xing->bytes = mad_bit_read(ptr, 32);
bitlen -= 32; bitlen -= 32;
} }
if (xing->flags & XING_TOC) { if (xing->flags & XING_TOC) {
int i;
if (bitlen < 800) goto fail; if (bitlen < 800) goto fail;
for (i = 0; i < 100; ++i) xing->toc[i] = mad_bit_read(&ptr, 8); for (i = 0; i < 100; ++i) xing->toc[i] = mad_bit_read(ptr, 8);
bitlen -= 800; bitlen -= 800;
} }
if (xing->flags & XING_SCALE) { if (xing->flags & XING_SCALE) {
if (bitlen < 32) goto fail; if (bitlen < 32) goto fail;
xing->scale = mad_bit_read(&ptr, 32); xing->scale = mad_bit_read(ptr, 32);
bitlen -= 32; bitlen -= 32;
} }
return 1; /* Make sure we consume no less than 120 bytes (960 bits) in hopes that
* the LAME tag is found there, and not right after the Xing header */
bitsleft = 960-(oldbitlen-bitlen);
if (bitsleft < 0) goto fail;
else if (bitsleft > 0) {
mad_bit_read(ptr, bitsleft);
bitlen -= bitsleft;
}
return bitlen;
fail: fail:
xing->flags = 0; xing->flags = 0;
return 0; return -1;
}
static int parse_extension_headers(struct xing *xing, struct mad_bitptr ptr,
int bitlen)
{
bitlen = parse_xing(xing, &ptr, bitlen);
if (bitlen < 0) return 0;
return 1;
} }
static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc, static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc,
@ -493,7 +531,8 @@ static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc,
if(!skip && ret==DECODE_OK) break; if(!skip && ret==DECODE_OK) break;
} }
if(parse_xing(&xing,data->stream.anc_ptr,data->stream.anc_bitlen)) { if(parse_extension_headers(&xing, data->stream.anc_ptr,
(int)data->stream.anc_bitlen)) {
if(xing.flags & XING_FRAMES) { if(xing.flags & XING_FRAMES) {
mad_timer_t duration = data->frame.header.duration; mad_timer_t duration = data->frame.header.duration;
mad_timer_multiply(&duration,xing.frames); mad_timer_multiply(&duration,xing.frames);