Mercurial > libavcodec.hg
annotate mpegaudio_parser.c @ 8991:ca768cb2bfb6 libavcodec
Use last decoded SPS as current SPS in order to parse picture timing SEI
correctly. This works around an apparent H.264 standard deficiency.
Patch by Ivan Schreter, schreter gmx net
author | cehoyos |
---|---|
date | Fri, 20 Feb 2009 16:20:01 +0000 |
parents | 54e2916c25a5 |
children | 043574c5c153 |
rev | line source |
---|---|
1613 | 1 /* |
4913 | 2 * MPEG Audio parser |
8629
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
8587
diff
changeset
|
3 * Copyright (c) 2003 Fabrice Bellard |
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
8587
diff
changeset
|
4 * Copyright (c) 2003 Michael Niedermayer |
1613 | 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 (Mns Rullgrd <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 */ | |
8420
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
47 int ff_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate) |
5050 | 48 { |
8641 | 49 MPADecodeHeader s1, *s = &s1; |
5050 | 50 |
51 if (ff_mpa_check_header(head) != 0) | |
52 return -1; | |
53 | |
5051 | 54 if (ff_mpegaudio_decode_header(s, head) != 0) { |
5050 | 55 return -1; |
56 } | |
57 | |
58 switch(s->layer) { | |
59 case 1: | |
8587 | 60 avctx->codec_id = CODEC_ID_MP1; |
8420
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
61 *frame_size = 384; |
5050 | 62 break; |
63 case 2: | |
8587 | 64 avctx->codec_id = CODEC_ID_MP2; |
8420
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
65 *frame_size = 1152; |
5050 | 66 break; |
67 default: | |
68 case 3: | |
8587 | 69 avctx->codec_id = CODEC_ID_MP3; |
5050 | 70 if (s->lsf) |
8420
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
71 *frame_size = 576; |
5050 | 72 else |
8420
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
73 *frame_size = 1152; |
5050 | 74 break; |
75 } | |
76 | |
77 *sample_rate = s->sample_rate; | |
8420
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
78 *channels = s->nb_channels; |
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
79 *bit_rate = s->bit_rate; |
5050 | 80 avctx->sub_id = s->layer; |
81 return s->frame_size; | |
82 } | |
83 | |
1613 | 84 static int mpegaudio_parse_init(AVCodecParserContext *s1) |
85 { | |
86 MpegAudioParseContext *s = s1->priv_data; | |
87 s->inbuf_ptr = s->inbuf; | |
88 return 0; | |
89 } | |
90 | |
91 static int mpegaudio_parse(AVCodecParserContext *s1, | |
92 AVCodecContext *avctx, | |
4931
0d1cc37d9430
make some parser parameters const to avoid casting const to non-const
aurel
parents:
4914
diff
changeset
|
93 const uint8_t **poutbuf, int *poutbuf_size, |
1613 | 94 const uint8_t *buf, int buf_size) |
95 { | |
96 MpegAudioParseContext *s = s1->priv_data; | |
8420
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
97 int len, ret, sr, channels, bit_rate, frame_size; |
1613 | 98 uint32_t header; |
99 const uint8_t *buf_ptr; | |
100 | |
101 *poutbuf = NULL; | |
102 *poutbuf_size = 0; | |
103 buf_ptr = buf; | |
104 while (buf_size > 0) { | |
2979 | 105 len = s->inbuf_ptr - s->inbuf; |
106 if (s->frame_size == 0) { | |
1613 | 107 /* special case for next header for first frame in free |
108 format case (XXX: find a simpler method) */ | |
109 if (s->free_format_next_header != 0) { | |
5089 | 110 AV_WB32(s->inbuf, s->free_format_next_header); |
1613 | 111 s->inbuf_ptr = s->inbuf + 4; |
112 s->free_format_next_header = 0; | |
113 goto got_header; | |
114 } | |
2979 | 115 /* no header seen : find one. We need at least MPA_HEADER_SIZE |
1613 | 116 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
|
117 len = FFMIN(MPA_HEADER_SIZE - len, buf_size); |
2979 | 118 if (len > 0) { |
119 memcpy(s->inbuf_ptr, buf_ptr, len); | |
120 buf_ptr += len; | |
121 buf_size -= len; | |
122 s->inbuf_ptr += len; | |
123 } | |
124 if ((s->inbuf_ptr - s->inbuf) >= MPA_HEADER_SIZE) { | |
1613 | 125 got_header: |
5089 | 126 header = AV_RB32(s->inbuf); |
1613 | 127 |
8420
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
128 ret = ff_mpa_decode_header(avctx, header, &sr, &channels, &frame_size, &bit_rate); |
1613 | 129 if (ret < 0) { |
2470
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
130 s->header_count= -2; |
2979 | 131 /* no sync found : move by one byte (inefficient, but simple!) */ |
132 memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); | |
133 s->inbuf_ptr--; | |
4652 | 134 dprintf(avctx, "skip %x\n", header); |
1613 | 135 /* reset free format frame size to give a chance |
136 to get a new bitrate */ | |
137 s->free_format_frame_size = 0; | |
2979 | 138 } else { |
2470
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
139 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
|
140 s->header_count= -3; |
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
141 s->header= header; |
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
142 s->header_count++; |
1613 | 143 s->frame_size = ret; |
2967 | 144 |
1613 | 145 #if 0 |
146 /* free format: prepare to compute frame size */ | |
8641 | 147 if (ff_mpegaudio_decode_header((MPADecodeHeader *)s, header) == 1) { |
2979 | 148 s->frame_size = -1; |
1613 | 149 } |
150 #endif | |
8420
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
151 if(s->header_count > 1){ |
5260 | 152 avctx->sample_rate= sr; |
8420
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
153 avctx->channels = channels; |
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
154 avctx->frame_size = frame_size; |
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
155 avctx->bit_rate = bit_rate; |
2b0d01be134f
Change mpeg audio parser so it only sets frame_size, channels and bit_rate
michael
parents:
5260
diff
changeset
|
156 } |
5259 | 157 } |
2979 | 158 } |
2967 | 159 } else |
1613 | 160 #if 0 |
161 if (s->frame_size == -1) { | |
162 /* free format : find next sync to compute frame size */ | |
2979 | 163 len = MPA_MAX_CODED_FRAME_SIZE - len; |
164 if (len > buf_size) | |
165 len = buf_size; | |
1613 | 166 if (len == 0) { |
2979 | 167 /* frame too long: resync */ |
1613 | 168 s->frame_size = 0; |
2979 | 169 memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); |
170 s->inbuf_ptr--; | |
1613 | 171 } else { |
172 uint8_t *p, *pend; | |
173 uint32_t header1; | |
174 int padding; | |
175 | |
176 memcpy(s->inbuf_ptr, buf_ptr, len); | |
177 /* check for header */ | |
178 p = s->inbuf_ptr - 3; | |
179 pend = s->inbuf_ptr + len - 4; | |
180 while (p <= pend) { | |
5089 | 181 header = AV_RB32(p); |
182 header1 = AV_RB32(s->inbuf); | |
1613 | 183 /* check with high probability that we have a |
184 valid header */ | |
185 if ((header & SAME_HEADER_MASK) == | |
186 (header1 & SAME_HEADER_MASK)) { | |
187 /* header found: update pointers */ | |
188 len = (p + 4) - s->inbuf_ptr; | |
189 buf_ptr += len; | |
190 buf_size -= len; | |
191 s->inbuf_ptr = p; | |
192 /* compute frame size */ | |
193 s->free_format_next_header = header; | |
194 s->free_format_frame_size = s->inbuf_ptr - s->inbuf; | |
195 padding = (header1 >> 9) & 1; | |
196 if (s->layer == 1) | |
197 s->free_format_frame_size -= padding * 4; | |
198 else | |
199 s->free_format_frame_size -= padding; | |
4652 | 200 dprintf(avctx, "free frame size=%d padding=%d\n", |
1613 | 201 s->free_format_frame_size, padding); |
8641 | 202 ff_mpegaudio_decode_header((MPADecodeHeader *)s, header1); |
1613 | 203 goto next_data; |
204 } | |
205 p++; | |
206 } | |
207 /* not found: simply increase pointers */ | |
208 buf_ptr += len; | |
209 s->inbuf_ptr += len; | |
210 buf_size -= len; | |
211 } | |
2979 | 212 } else |
1613 | 213 #endif |
214 if (len < s->frame_size) { | |
215 if (s->frame_size > MPA_MAX_CODED_FRAME_SIZE) | |
216 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
|
217 len = FFMIN(s->frame_size - len, buf_size); |
2979 | 218 memcpy(s->inbuf_ptr, buf_ptr, len); |
219 buf_ptr += len; | |
220 s->inbuf_ptr += len; | |
221 buf_size -= len; | |
222 } | |
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
|
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 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
|
225 && 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
|
226 if(s->header_count > 0){ |
4931
0d1cc37d9430
make some parser parameters const to avoid casting const to non-const
aurel
parents:
4914
diff
changeset
|
227 *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
|
228 *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
|
229 } |
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
230 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
|
231 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
|
232 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
|
233 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
|
234 } |
949bc256f1e3
dont copy frame if the whole mp1/2/3 frame is available in one piece in the input
michael
parents:
3456
diff
changeset
|
235 |
1613 | 236 // next_data: |
2967 | 237 if (s->frame_size > 0 && |
1613 | 238 (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
|
239 if(s->header_count > 0){ |
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
240 *poutbuf = s->inbuf; |
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
241 *poutbuf_size = s->inbuf_ptr - s->inbuf; |
06aafb585f69
require a few valid and equal mp3 headers for resync
michael
parents:
2389
diff
changeset
|
242 } |
2979 | 243 s->inbuf_ptr = s->inbuf; |
244 s->frame_size = 0; | |
245 break; | |
246 } | |
1613 | 247 } |
248 return buf_ptr - buf; | |
249 } | |
4397
acb9faabab8d
Allows the AC3 parser to read the frame size and codec parameters from E-AC3 streams,
gpoirier
parents:
4310
diff
changeset
|
250 |
acb9faabab8d
Allows the AC3 parser to read the frame size and codec parameters from E-AC3 streams,
gpoirier
parents:
4310
diff
changeset
|
251 |
1613 | 252 AVCodecParser mpegaudio_parser = { |
8586
d7d0cde5f308
Add dummy mp1_decoder to complement the existing dummy mp2/mp3 decoders.
michael
parents:
8420
diff
changeset
|
253 { CODEC_ID_MP1, CODEC_ID_MP2, CODEC_ID_MP3 }, |
1613 | 254 sizeof(MpegAudioParseContext), |
255 mpegaudio_parse_init, | |
256 mpegaudio_parse, | |
257 NULL, | |
258 }; |