Mercurial > libavcodec.hg
annotate 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 | cdd8fa4a362a |
children | d4c12f2d226b |
rev | line source |
---|---|
1613 | 1 /* |
2 * Audio and Video frame extraction | |
8629
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
8044
diff
changeset
|
3 * Copyright (c) 2003 Fabrice Bellard |
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
8044
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 */ |
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 |
7992 | 25 static AVCodecParser *av_first_parser = NULL; |
1613 | 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; |
8973
34f2c7189710
Add key_frame to AVCodecParserContext, used in libavformat.
cehoyos
parents:
8629
diff
changeset
|
76 s->key_frame = -1; |
8989 | 77 s->convergence_duration = AV_NOPTS_VALUE; |
1613 | 78 return s; |
79 } | |
80 | |
6985
7c8df4f99d08
Allow matching timestamps to be removed by fetch_timestamp().
michael
parents:
6984
diff
changeset
|
81 void ff_fetch_timestamp(AVCodecParserContext *s, int off, int remove){ |
6983 | 82 int i; |
6986 | 83 |
6983 | 84 s->dts= s->pts= AV_NOPTS_VALUE; |
85 s->offset= 0; | |
86 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
|
87 if ( s->next_frame_offset + off >= s->cur_frame_offset[i] |
6986 | 88 &&(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
|
89 //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
|
90 && /*s->next_frame_offset + off <*/ s->cur_frame_end[i]){ |
6983 | 91 s->dts= s->cur_frame_dts[i]; |
92 s->pts= s->cur_frame_pts[i]; | |
93 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
|
94 if(remove) |
7c8df4f99d08
Allow matching timestamps to be removed by fetch_timestamp().
michael
parents:
6984
diff
changeset
|
95 s->cur_frame_offset[i]= INT64_MAX; |
6983 | 96 } |
97 } | |
98 } | |
99 | |
3989 | 100 /** |
101 * | |
102 * @param buf input | |
103 * @param buf_size input length, to signal EOF, this should be 0 (so that the last frame can be output) | |
104 * @param pts input presentation timestamp | |
105 * @param dts input decoding timestamp | |
106 * @param poutbuf will contain a pointer to the first byte of the output frame | |
107 * @param poutbuf_size will contain the length of the output frame | |
108 * @return the number of bytes of the input bitstream used | |
109 * | |
110 * Example: | |
111 * @code | |
112 * while(in_len){ | |
113 * len = av_parser_parse(myparser, AVCodecContext, &data, &size, | |
114 * in_data, in_len, | |
115 * pts, dts); | |
116 * in_data += len; | |
117 * in_len -= len; | |
118 * | |
4310 | 119 * if(size) |
120 * decode_frame(data, size); | |
3989 | 121 * } |
122 * @endcode | |
123 */ | |
2967 | 124 int av_parser_parse(AVCodecParserContext *s, |
1613 | 125 AVCodecContext *avctx, |
2967 | 126 uint8_t **poutbuf, int *poutbuf_size, |
1696 | 127 const uint8_t *buf, int buf_size, |
128 int64_t pts, int64_t dts) | |
1613 | 129 { |
6982 | 130 int index, i; |
1694
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
131 uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE]; |
2967 | 132 |
1694
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
133 if (buf_size == 0) { |
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
134 /* 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
|
135 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
|
136 buf = dummy_buf; |
1696 | 137 } else { |
138 /* add a new packet descriptor */ | |
6989 | 139 if(pts != AV_NOPTS_VALUE || dts != AV_NOPTS_VALUE){ |
6990 | 140 i = (s->cur_frame_start_index + 1) & (AV_PARSER_PTS_NB - 1); |
141 s->cur_frame_start_index = i; | |
142 s->cur_frame_offset[i] = s->cur_offset; | |
143 s->cur_frame_end[i] = s->cur_offset + buf_size; | |
144 s->cur_frame_pts[i] = pts; | |
145 s->cur_frame_dts[i] = dts; | |
6989 | 146 } |
6977 | 147 } |
1696 | 148 |
6980 | 149 if (s->fetch_timestamp){ |
150 s->fetch_timestamp=0; | |
6977 | 151 s->last_pts = s->pts; |
152 s->last_dts = s->dts; | |
6985
7c8df4f99d08
Allow matching timestamps to be removed by fetch_timestamp().
michael
parents:
6984
diff
changeset
|
153 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
|
154 } |
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
155 |
1613 | 156 /* 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
|
157 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
|
158 //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 | 159 /* update the file pointer */ |
160 if (*poutbuf_size) { | |
1696 | 161 /* fill the data for the current frame */ |
6979 | 162 s->frame_offset = s->next_frame_offset; |
2967 | 163 |
1696 | 164 /* offset of the next frame */ |
6979 | 165 s->next_frame_offset = s->cur_offset + index; |
6980 | 166 s->fetch_timestamp=1; |
1613 | 167 } |
168 if (index < 0) | |
169 index = 0; | |
170 s->cur_offset += index; | |
171 return index; | |
172 } | |
173 | |
2777 | 174 /** |
175 * | |
176 * @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
|
177 * @deprecated use AVBitstreamFilter |
2777 | 178 */ |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
179 int av_parser_change(AVCodecParserContext *s, |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
180 AVCodecContext *avctx, |
2967 | 181 uint8_t **poutbuf, int *poutbuf_size, |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
182 const uint8_t *buf, int buf_size, int keyframe){ |
2967 | 183 |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
184 if(s && s->parser->split){ |
2777 | 185 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
|
186 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
|
187 buf += i; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
188 buf_size -= i; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
189 } |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
190 } |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
191 |
2864
95bac7109ff0
Kill some compiler warnings. Compiled code verified identical after changes.
mru
parents:
2846
diff
changeset
|
192 /* cast to avoid warning about discarding qualifiers */ |
95bac7109ff0
Kill some compiler warnings. Compiled code verified identical after changes.
mru
parents:
2846
diff
changeset
|
193 *poutbuf= (uint8_t *) buf; |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
194 *poutbuf_size= buf_size; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
195 if(avctx->extradata){ |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
196 if( (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)) |
6481 | 197 /*||(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
|
198 /*||(? && (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
|
199 int size= buf_size + avctx->extradata_size; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
200 *poutbuf_size= size; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
201 *poutbuf= av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); |
2967 | 202 |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
203 memcpy(*poutbuf, avctx->extradata, avctx->extradata_size); |
2777 | 204 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
|
205 return 1; |
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 } |
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 return 0; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
210 } |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
211 |
1613 | 212 void av_parser_close(AVCodecParserContext *s) |
213 { | |
6891 | 214 if(s){ |
6892 | 215 if (s->parser->parser_close) |
216 s->parser->parser_close(s); | |
217 av_free(s->priv_data); | |
218 av_free(s); | |
6891 | 219 } |
1613 | 220 } |
221 | |
222 /*****************************************************/ | |
223 | |
224 /** | |
225 * combines the (truncated) bitstream to a complete frame | |
6534 | 226 * @returns -1 if no complete frame could be created, AVERROR(ENOMEM) if there was a memory allocation error |
1613 | 227 */ |
4931
0d1cc37d9430
make some parser parameters const to avoid casting const to non-const
aurel
parents:
4913
diff
changeset
|
228 int ff_combine_frame(ParseContext *pc, int next, const uint8_t **buf, int *buf_size) |
1613 | 229 { |
230 #if 0 | |
231 if(pc->overread){ | |
232 printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); | |
233 printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); | |
234 } | |
235 #endif | |
236 | |
4795 | 237 /* Copy overread bytes from last frame into buffer. */ |
1613 | 238 for(; pc->overread>0; pc->overread--){ |
239 pc->buffer[pc->index++]= pc->buffer[pc->overread_index++]; | |
240 } | |
2386 | 241 |
242 /* flush remaining if EOF */ | |
243 if(!*buf_size && next == END_NOT_FOUND){ | |
244 next= 0; | |
245 } | |
246 | |
1613 | 247 pc->last_index= pc->index; |
248 | |
249 /* copy into buffer end return */ | |
250 if(next == END_NOT_FOUND){ | |
6534 | 251 void* new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, (*buf_size) + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); |
1613 | 252 |
6534 | 253 if(!new_buffer) |
254 return AVERROR(ENOMEM); | |
255 pc->buffer = new_buffer; | |
1613 | 256 memcpy(&pc->buffer[pc->index], *buf, *buf_size); |
257 pc->index += *buf_size; | |
258 return -1; | |
259 } | |
260 | |
261 *buf_size= | |
262 pc->overread_index= pc->index + next; | |
2967 | 263 |
1613 | 264 /* append to buffer */ |
265 if(pc->index){ | |
6534 | 266 void* new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, next + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); |
1613 | 267 |
6534 | 268 if(!new_buffer) |
269 return AVERROR(ENOMEM); | |
270 pc->buffer = new_buffer; | |
1613 | 271 memcpy(&pc->buffer[pc->index], *buf, next + FF_INPUT_BUFFER_PADDING_SIZE ); |
272 pc->index = 0; | |
273 *buf= pc->buffer; | |
274 } | |
275 | |
276 /* store overread bytes */ | |
277 for(;next < 0; next++){ | |
278 pc->state = (pc->state<<8) | pc->buffer[pc->last_index + next]; | |
8044
8c1e1047ec78
add state64 field to ParseContext storing last 8 bytes, to be able to check for longer startcodes
bcoudurier
parents:
8040
diff
changeset
|
279 pc->state64 = (pc->state64<<8) | pc->buffer[pc->last_index + next]; |
1613 | 280 pc->overread++; |
281 } | |
282 | |
283 #if 0 | |
284 if(pc->overread){ | |
285 printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); | |
286 printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); | |
287 } | |
288 #endif | |
289 | |
290 return 0; | |
291 } | |
292 | |
1988 | 293 void ff_parse_close(AVCodecParserContext *s) |
1613 | 294 { |
1988 | 295 ParseContext *pc = s->priv_data; |
1613 | 296 |
8040 | 297 av_freep(&pc->buffer); |
1988 | 298 } |
299 | |
4150
2205aefb22b7
move AVCodecParser prototypes and definitions to parser.h, and move mpegvideo parser to mpeg12.c
bcoudurier
parents:
4146
diff
changeset
|
300 void ff_parse1_close(AVCodecParserContext *s) |
1988 | 301 { |
302 ParseContext1 *pc1 = s->priv_data; | |
303 | |
304 av_free(pc1->pc.buffer); | |
305 av_free(pc1->enc); | |
1613 | 306 } |
307 | |
308 /*************************/ | |
309 | |
4175
b3328ed50a5e
make mpeg4video_split public as ff_mpeg4video_split
stefang
parents:
4150
diff
changeset
|
310 int ff_mpeg4video_split(AVCodecContext *avctx, |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
311 const uint8_t *buf, int buf_size) |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
312 { |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
313 int i; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
314 uint32_t state= -1; |
2967 | 315 |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
316 for(i=0; i<buf_size; i++){ |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
317 state= (state<<8) | buf[i]; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
318 if(state == 0x1B3 || state == 0x1B6) |
2777 | 319 return i-3; |
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
320 } |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
321 return 0; |
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
322 } |