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