diff --git a/libavcodec/bitstream_filter.c b/libavcodec/bitstream_filter.c index ef2d7414a6..e4be773c6e 100644 --- a/libavcodec/bitstream_filter.c +++ b/libavcodec/bitstream_filter.c @@ -125,21 +125,24 @@ static int noise(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const ch return 1; } +#define MP3_MASK 0xFFFE0CCF + static int mp3_header_compress(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size, int keyframe){ - uint32_t header; - int mode_extension; + uint32_t header, extraheader; + int mode_extension, header_size; if(avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){ av_log(avctx, AV_LOG_ERROR, "not standards compliant\n"); return -1; } - header = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + header = BE_32(buf); mode_extension= (header>>4)&3; - if(ff_mpa_check_header(header) < 0 || (header&0x70000) != 0x30000){ + if(ff_mpa_check_header(header) < 0 || (header&0x60000) != 0x20000){ +output_unchanged: *poutbuf= (uint8_t *) buf; *poutbuf_size= buf_size; @@ -147,9 +150,25 @@ static int mp3_header_compress(AVBitStreamFilterContext *bsfc, AVCodecContext *a return 0; } - *poutbuf_size= buf_size - 4; - *poutbuf= av_malloc(buf_size - 4 + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy(*poutbuf, buf + 4, buf_size - 4 + FF_INPUT_BUFFER_PADDING_SIZE); + if(avctx->extradata_size == 0){ + avctx->extradata_size=15; + avctx->extradata= av_malloc(avctx->extradata_size); + strcpy(avctx->extradata, "FFCMP3 0.0"); + memcpy(avctx->extradata+11, buf, 4); + } + if(avctx->extradata_size != 15){ + av_log(avctx, AV_LOG_ERROR, "Extradata invalid\n"); + return -1; + } + extraheader = BE_32(avctx->extradata+11); + if((extraheader&MP3_MASK) != (header&MP3_MASK)) + goto output_unchanged; + + header_size= (header&0x10000) ? 4 : 6; + + *poutbuf_size= buf_size - header_size; + *poutbuf= av_malloc(buf_size - header_size + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(*poutbuf, buf + header_size, buf_size - header_size + FF_INPUT_BUFFER_PADDING_SIZE); if(avctx->channels==2){ if((header & (3<<19)) != 3<<19){ @@ -173,7 +192,7 @@ static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext int sample_rate_index=0; int lsf, mpeg25, bitrate_index, frame_size; - header = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + header = BE_32(buf); if(ff_mpa_check_header(header) >= 0){ *poutbuf= (uint8_t *) buf; *poutbuf_size= buf_size; @@ -181,18 +200,16 @@ static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext return 0; } - header= 0xFFE00000 | ((4-3)<<17) | (1<<16); //FIXME simplify + if(avctx->extradata_size != 15 || strcmp(avctx->extradata, "FFCMP3 0.0")){ + av_log(avctx, AV_LOG_ERROR, "Extradata invalid %d\n", avctx->extradata_size); + return -1; + } + + header= BE_32(avctx->extradata+11) & MP3_MASK; lsf = sample_rate < (24000+32000)/2; mpeg25 = sample_rate < (12000+16000)/2; - header |= (!mpeg25)<<20; - header |= (!lsf )<<19; - if(sample_rate<<(lsf+mpeg25) < (44100+32000)/2) - sample_rate_index |= 2; - else if(sample_rate<<(lsf+mpeg25) > (44100+48000)/2) - sample_rate_index |= 1; - - header |= sample_rate_index<<10; + sample_rate_index= (header>>10)&3; sample_rate= mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off for(bitrate_index=2; bitrate_index<30; bitrate_index++){ @@ -200,6 +217,8 @@ static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1); if(frame_size == buf_size + 4) break; + if(frame_size == buf_size + 6) + break; } if(bitrate_index == 30){ av_log(avctx, AV_LOG_ERROR, "couldnt find bitrate_index\n"); @@ -208,18 +227,19 @@ static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext header |= (bitrate_index&1)<<9; header |= (bitrate_index>>1)<<12; - header |= (avctx->channels==1 ? MPA_MONO : MPA_JSTEREO)<<6; + header |= (frame_size == buf_size + 4)<<16; //FIXME actually set a correct crc instead of 0 - *poutbuf_size= buf_size + 4; - *poutbuf= av_malloc(buf_size + 4 + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy(*poutbuf + 4, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + *poutbuf_size= frame_size; + *poutbuf= av_malloc(frame_size + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(*poutbuf + frame_size - buf_size, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); if(avctx->channels==2){ + uint8_t *p= *poutbuf + frame_size - buf_size; if(lsf){ - FFSWAP(int, (*poutbuf)[5], (*poutbuf)[6]); - header |= ((*poutbuf)[5] & 0xC0)>>2; + FFSWAP(int, p[1], p[2]); + header |= (p[1] & 0xC0)>>2; }else{ - header |= (*poutbuf)[5] & 0x30; + header |= p[1] & 0x30; } }