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:
parent
e7566b9643
commit
6ea0ba392a
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user