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