Mercurial > libavcodec.hg
annotate parser.c @ 6994:5a5ded44808a libavcodec
In mpeg1/2 timestamps are associated with the access unit which
contains the first picture startcode that commences in the PES
packet, instead of the first access unit that commences in the
PES packet. Fix the parser to
handle that properly. This was a very long standing bug ...
The change to the seek regressions is because the mpeg ts muxer
stores too many invalid and randomized timestamps which overflow
the 4 entry buffer we use in the parser.
author | michael |
---|---|
date | Tue, 03 Jun 2008 02:43:17 +0000 |
parents | f855f314fb62 |
children | b5f5257c0c70 |
rev | line source |
---|---|
1613 | 1 /* |
2 * Audio and Video frame extraction | |
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 */ |
4943 | 22 |
4150
2205aefb22b7
move AVCodecParser prototypes and definitions to parser.h, and move mpegvideo parser to mpeg12.c
bcoudurier
parents:
4146
diff
changeset
|
23 #include "parser.h" |
1613 | 24 |
25 AVCodecParser *av_first_parser = NULL; | |
26 | |
6011 | 27 AVCodecParser* av_parser_next(AVCodecParser *p){ |
28 if(p) return p->next; | |
29 else return av_first_parser; | |
30 } | |
31 | |
1613 | 32 void av_register_codec_parser(AVCodecParser *parser) |
33 { | |
34 parser->next = av_first_parser; | |
35 av_first_parser = parser; | |
36 } | |
37 | |
38 AVCodecParserContext *av_parser_init(int codec_id) | |
39 { | |
40 AVCodecParserContext *s; | |
41 AVCodecParser *parser; | |
42 int ret; | |
2967 | 43 |
2486
f2a9559db6ac
10l (array gets padded with 0 which is CODEC_ID_NONE -> parsers claim to support CODEC_ID_NONE)
michael
parents:
2480
diff
changeset
|
44 if(codec_id == CODEC_ID_NONE) |
f2a9559db6ac
10l (array gets padded with 0 which is CODEC_ID_NONE -> parsers claim to support CODEC_ID_NONE)
michael
parents:
2480
diff
changeset
|
45 return NULL; |
1613 | 46 |
47 for(parser = av_first_parser; parser != NULL; parser = parser->next) { | |
48 if (parser->codec_ids[0] == codec_id || | |
49 parser->codec_ids[1] == codec_id || | |
2348 | 50 parser->codec_ids[2] == codec_id || |
51 parser->codec_ids[3] == codec_id || | |
52 parser->codec_ids[4] == codec_id) | |
1613 | 53 goto found; |
54 } | |
55 return NULL; | |
56 found: | |
57 s = av_mallocz(sizeof(AVCodecParserContext)); | |
58 if (!s) | |
59 return NULL; | |
60 s->parser = parser; | |
61 s->priv_data = av_mallocz(parser->priv_data_size); | |
62 if (!s->priv_data) { | |
63 av_free(s); | |
64 return NULL; | |
65 } | |
66 if (parser->parser_init) { | |
67 ret = parser->parser_init(s); | |
68 if (ret != 0) { | |
69 av_free(s->priv_data); | |
70 av_free(s); | |
71 return NULL; | |
72 } | |
73 } | |
2030 | 74 s->fetch_timestamp=1; |
4739
9b4c5d2fb8ce
set pict_type to I type during init so parsers which dont set it get all i frames, fixes mp3 seeking
michael
parents:
4679
diff
changeset
|
75 s->pict_type = FF_I_TYPE; |
1613 | 76 return s; |
77 } | |
78 | |
6985
7c8df4f99d08
Allow matching timestamps to be removed by fetch_timestamp().
michael
parents:
6984
diff
changeset
|
79 void ff_fetch_timestamp(AVCodecParserContext *s, int off, int remove){ |
6983 | 80 int i; |
6986 | 81 |
6983 | 82 s->dts= s->pts= AV_NOPTS_VALUE; |
83 s->offset= 0; | |
84 for(i = 0; i < AV_PARSER_PTS_NB; i++) { | |
6984
22a3d9efb4a2
Add off argument so that fetch_timestamp can search for timestamps
michael
parents:
6983
diff
changeset
|
85 if ( s->next_frame_offset + off >= s->cur_frame_offset[i] |
6986 | 86 &&(s-> frame_offset < s->cur_frame_offset[i] || !s->frame_offset) |
6988
c67a4cff28a1
Our MPEG-TS demuxer does not send complete PES packets but sends them
michael
parents:
6986
diff
changeset
|
87 //check is disabled becausue mpeg-ts doesnt send complete PES packets |
c67a4cff28a1
Our MPEG-TS demuxer does not send complete PES packets but sends them
michael
parents:
6986
diff
changeset
|
88 && /*s->next_frame_offset + off <*/ s->cur_frame_end[i]){ |
6983 | 89 s->dts= s->cur_frame_dts[i]; |
90 s->pts= s->cur_frame_pts[i]; | |
91 s->offset = s->next_frame_offset - s->cur_frame_offset[i]; | |
6985
7c8df4f99d08
Allow matching timestamps to be removed by fetch_timestamp().
michael
parents:
6984
diff
changeset
|
92 if(remove) |
7c8df4f99d08
Allow matching timestamps to be removed by fetch_timestamp().
michael
parents:
6984
diff
changeset
|
93 s->cur_frame_offset[i]= INT64_MAX; |
6983 | 94 } |
95 } | |
96 } | |
97 | |
3989 | 98 /** |
99 * | |
100 * @param buf input | |
101 * @param buf_size input length, to signal EOF, this should be 0 (so that the last frame can be output) | |
102 * @param pts input presentation timestamp | |
103 * @param dts input decoding timestamp | |
104 * @param poutbuf will contain a pointer to the first byte of the output frame | |
105 * @param poutbuf_size will contain the length of the output frame | |
106 * @return the number of bytes of the input bitstream used | |
107 * | |
108 * Example: | |
109 * @code | |
110 * while(in_len){ | |
111 * len = av_parser_parse(myparser, AVCodecContext, &data, &size, | |
112 * in_data, in_len, | |
113 * pts, dts); | |
114 * in_data += len; | |
115 * in_len -= len; | |
116 * | |
4310 | 117 * if(size) |
118 * decode_frame(data, size); | |
3989 | 119 * } |
120 * @endcode | |
121 */ | |
2967 | 122 int av_parser_parse(AVCodecParserContext *s, |
1613 | 123 AVCodecContext *avctx, |
2967 | 124 uint8_t **poutbuf, int *poutbuf_size, |
1696 | 125 const uint8_t *buf, int buf_size, |
126 int64_t pts, int64_t dts) | |
1613 | 127 { |
6982 | 128 int index, i; |
1694
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
129 uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE]; |
2967 | 130 |
1694
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
131 if (buf_size == 0) { |
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
132 /* padding is always necessary even if EOF, so we add it here */ |
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
133 memset(dummy_buf, 0, sizeof(dummy_buf)); |
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
134 buf = dummy_buf; |
1696 | 135 } else { |
136 /* add a new packet descriptor */ | |
6989 | 137 if(pts != AV_NOPTS_VALUE || dts != AV_NOPTS_VALUE){ |
6990 | 138 i = (s->cur_frame_start_index + 1) & (AV_PARSER_PTS_NB - 1); |
139 s->cur_frame_start_index = i; | |
140 s->cur_frame_offset[i] = s->cur_offset; | |
141 s->cur_frame_end[i] = s->cur_offset + buf_size; | |
142 s->cur_frame_pts[i] = pts; | |
143 s->cur_frame_dts[i] = dts; | |
6989 | 144 } |
6977 | 145 } |
1696 | 146 |
6980 | 147 if (s->fetch_timestamp){ |
148 s->fetch_timestamp=0; | |
6977 | 149 s->last_pts = s->pts; |
150 s->last_dts = s->dts; | |
6985
7c8df4f99d08
Allow matching timestamps to be removed by fetch_timestamp().
michael
parents:
6984
diff
changeset
|
151 ff_fetch_timestamp(s, 0, 0); |
1694
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
152 } |
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
153 |
1613 | 154 /* WARNING: the returned index can be negative */ |
4931
0d1cc37d9430
make some parser parameters const to avoid casting const to non-const
aurel
parents:
4913
diff
changeset
|
155 index = s->parser->parser_parse(s, avctx, (const uint8_t **)poutbuf, poutbuf_size, buf, buf_size); |
4122
daae66c03857
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
4104
diff
changeset
|
156 //av_log(NULL, AV_LOG_DEBUG, "parser: in:%"PRId64", %"PRId64", out:%"PRId64", %"PRId64", in:%d out:%d id:%d\n", pts, dts, s->last_pts, s->last_dts, buf_size, *poutbuf_size, avctx->codec_id); |
1613 | 157 /* update the file pointer */ |
158 if (*poutbuf_size) { | |
1696 | 159 /* fill the data for the current frame */ |
6979 | 160 s->frame_offset = s->next_frame_offset; |
2967 | 161 |
1696 | 162 /* offset of the next frame */ |
6979 | 163 s->next_frame_offset = s->cur_offset + index; |
6980 | 164 s->fetch_timestamp=1; |
1613 | 165 } |
166 if (index < 0) | |
167 index = 0; | |
168 s->cur_offset += index; | |
169 return index; | |
170 } | |
171 | |
2777 | 172 /** |
173 * | |
174 * @return 0 if the output buffer is a subset of the input, 1 if it is allocated and must be freed | |
3421
b7826511f7b6
AVBitStreamFilter (some thingy which can modify the bitstream like add or remove global headers or change the headers or ...)
michael
parents:
3395
diff
changeset
|
175 * @deprecated use AVBitstreamFilter |
2777 | 176 */ |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
177 int av_parser_change(AVCodecParserContext *s, |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
178 AVCodecContext *avctx, |
2967 | 179 uint8_t **poutbuf, int *poutbuf_size, |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
180 const uint8_t *buf, int buf_size, int keyframe){ |
2967 | 181 |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
182 if(s && s->parser->split){ |
2777 | 183 if((avctx->flags & CODEC_FLAG_GLOBAL_HEADER) || (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)){ |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
184 int i= s->parser->split(avctx, buf, buf_size); |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
185 buf += i; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
186 buf_size -= i; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
187 } |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
188 } |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
189 |
2864
95bac7109ff0
Kill some compiler warnings. Compiled code verified identical after changes.
mru
parents:
2846
diff
changeset
|
190 /* cast to avoid warning about discarding qualifiers */ |
95bac7109ff0
Kill some compiler warnings. Compiled code verified identical after changes.
mru
parents:
2846
diff
changeset
|
191 *poutbuf= (uint8_t *) buf; |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
192 *poutbuf_size= buf_size; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
193 if(avctx->extradata){ |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
194 if( (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)) |
6481 | 195 /*||(s->pict_type != FF_I_TYPE && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_NOKEY))*/ |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
196 /*||(? && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_BEGIN)*/){ |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
197 int size= buf_size + avctx->extradata_size; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
198 *poutbuf_size= size; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
199 *poutbuf= av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); |
2967 | 200 |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
201 memcpy(*poutbuf, avctx->extradata, avctx->extradata_size); |
2777 | 202 memcpy((*poutbuf) + avctx->extradata_size, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
203 return 1; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
204 } |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
205 } |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
206 |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
207 return 0; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
208 } |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
209 |
1613 | 210 void av_parser_close(AVCodecParserContext *s) |
211 { | |
6891 | 212 if(s){ |
6892 | 213 if (s->parser->parser_close) |
214 s->parser->parser_close(s); | |
215 av_free(s->priv_data); | |
216 av_free(s); | |
6891 | 217 } |
1613 | 218 } |
219 | |
220 /*****************************************************/ | |
221 | |
222 /** | |
223 * combines the (truncated) bitstream to a complete frame | |
6534 | 224 * @returns -1 if no complete frame could be created, AVERROR(ENOMEM) if there was a memory allocation error |
1613 | 225 */ |
4931
0d1cc37d9430
make some parser parameters const to avoid casting const to non-const
aurel
parents:
4913
diff
changeset
|
226 int ff_combine_frame(ParseContext *pc, int next, const uint8_t **buf, int *buf_size) |
1613 | 227 { |
228 #if 0 | |
229 if(pc->overread){ | |
230 printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); | |
231 printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); | |
232 } | |
233 #endif | |
234 | |
4795 | 235 /* Copy overread bytes from last frame into buffer. */ |
1613 | 236 for(; pc->overread>0; pc->overread--){ |
237 pc->buffer[pc->index++]= pc->buffer[pc->overread_index++]; | |
238 } | |
2386 | 239 |
240 /* flush remaining if EOF */ | |
241 if(!*buf_size && next == END_NOT_FOUND){ | |
242 next= 0; | |
243 } | |
244 | |
1613 | 245 pc->last_index= pc->index; |
246 | |
247 /* copy into buffer end return */ | |
248 if(next == END_NOT_FOUND){ | |
6534 | 249 void* new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, (*buf_size) + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); |
1613 | 250 |
6534 | 251 if(!new_buffer) |
252 return AVERROR(ENOMEM); | |
253 pc->buffer = new_buffer; | |
1613 | 254 memcpy(&pc->buffer[pc->index], *buf, *buf_size); |
255 pc->index += *buf_size; | |
256 return -1; | |
257 } | |
258 | |
259 *buf_size= | |
260 pc->overread_index= pc->index + next; | |
2967 | 261 |
1613 | 262 /* append to buffer */ |
263 if(pc->index){ | |
6534 | 264 void* new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, next + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); |
1613 | 265 |
6534 | 266 if(!new_buffer) |
267 return AVERROR(ENOMEM); | |
268 pc->buffer = new_buffer; | |
1613 | 269 memcpy(&pc->buffer[pc->index], *buf, next + FF_INPUT_BUFFER_PADDING_SIZE ); |
270 pc->index = 0; | |
271 *buf= pc->buffer; | |
272 } | |
273 | |
274 /* store overread bytes */ | |
275 for(;next < 0; next++){ | |
276 pc->state = (pc->state<<8) | pc->buffer[pc->last_index + next]; | |
277 pc->overread++; | |
278 } | |
279 | |
280 #if 0 | |
281 if(pc->overread){ | |
282 printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); | |
283 printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); | |
284 } | |
285 #endif | |
286 | |
287 return 0; | |
288 } | |
289 | |
1988 | 290 void ff_parse_close(AVCodecParserContext *s) |
1613 | 291 { |
1988 | 292 ParseContext *pc = s->priv_data; |
1613 | 293 |
294 av_free(pc->buffer); | |
1988 | 295 } |
296 | |
4150
2205aefb22b7
move AVCodecParser prototypes and definitions to parser.h, and move mpegvideo parser to mpeg12.c
bcoudurier
parents:
4146
diff
changeset
|
297 void ff_parse1_close(AVCodecParserContext *s) |
1988 | 298 { |
299 ParseContext1 *pc1 = s->priv_data; | |
300 | |
301 av_free(pc1->pc.buffer); | |
302 av_free(pc1->enc); | |
1613 | 303 } |
304 | |
305 /*************************/ | |
306 | |
4175
b3328ed50a5e
make mpeg4video_split public as ff_mpeg4video_split
stefang
parents:
4150
diff
changeset
|
307 int ff_mpeg4video_split(AVCodecContext *avctx, |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
308 const uint8_t *buf, int buf_size) |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
309 { |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
310 int i; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
311 uint32_t state= -1; |
2967 | 312 |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
313 for(i=0; i<buf_size; i++){ |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
314 state= (state<<8) | buf[i]; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
315 if(state == 0x1B3 || state == 0x1B6) |
2777 | 316 return i-3; |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
317 } |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
318 return 0; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
319 } |