/src/ffmpeg/libavcodec/bsf/extract_extradata.c
Line | Count | Source |
1 | | /* |
2 | | * This file is part of FFmpeg. |
3 | | * |
4 | | * FFmpeg is free software; you can redistribute it and/or |
5 | | * modify it under the terms of the GNU Lesser General Public |
6 | | * License as published by the Free Software Foundation; either |
7 | | * version 2.1 of the License, or (at your option) any later version. |
8 | | * |
9 | | * FFmpeg is distributed in the hope that it will be useful, |
10 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | | * Lesser General Public License for more details. |
13 | | * |
14 | | * You should have received a copy of the GNU Lesser General Public |
15 | | * License along with FFmpeg; if not, write to the Free Software |
16 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
17 | | */ |
18 | | |
19 | | #include <stdint.h> |
20 | | |
21 | | #include "libavutil/log.h" |
22 | | #include "libavutil/mem.h" |
23 | | #include "libavutil/opt.h" |
24 | | |
25 | | #include "av1.h" |
26 | | #include "av1_parse.h" |
27 | | #include "bsf.h" |
28 | | #include "bsf_internal.h" |
29 | | #include "bytestream.h" |
30 | | #include "h2645_parse.h" |
31 | | #include "h264.h" |
32 | | #include "lcevc.h" |
33 | | #include "lcevc_parse.h" |
34 | | #include "startcode.h" |
35 | | #include "vc1_common.h" |
36 | | #include "vvc.h" |
37 | | |
38 | | #include "hevc/hevc.h" |
39 | | |
40 | | typedef struct ExtractExtradataContext { |
41 | | const AVClass *class; |
42 | | |
43 | | int (*extract)(AVBSFContext *ctx, AVPacket *pkt, |
44 | | uint8_t **data, int *size); |
45 | | |
46 | | /* AV1 specific fields */ |
47 | | AV1Packet av1_pkt; |
48 | | |
49 | | /* H264/HEVC specific fields */ |
50 | | H2645Packet h2645_pkt; |
51 | | |
52 | | /* AVOptions */ |
53 | | int remove; |
54 | | } ExtractExtradataContext; |
55 | | |
56 | | static int val_in_array(const int *arr, size_t len, int val) |
57 | 6.06M | { |
58 | 18.4M | for (size_t i = 0; i < len; i++) |
59 | 12.6M | if (arr[i] == val) |
60 | 243k | return 1; |
61 | 5.82M | return 0; |
62 | 6.06M | } |
63 | | |
64 | | static int metadata_is_global(const AV1OBU *obu) |
65 | 2.31k | { |
66 | 2.31k | static const int metadata_obu_types[] = { |
67 | 2.31k | AV1_METADATA_TYPE_HDR_CLL, AV1_METADATA_TYPE_HDR_MDCV, |
68 | 2.31k | }; |
69 | 2.31k | GetBitContext gb; |
70 | 2.31k | int metadata_type; |
71 | | |
72 | 2.31k | if (init_get_bits(&gb, obu->data, obu->size_bits) < 0) |
73 | 0 | return 0; |
74 | | |
75 | 2.31k | metadata_type = get_leb(&gb); |
76 | | |
77 | 2.31k | return val_in_array(metadata_obu_types, FF_ARRAY_ELEMS(metadata_obu_types), |
78 | 2.31k | metadata_type); |
79 | 2.31k | } |
80 | | |
81 | | static int obu_is_global(const AV1OBU *obu) |
82 | 1.98M | { |
83 | 1.98M | static const int extradata_obu_types[] = { |
84 | 1.98M | AV1_OBU_SEQUENCE_HEADER, AV1_OBU_METADATA, |
85 | 1.98M | }; |
86 | | |
87 | 1.98M | if (!val_in_array(extradata_obu_types, FF_ARRAY_ELEMS(extradata_obu_types), |
88 | 1.98M | obu->type)) |
89 | 1.97M | return 0; |
90 | 7.43k | if (obu->type != AV1_OBU_METADATA) |
91 | 5.11k | return 1; |
92 | | |
93 | 2.31k | return metadata_is_global(obu); |
94 | 7.43k | } |
95 | | |
96 | | static int extract_extradata_av1(AVBSFContext *ctx, AVPacket *pkt, |
97 | | uint8_t **data, int *size) |
98 | 8.49k | { |
99 | | |
100 | 8.49k | ExtractExtradataContext *s = ctx->priv_data; |
101 | | |
102 | 8.49k | int extradata_size = 0, filtered_size = 0; |
103 | 8.49k | int i, has_seq = 0, ret = 0; |
104 | | |
105 | 8.49k | ret = ff_av1_packet_split(&s->av1_pkt, pkt->data, pkt->size, ctx); |
106 | 8.49k | if (ret < 0) |
107 | 2.29k | return ret; |
108 | | |
109 | 1.00M | for (i = 0; i < s->av1_pkt.nb_obus; i++) { |
110 | 995k | AV1OBU *obu = &s->av1_pkt.obus[i]; |
111 | 995k | if (obu_is_global(obu)) { |
112 | 3.00k | extradata_size += obu->raw_size; |
113 | 3.00k | if (obu->type == AV1_OBU_SEQUENCE_HEADER) |
114 | 2.55k | has_seq = 1; |
115 | 992k | } else { |
116 | 992k | filtered_size += obu->raw_size; |
117 | 992k | } |
118 | 995k | } |
119 | | |
120 | 6.19k | if (extradata_size && has_seq) { |
121 | 2.33k | AVBufferRef *filtered_buf = NULL; |
122 | 2.33k | PutByteContext pb_filtered_data, pb_extradata; |
123 | 2.33k | uint8_t *extradata; |
124 | | |
125 | 2.33k | if (s->remove) { |
126 | 619 | filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); |
127 | 619 | if (!filtered_buf) { |
128 | 0 | return AVERROR(ENOMEM); |
129 | 0 | } |
130 | 619 | memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
131 | 619 | } |
132 | | |
133 | 2.33k | extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |
134 | 2.33k | if (!extradata) { |
135 | 0 | av_buffer_unref(&filtered_buf); |
136 | 0 | return AVERROR(ENOMEM); |
137 | 0 | } |
138 | | |
139 | 2.33k | *data = extradata; |
140 | 2.33k | *size = extradata_size; |
141 | | |
142 | 2.33k | bytestream2_init_writer(&pb_extradata, extradata, extradata_size); |
143 | 2.33k | if (s->remove) |
144 | 619 | bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size); |
145 | | |
146 | 990k | for (i = 0; i < s->av1_pkt.nb_obus; i++) { |
147 | 987k | AV1OBU *obu = &s->av1_pkt.obus[i]; |
148 | 987k | if (obu_is_global(obu)) { |
149 | 2.77k | bytestream2_put_bufferu(&pb_extradata, obu->raw_data, obu->raw_size); |
150 | 984k | } else if (s->remove) { |
151 | 939 | bytestream2_put_bufferu(&pb_filtered_data, obu->raw_data, obu->raw_size); |
152 | 939 | } |
153 | 987k | } |
154 | | |
155 | 2.33k | if (s->remove) { |
156 | 619 | av_buffer_unref(&pkt->buf); |
157 | 619 | pkt->buf = filtered_buf; |
158 | 619 | pkt->data = filtered_buf->data; |
159 | 619 | pkt->size = filtered_size; |
160 | 619 | } |
161 | 2.33k | } |
162 | | |
163 | 6.19k | return 0; |
164 | 6.19k | } |
165 | | |
166 | | static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, |
167 | | uint8_t **data, int *size) |
168 | 31.4k | { |
169 | 31.4k | static const int extradata_nal_types_vvc[] = { |
170 | 31.4k | VVC_VPS_NUT, VVC_SPS_NUT, VVC_PPS_NUT, |
171 | 31.4k | }; |
172 | 31.4k | static const int extradata_nal_types_hevc[] = { |
173 | 31.4k | HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS, |
174 | 31.4k | }; |
175 | 31.4k | static const int extradata_nal_types_h264[] = { |
176 | 31.4k | H264_NAL_SPS, H264_NAL_PPS, |
177 | 31.4k | }; |
178 | | |
179 | 31.4k | ExtractExtradataContext *s = ctx->priv_data; |
180 | | |
181 | 31.4k | int extradata_size = 0, filtered_size = 0; |
182 | 31.4k | const int *extradata_nal_types; |
183 | 31.4k | size_t nb_extradata_nal_types; |
184 | 31.4k | int filtered_nb_nals = 0; |
185 | 31.4k | int i, has_sps = 0, has_vps = 0, ret = 0; |
186 | | |
187 | 31.4k | if (ctx->par_in->codec_id == AV_CODEC_ID_VVC) { |
188 | 7.05k | extradata_nal_types = extradata_nal_types_vvc; |
189 | 7.05k | nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_vvc); |
190 | 24.3k | } else if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { |
191 | 14.4k | extradata_nal_types = extradata_nal_types_hevc; |
192 | 14.4k | nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc); |
193 | 14.4k | } else { |
194 | 9.89k | extradata_nal_types = extradata_nal_types_h264; |
195 | 9.89k | nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_h264); |
196 | 9.89k | } |
197 | | |
198 | 31.4k | ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size, |
199 | 31.4k | ctx, 0, ctx->par_in->codec_id, H2645_FLAG_SMALL_PADDING); |
200 | 31.4k | if (ret < 0) |
201 | 1.46k | return ret; |
202 | | |
203 | 2.57M | for (i = 0; i < s->h2645_pkt.nb_nals; i++) { |
204 | 2.54M | H2645NAL *nal = &s->h2645_pkt.nals[i]; |
205 | 2.54M | if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { |
206 | 118k | extradata_size += nal->raw_size + 4; |
207 | 118k | if (ctx->par_in->codec_id == AV_CODEC_ID_VVC) { |
208 | 8.57k | if (nal->type == VVC_SPS_NUT) has_sps = 1; |
209 | 8.57k | if (nal->type == VVC_VPS_NUT) has_vps = 1; |
210 | 109k | } else if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { |
211 | 48.1k | if (nal->type == HEVC_NAL_SPS) has_sps = 1; |
212 | 48.1k | if (nal->type == HEVC_NAL_VPS) has_vps = 1; |
213 | 61.4k | } else { |
214 | 61.4k | if (nal->type == H264_NAL_SPS) has_sps = 1; |
215 | 61.4k | } |
216 | 2.42M | } else { |
217 | 2.42M | filtered_size += nal->raw_size + 3 + |
218 | 2.42M | ff_h2645_unit_requires_zero_byte(ctx->par_in->codec_id, nal->type, filtered_nb_nals++); |
219 | 2.42M | } |
220 | 2.54M | } |
221 | | |
222 | 29.9k | if (extradata_size && |
223 | 15.0k | ((ctx->par_in->codec_id == AV_CODEC_ID_VVC && has_sps) || |
224 | 13.0k | (ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) || |
225 | 9.02k | (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) { |
226 | 9.02k | AVBufferRef *filtered_buf = NULL; |
227 | 9.02k | PutByteContext pb_filtered_data, pb_extradata; |
228 | 9.02k | uint8_t *extradata; |
229 | | |
230 | 9.02k | if (s->remove) { |
231 | 649 | filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); |
232 | 649 | if (!filtered_buf) { |
233 | 0 | return AVERROR(ENOMEM); |
234 | 0 | } |
235 | 649 | memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
236 | 649 | } |
237 | | |
238 | 9.02k | extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |
239 | 9.02k | if (!extradata) { |
240 | 0 | av_buffer_unref(&filtered_buf); |
241 | 0 | return AVERROR(ENOMEM); |
242 | 0 | } |
243 | | |
244 | 9.02k | *data = extradata; |
245 | 9.02k | *size = extradata_size; |
246 | | |
247 | 9.02k | bytestream2_init_writer(&pb_extradata, extradata, extradata_size); |
248 | 9.02k | if (s->remove) |
249 | 649 | bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size); |
250 | | |
251 | 9.02k | filtered_nb_nals = 0; |
252 | 1.48M | for (i = 0; i < s->h2645_pkt.nb_nals; i++) { |
253 | 1.47M | H2645NAL *nal = &s->h2645_pkt.nals[i]; |
254 | 1.47M | if (val_in_array(extradata_nal_types, nb_extradata_nal_types, |
255 | 1.47M | nal->type)) { |
256 | 106k | bytestream2_put_be32u(&pb_extradata, 1); //startcode |
257 | 106k | bytestream2_put_bufferu(&pb_extradata, nal->raw_data, nal->raw_size); |
258 | 1.36M | } else if (s->remove) { |
259 | 92.9k | if (ff_h2645_unit_requires_zero_byte(ctx->par_in->codec_id, nal->type, filtered_nb_nals++)) |
260 | 296 | bytestream2_put_byteu(&pb_filtered_data, 0); // zero_byte |
261 | 92.9k | bytestream2_put_be24u(&pb_filtered_data, 1); // startcode |
262 | 92.9k | bytestream2_put_bufferu(&pb_filtered_data, nal->raw_data, nal->raw_size); |
263 | 92.9k | } |
264 | 1.47M | } |
265 | | |
266 | 9.02k | if (s->remove) { |
267 | 649 | av_buffer_unref(&pkt->buf); |
268 | 649 | pkt->buf = filtered_buf; |
269 | 649 | pkt->data = filtered_buf->data; |
270 | 649 | pkt->size = filtered_size; |
271 | 649 | } |
272 | 9.02k | } |
273 | | |
274 | 29.9k | return 0; |
275 | 29.9k | } |
276 | | |
277 | | /** |
278 | | * Rewrite the NALu stripping the unneeded blocks. |
279 | | * Given that length fields coded inside the NALu are not aware of any emulation_3bytes |
280 | | * present in the bitstream, we need to keep track of the raw buffer as we navigate |
281 | | * the stripped buffer. |
282 | | */ |
283 | | static int process_lcevc_nalu(PutByteContext *extradata, PutByteContext *data, |
284 | | int *extradata_sizep, int *data_sizep, const H2645NAL *nal) |
285 | 9.76k | { |
286 | 9.76k | GetByteContext gbc, raw_gbc; |
287 | 9.76k | int sc = 0, gc = 0; |
288 | 9.76k | int skipped_byte_pos = 0; |
289 | 9.76k | int extradata_size = 0, data_size = 0; |
290 | | |
291 | 9.76k | if (nal->size < 2) |
292 | 205 | return AVERROR_INVALIDDATA; |
293 | | |
294 | 9.55k | bytestream2_init(&gbc, nal->data, nal->size); |
295 | 9.55k | bytestream2_init(&raw_gbc, nal->raw_data, nal->raw_size); |
296 | | |
297 | 9.55k | unsigned nalu_header = bytestream2_get_be16u(&gbc); |
298 | | |
299 | 9.55k | if (data) |
300 | 704 | bytestream2_put_be16u(data, nalu_header); |
301 | 9.55k | data_size += 2; |
302 | 9.55k | bytestream2_skipu(&raw_gbc, 2); |
303 | | |
304 | 7.44M | while (bytestream2_get_bytes_left(&gbc) > 1) { |
305 | 7.43M | GetBitContext gb; |
306 | 7.43M | int payload_size_type, payload_type; |
307 | 7.43M | uint64_t payload_size; |
308 | 7.43M | int block_size, raw_block_size, block_end; |
309 | | |
310 | 7.43M | av_unused int ret = init_get_bits8(&gb, gbc.buffer, bytestream2_get_bytes_left(&gbc)); |
311 | 7.43M | av_assert1(ret >= 0); // h2645_parse already opened a GetBitContext with this data |
312 | | |
313 | 7.43M | payload_size_type = get_bits(&gb, 3); |
314 | 7.43M | payload_type = get_bits(&gb, 5); |
315 | 7.43M | payload_size = payload_size_type; |
316 | 7.43M | if (payload_size_type == 6) |
317 | 285 | return AVERROR_INVALIDDATA; |
318 | 7.43M | if (payload_size_type == 7) |
319 | 4.43k | payload_size = get_mb(&gb); |
320 | | |
321 | 7.43M | if (payload_size > INT_MAX - (get_bits_count(&gb) >> 3)) |
322 | 918 | return AVERROR_INVALIDDATA; |
323 | | |
324 | 7.43M | block_size = raw_block_size = payload_size + (get_bits_count(&gb) >> 3); |
325 | 7.43M | if (block_size >= bytestream2_get_bytes_left(&gbc)) |
326 | 401 | return AVERROR_INVALIDDATA; |
327 | | |
328 | 7.43M | block_end = bytestream2_tell(&gbc) + block_size; |
329 | | // Take into account removed emulation 3bytes, as payload_size in |
330 | | // the bitstream is not aware of them. |
331 | 8.20M | for (; skipped_byte_pos < nal->skipped_bytes; skipped_byte_pos++) { |
332 | 1.26M | if (nal->skipped_bytes_pos[skipped_byte_pos] >= block_end) |
333 | 495k | break; |
334 | 768k | raw_block_size++; |
335 | 768k | } |
336 | 7.43M | if (raw_block_size > bytestream2_get_bytes_left(&raw_gbc)) |
337 | 0 | return AVERROR_INVALIDDATA; |
338 | | |
339 | 7.43M | switch (payload_type) { |
340 | 3.68M | case LCEVC_PAYLOAD_TYPE_SEQUENCE_CONFIG: |
341 | 4.94M | case LCEVC_PAYLOAD_TYPE_GLOBAL_CONFIG: |
342 | 5.58M | case LCEVC_PAYLOAD_TYPE_ADDITIONAL_INFO: |
343 | 5.58M | if (!extradata_size) { |
344 | 8.04k | extradata_size = 2; |
345 | 8.04k | if (extradata) |
346 | 3.46k | bytestream2_put_be16u(extradata, nalu_header); |
347 | 8.04k | } |
348 | 5.58M | if (extradata) |
349 | 2.72M | bytestream2_put_bufferu(extradata, raw_gbc.buffer, raw_block_size); |
350 | 5.58M | extradata_size += raw_block_size; |
351 | 5.58M | sc |= payload_type == LCEVC_PAYLOAD_TYPE_SEQUENCE_CONFIG; |
352 | 5.58M | gc |= payload_type == LCEVC_PAYLOAD_TYPE_GLOBAL_CONFIG; |
353 | 5.58M | break; |
354 | 1.85M | default: |
355 | 1.85M | if (data) |
356 | 763k | bytestream2_put_bufferu(data, raw_gbc.buffer, raw_block_size); |
357 | 1.85M | data_size += raw_block_size; |
358 | 1.85M | break; |
359 | 7.43M | } |
360 | | |
361 | 7.43M | bytestream2_skip(&gbc, block_size); |
362 | 7.43M | bytestream2_skip(&raw_gbc, raw_block_size); |
363 | 7.43M | } |
364 | | |
365 | 7.95k | ++data_size; |
366 | 7.95k | *data_sizep = data_size; |
367 | 7.95k | if (data) |
368 | 704 | bytestream2_put_byteu(data, 0x80); // rbsp_alignment bits |
369 | 7.95k | if (extradata_size > 0) { |
370 | 7.31k | if (!sc && !gc) |
371 | 250 | return AVERROR_INVALIDDATA; |
372 | | |
373 | 7.06k | ++extradata_size; |
374 | 7.06k | if (extradata) { |
375 | 3.46k | bytestream2_put_byteu(extradata, 0x80); // rbsp_alignment bits |
376 | 3.46k | } else |
377 | 3.60k | *extradata_sizep = extradata_size; |
378 | 7.06k | return 1; // has extradata |
379 | 7.31k | } |
380 | 633 | return 0; // no extradata |
381 | 7.95k | } |
382 | | |
383 | | static int extract_extradata_lcevc(AVBSFContext *ctx, AVPacket *pkt, |
384 | | uint8_t **data, int *size) |
385 | 11.7k | { |
386 | 11.7k | static const int extradata_nal_types[] = { |
387 | 11.7k | LCEVC_IDR_NUT, LCEVC_NON_IDR_NUT, |
388 | 11.7k | }; |
389 | | |
390 | 11.7k | ExtractExtradataContext *s = ctx->priv_data; |
391 | 11.7k | unsigned extradata_size = 0, filtered_size = 0; |
392 | 11.7k | size_t nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types); |
393 | 11.7k | int i, ret = 0; |
394 | | |
395 | 11.7k | ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size, |
396 | 11.7k | ctx, 0, AV_CODEC_ID_LCEVC, H2645_FLAG_SMALL_PADDING); |
397 | 11.7k | if (ret < 0) |
398 | 2.21k | return ret; |
399 | | |
400 | 53.8k | for (i = 0; i < s->h2645_pkt.nb_nals; i++) { |
401 | 46.3k | H2645NAL *nal = &s->h2645_pkt.nals[i]; |
402 | 46.3k | unsigned start_code_size = 3 + !filtered_size; |
403 | | |
404 | 46.3k | if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { |
405 | 5.99k | int extra_size, data_size; |
406 | 5.99k | ret = process_lcevc_nalu(NULL, NULL, &extra_size, &data_size, nal); |
407 | 5.99k | if (ret < 0) |
408 | 2.05k | return ret; |
409 | 3.93k | if (ret > 0) { // has extradata |
410 | 3.60k | unsigned extra_start_code_size = 3 + !extradata_size; |
411 | 3.60k | extradata_size += extra_start_code_size + extra_size; |
412 | 3.60k | if (extradata_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
413 | 0 | return AVERROR_INVALIDDATA; |
414 | 3.60k | } |
415 | 3.93k | filtered_size += start_code_size + data_size; |
416 | 3.93k | } else |
417 | 40.3k | filtered_size += start_code_size + nal->raw_size; |
418 | 44.3k | if (filtered_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
419 | 0 | return AVERROR_INVALIDDATA; |
420 | 44.3k | } |
421 | | |
422 | 7.43k | if (extradata_size) { |
423 | 867 | AVBufferRef *filtered_buf = NULL; |
424 | 867 | PutByteContext pb_extradata; |
425 | 867 | PutByteContext pb_filtered_data; |
426 | 867 | uint8_t *extradata; |
427 | | |
428 | 867 | if (s->remove) { |
429 | 389 | ret = av_buffer_realloc(&filtered_buf, filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); |
430 | 389 | if (ret < 0) |
431 | 0 | return ret; |
432 | 389 | bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size); |
433 | | // this is the first byte of a four-byte startcode; we write it here |
434 | | // so that we only need to write three-byte startcodes below |
435 | 389 | bytestream2_put_byteu(&pb_filtered_data, 0x00); |
436 | 389 | } |
437 | | |
438 | 867 | extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |
439 | 867 | if (!extradata) { |
440 | 0 | av_buffer_unref(&filtered_buf); |
441 | 0 | return AVERROR(ENOMEM); |
442 | 0 | } |
443 | | |
444 | 867 | *data = extradata; |
445 | 867 | *size = extradata_size; |
446 | | |
447 | 867 | bytestream2_init_writer(&pb_extradata, extradata, extradata_size); |
448 | | // We write the startcodes before the actual units because we do not |
449 | | // know in advance whether a given unit will contribute to extradata, |
450 | | // but we know when we have encountered the last unit containing |
451 | | // extradata. (The alternative is writing it and then undoing this |
452 | | // if the NALU did not contain extradata.) |
453 | 867 | bytestream2_put_be32u(&pb_extradata, 0x00000001); |
454 | | |
455 | 19.6k | for (i = 0; i < s->h2645_pkt.nb_nals; i++) { |
456 | 18.8k | H2645NAL *nal = &s->h2645_pkt.nals[i]; |
457 | 18.8k | if (s->remove) |
458 | 4.89k | bytestream2_put_be24u(&pb_filtered_data, 0x000001); |
459 | 18.8k | if (val_in_array(extradata_nal_types, nb_extradata_nal_types, |
460 | 18.8k | nal->type)) { |
461 | 3.77k | int dummy; |
462 | 3.77k | ret = process_lcevc_nalu(&pb_extradata, s->remove ? &pb_filtered_data : NULL, |
463 | 3.77k | NULL, &dummy, nal); |
464 | 3.77k | av_assert1(ret >= 0); // already checked in the first pass |
465 | 3.77k | if (ret > 0) {// NALU contained extradata |
466 | 3.46k | if (extradata_size != bytestream2_tell_p(&pb_extradata)) { |
467 | | // There will be another NALU containing extradata. |
468 | | // Already write the next start code. |
469 | 2.59k | bytestream2_put_be24u(&pb_extradata, 0x000001); |
470 | 2.59k | } |
471 | 3.46k | } |
472 | 15.0k | } else if (s->remove) { |
473 | 4.18k | bytestream2_put_bufferu(&pb_filtered_data, nal->raw_data, nal->raw_size); |
474 | 4.18k | } |
475 | 18.8k | } |
476 | 867 | av_assert1(bytestream2_tell_p(&pb_extradata) == extradata_size); |
477 | | |
478 | 867 | if (s->remove) { |
479 | 389 | av_assert1(bytestream2_tell_p(&pb_filtered_data) == filtered_size); |
480 | 389 | memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
481 | 389 | av_buffer_unref(&pkt->buf); |
482 | 389 | pkt->buf = filtered_buf; |
483 | 389 | pkt->data = filtered_buf->data; |
484 | 389 | pkt->size = filtered_size; |
485 | 389 | } |
486 | 867 | } |
487 | | |
488 | 7.43k | return 0; |
489 | 7.43k | } |
490 | | |
491 | | static int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt, |
492 | | uint8_t **data, int *size) |
493 | 4.64k | { |
494 | 4.64k | ExtractExtradataContext *s = ctx->priv_data; |
495 | 4.64k | const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size; |
496 | 4.64k | uint32_t state = UINT32_MAX; |
497 | 4.64k | int has_extradata = 0, extradata_size = 0; |
498 | | |
499 | 42.9k | while (ptr < end) { |
500 | 39.7k | ptr = avpriv_find_start_code(ptr, end, &state); |
501 | 39.7k | if (state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT) { |
502 | 4.29k | has_extradata = 1; |
503 | 35.4k | } else if (has_extradata && IS_MARKER(state)) { |
504 | 1.45k | extradata_size = ptr - 4 - pkt->data; |
505 | 1.45k | break; |
506 | 1.45k | } |
507 | 39.7k | } |
508 | | |
509 | 4.64k | if (extradata_size) { |
510 | 1.45k | *data = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |
511 | 1.45k | if (!*data) |
512 | 0 | return AVERROR(ENOMEM); |
513 | | |
514 | 1.45k | memcpy(*data, pkt->data, extradata_size); |
515 | 1.45k | *size = extradata_size; |
516 | | |
517 | 1.45k | if (s->remove) { |
518 | 212 | pkt->data += extradata_size; |
519 | 212 | pkt->size -= extradata_size; |
520 | 212 | } |
521 | 1.45k | } |
522 | | |
523 | 4.64k | return 0; |
524 | 4.64k | } |
525 | | |
526 | | static int extract_extradata_mpeg12(AVBSFContext *ctx, AVPacket *pkt, |
527 | | uint8_t **data, int *size) |
528 | 6.52k | { |
529 | 6.52k | ExtractExtradataContext *s = ctx->priv_data; |
530 | 6.52k | uint32_t state = UINT32_MAX; |
531 | 6.52k | int i, found = 0; |
532 | | |
533 | 10.5M | for (i = 0; i < pkt->size; i++) { |
534 | 10.5M | state = (state << 8) | pkt->data[i]; |
535 | 10.5M | if (state == 0x1B3) |
536 | 1.70k | found = 1; |
537 | 10.5M | else if (found && state != 0x1B5 && state < 0x200 && state >= 0x100) { |
538 | 1.13k | *size = i - 3; |
539 | 1.13k | *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE); |
540 | 1.13k | if (!*data) |
541 | 0 | return AVERROR(ENOMEM); |
542 | | |
543 | 1.13k | memcpy(*data, pkt->data, *size); |
544 | | |
545 | 1.13k | if (s->remove) { |
546 | 235 | pkt->data += *size; |
547 | 235 | pkt->size -= *size; |
548 | 235 | } |
549 | 1.13k | break; |
550 | 1.13k | } |
551 | 10.5M | } |
552 | 6.52k | return 0; |
553 | 6.52k | } |
554 | | |
555 | | static int extract_extradata_mpeg4(AVBSFContext *ctx, AVPacket *pkt, |
556 | | uint8_t **data, int *size) |
557 | 11.8k | { |
558 | 11.8k | ExtractExtradataContext *s = ctx->priv_data; |
559 | 11.8k | const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size; |
560 | 11.8k | uint32_t state = UINT32_MAX; |
561 | | |
562 | 102k | while (ptr < end) { |
563 | 94.5k | ptr = avpriv_find_start_code(ptr, end, &state); |
564 | 94.5k | if (state == 0x1B3 || state == 0x1B6) { |
565 | 3.71k | if (ptr - pkt->data > 4) { |
566 | 3.13k | *size = ptr - 4 - pkt->data; |
567 | 3.13k | *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE); |
568 | 3.13k | if (!*data) |
569 | 0 | return AVERROR(ENOMEM); |
570 | | |
571 | 3.13k | memcpy(*data, pkt->data, *size); |
572 | | |
573 | 3.13k | if (s->remove) { |
574 | 228 | pkt->data += *size; |
575 | 228 | pkt->size -= *size; |
576 | 228 | } |
577 | 3.13k | } |
578 | 3.71k | break; |
579 | 3.71k | } |
580 | 94.5k | } |
581 | 11.8k | return 0; |
582 | 11.8k | } |
583 | | |
584 | | static const struct { |
585 | | enum AVCodecID id; |
586 | | int (*extract)(AVBSFContext *ctx, AVPacket *pkt, |
587 | | uint8_t **data, int *size); |
588 | | } extract_tab[] = { |
589 | | { AV_CODEC_ID_AV1, extract_extradata_av1 }, |
590 | | { AV_CODEC_ID_AVS2, extract_extradata_mpeg4 }, |
591 | | { AV_CODEC_ID_AVS3, extract_extradata_mpeg4 }, |
592 | | { AV_CODEC_ID_CAVS, extract_extradata_mpeg4 }, |
593 | | { AV_CODEC_ID_H264, extract_extradata_h2645 }, |
594 | | { AV_CODEC_ID_HEVC, extract_extradata_h2645 }, |
595 | | { AV_CODEC_ID_LCEVC, extract_extradata_lcevc }, |
596 | | { AV_CODEC_ID_MPEG1VIDEO, extract_extradata_mpeg12 }, |
597 | | { AV_CODEC_ID_MPEG2VIDEO, extract_extradata_mpeg12 }, |
598 | | { AV_CODEC_ID_MPEG4, extract_extradata_mpeg4 }, |
599 | | { AV_CODEC_ID_VC1, extract_extradata_vc1 }, |
600 | | { AV_CODEC_ID_VVC, extract_extradata_h2645 }, |
601 | | }; |
602 | | |
603 | | static int extract_extradata_init(AVBSFContext *ctx) |
604 | 17.4k | { |
605 | 17.4k | ExtractExtradataContext *s = ctx->priv_data; |
606 | 17.4k | int i; |
607 | | |
608 | 130k | for (i = 0; i < FF_ARRAY_ELEMS(extract_tab); i++) { |
609 | 130k | if (extract_tab[i].id == ctx->par_in->codec_id) { |
610 | 17.4k | s->extract = extract_tab[i].extract; |
611 | 17.4k | break; |
612 | 17.4k | } |
613 | 130k | } |
614 | 17.4k | if (!s->extract) |
615 | 0 | return AVERROR_BUG; |
616 | | |
617 | 17.4k | return 0; |
618 | 17.4k | } |
619 | | |
620 | | static int extract_extradata_filter(AVBSFContext *ctx, AVPacket *pkt) |
621 | 130k | { |
622 | 130k | ExtractExtradataContext *s = ctx->priv_data; |
623 | 130k | uint8_t *extradata = NULL; |
624 | 130k | int extradata_size; |
625 | 130k | int ret = 0; |
626 | | |
627 | 130k | ret = ff_bsf_get_packet_ref(ctx, pkt); |
628 | 130k | if (ret < 0) |
629 | 55.8k | return ret; |
630 | | |
631 | 74.6k | ret = s->extract(ctx, pkt, &extradata, &extradata_size); |
632 | 74.6k | if (ret < 0) |
633 | 8.03k | goto fail; |
634 | | |
635 | 66.5k | if (extradata) { |
636 | 17.9k | memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
637 | 17.9k | ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, |
638 | 17.9k | extradata, extradata_size); |
639 | 17.9k | if (ret < 0) { |
640 | 0 | av_freep(&extradata); |
641 | 0 | goto fail; |
642 | 0 | } |
643 | 17.9k | } |
644 | | |
645 | 66.5k | return 0; |
646 | | |
647 | 8.03k | fail: |
648 | 8.03k | av_packet_unref(pkt); |
649 | 8.03k | return ret; |
650 | 66.5k | } |
651 | | |
652 | | static void extract_extradata_close(AVBSFContext *ctx) |
653 | 17.4k | { |
654 | 17.4k | ExtractExtradataContext *s = ctx->priv_data; |
655 | 17.4k | ff_av1_packet_uninit(&s->av1_pkt); |
656 | 17.4k | ff_h2645_packet_uninit(&s->h2645_pkt); |
657 | 17.4k | } |
658 | | |
659 | | static const enum AVCodecID codec_ids[] = { |
660 | | AV_CODEC_ID_AV1, |
661 | | AV_CODEC_ID_AVS2, |
662 | | AV_CODEC_ID_AVS3, |
663 | | AV_CODEC_ID_CAVS, |
664 | | AV_CODEC_ID_H264, |
665 | | AV_CODEC_ID_HEVC, |
666 | | AV_CODEC_ID_LCEVC, |
667 | | AV_CODEC_ID_MPEG1VIDEO, |
668 | | AV_CODEC_ID_MPEG2VIDEO, |
669 | | AV_CODEC_ID_MPEG4, |
670 | | AV_CODEC_ID_VC1, |
671 | | AV_CODEC_ID_VVC, |
672 | | AV_CODEC_ID_NONE, |
673 | | }; |
674 | | |
675 | | #define OFFSET(x) offsetof(ExtractExtradataContext, x) |
676 | | #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) |
677 | | static const AVOption options[] = { |
678 | | { "remove", "remove the extradata from the bitstream", OFFSET(remove), AV_OPT_TYPE_INT, |
679 | | { .i64 = 0 }, 0, 1, FLAGS }, |
680 | | { NULL }, |
681 | | }; |
682 | | |
683 | | static const AVClass extract_extradata_class = { |
684 | | .class_name = "extract_extradata", |
685 | | .item_name = av_default_item_name, |
686 | | .option = options, |
687 | | .version = LIBAVUTIL_VERSION_INT, |
688 | | }; |
689 | | |
690 | | const FFBitStreamFilter ff_extract_extradata_bsf = { |
691 | | .p.name = "extract_extradata", |
692 | | .p.codec_ids = codec_ids, |
693 | | .p.priv_class = &extract_extradata_class, |
694 | | .priv_data_size = sizeof(ExtractExtradataContext), |
695 | | .init = extract_extradata_init, |
696 | | .filter = extract_extradata_filter, |
697 | | .close = extract_extradata_close, |
698 | | }; |