Mercurial > libavcodec.hg
annotate 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 | 493dc59d469a |
| children | 23b2a64342f2 |
| 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 | |
| 3989 | 79 /** |
| 80 * | |
| 81 * @param buf input | |
| 82 * @param buf_size input length, to signal EOF, this should be 0 (so that the last frame can be output) | |
| 83 * @param pts input presentation timestamp | |
| 84 * @param dts input decoding timestamp | |
| 85 * @param poutbuf will contain a pointer to the first byte of the output frame | |
| 86 * @param poutbuf_size will contain the length of the output frame | |
| 87 * @return the number of bytes of the input bitstream used | |
| 88 * | |
| 89 * Example: | |
| 90 * @code | |
| 91 * while(in_len){ | |
| 92 * len = av_parser_parse(myparser, AVCodecContext, &data, &size, | |
| 93 * in_data, in_len, | |
| 94 * pts, dts); | |
| 95 * in_data += len; | |
| 96 * in_len -= len; | |
| 97 * | |
| 4310 | 98 * if(size) |
| 99 * decode_frame(data, size); | |
| 3989 | 100 * } |
| 101 * @endcode | |
| 102 */ | |
| 2967 | 103 int av_parser_parse(AVCodecParserContext *s, |
| 1613 | 104 AVCodecContext *avctx, |
| 2967 | 105 uint8_t **poutbuf, int *poutbuf_size, |
| 1696 | 106 const uint8_t *buf, int buf_size, |
| 107 int64_t pts, int64_t dts) | |
| 1613 | 108 { |
| 1696 | 109 int index, i, k; |
|
1694
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
110 uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE]; |
| 2967 | 111 |
|
1694
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
112 if (buf_size == 0) { |
|
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
113 /* 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
|
114 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
|
115 buf = dummy_buf; |
| 1696 | 116 } else { |
| 117 /* add a new packet descriptor */ | |
| 118 k = (s->cur_frame_start_index + 1) & (AV_PARSER_PTS_NB - 1); | |
| 119 s->cur_frame_start_index = k; | |
| 120 s->cur_frame_offset[k] = s->cur_offset; | |
| 121 s->cur_frame_pts[k] = pts; | |
| 122 s->cur_frame_dts[k] = dts; | |
| 123 | |
| 124 /* fill first PTS/DTS */ | |
| 2030 | 125 if (s->fetch_timestamp){ |
| 126 s->fetch_timestamp=0; | |
| 1696 | 127 s->last_pts = pts; |
| 128 s->last_dts = dts; | |
| 4846 | 129 s->last_offset = 0; |
| 2107 | 130 s->cur_frame_pts[k] = |
| 131 s->cur_frame_dts[k] = AV_NOPTS_VALUE; | |
| 1696 | 132 } |
|
1694
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
133 } |
|
13169235c306
added End Of File handling to return last picture for MPEG1/2/4
bellard
parents:
1681
diff
changeset
|
134 |
| 1613 | 135 /* 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
|
136 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
|
137 //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 | 138 /* update the file pointer */ |
| 139 if (*poutbuf_size) { | |
| 1696 | 140 /* fill the data for the current frame */ |
| 1613 | 141 s->frame_offset = s->last_frame_offset; |
| 1696 | 142 s->pts = s->last_pts; |
| 143 s->dts = s->last_dts; | |
| 4846 | 144 s->offset = s->last_offset; |
| 2967 | 145 |
| 1696 | 146 /* offset of the next frame */ |
| 1613 | 147 s->last_frame_offset = s->cur_offset + index; |
| 1696 | 148 /* find the packet in which the new frame starts. It |
| 149 is tricky because of MPEG video start codes | |
| 150 which can begin in one packet and finish in | |
| 151 another packet. In the worst case, an MPEG | |
| 152 video start code could be in 4 different | |
| 153 packets. */ | |
| 154 k = s->cur_frame_start_index; | |
| 155 for(i = 0; i < AV_PARSER_PTS_NB; i++) { | |
| 156 if (s->last_frame_offset >= s->cur_frame_offset[k]) | |
| 157 break; | |
| 158 k = (k - 1) & (AV_PARSER_PTS_NB - 1); | |
| 159 } | |
| 2030 | 160 |
| 1696 | 161 s->last_pts = s->cur_frame_pts[k]; |
| 162 s->last_dts = s->cur_frame_dts[k]; | |
| 4846 | 163 s->last_offset = s->last_frame_offset - s->cur_frame_offset[k]; |
| 2967 | 164 |
| 2030 | 165 /* some parsers tell us the packet size even before seeing the first byte of the next packet, |
| 166 so the next pts/dts is in the next chunk */ | |
| 167 if(index == buf_size){ | |
| 168 s->fetch_timestamp=1; | |
| 169 } | |
| 1613 | 170 } |
| 171 if (index < 0) | |
| 172 index = 0; | |
| 173 s->cur_offset += index; | |
| 174 return index; | |
| 175 } | |
| 176 | |
| 2777 | 177 /** |
| 178 * | |
| 179 * @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
|
180 * @deprecated use AVBitstreamFilter |
| 2777 | 181 */ |
|
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
182 int av_parser_change(AVCodecParserContext *s, |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
183 AVCodecContext *avctx, |
| 2967 | 184 uint8_t **poutbuf, int *poutbuf_size, |
|
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
185 const uint8_t *buf, int buf_size, int keyframe){ |
| 2967 | 186 |
|
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
187 if(s && s->parser->split){ |
| 2777 | 188 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
|
189 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
|
190 buf += i; |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
191 buf_size -= i; |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
192 } |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
193 } |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
194 |
|
2864
95bac7109ff0
Kill some compiler warnings. Compiled code verified identical after changes.
mru
parents:
2846
diff
changeset
|
195 /* cast to avoid warning about discarding qualifiers */ |
|
95bac7109ff0
Kill some compiler warnings. Compiled code verified identical after changes.
mru
parents:
2846
diff
changeset
|
196 *poutbuf= (uint8_t *) buf; |
|
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
197 *poutbuf_size= buf_size; |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
198 if(avctx->extradata){ |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
199 if( (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)) |
| 6481 | 200 /*||(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
|
201 /*||(? && (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
|
202 int size= buf_size + avctx->extradata_size; |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
203 *poutbuf_size= size; |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
204 *poutbuf= av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); |
| 2967 | 205 |
|
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
206 memcpy(*poutbuf, avctx->extradata, avctx->extradata_size); |
| 2777 | 207 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
|
208 return 1; |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
209 } |
|
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 |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
212 return 0; |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
213 } |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
214 |
| 1613 | 215 void av_parser_close(AVCodecParserContext *s) |
| 216 { | |
| 217 if (s->parser->parser_close) | |
| 218 s->parser->parser_close(s); | |
| 219 av_free(s->priv_data); | |
| 220 av_free(s); | |
| 221 } | |
| 222 | |
| 223 /*****************************************************/ | |
| 224 | |
| 225 /** | |
| 226 * combines the (truncated) bitstream to a complete frame | |
| 227 * @returns -1 if no complete frame could be created | |
| 228 */ | |
|
4931
0d1cc37d9430
make some parser parameters const to avoid casting const to non-const
aurel
parents:
4913
diff
changeset
|
229 int ff_combine_frame(ParseContext *pc, int next, const uint8_t **buf, int *buf_size) |
| 1613 | 230 { |
| 231 #if 0 | |
| 232 if(pc->overread){ | |
| 233 printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); | |
| 234 printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); | |
| 235 } | |
| 236 #endif | |
| 237 | |
| 4795 | 238 /* Copy overread bytes from last frame into buffer. */ |
| 1613 | 239 for(; pc->overread>0; pc->overread--){ |
| 240 pc->buffer[pc->index++]= pc->buffer[pc->overread_index++]; | |
| 241 } | |
| 2386 | 242 |
| 243 /* flush remaining if EOF */ | |
| 244 if(!*buf_size && next == END_NOT_FOUND){ | |
| 245 next= 0; | |
| 246 } | |
| 247 | |
| 1613 | 248 pc->last_index= pc->index; |
| 249 | |
| 250 /* copy into buffer end return */ | |
| 251 if(next == END_NOT_FOUND){ | |
| 252 pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, (*buf_size) + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); | |
| 253 | |
| 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){ | |
| 264 pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, next + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); | |
| 265 | |
| 266 memcpy(&pc->buffer[pc->index], *buf, next + FF_INPUT_BUFFER_PADDING_SIZE ); | |
| 267 pc->index = 0; | |
| 268 *buf= pc->buffer; | |
| 269 } | |
| 270 | |
| 271 /* store overread bytes */ | |
| 272 for(;next < 0; next++){ | |
| 273 pc->state = (pc->state<<8) | pc->buffer[pc->last_index + next]; | |
| 274 pc->overread++; | |
| 275 } | |
| 276 | |
| 277 #if 0 | |
| 278 if(pc->overread){ | |
| 279 printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); | |
| 280 printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); | |
| 281 } | |
| 282 #endif | |
| 283 | |
| 284 return 0; | |
| 285 } | |
| 286 | |
| 1988 | 287 void ff_parse_close(AVCodecParserContext *s) |
| 1613 | 288 { |
| 1988 | 289 ParseContext *pc = s->priv_data; |
| 1613 | 290 |
| 291 av_free(pc->buffer); | |
| 1988 | 292 } |
| 293 | |
|
4150
2205aefb22b7
move AVCodecParser prototypes and definitions to parser.h, and move mpegvideo parser to mpeg12.c
bcoudurier
parents:
4146
diff
changeset
|
294 void ff_parse1_close(AVCodecParserContext *s) |
| 1988 | 295 { |
| 296 ParseContext1 *pc1 = s->priv_data; | |
| 297 | |
| 298 av_free(pc1->pc.buffer); | |
| 299 av_free(pc1->enc); | |
| 1613 | 300 } |
| 301 | |
| 302 /*************************/ | |
| 303 | |
|
4175
b3328ed50a5e
make mpeg4video_split public as ff_mpeg4video_split
stefang
parents:
4150
diff
changeset
|
304 int ff_mpeg4video_split(AVCodecContext *avctx, |
|
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
305 const uint8_t *buf, int buf_size) |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
306 { |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
307 int i; |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
308 uint32_t state= -1; |
| 2967 | 309 |
|
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
310 for(i=0; i<buf_size; i++){ |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
311 state= (state<<8) | buf[i]; |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
312 if(state == 0x1B3 || state == 0x1B6) |
| 2777 | 313 return i-3; |
|
2769
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
314 } |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
315 return 0; |
|
1394b45a7bf4
support changing in bitstream global headers into extradata style and back
michael
parents:
2637
diff
changeset
|
316 } |
