Mercurial > libavcodec.hg
comparison mpegaudio_parser.c @ 9894:78b2fc137c27 libavcodec
Rewrite mp3 parser. New code is much simpler and does not drop
stuff at random.
author | michael |
---|---|
date | Tue, 30 Jun 2009 03:12:50 +0000 |
parents | 6409c6ba8040 |
children | 30dad2d5e7fe |
comparison
equal
deleted
inserted
replaced
9893:1d10ec092b64 | 9894:78b2fc137c27 |
---|---|
24 #include "mpegaudio.h" | 24 #include "mpegaudio.h" |
25 #include "mpegaudiodecheader.h" | 25 #include "mpegaudiodecheader.h" |
26 | 26 |
27 | 27 |
28 typedef struct MpegAudioParseContext { | 28 typedef struct MpegAudioParseContext { |
29 uint8_t inbuf[MPA_MAX_CODED_FRAME_SIZE]; /* input buffer */ | 29 ParseContext pc; |
30 uint8_t *inbuf_ptr; | |
31 int frame_size; | 30 int frame_size; |
32 int free_format_frame_size; | |
33 int free_format_next_header; | |
34 uint32_t header; | 31 uint32_t header; |
35 int header_count; | 32 int header_count; |
36 } MpegAudioParseContext; | 33 } MpegAudioParseContext; |
37 | 34 |
38 #define MPA_HEADER_SIZE 4 | 35 #define MPA_HEADER_SIZE 4 |
79 *bit_rate = s->bit_rate; | 76 *bit_rate = s->bit_rate; |
80 avctx->sub_id = s->layer; | 77 avctx->sub_id = s->layer; |
81 return s->frame_size; | 78 return s->frame_size; |
82 } | 79 } |
83 | 80 |
84 static av_cold 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, | 81 static int mpegaudio_parse(AVCodecParserContext *s1, |
92 AVCodecContext *avctx, | 82 AVCodecContext *avctx, |
93 const uint8_t **poutbuf, int *poutbuf_size, | 83 const uint8_t **poutbuf, int *poutbuf_size, |
94 const uint8_t *buf, int buf_size) | 84 const uint8_t *buf, int buf_size) |
95 { | 85 { |
96 MpegAudioParseContext *s = s1->priv_data; | 86 MpegAudioParseContext *s = s1->priv_data; |
97 int len, ret, sr, channels, bit_rate, frame_size; | 87 ParseContext *pc = &s->pc; |
98 uint32_t header; | 88 uint32_t state= pc->state; |
99 const uint8_t *buf_ptr; | 89 int i; |
90 int next= END_NOT_FOUND; | |
100 | 91 |
101 *poutbuf = NULL; | 92 for(i=0; i<buf_size; ){ |
102 *poutbuf_size = 0; | 93 if(s->frame_size){ |
103 buf_ptr = buf; | 94 int inc= FFMIN(buf_size - i, s->frame_size); |
104 while (buf_size > 0) { | 95 i += inc; |
105 len = s->inbuf_ptr - s->inbuf; | 96 s->frame_size -= inc; |
106 if (s->frame_size == 0) { | 97 |
107 /* special case for next header for first frame in free | 98 if(!s->frame_size){ |
108 format case (XXX: find a simpler method) */ | 99 next= i; |
109 if (s->free_format_next_header != 0) { | 100 break; |
110 AV_WB32(s->inbuf, s->free_format_next_header); | |
111 s->inbuf_ptr = s->inbuf + 4; | |
112 s->free_format_next_header = 0; | |
113 goto got_header; | |
114 } | 101 } |
115 /* no header seen : find one. We need at least MPA_HEADER_SIZE | 102 }else{ |
116 bytes to parse it */ | 103 while(i<buf_size){ |
117 len = FFMIN(MPA_HEADER_SIZE - len, buf_size); | 104 int ret, sr, channels, bit_rate, frame_size; |
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) { | |
125 got_header: | |
126 header = AV_RB32(s->inbuf); | |
127 | 105 |
128 ret = ff_mpa_decode_header(avctx, header, &sr, &channels, &frame_size, &bit_rate); | 106 state= (state<<8) + buf[i++]; |
129 if (ret < 0) { | 107 |
108 ret = ff_mpa_decode_header(avctx, state, &sr, &channels, &frame_size, &bit_rate); | |
109 if (ret < 4) { | |
130 s->header_count= -2; | 110 s->header_count= -2; |
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--; | |
134 dprintf(avctx, "skip %x\n", header); | |
135 /* reset free format frame size to give a chance | |
136 to get a new bitrate */ | |
137 s->free_format_frame_size = 0; | |
138 } else { | 111 } else { |
139 if((header&SAME_HEADER_MASK) != (s->header&SAME_HEADER_MASK) && s->header) | 112 if((state&SAME_HEADER_MASK) != (s->header&SAME_HEADER_MASK) && s->header) |
140 s->header_count= -3; | 113 s->header_count= -3; |
141 s->header= header; | 114 s->header= state; |
142 s->header_count++; | 115 s->header_count++; |
143 s->frame_size = ret; | 116 s->frame_size = ret-4; |
144 | 117 |
145 #if 0 | |
146 /* free format: prepare to compute frame size */ | |
147 if (ff_mpegaudio_decode_header((MPADecodeHeader *)s, header) == 1) { | |
148 s->frame_size = -1; | |
149 } | |
150 #endif | |
151 if(s->header_count > 1){ | 118 if(s->header_count > 1){ |
152 avctx->sample_rate= sr; | 119 avctx->sample_rate= sr; |
153 avctx->channels = channels; | 120 avctx->channels = channels; |
154 avctx->frame_size = frame_size; | 121 avctx->frame_size = frame_size; |
155 avctx->bit_rate = bit_rate; | 122 avctx->bit_rate = bit_rate; |
156 } | 123 } |
124 break; | |
157 } | 125 } |
158 } | 126 } |
159 } else | |
160 #if 0 | |
161 if (s->frame_size == -1) { | |
162 /* free format : find next sync to compute frame size */ | |
163 len = MPA_MAX_CODED_FRAME_SIZE - len; | |
164 if (len > buf_size) | |
165 len = buf_size; | |
166 if (len == 0) { | |
167 /* frame too long: resync */ | |
168 s->frame_size = 0; | |
169 memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); | |
170 s->inbuf_ptr--; | |
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) { | |
181 header = AV_RB32(p); | |
182 header1 = AV_RB32(s->inbuf); | |
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; | |
200 dprintf(avctx, "free frame size=%d padding=%d\n", | |
201 s->free_format_frame_size, padding); | |
202 ff_mpegaudio_decode_header((MPADecodeHeader *)s, header1); | |
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 } | |
212 } else | |
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; | |
217 len = FFMIN(s->frame_size - len, buf_size); | |
218 memcpy(s->inbuf_ptr, buf_ptr, len); | |
219 buf_ptr += len; | |
220 s->inbuf_ptr += len; | |
221 buf_size -= len; | |
222 } | |
223 | |
224 if(s->frame_size > 0 && buf_ptr - buf == s->inbuf_ptr - s->inbuf | |
225 && buf_size + buf_ptr - buf >= s->frame_size){ | |
226 *poutbuf = buf; | |
227 *poutbuf_size = s->frame_size; | |
228 buf_ptr = buf + s->frame_size; | |
229 s->inbuf_ptr = s->inbuf; | |
230 s->frame_size = 0; | |
231 break; | |
232 } | |
233 | |
234 // next_data: | |
235 if (s->frame_size > 0 && | |
236 (s->inbuf_ptr - s->inbuf) >= s->frame_size) { | |
237 *poutbuf = s->inbuf; | |
238 *poutbuf_size = s->inbuf_ptr - s->inbuf; | |
239 s->inbuf_ptr = s->inbuf; | |
240 s->frame_size = 0; | |
241 break; | |
242 } | 127 } |
243 } | 128 } |
244 return buf_ptr - buf; | 129 |
130 pc->state= state; | |
131 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { | |
132 *poutbuf = NULL; | |
133 *poutbuf_size = 0; | |
134 return buf_size; | |
135 } | |
136 | |
137 *poutbuf = buf; | |
138 *poutbuf_size = buf_size; | |
139 return next; | |
245 } | 140 } |
246 | 141 |
247 | 142 |
248 AVCodecParser mpegaudio_parser = { | 143 AVCodecParser mpegaudio_parser = { |
249 { CODEC_ID_MP1, CODEC_ID_MP2, CODEC_ID_MP3 }, | 144 { CODEC_ID_MP1, CODEC_ID_MP2, CODEC_ID_MP3 }, |
250 sizeof(MpegAudioParseContext), | 145 sizeof(MpegAudioParseContext), |
251 mpegaudio_parse_init, | 146 NULL, |
252 mpegaudio_parse, | 147 mpegaudio_parse, |
253 NULL, | 148 NULL, |
254 }; | 149 }; |