Mercurial > libavcodec.hg
annotate mpegaudio_parser.c @ 6528:28d0e7dac45d libavcodec
pld instruction are used in libavcodec/armv4l/dsputil_arm_s.S which can be used
on armv4 that doesn't support this instruction. Futhermore pld is a nop on some
armv5 processor like arm926. Detect if pld is supported and have the
preprocessor remove it when it's not supported.
Fixes issue 393.
patch by matthieu castet, castet.matthieu free fr
| author | diego |
|---|---|
| date | Mon, 24 Mar 2008 11:49:59 +0000 |
| parents | d623b3171830 |
| children | 2b0d01be134f |
| rev | line source |
|---|---|
| 1613 | 1 /* |
| 4913 | 2 * MPEG Audio parser |
| 1613 | 3 * Copyright (c) 2003 Fabrice Bellard. |
| 4 * Copyright (c) 2003 Michael Niedermayer. | |
| 5 * | |
|
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3776
diff
changeset
|
6 * This file is part of FFmpeg. |
|
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3776
diff
changeset
|
7 * |
|
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3776
diff
changeset
|
8 * FFmpeg is free software; you can redistribute it and/or |
| 1613 | 9 * modify it under the terms of the GNU Lesser General Public |
| 10 * License as published by the Free Software Foundation; either | |
|
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3776
diff
changeset
|
11 * version 2.1 of the License, or (at your option) any later version. |
| 1613 | 12 * |
|
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3776
diff
changeset
|
13 * FFmpeg is distributed in the hope that it will be useful, |
| 1613 | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 16 * Lesser General Public License for more details. | |
| 17 * | |
| 18 * You should have received a copy of the GNU Lesser General Public | |
|
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3776
diff
changeset
|
19 * License along with FFmpeg; if not, write to the Free Software |
|
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2979
diff
changeset
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 1613 | 21 */ |
| 2967 | 22 |
| 4913 | 23 #include "parser.h" |
| 24 #include "mpegaudio.h" | |
| 5050 | 25 #include "mpegaudiodecheader.h" |
| 2386 | 26 |
| 27 | |
| 1613 | 28 typedef struct MpegAudioParseContext { |
| 2979 | 29 uint8_t inbuf[MPA_MAX_CODED_FRAME_SIZE]; /* input buffer */ |
| 1613 | 30 uint8_t *inbuf_ptr; |
| 31 int frame_size; | |
| 32 int free_format_frame_size; | |
| 33 int free_format_next_header; | |
|
2470
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
34 uint32_t header; |
|
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
35 int header_count; |
| 1613 | 36 } MpegAudioParseContext; |
| 37 | |
| 38 #define MPA_HEADER_SIZE 4 | |
| 39 | |
| 40 /* header + layer + bitrate + freq + lsf/mpeg25 */ | |
|
2522
e25782262d7d
kill warnings patch by (M?ns Rullg?rd <mru inprovide com>)
michael
parents:
2486
diff
changeset
|
41 #undef SAME_HEADER_MASK /* mpegaudio.h defines different version */ |
| 1613 | 42 #define SAME_HEADER_MASK \ |
| 2480 | 43 (0xffe00000 | (3 << 17) | (3 << 10) | (3 << 19)) |
| 1613 | 44 |
| 5050 | 45 /* useful helper to get mpeg audio stream infos. Return -1 if error in |
| 46 header, otherwise the coded frame size in bytes */ | |
| 5051 | 47 int ff_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate) |
| 5050 | 48 { |
| 49 MPADecodeContext s1, *s = &s1; | |
| 50 s1.avctx = avctx; | |
| 51 | |
| 52 if (ff_mpa_check_header(head) != 0) | |
| 53 return -1; | |
| 54 | |
| 5051 | 55 if (ff_mpegaudio_decode_header(s, head) != 0) { |
| 5050 | 56 return -1; |
| 57 } | |
| 58 | |
| 59 switch(s->layer) { | |
| 60 case 1: | |
| 61 avctx->frame_size = 384; | |
| 62 break; | |
| 63 case 2: | |
| 64 avctx->frame_size = 1152; | |
| 65 break; | |
| 66 default: | |
| 67 case 3: | |
| 68 if (s->lsf) | |
| 69 avctx->frame_size = 576; | |
| 70 else | |
| 71 avctx->frame_size = 1152; | |
| 72 break; | |
| 73 } | |
| 74 | |
| 75 *sample_rate = s->sample_rate; | |
| 76 avctx->channels = s->nb_channels; | |
| 77 avctx->bit_rate = s->bit_rate; | |
| 78 avctx->sub_id = s->layer; | |
| 79 return s->frame_size; | |
| 80 } | |
| 81 | |
| 1613 | 82 static int mpegaudio_parse_init(AVCodecParserContext *s1) |
| 83 { | |
| 84 MpegAudioParseContext *s = s1->priv_data; | |
| 85 s->inbuf_ptr = s->inbuf; | |
| 86 return 0; | |
| 87 } | |
| 88 | |
| 89 static int mpegaudio_parse(AVCodecParserContext *s1, | |
| 90 AVCodecContext *avctx, | |
|
4931
0d1cc37d9430
make some parser parameters const to avoid casting const to non-const
aurel
parents:
4914
diff
changeset
|
91 const uint8_t **poutbuf, int *poutbuf_size, |
| 1613 | 92 const uint8_t *buf, int buf_size) |
| 93 { | |
| 94 MpegAudioParseContext *s = s1->priv_data; | |
|
2470
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
95 int len, ret, sr; |
| 1613 | 96 uint32_t header; |
| 97 const uint8_t *buf_ptr; | |
| 98 | |
| 99 *poutbuf = NULL; | |
| 100 *poutbuf_size = 0; | |
| 101 buf_ptr = buf; | |
| 102 while (buf_size > 0) { | |
| 2979 | 103 len = s->inbuf_ptr - s->inbuf; |
| 104 if (s->frame_size == 0) { | |
| 1613 | 105 /* special case for next header for first frame in free |
| 106 format case (XXX: find a simpler method) */ | |
| 107 if (s->free_format_next_header != 0) { | |
| 5089 | 108 AV_WB32(s->inbuf, s->free_format_next_header); |
| 1613 | 109 s->inbuf_ptr = s->inbuf + 4; |
| 110 s->free_format_next_header = 0; | |
| 111 goto got_header; | |
| 112 } | |
| 2979 | 113 /* no header seen : find one. We need at least MPA_HEADER_SIZE |
| 1613 | 114 bytes to parse it */ |
|
3639
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
115 len = FFMIN(MPA_HEADER_SIZE - len, buf_size); |
| 2979 | 116 if (len > 0) { |
| 117 memcpy(s->inbuf_ptr, buf_ptr, len); | |
| 118 buf_ptr += len; | |
| 119 buf_size -= len; | |
| 120 s->inbuf_ptr += len; | |
| 121 } | |
| 122 if ((s->inbuf_ptr - s->inbuf) >= MPA_HEADER_SIZE) { | |
| 1613 | 123 got_header: |
| 5089 | 124 header = AV_RB32(s->inbuf); |
| 1613 | 125 |
| 5051 | 126 ret = ff_mpa_decode_header(avctx, header, &sr); |
| 1613 | 127 if (ret < 0) { |
|
2470
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
128 s->header_count= -2; |
| 2979 | 129 /* no sync found : move by one byte (inefficient, but simple!) */ |
| 130 memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); | |
| 131 s->inbuf_ptr--; | |
| 4652 | 132 dprintf(avctx, "skip %x\n", header); |
| 1613 | 133 /* reset free format frame size to give a chance |
| 134 to get a new bitrate */ | |
| 135 s->free_format_frame_size = 0; | |
| 2979 | 136 } else { |
|
2470
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
137 if((header&SAME_HEADER_MASK) != (s->header&SAME_HEADER_MASK) && s->header) |
|
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
138 s->header_count= -3; |
|
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
139 s->header= header; |
|
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
140 s->header_count++; |
| 1613 | 141 s->frame_size = ret; |
| 2967 | 142 |
| 1613 | 143 #if 0 |
| 144 /* free format: prepare to compute frame size */ | |
| 5051 | 145 if (ff_mpegaudio_decode_header(s, header) == 1) { |
| 2979 | 146 s->frame_size = -1; |
| 1613 | 147 } |
| 148 #endif | |
| 5260 | 149 if(s->header_count > 1) |
| 150 avctx->sample_rate= sr; | |
| 5259 | 151 } |
| 2979 | 152 } |
| 2967 | 153 } else |
| 1613 | 154 #if 0 |
| 155 if (s->frame_size == -1) { | |
| 156 /* free format : find next sync to compute frame size */ | |
| 2979 | 157 len = MPA_MAX_CODED_FRAME_SIZE - len; |
| 158 if (len > buf_size) | |
| 159 len = buf_size; | |
| 1613 | 160 if (len == 0) { |
| 2979 | 161 /* frame too long: resync */ |
| 1613 | 162 s->frame_size = 0; |
| 2979 | 163 memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); |
| 164 s->inbuf_ptr--; | |
| 1613 | 165 } else { |
| 166 uint8_t *p, *pend; | |
| 167 uint32_t header1; | |
| 168 int padding; | |
| 169 | |
| 170 memcpy(s->inbuf_ptr, buf_ptr, len); | |
| 171 /* check for header */ | |
| 172 p = s->inbuf_ptr - 3; | |
| 173 pend = s->inbuf_ptr + len - 4; | |
| 174 while (p <= pend) { | |
| 5089 | 175 header = AV_RB32(p); |
| 176 header1 = AV_RB32(s->inbuf); | |
| 1613 | 177 /* check with high probability that we have a |
| 178 valid header */ | |
| 179 if ((header & SAME_HEADER_MASK) == | |
| 180 (header1 & SAME_HEADER_MASK)) { | |
| 181 /* header found: update pointers */ | |
| 182 len = (p + 4) - s->inbuf_ptr; | |
| 183 buf_ptr += len; | |
| 184 buf_size -= len; | |
| 185 s->inbuf_ptr = p; | |
| 186 /* compute frame size */ | |
| 187 s->free_format_next_header = header; | |
| 188 s->free_format_frame_size = s->inbuf_ptr - s->inbuf; | |
| 189 padding = (header1 >> 9) & 1; | |
| 190 if (s->layer == 1) | |
| 191 s->free_format_frame_size -= padding * 4; | |
| 192 else | |
| 193 s->free_format_frame_size -= padding; | |
| 4652 | 194 dprintf(avctx, "free frame size=%d padding=%d\n", |
| 1613 | 195 s->free_format_frame_size, padding); |
| 5051 | 196 ff_mpegaudio_decode_header(s, header1); |
| 1613 | 197 goto next_data; |
| 198 } | |
| 199 p++; | |
| 200 } | |
| 201 /* not found: simply increase pointers */ | |
| 202 buf_ptr += len; | |
| 203 s->inbuf_ptr += len; | |
| 204 buf_size -= len; | |
| 205 } | |
| 2979 | 206 } else |
| 1613 | 207 #endif |
| 208 if (len < s->frame_size) { | |
| 209 if (s->frame_size > MPA_MAX_CODED_FRAME_SIZE) | |
| 210 s->frame_size = MPA_MAX_CODED_FRAME_SIZE; | |
|
3639
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
211 len = FFMIN(s->frame_size - len, buf_size); |
| 2979 | 212 memcpy(s->inbuf_ptr, buf_ptr, len); |
| 213 buf_ptr += len; | |
| 214 s->inbuf_ptr += len; | |
| 215 buf_size -= len; | |
| 216 } | |
|
3639
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
217 |
|
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
218 if(s->frame_size > 0 && buf_ptr - buf == s->inbuf_ptr - s->inbuf |
|
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
219 && buf_size + buf_ptr - buf >= s->frame_size){ |
|
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
220 if(s->header_count > 0){ |
|
4931
0d1cc37d9430
make some parser parameters const to avoid casting const to non-const
aurel
parents:
4914
diff
changeset
|
221 *poutbuf = buf; |
|
3639
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
222 *poutbuf_size = s->frame_size; |
|
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
223 } |
|
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
224 buf_ptr = buf + s->frame_size; |
|
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
225 s->inbuf_ptr = s->inbuf; |
|
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
226 s->frame_size = 0; |
|
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
227 break; |
|
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
228 } |
|
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
229 |
| 1613 | 230 // next_data: |
| 2967 | 231 if (s->frame_size > 0 && |
| 1613 | 232 (s->inbuf_ptr - s->inbuf) >= s->frame_size) { |
|
2470
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
233 if(s->header_count > 0){ |
|
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
234 *poutbuf = s->inbuf; |
|
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
235 *poutbuf_size = s->inbuf_ptr - s->inbuf; |
|
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
236 } |
| 2979 | 237 s->inbuf_ptr = s->inbuf; |
| 238 s->frame_size = 0; | |
| 239 break; | |
| 240 } | |
| 1613 | 241 } |
| 242 return buf_ptr - buf; | |
| 243 } | |
|
4397
acb9faabab8d
Allows the AC3 parser to read the frame size and codec parameters from E-AC3 streams,
gpoirier
parents:
4310
diff
changeset
|
244 |
|
acb9faabab8d
Allows the AC3 parser to read the frame size and codec parameters from E-AC3 streams,
gpoirier
parents:
4310
diff
changeset
|
245 |
| 1613 | 246 AVCodecParser mpegaudio_parser = { |
| 247 { CODEC_ID_MP2, CODEC_ID_MP3 }, | |
| 248 sizeof(MpegAudioParseContext), | |
| 249 mpegaudio_parse_init, | |
| 250 mpegaudio_parse, | |
| 251 NULL, | |
| 252 }; |
