diff options
Diffstat (limited to 'src/inputPlugins/mp3_plugin.c')
-rw-r--r-- | src/inputPlugins/mp3_plugin.c | 69 |
1 files changed, 54 insertions, 15 deletions
diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c index 02c1733d9..4ba2ee539 100644 --- a/src/inputPlugins/mp3_plugin.c +++ b/src/inputPlugins/mp3_plugin.c @@ -402,16 +402,24 @@ static int decodeNextFrame(mp3DecodeData * data) { 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 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 { long flags; /* valid fields (see below) */ unsigned long frames; /* total number of frames */ unsigned long bytes; /* total number of bytes */ unsigned char toc[100]; /* 100-point seek table */ - long scale; /* ?? */ + long scale; /* VBR quality */ + enum xing_magic magic; /* header magic */ }; enum { @@ -421,54 +429,84 @@ enum { 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; + int oldbitlen; + int bitsleft; + int i; + + oldbitlen = bitlen; if (bitlen < 16) goto fail; - bits = mad_bit_read(&ptr, 16); + bits = mad_bit_read(ptr, 16); bitlen -= 16; if (bits == XI_MAGIC) { 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; + 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; - xing->flags = mad_bit_read(&ptr, 32); + xing->flags = mad_bit_read(ptr, 32); bitlen -= 32; if (xing->flags & XING_FRAMES) { if (bitlen < 32) goto fail; - xing->frames = mad_bit_read(&ptr, 32); + xing->frames = mad_bit_read(ptr, 32); bitlen -= 32; } if (xing->flags & XING_BYTES) { if (bitlen < 32) goto fail; - xing->bytes = mad_bit_read(&ptr, 32); + xing->bytes = mad_bit_read(ptr, 32); bitlen -= 32; } if (xing->flags & XING_TOC) { - int i; 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; } if (xing->flags & XING_SCALE) { if (bitlen < 32) goto fail; - xing->scale = mad_bit_read(&ptr, 32); + xing->scale = mad_bit_read(ptr, 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: 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, @@ -493,7 +531,8 @@ static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc, 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) { mad_timer_t duration = data->frame.header.duration; mad_timer_multiply(&duration,xing.frames); |