1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include "libavutil/common.h" 22cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 23cabdff1aSopenharmony_ci#include "bsf.h" 24cabdff1aSopenharmony_ci#include "bsf_internal.h" 25cabdff1aSopenharmony_ci#include "defs.h" 26cabdff1aSopenharmony_ci#include "mpegaudiodecheader.h" 27cabdff1aSopenharmony_ci#include "mpegaudiodata.h" 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_cistatic int mp3_header_decompress(AVBSFContext *ctx, AVPacket *out) 31cabdff1aSopenharmony_ci{ 32cabdff1aSopenharmony_ci AVPacket *in; 33cabdff1aSopenharmony_ci uint32_t header; 34cabdff1aSopenharmony_ci int sample_rate= ctx->par_in->sample_rate; 35cabdff1aSopenharmony_ci int sample_rate_index=0; 36cabdff1aSopenharmony_ci int lsf, mpeg25, bitrate_index, frame_size, ret; 37cabdff1aSopenharmony_ci uint8_t *buf; 38cabdff1aSopenharmony_ci int buf_size; 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_ci ret = ff_bsf_get_packet(ctx, &in); 41cabdff1aSopenharmony_ci if (ret < 0) 42cabdff1aSopenharmony_ci return ret; 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_ci buf = in->data; 45cabdff1aSopenharmony_ci buf_size = in->size; 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ci header = AV_RB32(buf); 48cabdff1aSopenharmony_ci if(ff_mpa_check_header(header) >= 0){ 49cabdff1aSopenharmony_ci av_packet_move_ref(out, in); 50cabdff1aSopenharmony_ci av_packet_free(&in); 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci return 0; 53cabdff1aSopenharmony_ci } 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci if(ctx->par_in->extradata_size != 15 || strcmp(ctx->par_in->extradata, "FFCMP3 0.0")){ 56cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Extradata invalid %d\n", ctx->par_in->extradata_size); 57cabdff1aSopenharmony_ci ret = AVERROR(EINVAL); 58cabdff1aSopenharmony_ci goto fail; 59cabdff1aSopenharmony_ci } 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci header= AV_RB32(ctx->par_in->extradata+11) & MP3_MASK; 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci lsf = sample_rate < (24000+32000)/2; 64cabdff1aSopenharmony_ci mpeg25 = sample_rate < (12000+16000)/2; 65cabdff1aSopenharmony_ci sample_rate_index= (header>>10)&3; 66cabdff1aSopenharmony_ci if (sample_rate_index == 3) { 67cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 68cabdff1aSopenharmony_ci goto fail; 69cabdff1aSopenharmony_ci } 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci for(bitrate_index=2; bitrate_index<30; bitrate_index++){ 74cabdff1aSopenharmony_ci frame_size = ff_mpa_bitrate_tab[lsf][2][bitrate_index>>1]; 75cabdff1aSopenharmony_ci frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1); 76cabdff1aSopenharmony_ci if(frame_size == buf_size + 4) 77cabdff1aSopenharmony_ci break; 78cabdff1aSopenharmony_ci if(frame_size == buf_size + 6) 79cabdff1aSopenharmony_ci break; 80cabdff1aSopenharmony_ci } 81cabdff1aSopenharmony_ci if(bitrate_index == 30){ 82cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Could not find bitrate_index.\n"); 83cabdff1aSopenharmony_ci ret = AVERROR(EINVAL); 84cabdff1aSopenharmony_ci goto fail; 85cabdff1aSopenharmony_ci } 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci header |= (bitrate_index&1)<<9; 88cabdff1aSopenharmony_ci header |= (bitrate_index>>1)<<12; 89cabdff1aSopenharmony_ci header |= (frame_size == buf_size + 4)<<16; //FIXME actually set a correct crc instead of 0 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_ci ret = av_new_packet(out, frame_size); 92cabdff1aSopenharmony_ci if (ret < 0) 93cabdff1aSopenharmony_ci goto fail; 94cabdff1aSopenharmony_ci ret = av_packet_copy_props(out, in); 95cabdff1aSopenharmony_ci if (ret < 0) { 96cabdff1aSopenharmony_ci av_packet_unref(out); 97cabdff1aSopenharmony_ci goto fail; 98cabdff1aSopenharmony_ci } 99cabdff1aSopenharmony_ci memcpy(out->data + frame_size - buf_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE); 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci if (ctx->par_in->ch_layout.nb_channels == 2){ 102cabdff1aSopenharmony_ci uint8_t *p= out->data + frame_size - buf_size; 103cabdff1aSopenharmony_ci if(lsf){ 104cabdff1aSopenharmony_ci FFSWAP(int, p[1], p[2]); 105cabdff1aSopenharmony_ci header |= (p[1] & 0xC0)>>2; 106cabdff1aSopenharmony_ci p[1] &= 0x3F; 107cabdff1aSopenharmony_ci }else{ 108cabdff1aSopenharmony_ci header |= p[1] & 0x30; 109cabdff1aSopenharmony_ci p[1] &= 0xCF; 110cabdff1aSopenharmony_ci } 111cabdff1aSopenharmony_ci } 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_ci AV_WB32(out->data, header); 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci ret = 0; 116cabdff1aSopenharmony_ci 117cabdff1aSopenharmony_cifail: 118cabdff1aSopenharmony_ci av_packet_free(&in); 119cabdff1aSopenharmony_ci return ret; 120cabdff1aSopenharmony_ci} 121cabdff1aSopenharmony_ci 122cabdff1aSopenharmony_cistatic const enum AVCodecID codec_ids[] = { 123cabdff1aSopenharmony_ci AV_CODEC_ID_MP3, AV_CODEC_ID_NONE, 124cabdff1aSopenharmony_ci}; 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_mp3_header_decompress_bsf = { 127cabdff1aSopenharmony_ci .p.name = "mp3decomp", 128cabdff1aSopenharmony_ci .p.codec_ids = codec_ids, 129cabdff1aSopenharmony_ci .filter = mp3_header_decompress, 130cabdff1aSopenharmony_ci}; 131