| 1 | /* |
| 2 | * Audio and Video frame extraction |
| 3 | * Copyright (c) 2003 Fabrice Bellard |
| 4 | * Copyright (c) 2003 Michael Niedermayer |
| 5 | * |
| 6 | * This file is part of FFmpeg. |
| 7 | * |
| 8 | * FFmpeg is free software; you can redistribute it and/or |
| 9 | * modify it under the terms of the GNU Lesser General Public |
| 10 | * License as published by the Free Software Foundation; either |
| 11 | * version 2.1 of the License, or (at your option) any later version. |
| 12 | * |
| 13 | * FFmpeg is distributed in the hope that it will be useful, |
| 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 |
| 19 | * License along with FFmpeg; if not, write to the Free Software |
| 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 21 | */ |
| 22 | |
| 23 | #include <stdint.h> |
| 24 | #include <string.h> |
| 25 | |
| 26 | #include "libavutil/atomic.h" |
| 27 | #include "libavutil/mem.h" |
| 28 | |
| 29 | #include "parser.h" |
| 30 | |
| 31 | static AVCodecParser *av_first_parser = NULL; |
| 32 | |
| 33 | AVCodecParser *av_parser_next(const AVCodecParser *p) |
| 34 | { |
| 35 | if (p) |
| 36 | return p->next; |
| 37 | else |
| 38 | return av_first_parser; |
| 39 | } |
| 40 | |
| 41 | void av_register_codec_parser(AVCodecParser *parser) |
| 42 | { |
| 43 | do { |
| 44 | parser->next = av_first_parser; |
| 45 | } while (parser->next != avpriv_atomic_ptr_cas((void * volatile *)&av_first_parser, parser->next, parser)); |
| 46 | } |
| 47 | |
| 48 | AVCodecParserContext *av_parser_init(int codec_id) |
| 49 | { |
| 50 | AVCodecParserContext *s = NULL; |
| 51 | AVCodecParser *parser; |
| 52 | int ret; |
| 53 | |
| 54 | if (codec_id == AV_CODEC_ID_NONE) |
| 55 | return NULL; |
| 56 | |
| 57 | for (parser = av_first_parser; parser; parser = parser->next) { |
| 58 | if (parser->codec_ids[0] == codec_id || |
| 59 | parser->codec_ids[1] == codec_id || |
| 60 | parser->codec_ids[2] == codec_id || |
| 61 | parser->codec_ids[3] == codec_id || |
| 62 | parser->codec_ids[4] == codec_id) |
| 63 | goto found; |
| 64 | } |
| 65 | return NULL; |
| 66 | |
| 67 | found: |
| 68 | s = av_mallocz(sizeof(AVCodecParserContext)); |
| 69 | if (!s) |
| 70 | goto err_out; |
| 71 | s->parser = parser; |
| 72 | s->priv_data = av_mallocz(parser->priv_data_size); |
| 73 | if (!s->priv_data) |
| 74 | goto err_out; |
| 75 | s->fetch_timestamp=1; |
| 76 | s->pict_type = AV_PICTURE_TYPE_I; |
| 77 | if (parser->parser_init) { |
| 78 | ret = parser->parser_init(s); |
| 79 | if (ret != 0) |
| 80 | goto err_out; |
| 81 | } |
| 82 | s->key_frame = -1; |
| 83 | s->convergence_duration = 0; |
| 84 | s->dts_sync_point = INT_MIN; |
| 85 | s->dts_ref_dts_delta = INT_MIN; |
| 86 | s->pts_dts_delta = INT_MIN; |
| 87 | return s; |
| 88 | |
| 89 | err_out: |
| 90 | if (s) |
| 91 | av_freep(&s->priv_data); |
| 92 | av_free(s); |
| 93 | return NULL; |
| 94 | } |
| 95 | |
| 96 | void ff_fetch_timestamp(AVCodecParserContext *s, int off, int remove) |
| 97 | { |
| 98 | int i; |
| 99 | |
| 100 | s->dts = |
| 101 | s->pts = AV_NOPTS_VALUE; |
| 102 | s->pos = -1; |
| 103 | s->offset = 0; |
| 104 | for (i = 0; i < AV_PARSER_PTS_NB; i++) { |
| 105 | if (s->cur_offset + off >= s->cur_frame_offset[i] && |
| 106 | (s->frame_offset < s->cur_frame_offset[i] || |
| 107 | (!s->frame_offset && !s->next_frame_offset)) && // first field/frame |
| 108 | // check disabled since MPEG-TS does not send complete PES packets |
| 109 | /*s->next_frame_offset + off <*/ s->cur_frame_end[i]){ |
| 110 | |
| 111 | s->dts = s->cur_frame_dts[i]; |
| 112 | s->pts = s->cur_frame_pts[i]; |
| 113 | s->pos = s->cur_frame_pos[i]; |
| 114 | s->offset = s->next_frame_offset - s->cur_frame_offset[i]; |
| 115 | if (remove) |
| 116 | s->cur_frame_offset[i] = INT64_MAX; |
| 117 | if (s->cur_offset + off < s->cur_frame_end[i]) |
| 118 | break; |
| 119 | } |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | int av_parser_parse2(AVCodecParserContext *s, AVCodecContext *avctx, |
| 124 | uint8_t **poutbuf, int *poutbuf_size, |
| 125 | const uint8_t *buf, int buf_size, |
| 126 | int64_t pts, int64_t dts, int64_t pos) |
| 127 | { |
| 128 | int index, i; |
| 129 | uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE]; |
| 130 | |
| 131 | if (!(s->flags & PARSER_FLAG_FETCHED_OFFSET)) { |
| 132 | s->next_frame_offset = |
| 133 | s->cur_offset = pos; |
| 134 | s->flags |= PARSER_FLAG_FETCHED_OFFSET; |
| 135 | } |
| 136 | |
| 137 | if (buf_size == 0) { |
| 138 | /* padding is always necessary even if EOF, so we add it here */ |
| 139 | memset(dummy_buf, 0, sizeof(dummy_buf)); |
| 140 | buf = dummy_buf; |
| 141 | } else if (s->cur_offset + buf_size != s->cur_frame_end[s->cur_frame_start_index]) { /* skip remainder packets */ |
| 142 | /* add a new packet descriptor */ |
| 143 | i = (s->cur_frame_start_index + 1) & (AV_PARSER_PTS_NB - 1); |
| 144 | s->cur_frame_start_index = i; |
| 145 | s->cur_frame_offset[i] = s->cur_offset; |
| 146 | s->cur_frame_end[i] = s->cur_offset + buf_size; |
| 147 | s->cur_frame_pts[i] = pts; |
| 148 | s->cur_frame_dts[i] = dts; |
| 149 | s->cur_frame_pos[i] = pos; |
| 150 | } |
| 151 | |
| 152 | if (s->fetch_timestamp) { |
| 153 | s->fetch_timestamp = 0; |
| 154 | s->last_pts = s->pts; |
| 155 | s->last_dts = s->dts; |
| 156 | s->last_pos = s->pos; |
| 157 | ff_fetch_timestamp(s, 0, 0); |
| 158 | } |
| 159 | /* WARNING: the returned index can be negative */ |
| 160 | index = s->parser->parser_parse(s, avctx, (const uint8_t **) poutbuf, |
| 161 | poutbuf_size, buf, buf_size); |
| 162 | /* update the file pointer */ |
| 163 | if (*poutbuf_size) { |
| 164 | /* fill the data for the current frame */ |
| 165 | s->frame_offset = s->next_frame_offset; |
| 166 | |
| 167 | /* offset of the next frame */ |
| 168 | s->next_frame_offset = s->cur_offset + index; |
| 169 | s->fetch_timestamp = 1; |
| 170 | } |
| 171 | if (index < 0) |
| 172 | index = 0; |
| 173 | s->cur_offset += index; |
| 174 | return index; |
| 175 | } |
| 176 | |
| 177 | int av_parser_change(AVCodecParserContext *s, AVCodecContext *avctx, |
| 178 | uint8_t **poutbuf, int *poutbuf_size, |
| 179 | const uint8_t *buf, int buf_size, int keyframe) |
| 180 | { |
| 181 | if (s && s->parser->split) { |
| 182 | if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER || |
| 183 | avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER) { |
| 184 | int i = s->parser->split(avctx, buf, buf_size); |
| 185 | buf += i; |
| 186 | buf_size -= i; |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | /* cast to avoid warning about discarding qualifiers */ |
| 191 | *poutbuf = (uint8_t *) buf; |
| 192 | *poutbuf_size = buf_size; |
| 193 | if (avctx->extradata) { |
| 194 | if (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)) { |
| 195 | int size = buf_size + avctx->extradata_size; |
| 196 | |
| 197 | *poutbuf_size = size; |
| 198 | *poutbuf = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); |
| 199 | |
| 200 | memcpy(*poutbuf, avctx->extradata, avctx->extradata_size); |
| 201 | memcpy(*poutbuf + avctx->extradata_size, buf, |
| 202 | buf_size + FF_INPUT_BUFFER_PADDING_SIZE); |
| 203 | return 1; |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | return 0; |
| 208 | } |
| 209 | |
| 210 | void av_parser_close(AVCodecParserContext *s) |
| 211 | { |
| 212 | if (s) { |
| 213 | if (s->parser->parser_close) |
| 214 | s->parser->parser_close(s); |
| 215 | av_free(s->priv_data); |
| 216 | av_free(s); |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | int ff_combine_frame(ParseContext *pc, int next, |
| 221 | const uint8_t **buf, int *buf_size) |
| 222 | { |
| 223 | if (pc->overread) { |
| 224 | av_dlog(NULL, "overread %d, state:%X next:%d index:%d o_index:%d\n", |
| 225 | pc->overread, pc->state, next, pc->index, pc->overread_index); |
| 226 | av_dlog(NULL, "%X %X %X %X\n", |
| 227 | (*buf)[0], (*buf)[1], (*buf)[2], (*buf)[3]); |
| 228 | } |
| 229 | |
| 230 | /* Copy overread bytes from last frame into buffer. */ |
| 231 | for (; pc->overread > 0; pc->overread--) |
| 232 | pc->buffer[pc->index++] = pc->buffer[pc->overread_index++]; |
| 233 | |
| 234 | /* flush remaining if EOF */ |
| 235 | if (!*buf_size && next == END_NOT_FOUND) |
| 236 | next = 0; |
| 237 | |
| 238 | pc->last_index = pc->index; |
| 239 | |
| 240 | /* copy into buffer end return */ |
| 241 | if (next == END_NOT_FOUND) { |
| 242 | void *new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, |
| 243 | *buf_size + pc->index + |
| 244 | FF_INPUT_BUFFER_PADDING_SIZE); |
| 245 | |
| 246 | if (!new_buffer) { |
| 247 | pc->index = 0; |
| 248 | return AVERROR(ENOMEM); |
| 249 | } |
| 250 | pc->buffer = new_buffer; |
| 251 | memcpy(&pc->buffer[pc->index], *buf, *buf_size); |
| 252 | pc->index += *buf_size; |
| 253 | return -1; |
| 254 | } |
| 255 | |
| 256 | *buf_size = |
| 257 | pc->overread_index = pc->index + next; |
| 258 | |
| 259 | /* append to buffer */ |
| 260 | if (pc->index) { |
| 261 | void *new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, |
| 262 | next + pc->index + |
| 263 | FF_INPUT_BUFFER_PADDING_SIZE); |
| 264 | if (!new_buffer) { |
| 265 | pc->overread_index = |
| 266 | pc->index = 0; |
| 267 | return AVERROR(ENOMEM); |
| 268 | } |
| 269 | pc->buffer = new_buffer; |
| 270 | if (next > -FF_INPUT_BUFFER_PADDING_SIZE) |
| 271 | memcpy(&pc->buffer[pc->index], *buf, |
| 272 | next + FF_INPUT_BUFFER_PADDING_SIZE); |
| 273 | pc->index = 0; |
| 274 | *buf = pc->buffer; |
| 275 | } |
| 276 | |
| 277 | /* store overread bytes */ |
| 278 | for (; next < 0; next++) { |
| 279 | pc->state = pc->state << 8 | pc->buffer[pc->last_index + next]; |
| 280 | pc->state64 = pc->state64 << 8 | pc->buffer[pc->last_index + next]; |
| 281 | pc->overread++; |
| 282 | } |
| 283 | |
| 284 | if (pc->overread) { |
| 285 | av_dlog(NULL, "overread %d, state:%X next:%d index:%d o_index:%d\n", |
| 286 | pc->overread, pc->state, next, pc->index, pc->overread_index); |
| 287 | av_dlog(NULL, "%X %X %X %X\n", |
| 288 | (*buf)[0], (*buf)[1], (*buf)[2], (*buf)[3]); |
| 289 | } |
| 290 | |
| 291 | return 0; |
| 292 | } |
| 293 | |
| 294 | void ff_parse_close(AVCodecParserContext *s) |
| 295 | { |
| 296 | ParseContext *pc = s->priv_data; |
| 297 | |
| 298 | av_freep(&pc->buffer); |
| 299 | } |
| 300 | |
| 301 | int ff_mpeg4video_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size) |
| 302 | { |
| 303 | int i; |
| 304 | uint32_t state = -1; |
| 305 | |
| 306 | for (i = 0; i < buf_size; i++) { |
| 307 | state = state << 8 | buf[i]; |
| 308 | if (state == 0x1B3 || state == 0x1B6) |
| 309 | return i - 3; |
| 310 | } |
| 311 | return 0; |
| 312 | } |