1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * This file is part of FFmpeg.
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cabdff1aSopenharmony_ci * Lesser General Public License for more details.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17cabdff1aSopenharmony_ci */
18cabdff1aSopenharmony_ci
19cabdff1aSopenharmony_ci#include <stdint.h>
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci#include "libavutil/log.h"
22cabdff1aSopenharmony_ci#include "libavutil/opt.h"
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#include "av1.h"
25cabdff1aSopenharmony_ci#include "av1_parse.h"
26cabdff1aSopenharmony_ci#include "bsf.h"
27cabdff1aSopenharmony_ci#include "bsf_internal.h"
28cabdff1aSopenharmony_ci#include "bytestream.h"
29cabdff1aSopenharmony_ci#include "h2645_parse.h"
30cabdff1aSopenharmony_ci#include "h264.h"
31cabdff1aSopenharmony_ci#include "hevc.h"
32cabdff1aSopenharmony_ci#include "startcode.h"
33cabdff1aSopenharmony_ci#include "vc1_common.h"
34cabdff1aSopenharmony_ci
35cabdff1aSopenharmony_citypedef struct ExtractExtradataContext {
36cabdff1aSopenharmony_ci    const AVClass *class;
37cabdff1aSopenharmony_ci
38cabdff1aSopenharmony_ci    int (*extract)(AVBSFContext *ctx, AVPacket *pkt,
39cabdff1aSopenharmony_ci                   uint8_t **data, int *size);
40cabdff1aSopenharmony_ci
41cabdff1aSopenharmony_ci    /* AV1 specific fields */
42cabdff1aSopenharmony_ci    AV1Packet av1_pkt;
43cabdff1aSopenharmony_ci
44cabdff1aSopenharmony_ci    /* H264/HEVC specific fields */
45cabdff1aSopenharmony_ci    H2645Packet h2645_pkt;
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ci    /* AVOptions */
48cabdff1aSopenharmony_ci    int remove;
49cabdff1aSopenharmony_ci} ExtractExtradataContext;
50cabdff1aSopenharmony_ci
51cabdff1aSopenharmony_cistatic int val_in_array(const int *arr, int len, int val)
52cabdff1aSopenharmony_ci{
53cabdff1aSopenharmony_ci    int i;
54cabdff1aSopenharmony_ci    for (i = 0; i < len; i++)
55cabdff1aSopenharmony_ci        if (arr[i] == val)
56cabdff1aSopenharmony_ci            return 1;
57cabdff1aSopenharmony_ci    return 0;
58cabdff1aSopenharmony_ci}
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_cistatic int extract_extradata_av1(AVBSFContext *ctx, AVPacket *pkt,
61cabdff1aSopenharmony_ci                                 uint8_t **data, int *size)
62cabdff1aSopenharmony_ci{
63cabdff1aSopenharmony_ci    static const int extradata_obu_types[] = {
64cabdff1aSopenharmony_ci        AV1_OBU_SEQUENCE_HEADER, AV1_OBU_METADATA,
65cabdff1aSopenharmony_ci    };
66cabdff1aSopenharmony_ci    ExtractExtradataContext *s = ctx->priv_data;
67cabdff1aSopenharmony_ci
68cabdff1aSopenharmony_ci    int extradata_size = 0, filtered_size = 0;
69cabdff1aSopenharmony_ci    int nb_extradata_obu_types = FF_ARRAY_ELEMS(extradata_obu_types);
70cabdff1aSopenharmony_ci    int i, has_seq = 0, ret = 0;
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci    ret = ff_av1_packet_split(&s->av1_pkt, pkt->data, pkt->size, ctx);
73cabdff1aSopenharmony_ci    if (ret < 0)
74cabdff1aSopenharmony_ci        return ret;
75cabdff1aSopenharmony_ci
76cabdff1aSopenharmony_ci    for (i = 0; i < s->av1_pkt.nb_obus; i++) {
77cabdff1aSopenharmony_ci        AV1OBU *obu = &s->av1_pkt.obus[i];
78cabdff1aSopenharmony_ci        if (val_in_array(extradata_obu_types, nb_extradata_obu_types, obu->type)) {
79cabdff1aSopenharmony_ci            extradata_size += obu->raw_size;
80cabdff1aSopenharmony_ci            if (obu->type == AV1_OBU_SEQUENCE_HEADER)
81cabdff1aSopenharmony_ci                has_seq = 1;
82cabdff1aSopenharmony_ci        } else if (s->remove) {
83cabdff1aSopenharmony_ci            filtered_size += obu->raw_size;
84cabdff1aSopenharmony_ci        }
85cabdff1aSopenharmony_ci    }
86cabdff1aSopenharmony_ci
87cabdff1aSopenharmony_ci    if (extradata_size && has_seq) {
88cabdff1aSopenharmony_ci        AVBufferRef *filtered_buf = NULL;
89cabdff1aSopenharmony_ci        PutByteContext pb_filtered_data, pb_extradata;
90cabdff1aSopenharmony_ci        uint8_t *extradata;
91cabdff1aSopenharmony_ci
92cabdff1aSopenharmony_ci        if (s->remove) {
93cabdff1aSopenharmony_ci            filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE);
94cabdff1aSopenharmony_ci            if (!filtered_buf) {
95cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
96cabdff1aSopenharmony_ci            }
97cabdff1aSopenharmony_ci            memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
98cabdff1aSopenharmony_ci        }
99cabdff1aSopenharmony_ci
100cabdff1aSopenharmony_ci        extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
101cabdff1aSopenharmony_ci        if (!extradata) {
102cabdff1aSopenharmony_ci            av_buffer_unref(&filtered_buf);
103cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
104cabdff1aSopenharmony_ci        }
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ci        *data = extradata;
107cabdff1aSopenharmony_ci        *size = extradata_size;
108cabdff1aSopenharmony_ci
109cabdff1aSopenharmony_ci        bytestream2_init_writer(&pb_extradata, extradata, extradata_size);
110cabdff1aSopenharmony_ci        if (s->remove)
111cabdff1aSopenharmony_ci            bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size);
112cabdff1aSopenharmony_ci
113cabdff1aSopenharmony_ci        for (i = 0; i < s->av1_pkt.nb_obus; i++) {
114cabdff1aSopenharmony_ci            AV1OBU *obu = &s->av1_pkt.obus[i];
115cabdff1aSopenharmony_ci            if (val_in_array(extradata_obu_types, nb_extradata_obu_types,
116cabdff1aSopenharmony_ci                             obu->type)) {
117cabdff1aSopenharmony_ci                bytestream2_put_bufferu(&pb_extradata, obu->raw_data, obu->raw_size);
118cabdff1aSopenharmony_ci            } else if (s->remove) {
119cabdff1aSopenharmony_ci                bytestream2_put_bufferu(&pb_filtered_data, obu->raw_data, obu->raw_size);
120cabdff1aSopenharmony_ci            }
121cabdff1aSopenharmony_ci        }
122cabdff1aSopenharmony_ci
123cabdff1aSopenharmony_ci        if (s->remove) {
124cabdff1aSopenharmony_ci            av_buffer_unref(&pkt->buf);
125cabdff1aSopenharmony_ci            pkt->buf  = filtered_buf;
126cabdff1aSopenharmony_ci            pkt->data = filtered_buf->data;
127cabdff1aSopenharmony_ci            pkt->size = filtered_size;
128cabdff1aSopenharmony_ci        }
129cabdff1aSopenharmony_ci    }
130cabdff1aSopenharmony_ci
131cabdff1aSopenharmony_ci    return 0;
132cabdff1aSopenharmony_ci}
133cabdff1aSopenharmony_ci
134cabdff1aSopenharmony_cistatic int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt,
135cabdff1aSopenharmony_ci                                   uint8_t **data, int *size)
136cabdff1aSopenharmony_ci{
137cabdff1aSopenharmony_ci    static const int extradata_nal_types_hevc[] = {
138cabdff1aSopenharmony_ci        HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS,
139cabdff1aSopenharmony_ci    };
140cabdff1aSopenharmony_ci    static const int extradata_nal_types_h264[] = {
141cabdff1aSopenharmony_ci        H264_NAL_SPS, H264_NAL_PPS,
142cabdff1aSopenharmony_ci    };
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_ci    ExtractExtradataContext *s = ctx->priv_data;
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_ci    int extradata_size = 0, filtered_size = 0;
147cabdff1aSopenharmony_ci    const int *extradata_nal_types;
148cabdff1aSopenharmony_ci    int nb_extradata_nal_types;
149cabdff1aSopenharmony_ci    int i, has_sps = 0, has_vps = 0, ret = 0;
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_ci    if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) {
152cabdff1aSopenharmony_ci        extradata_nal_types    = extradata_nal_types_hevc;
153cabdff1aSopenharmony_ci        nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc);
154cabdff1aSopenharmony_ci    } else {
155cabdff1aSopenharmony_ci        extradata_nal_types    = extradata_nal_types_h264;
156cabdff1aSopenharmony_ci        nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_h264);
157cabdff1aSopenharmony_ci    }
158cabdff1aSopenharmony_ci
159cabdff1aSopenharmony_ci    ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size,
160cabdff1aSopenharmony_ci                                ctx, 0, 0, ctx->par_in->codec_id, 1, 0);
161cabdff1aSopenharmony_ci    if (ret < 0)
162cabdff1aSopenharmony_ci        return ret;
163cabdff1aSopenharmony_ci
164cabdff1aSopenharmony_ci    for (i = 0; i < s->h2645_pkt.nb_nals; i++) {
165cabdff1aSopenharmony_ci        H2645NAL *nal = &s->h2645_pkt.nals[i];
166cabdff1aSopenharmony_ci        if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) {
167cabdff1aSopenharmony_ci            extradata_size += nal->raw_size + 3;
168cabdff1aSopenharmony_ci            if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) {
169cabdff1aSopenharmony_ci                if (nal->type == HEVC_NAL_SPS) has_sps = 1;
170cabdff1aSopenharmony_ci                if (nal->type == HEVC_NAL_VPS) has_vps = 1;
171cabdff1aSopenharmony_ci            } else {
172cabdff1aSopenharmony_ci                if (nal->type == H264_NAL_SPS) has_sps = 1;
173cabdff1aSopenharmony_ci            }
174cabdff1aSopenharmony_ci        } else if (s->remove) {
175cabdff1aSopenharmony_ci            filtered_size += nal->raw_size + 3;
176cabdff1aSopenharmony_ci        }
177cabdff1aSopenharmony_ci    }
178cabdff1aSopenharmony_ci
179cabdff1aSopenharmony_ci    if (extradata_size &&
180cabdff1aSopenharmony_ci        ((ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) ||
181cabdff1aSopenharmony_ci         (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) {
182cabdff1aSopenharmony_ci        AVBufferRef *filtered_buf = NULL;
183cabdff1aSopenharmony_ci        PutByteContext pb_filtered_data, pb_extradata;
184cabdff1aSopenharmony_ci        uint8_t *extradata;
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci        if (s->remove) {
187cabdff1aSopenharmony_ci            filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE);
188cabdff1aSopenharmony_ci            if (!filtered_buf) {
189cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
190cabdff1aSopenharmony_ci            }
191cabdff1aSopenharmony_ci            memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
192cabdff1aSopenharmony_ci        }
193cabdff1aSopenharmony_ci
194cabdff1aSopenharmony_ci        extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
195cabdff1aSopenharmony_ci        if (!extradata) {
196cabdff1aSopenharmony_ci            av_buffer_unref(&filtered_buf);
197cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
198cabdff1aSopenharmony_ci        }
199cabdff1aSopenharmony_ci
200cabdff1aSopenharmony_ci        *data = extradata;
201cabdff1aSopenharmony_ci        *size = extradata_size;
202cabdff1aSopenharmony_ci
203cabdff1aSopenharmony_ci        bytestream2_init_writer(&pb_extradata, extradata, extradata_size);
204cabdff1aSopenharmony_ci        if (s->remove)
205cabdff1aSopenharmony_ci            bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size);
206cabdff1aSopenharmony_ci
207cabdff1aSopenharmony_ci        for (i = 0; i < s->h2645_pkt.nb_nals; i++) {
208cabdff1aSopenharmony_ci            H2645NAL *nal = &s->h2645_pkt.nals[i];
209cabdff1aSopenharmony_ci            if (val_in_array(extradata_nal_types, nb_extradata_nal_types,
210cabdff1aSopenharmony_ci                             nal->type)) {
211cabdff1aSopenharmony_ci                bytestream2_put_be24u(&pb_extradata, 1); //startcode
212cabdff1aSopenharmony_ci                bytestream2_put_bufferu(&pb_extradata, nal->raw_data, nal->raw_size);
213cabdff1aSopenharmony_ci            } else if (s->remove) {
214cabdff1aSopenharmony_ci                bytestream2_put_be24u(&pb_filtered_data, 1); // startcode
215cabdff1aSopenharmony_ci                bytestream2_put_bufferu(&pb_filtered_data, nal->raw_data, nal->raw_size);
216cabdff1aSopenharmony_ci            }
217cabdff1aSopenharmony_ci        }
218cabdff1aSopenharmony_ci
219cabdff1aSopenharmony_ci        if (s->remove) {
220cabdff1aSopenharmony_ci            av_buffer_unref(&pkt->buf);
221cabdff1aSopenharmony_ci            pkt->buf  = filtered_buf;
222cabdff1aSopenharmony_ci            pkt->data = filtered_buf->data;
223cabdff1aSopenharmony_ci            pkt->size = filtered_size;
224cabdff1aSopenharmony_ci        }
225cabdff1aSopenharmony_ci    }
226cabdff1aSopenharmony_ci
227cabdff1aSopenharmony_ci    return 0;
228cabdff1aSopenharmony_ci}
229cabdff1aSopenharmony_ci
230cabdff1aSopenharmony_cistatic int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt,
231cabdff1aSopenharmony_ci                                 uint8_t **data, int *size)
232cabdff1aSopenharmony_ci{
233cabdff1aSopenharmony_ci    ExtractExtradataContext *s = ctx->priv_data;
234cabdff1aSopenharmony_ci    const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size;
235cabdff1aSopenharmony_ci    uint32_t state = UINT32_MAX;
236cabdff1aSopenharmony_ci    int has_extradata = 0, extradata_size = 0;
237cabdff1aSopenharmony_ci
238cabdff1aSopenharmony_ci    while (ptr < end) {
239cabdff1aSopenharmony_ci        ptr = avpriv_find_start_code(ptr, end, &state);
240cabdff1aSopenharmony_ci        if (state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT) {
241cabdff1aSopenharmony_ci            has_extradata = 1;
242cabdff1aSopenharmony_ci        } else if (has_extradata && IS_MARKER(state)) {
243cabdff1aSopenharmony_ci            extradata_size = ptr - 4 - pkt->data;
244cabdff1aSopenharmony_ci            break;
245cabdff1aSopenharmony_ci        }
246cabdff1aSopenharmony_ci    }
247cabdff1aSopenharmony_ci
248cabdff1aSopenharmony_ci    if (extradata_size) {
249cabdff1aSopenharmony_ci        *data = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
250cabdff1aSopenharmony_ci        if (!*data)
251cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
252cabdff1aSopenharmony_ci
253cabdff1aSopenharmony_ci        memcpy(*data, pkt->data, extradata_size);
254cabdff1aSopenharmony_ci        *size = extradata_size;
255cabdff1aSopenharmony_ci
256cabdff1aSopenharmony_ci        if (s->remove) {
257cabdff1aSopenharmony_ci            pkt->data += extradata_size;
258cabdff1aSopenharmony_ci            pkt->size -= extradata_size;
259cabdff1aSopenharmony_ci        }
260cabdff1aSopenharmony_ci    }
261cabdff1aSopenharmony_ci
262cabdff1aSopenharmony_ci    return 0;
263cabdff1aSopenharmony_ci}
264cabdff1aSopenharmony_ci
265cabdff1aSopenharmony_cistatic int extract_extradata_mpeg12(AVBSFContext *ctx, AVPacket *pkt,
266cabdff1aSopenharmony_ci                                     uint8_t **data, int *size)
267cabdff1aSopenharmony_ci{
268cabdff1aSopenharmony_ci    ExtractExtradataContext *s = ctx->priv_data;
269cabdff1aSopenharmony_ci    uint32_t state = UINT32_MAX;
270cabdff1aSopenharmony_ci    int i, found = 0;
271cabdff1aSopenharmony_ci
272cabdff1aSopenharmony_ci    for (i = 0; i < pkt->size; i++) {
273cabdff1aSopenharmony_ci        state = (state << 8) | pkt->data[i];
274cabdff1aSopenharmony_ci        if (state == 0x1B3)
275cabdff1aSopenharmony_ci            found = 1;
276cabdff1aSopenharmony_ci        else if (found && state != 0x1B5 && state < 0x200 && state >= 0x100) {
277cabdff1aSopenharmony_ci            *size = i - 3;
278cabdff1aSopenharmony_ci            *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE);
279cabdff1aSopenharmony_ci            if (!*data)
280cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
281cabdff1aSopenharmony_ci
282cabdff1aSopenharmony_ci            memcpy(*data, pkt->data, *size);
283cabdff1aSopenharmony_ci
284cabdff1aSopenharmony_ci            if (s->remove) {
285cabdff1aSopenharmony_ci                pkt->data += *size;
286cabdff1aSopenharmony_ci                pkt->size -= *size;
287cabdff1aSopenharmony_ci            }
288cabdff1aSopenharmony_ci            break;
289cabdff1aSopenharmony_ci        }
290cabdff1aSopenharmony_ci    }
291cabdff1aSopenharmony_ci    return 0;
292cabdff1aSopenharmony_ci}
293cabdff1aSopenharmony_ci
294cabdff1aSopenharmony_cistatic int extract_extradata_mpeg4(AVBSFContext *ctx, AVPacket *pkt,
295cabdff1aSopenharmony_ci                                   uint8_t **data, int *size)
296cabdff1aSopenharmony_ci{
297cabdff1aSopenharmony_ci    ExtractExtradataContext *s = ctx->priv_data;
298cabdff1aSopenharmony_ci    const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size;
299cabdff1aSopenharmony_ci    uint32_t state = UINT32_MAX;
300cabdff1aSopenharmony_ci
301cabdff1aSopenharmony_ci    while (ptr < end) {
302cabdff1aSopenharmony_ci        ptr = avpriv_find_start_code(ptr, end, &state);
303cabdff1aSopenharmony_ci        if (state == 0x1B3 || state == 0x1B6) {
304cabdff1aSopenharmony_ci            if (ptr - pkt->data > 4) {
305cabdff1aSopenharmony_ci                *size = ptr - 4 - pkt->data;
306cabdff1aSopenharmony_ci                *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE);
307cabdff1aSopenharmony_ci                if (!*data)
308cabdff1aSopenharmony_ci                    return AVERROR(ENOMEM);
309cabdff1aSopenharmony_ci
310cabdff1aSopenharmony_ci                memcpy(*data, pkt->data, *size);
311cabdff1aSopenharmony_ci
312cabdff1aSopenharmony_ci                if (s->remove) {
313cabdff1aSopenharmony_ci                    pkt->data += *size;
314cabdff1aSopenharmony_ci                    pkt->size -= *size;
315cabdff1aSopenharmony_ci                }
316cabdff1aSopenharmony_ci            }
317cabdff1aSopenharmony_ci            break;
318cabdff1aSopenharmony_ci        }
319cabdff1aSopenharmony_ci    }
320cabdff1aSopenharmony_ci    return 0;
321cabdff1aSopenharmony_ci}
322cabdff1aSopenharmony_ci
323cabdff1aSopenharmony_cistatic const struct {
324cabdff1aSopenharmony_ci    enum AVCodecID id;
325cabdff1aSopenharmony_ci    int (*extract)(AVBSFContext *ctx, AVPacket *pkt,
326cabdff1aSopenharmony_ci                   uint8_t **data, int *size);
327cabdff1aSopenharmony_ci} extract_tab[] = {
328cabdff1aSopenharmony_ci    { AV_CODEC_ID_AV1,        extract_extradata_av1     },
329cabdff1aSopenharmony_ci    { AV_CODEC_ID_AVS2,       extract_extradata_mpeg4   },
330cabdff1aSopenharmony_ci    { AV_CODEC_ID_AVS3,       extract_extradata_mpeg4   },
331cabdff1aSopenharmony_ci    { AV_CODEC_ID_CAVS,       extract_extradata_mpeg4   },
332cabdff1aSopenharmony_ci    { AV_CODEC_ID_H264,       extract_extradata_h2645   },
333cabdff1aSopenharmony_ci    { AV_CODEC_ID_HEVC,       extract_extradata_h2645   },
334cabdff1aSopenharmony_ci    { AV_CODEC_ID_MPEG1VIDEO, extract_extradata_mpeg12  },
335cabdff1aSopenharmony_ci    { AV_CODEC_ID_MPEG2VIDEO, extract_extradata_mpeg12  },
336cabdff1aSopenharmony_ci    { AV_CODEC_ID_MPEG4,      extract_extradata_mpeg4   },
337cabdff1aSopenharmony_ci    { AV_CODEC_ID_VC1,        extract_extradata_vc1     },
338cabdff1aSopenharmony_ci};
339cabdff1aSopenharmony_ci
340cabdff1aSopenharmony_cistatic int extract_extradata_init(AVBSFContext *ctx)
341cabdff1aSopenharmony_ci{
342cabdff1aSopenharmony_ci    ExtractExtradataContext *s = ctx->priv_data;
343cabdff1aSopenharmony_ci    int i;
344cabdff1aSopenharmony_ci
345cabdff1aSopenharmony_ci    for (i = 0; i < FF_ARRAY_ELEMS(extract_tab); i++) {
346cabdff1aSopenharmony_ci        if (extract_tab[i].id == ctx->par_in->codec_id) {
347cabdff1aSopenharmony_ci            s->extract = extract_tab[i].extract;
348cabdff1aSopenharmony_ci            break;
349cabdff1aSopenharmony_ci        }
350cabdff1aSopenharmony_ci    }
351cabdff1aSopenharmony_ci    if (!s->extract)
352cabdff1aSopenharmony_ci        return AVERROR_BUG;
353cabdff1aSopenharmony_ci
354cabdff1aSopenharmony_ci    return 0;
355cabdff1aSopenharmony_ci}
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_cistatic int extract_extradata_filter(AVBSFContext *ctx, AVPacket *pkt)
358cabdff1aSopenharmony_ci{
359cabdff1aSopenharmony_ci    ExtractExtradataContext *s = ctx->priv_data;
360cabdff1aSopenharmony_ci    uint8_t *extradata = NULL;
361cabdff1aSopenharmony_ci    int extradata_size;
362cabdff1aSopenharmony_ci    int ret = 0;
363cabdff1aSopenharmony_ci
364cabdff1aSopenharmony_ci    ret = ff_bsf_get_packet_ref(ctx, pkt);
365cabdff1aSopenharmony_ci    if (ret < 0)
366cabdff1aSopenharmony_ci        return ret;
367cabdff1aSopenharmony_ci
368cabdff1aSopenharmony_ci    ret = s->extract(ctx, pkt, &extradata, &extradata_size);
369cabdff1aSopenharmony_ci    if (ret < 0)
370cabdff1aSopenharmony_ci        goto fail;
371cabdff1aSopenharmony_ci
372cabdff1aSopenharmony_ci    if (extradata) {
373cabdff1aSopenharmony_ci        memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
374cabdff1aSopenharmony_ci        ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
375cabdff1aSopenharmony_ci                                      extradata, extradata_size);
376cabdff1aSopenharmony_ci        if (ret < 0) {
377cabdff1aSopenharmony_ci            av_freep(&extradata);
378cabdff1aSopenharmony_ci            goto fail;
379cabdff1aSopenharmony_ci        }
380cabdff1aSopenharmony_ci    }
381cabdff1aSopenharmony_ci
382cabdff1aSopenharmony_ci    return 0;
383cabdff1aSopenharmony_ci
384cabdff1aSopenharmony_cifail:
385cabdff1aSopenharmony_ci    av_packet_unref(pkt);
386cabdff1aSopenharmony_ci    return ret;
387cabdff1aSopenharmony_ci}
388cabdff1aSopenharmony_ci
389cabdff1aSopenharmony_cistatic void extract_extradata_close(AVBSFContext *ctx)
390cabdff1aSopenharmony_ci{
391cabdff1aSopenharmony_ci    ExtractExtradataContext *s = ctx->priv_data;
392cabdff1aSopenharmony_ci    ff_av1_packet_uninit(&s->av1_pkt);
393cabdff1aSopenharmony_ci    ff_h2645_packet_uninit(&s->h2645_pkt);
394cabdff1aSopenharmony_ci}
395cabdff1aSopenharmony_ci
396cabdff1aSopenharmony_cistatic const enum AVCodecID codec_ids[] = {
397cabdff1aSopenharmony_ci    AV_CODEC_ID_AV1,
398cabdff1aSopenharmony_ci    AV_CODEC_ID_AVS2,
399cabdff1aSopenharmony_ci    AV_CODEC_ID_AVS3,
400cabdff1aSopenharmony_ci    AV_CODEC_ID_CAVS,
401cabdff1aSopenharmony_ci    AV_CODEC_ID_H264,
402cabdff1aSopenharmony_ci    AV_CODEC_ID_HEVC,
403cabdff1aSopenharmony_ci    AV_CODEC_ID_MPEG1VIDEO,
404cabdff1aSopenharmony_ci    AV_CODEC_ID_MPEG2VIDEO,
405cabdff1aSopenharmony_ci    AV_CODEC_ID_MPEG4,
406cabdff1aSopenharmony_ci    AV_CODEC_ID_VC1,
407cabdff1aSopenharmony_ci    AV_CODEC_ID_NONE,
408cabdff1aSopenharmony_ci};
409cabdff1aSopenharmony_ci
410cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(ExtractExtradataContext, x)
411cabdff1aSopenharmony_ci#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
412cabdff1aSopenharmony_cistatic const AVOption options[] = {
413cabdff1aSopenharmony_ci    { "remove", "remove the extradata from the bitstream", OFFSET(remove), AV_OPT_TYPE_INT,
414cabdff1aSopenharmony_ci        { .i64 = 0 }, 0, 1, FLAGS },
415cabdff1aSopenharmony_ci    { NULL },
416cabdff1aSopenharmony_ci};
417cabdff1aSopenharmony_ci
418cabdff1aSopenharmony_cistatic const AVClass extract_extradata_class = {
419cabdff1aSopenharmony_ci    .class_name = "extract_extradata",
420cabdff1aSopenharmony_ci    .item_name  = av_default_item_name,
421cabdff1aSopenharmony_ci    .option     = options,
422cabdff1aSopenharmony_ci    .version    = LIBAVUTIL_VERSION_INT,
423cabdff1aSopenharmony_ci};
424cabdff1aSopenharmony_ci
425cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_extract_extradata_bsf = {
426cabdff1aSopenharmony_ci    .p.name         = "extract_extradata",
427cabdff1aSopenharmony_ci    .p.codec_ids    = codec_ids,
428cabdff1aSopenharmony_ci    .p.priv_class   = &extract_extradata_class,
429cabdff1aSopenharmony_ci    .priv_data_size = sizeof(ExtractExtradataContext),
430cabdff1aSopenharmony_ci    .init           = extract_extradata_init,
431cabdff1aSopenharmony_ci    .filter         = extract_extradata_filter,
432cabdff1aSopenharmony_ci    .close          = extract_extradata_close,
433cabdff1aSopenharmony_ci};
434