/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 "libavcodec/av1.h" |
26 | | #include "libavcodec/av1_parse.h" |
27 | | #include "libavcodec/bsf.h" |
28 | | #include "libavcodec/bsf_internal.h" |
29 | | #include "libavcodec/bytestream.h" |
30 | | #include "libavcodec/h2645_parse.h" |
31 | | #include "libavcodec/h264.h" |
32 | | #include "libavcodec/lcevc.h" |
33 | | #include "libavcodec/lcevc_parse.h" |
34 | | #include "libavcodec/startcode.h" |
35 | | #include "libavcodec/vc1_common.h" |
36 | | #include "libavcodec/vvc.h" |
37 | | |
38 | | #include "libavcodec/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.08M | { |
58 | 18.4M | for (size_t i = 0; i < len; i++) |
59 | 12.6M | if (arr[i] == val) |
60 | 213k | return 1; |
61 | 5.87M | return 0; |
62 | 6.08M | } |
63 | | |
64 | | static int metadata_is_global(const AV1OBU *obu) |
65 | 2.26k | { |
66 | 2.26k | static const int metadata_obu_types[] = { |
67 | 2.26k | AV1_METADATA_TYPE_HDR_CLL, AV1_METADATA_TYPE_HDR_MDCV, |
68 | 2.26k | }; |
69 | 2.26k | GetBitContext gb; |
70 | 2.26k | int metadata_type; |
71 | | |
72 | 2.26k | if (init_get_bits(&gb, obu->data, obu->size_bits) < 0) |
73 | 0 | return 0; |
74 | | |
75 | 2.26k | metadata_type = get_leb(&gb); |
76 | | |
77 | 2.26k | return val_in_array(metadata_obu_types, FF_ARRAY_ELEMS(metadata_obu_types), |
78 | 2.26k | metadata_type); |
79 | 2.26k | } |
80 | | |
81 | | static int obu_is_global(const AV1OBU *obu) |
82 | 2.07M | { |
83 | 2.07M | static const int extradata_obu_types[] = { |
84 | 2.07M | AV1_OBU_SEQUENCE_HEADER, AV1_OBU_METADATA, |
85 | 2.07M | }; |
86 | | |
87 | 2.07M | if (!val_in_array(extradata_obu_types, FF_ARRAY_ELEMS(extradata_obu_types), |
88 | 2.07M | obu->type)) |
89 | 2.06M | return 0; |
90 | 7.76k | if (obu->type != AV1_OBU_METADATA) |
91 | 5.49k | return 1; |
92 | | |
93 | 2.26k | return metadata_is_global(obu); |
94 | 7.76k | } |
95 | | |
96 | | static int extract_extradata_av1(AVBSFContext *ctx, AVPacket *pkt, |
97 | | uint8_t **data, int *size) |
98 | 8.14k | { |
99 | | |
100 | 8.14k | ExtractExtradataContext *s = ctx->priv_data; |
101 | | |
102 | 8.14k | int extradata_size = 0, filtered_size = 0; |
103 | 8.14k | int i, has_seq = 0, ret = 0; |
104 | | |
105 | 8.14k | ret = ff_av1_packet_split(&s->av1_pkt, pkt->data, pkt->size, ctx); |
106 | 8.14k | if (ret < 0) |
107 | 2.09k | return ret; |
108 | | |
109 | 1.04M | for (i = 0; i < s->av1_pkt.nb_obus; i++) { |
110 | 1.04M | AV1OBU *obu = &s->av1_pkt.obus[i]; |
111 | 1.04M | if (obu_is_global(obu)) { |
112 | 3.29k | extradata_size += obu->raw_size; |
113 | 3.29k | if (obu->type == AV1_OBU_SEQUENCE_HEADER) |
114 | 2.74k | has_seq = 1; |
115 | 1.03M | } else { |
116 | 1.03M | filtered_size += obu->raw_size; |
117 | 1.03M | } |
118 | 1.04M | } |
119 | | |
120 | 6.05k | if (extradata_size && has_seq) { |
121 | 2.44k | AVBufferRef *filtered_buf = NULL; |
122 | 2.44k | PutByteContext pb_filtered_data, pb_extradata; |
123 | 2.44k | uint8_t *extradata; |
124 | | |
125 | 2.44k | if (s->remove) { |
126 | 362 | filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); |
127 | 362 | if (!filtered_buf) { |
128 | 0 | return AVERROR(ENOMEM); |
129 | 0 | } |
130 | 362 | memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
131 | 362 | } |
132 | | |
133 | 2.44k | extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |
134 | 2.44k | if (!extradata) { |
135 | 0 | av_buffer_unref(&filtered_buf); |
136 | 0 | return AVERROR(ENOMEM); |
137 | 0 | } |
138 | | |
139 | 2.44k | *data = extradata; |
140 | 2.44k | *size = extradata_size; |
141 | | |
142 | 2.44k | bytestream2_init_writer(&pb_extradata, extradata, extradata_size); |
143 | 2.44k | if (s->remove) |
144 | 362 | bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size); |
145 | | |
146 | 1.03M | for (i = 0; i < s->av1_pkt.nb_obus; i++) { |
147 | 1.03M | AV1OBU *obu = &s->av1_pkt.obus[i]; |
148 | 1.03M | if (obu_is_global(obu)) { |
149 | 3.08k | bytestream2_put_bufferu(&pb_extradata, obu->raw_data, obu->raw_size); |
150 | 1.03M | } else if (s->remove) { |
151 | 459 | bytestream2_put_bufferu(&pb_filtered_data, obu->raw_data, obu->raw_size); |
152 | 459 | } |
153 | 1.03M | } |
154 | | |
155 | 2.44k | if (s->remove) { |
156 | 362 | av_buffer_unref(&pkt->buf); |
157 | 362 | pkt->buf = filtered_buf; |
158 | 362 | pkt->data = filtered_buf->data; |
159 | 362 | pkt->size = filtered_size; |
160 | 362 | } |
161 | 2.44k | } |
162 | | |
163 | 6.05k | return 0; |
164 | 6.05k | } |
165 | | |
166 | | static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, |
167 | | uint8_t **data, int *size) |
168 | 35.5k | { |
169 | 35.5k | static const int extradata_nal_types_vvc[] = { |
170 | 35.5k | VVC_VPS_NUT, VVC_SPS_NUT, VVC_PPS_NUT, |
171 | 35.5k | }; |
172 | 35.5k | static const int extradata_nal_types_hevc[] = { |
173 | 35.5k | HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS, |
174 | 35.5k | }; |
175 | 35.5k | static const int extradata_nal_types_h264[] = { |
176 | 35.5k | H264_NAL_SPS, H264_NAL_PPS, |
177 | 35.5k | }; |
178 | | |
179 | 35.5k | ExtractExtradataContext *s = ctx->priv_data; |
180 | | |
181 | 35.5k | int extradata_size = 0, filtered_size = 0; |
182 | 35.5k | const int *extradata_nal_types; |
183 | 35.5k | size_t nb_extradata_nal_types; |
184 | 35.5k | int filtered_nb_nals = 0; |
185 | 35.5k | int i, has_sps = 0, has_vps = 0, ret = 0; |
186 | | |
187 | 35.5k | if (ctx->par_in->codec_id == AV_CODEC_ID_VVC) { |
188 | 6.17k | extradata_nal_types = extradata_nal_types_vvc; |
189 | 6.17k | nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_vvc); |
190 | 29.3k | } else if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { |
191 | 11.5k | extradata_nal_types = extradata_nal_types_hevc; |
192 | 11.5k | nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc); |
193 | 17.7k | } else { |
194 | 17.7k | extradata_nal_types = extradata_nal_types_h264; |
195 | 17.7k | nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_h264); |
196 | 17.7k | } |
197 | | |
198 | 35.5k | ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size, |
199 | 35.5k | ctx, 0, ctx->par_in->codec_id, H2645_FLAG_SMALL_PADDING); |
200 | 35.5k | if (ret < 0) |
201 | 1.15k | return ret; |
202 | | |
203 | 2.17M | for (i = 0; i < s->h2645_pkt.nb_nals; i++) { |
204 | 2.14M | H2645NAL *nal = &s->h2645_pkt.nals[i]; |
205 | 2.14M | if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { |
206 | 93.9k | extradata_size += nal->raw_size + 4; |
207 | 93.9k | if (ctx->par_in->codec_id == AV_CODEC_ID_VVC) { |
208 | 7.55k | if (nal->type == VVC_SPS_NUT) has_sps = 1; |
209 | 7.55k | if (nal->type == VVC_VPS_NUT) has_vps = 1; |
210 | 86.4k | } else if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { |
211 | 42.3k | if (nal->type == HEVC_NAL_SPS) has_sps = 1; |
212 | 42.3k | if (nal->type == HEVC_NAL_VPS) has_vps = 1; |
213 | 44.1k | } else { |
214 | 44.1k | if (nal->type == H264_NAL_SPS) has_sps = 1; |
215 | 44.1k | } |
216 | 2.04M | } else { |
217 | 2.04M | filtered_size += nal->raw_size + 3 + |
218 | 2.04M | ff_h2645_unit_requires_zero_byte(ctx->par_in->codec_id, nal->type, filtered_nb_nals++); |
219 | 2.04M | } |
220 | 2.14M | } |
221 | | |
222 | 34.3k | if (extradata_size && |
223 | 13.2k | ((ctx->par_in->codec_id == AV_CODEC_ID_VVC && has_sps) || |
224 | 11.6k | (ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) || |
225 | 7.95k | (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) { |
226 | 7.95k | AVBufferRef *filtered_buf = NULL; |
227 | 7.95k | PutByteContext pb_filtered_data, pb_extradata; |
228 | 7.95k | uint8_t *extradata; |
229 | | |
230 | 7.95k | if (s->remove) { |
231 | 365 | filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); |
232 | 365 | if (!filtered_buf) { |
233 | 0 | return AVERROR(ENOMEM); |
234 | 0 | } |
235 | 365 | memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
236 | 365 | } |
237 | | |
238 | 7.95k | extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |
239 | 7.95k | if (!extradata) { |
240 | 0 | av_buffer_unref(&filtered_buf); |
241 | 0 | return AVERROR(ENOMEM); |
242 | 0 | } |
243 | | |
244 | 7.95k | *data = extradata; |
245 | 7.95k | *size = extradata_size; |
246 | | |
247 | 7.95k | bytestream2_init_writer(&pb_extradata, extradata, extradata_size); |
248 | 7.95k | if (s->remove) |
249 | 365 | bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size); |
250 | | |
251 | 7.95k | filtered_nb_nals = 0; |
252 | 1.09M | for (i = 0; i < s->h2645_pkt.nb_nals; i++) { |
253 | 1.08M | H2645NAL *nal = &s->h2645_pkt.nals[i]; |
254 | 1.08M | if (val_in_array(extradata_nal_types, nb_extradata_nal_types, |
255 | 1.08M | nal->type)) { |
256 | 83.7k | bytestream2_put_be32u(&pb_extradata, 1); //startcode |
257 | 83.7k | bytestream2_put_bufferu(&pb_extradata, nal->raw_data, nal->raw_size); |
258 | 1.00M | } else if (s->remove) { |
259 | 48.5k | if (ff_h2645_unit_requires_zero_byte(ctx->par_in->codec_id, nal->type, filtered_nb_nals++)) |
260 | 259 | bytestream2_put_byteu(&pb_filtered_data, 0); // zero_byte |
261 | 48.5k | bytestream2_put_be24u(&pb_filtered_data, 1); // startcode |
262 | 48.5k | bytestream2_put_bufferu(&pb_filtered_data, nal->raw_data, nal->raw_size); |
263 | 48.5k | } |
264 | 1.08M | } |
265 | | |
266 | 7.95k | if (s->remove) { |
267 | 365 | av_buffer_unref(&pkt->buf); |
268 | 365 | pkt->buf = filtered_buf; |
269 | 365 | pkt->data = filtered_buf->data; |
270 | 365 | pkt->size = filtered_size; |
271 | 365 | } |
272 | 7.95k | } |
273 | | |
274 | 34.3k | return 0; |
275 | 34.3k | } |
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 | 26.7k | { |
286 | 26.7k | GetByteContext gbc, raw_gbc; |
287 | 26.7k | int sc = 0, gc = 0; |
288 | 26.7k | int skipped_byte_pos = 0; |
289 | 26.7k | int extradata_size = 0, data_size = 0; |
290 | | |
291 | 26.7k | if (nal->size < 2) |
292 | 403 | return AVERROR_INVALIDDATA; |
293 | | |
294 | 26.3k | bytestream2_init(&gbc, nal->data, nal->size); |
295 | 26.3k | bytestream2_init(&raw_gbc, nal->raw_data, nal->raw_size); |
296 | | |
297 | 26.3k | unsigned nalu_header = bytestream2_get_be16u(&gbc); |
298 | | |
299 | 26.3k | if (data) |
300 | 4.64k | bytestream2_put_be16u(data, nalu_header); |
301 | 26.3k | data_size += 2; |
302 | 26.3k | bytestream2_skipu(&raw_gbc, 2); |
303 | | |
304 | 13.1M | while (bytestream2_get_bytes_left(&gbc) > 1) { |
305 | 13.1M | GetBitContext gb; |
306 | 13.1M | int payload_size_type, payload_type; |
307 | 13.1M | uint64_t payload_size; |
308 | 13.1M | int block_size, raw_block_size, block_end; |
309 | | |
310 | 13.1M | av_unused int ret = init_get_bits8(&gb, gbc.buffer, bytestream2_get_bytes_left(&gbc)); |
311 | 13.1M | av_assert1(ret >= 0); // h2645_parse already opened a GetBitContext with this data |
312 | | |
313 | 13.1M | payload_size_type = get_bits(&gb, 3); |
314 | 13.1M | payload_type = get_bits(&gb, 5); |
315 | 13.1M | payload_size = payload_size_type; |
316 | 13.1M | if (payload_size_type == 6) |
317 | 360 | return AVERROR_INVALIDDATA; |
318 | 13.1M | if (payload_size_type == 7) |
319 | 2.49k | payload_size = get_mb(&gb); |
320 | | |
321 | 13.1M | if (payload_size > INT_MAX - (get_bits_count(&gb) >> 3)) |
322 | 610 | return AVERROR_INVALIDDATA; |
323 | | |
324 | 13.1M | block_size = raw_block_size = payload_size + (get_bits_count(&gb) >> 3); |
325 | 13.1M | if (block_size >= bytestream2_get_bytes_left(&gbc)) |
326 | 407 | return AVERROR_INVALIDDATA; |
327 | | |
328 | 13.1M | 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 | 14.4M | for (; skipped_byte_pos < nal->skipped_bytes; skipped_byte_pos++) { |
332 | 2.37M | if (nal->skipped_bytes_pos[skipped_byte_pos] >= block_end) |
333 | 1.01M | break; |
334 | 1.36M | raw_block_size++; |
335 | 1.36M | } |
336 | 13.1M | if (raw_block_size > bytestream2_get_bytes_left(&raw_gbc)) |
337 | 0 | return AVERROR_INVALIDDATA; |
338 | | |
339 | 13.1M | switch (payload_type) { |
340 | 12.0M | case LCEVC_PAYLOAD_TYPE_SEQUENCE_CONFIG: |
341 | 12.1M | case LCEVC_PAYLOAD_TYPE_GLOBAL_CONFIG: |
342 | 12.2M | case LCEVC_PAYLOAD_TYPE_ADDITIONAL_INFO: |
343 | 12.2M | if (!extradata_size) { |
344 | 24.3k | extradata_size = 2; |
345 | 24.3k | if (extradata) |
346 | 8.85k | bytestream2_put_be16u(extradata, nalu_header); |
347 | 24.3k | } |
348 | 12.2M | if (extradata) |
349 | 5.08M | bytestream2_put_bufferu(extradata, raw_gbc.buffer, raw_block_size); |
350 | 12.2M | extradata_size += raw_block_size; |
351 | 12.2M | sc |= payload_type == LCEVC_PAYLOAD_TYPE_SEQUENCE_CONFIG; |
352 | 12.2M | gc |= payload_type == LCEVC_PAYLOAD_TYPE_GLOBAL_CONFIG; |
353 | 12.2M | break; |
354 | 853k | default: |
355 | 853k | if (data) |
356 | 74.4k | bytestream2_put_bufferu(data, raw_gbc.buffer, raw_block_size); |
357 | 853k | data_size += raw_block_size; |
358 | 853k | break; |
359 | 13.1M | } |
360 | | |
361 | 13.1M | bytestream2_skip(&gbc, block_size); |
362 | 13.1M | bytestream2_skip(&raw_gbc, raw_block_size); |
363 | 13.1M | } |
364 | | |
365 | 24.9k | ++data_size; |
366 | 24.9k | *data_sizep = data_size; |
367 | 24.9k | if (data) |
368 | 4.64k | bytestream2_put_byteu(data, 0x80); // rbsp_alignment bits |
369 | 24.9k | if (extradata_size > 0) { |
370 | 23.7k | if (!sc && !gc) |
371 | 202 | return AVERROR_INVALIDDATA; |
372 | | |
373 | 23.5k | ++extradata_size; |
374 | 23.5k | if (extradata) { |
375 | 8.85k | bytestream2_put_byteu(extradata, 0x80); // rbsp_alignment bits |
376 | 8.85k | } else |
377 | 14.7k | *extradata_sizep = extradata_size; |
378 | 23.5k | return 1; // has extradata |
379 | 23.7k | } |
380 | 1.17k | return 0; // no extradata |
381 | 24.9k | } |
382 | | |
383 | | static int extract_extradata_lcevc(AVBSFContext *ctx, AVPacket *pkt, |
384 | | uint8_t **data, int *size) |
385 | 7.18k | { |
386 | 7.18k | static const int extradata_nal_types[] = { |
387 | 7.18k | LCEVC_IDR_NUT, LCEVC_NON_IDR_NUT, |
388 | 7.18k | }; |
389 | | |
390 | 7.18k | ExtractExtradataContext *s = ctx->priv_data; |
391 | 7.18k | unsigned extradata_size = 0, filtered_size = 0; |
392 | 7.18k | size_t nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types); |
393 | 7.18k | int i, ret = 0; |
394 | | |
395 | 7.18k | ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size, |
396 | 7.18k | ctx, 0, AV_CODEC_ID_LCEVC, H2645_FLAG_SMALL_PADDING); |
397 | 7.18k | if (ret < 0) |
398 | 880 | return ret; |
399 | | |
400 | 457k | for (i = 0; i < s->h2645_pkt.nb_nals; i++) { |
401 | 452k | H2645NAL *nal = &s->h2645_pkt.nals[i]; |
402 | 452k | unsigned start_code_size = 3 + !filtered_size; |
403 | | |
404 | 452k | if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { |
405 | 17.3k | int extra_size, data_size; |
406 | 17.3k | ret = process_lcevc_nalu(NULL, NULL, &extra_size, &data_size, nal); |
407 | 17.3k | if (ret < 0) |
408 | 1.98k | return ret; |
409 | 15.3k | if (ret > 0) { // has extradata |
410 | 14.7k | unsigned extra_start_code_size = 3 + !extradata_size; |
411 | 14.7k | extradata_size += extra_start_code_size + extra_size; |
412 | 14.7k | if (extradata_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
413 | 0 | return AVERROR_INVALIDDATA; |
414 | 14.7k | } |
415 | 15.3k | filtered_size += start_code_size + data_size; |
416 | 15.3k | } else |
417 | 435k | filtered_size += start_code_size + nal->raw_size; |
418 | 450k | if (filtered_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
419 | 0 | return AVERROR_INVALIDDATA; |
420 | 450k | } |
421 | | |
422 | 4.32k | if (extradata_size) { |
423 | 793 | AVBufferRef *filtered_buf = NULL; |
424 | 793 | PutByteContext pb_extradata; |
425 | 793 | PutByteContext pb_filtered_data; |
426 | 793 | uint8_t *extradata; |
427 | | |
428 | 793 | if (s->remove) { |
429 | 286 | ret = av_buffer_realloc(&filtered_buf, filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); |
430 | 286 | if (ret < 0) |
431 | 0 | return ret; |
432 | 286 | 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 | 286 | bytestream2_put_byteu(&pb_filtered_data, 0x00); |
436 | 286 | } |
437 | | |
438 | 793 | extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |
439 | 793 | if (!extradata) { |
440 | 0 | av_buffer_unref(&filtered_buf); |
441 | 0 | return AVERROR(ENOMEM); |
442 | 0 | } |
443 | | |
444 | 793 | *data = extradata; |
445 | 793 | *size = extradata_size; |
446 | | |
447 | 793 | 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 | 793 | bytestream2_put_be32u(&pb_extradata, 0x00000001); |
454 | | |
455 | 335k | for (i = 0; i < s->h2645_pkt.nb_nals; i++) { |
456 | 334k | H2645NAL *nal = &s->h2645_pkt.nals[i]; |
457 | 334k | if (s->remove) |
458 | 15.2k | bytestream2_put_be24u(&pb_filtered_data, 0x000001); |
459 | 334k | if (val_in_array(extradata_nal_types, nb_extradata_nal_types, |
460 | 334k | nal->type)) { |
461 | 9.42k | int dummy; |
462 | 9.42k | ret = process_lcevc_nalu(&pb_extradata, s->remove ? &pb_filtered_data : NULL, |
463 | 9.42k | NULL, &dummy, nal); |
464 | 9.42k | av_assert1(ret >= 0); // already checked in the first pass |
465 | 9.42k | if (ret > 0) {// NALU contained extradata |
466 | 8.85k | if (extradata_size != bytestream2_tell_p(&pb_extradata)) { |
467 | | // There will be another NALU containing extradata. |
468 | | // Already write the next start code. |
469 | 8.06k | bytestream2_put_be24u(&pb_extradata, 0x000001); |
470 | 8.06k | } |
471 | 8.85k | } |
472 | 325k | } else if (s->remove) { |
473 | 10.6k | bytestream2_put_bufferu(&pb_filtered_data, nal->raw_data, nal->raw_size); |
474 | 10.6k | } |
475 | 334k | } |
476 | 793 | av_assert1(bytestream2_tell_p(&pb_extradata) == extradata_size); |
477 | | |
478 | 793 | if (s->remove) { |
479 | 286 | av_assert1(bytestream2_tell_p(&pb_filtered_data) == filtered_size); |
480 | 286 | memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
481 | 286 | av_buffer_unref(&pkt->buf); |
482 | 286 | pkt->buf = filtered_buf; |
483 | 286 | pkt->data = filtered_buf->data; |
484 | 286 | pkt->size = filtered_size; |
485 | 286 | } |
486 | 793 | } |
487 | | |
488 | 4.32k | return 0; |
489 | 4.32k | } |
490 | | |
491 | | static int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt, |
492 | | uint8_t **data, int *size) |
493 | 3.56k | { |
494 | 3.56k | ExtractExtradataContext *s = ctx->priv_data; |
495 | 3.56k | const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size; |
496 | 3.56k | uint32_t state = UINT32_MAX; |
497 | 3.56k | int has_extradata = 0, extradata_size = 0; |
498 | | |
499 | 30.2k | while (ptr < end) { |
500 | 27.9k | ptr = avpriv_find_start_code(ptr, end, &state); |
501 | 27.9k | if (state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT) { |
502 | 3.92k | has_extradata = 1; |
503 | 24.0k | } else if (has_extradata && IS_MARKER(state)) { |
504 | 1.28k | extradata_size = ptr - 4 - pkt->data; |
505 | 1.28k | break; |
506 | 1.28k | } |
507 | 27.9k | } |
508 | | |
509 | 3.56k | if (extradata_size) { |
510 | 1.28k | *data = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |
511 | 1.28k | if (!*data) |
512 | 0 | return AVERROR(ENOMEM); |
513 | | |
514 | 1.28k | memcpy(*data, pkt->data, extradata_size); |
515 | 1.28k | *size = extradata_size; |
516 | | |
517 | 1.28k | if (s->remove) { |
518 | 220 | pkt->data += extradata_size; |
519 | 220 | pkt->size -= extradata_size; |
520 | 220 | } |
521 | 1.28k | } |
522 | | |
523 | 3.56k | return 0; |
524 | 3.56k | } |
525 | | |
526 | | static int extract_extradata_mpeg12(AVBSFContext *ctx, AVPacket *pkt, |
527 | | uint8_t **data, int *size) |
528 | 6.25k | { |
529 | 6.25k | ExtractExtradataContext *s = ctx->priv_data; |
530 | 6.25k | uint32_t state = UINT32_MAX; |
531 | 6.25k | int i, found = 0; |
532 | | |
533 | 10.1M | for (i = 0; i < pkt->size; i++) { |
534 | 10.1M | state = (state << 8) | pkt->data[i]; |
535 | 10.1M | if (state == 0x1B3) |
536 | 1.71k | found = 1; |
537 | 10.1M | else if (found && state != 0x1B5 && state < 0x200 && state >= 0x100) { |
538 | 1.18k | *size = i - 3; |
539 | 1.18k | *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE); |
540 | 1.18k | if (!*data) |
541 | 0 | return AVERROR(ENOMEM); |
542 | | |
543 | 1.18k | memcpy(*data, pkt->data, *size); |
544 | | |
545 | 1.18k | if (s->remove) { |
546 | 233 | pkt->data += *size; |
547 | 233 | pkt->size -= *size; |
548 | 233 | } |
549 | 1.18k | break; |
550 | 1.18k | } |
551 | 10.1M | } |
552 | 6.25k | return 0; |
553 | 6.25k | } |
554 | | |
555 | | static int extract_extradata_mpeg4(AVBSFContext *ctx, AVPacket *pkt, |
556 | | uint8_t **data, int *size) |
557 | 10.4k | { |
558 | 10.4k | ExtractExtradataContext *s = ctx->priv_data; |
559 | 10.4k | const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size; |
560 | 10.4k | uint32_t state = UINT32_MAX; |
561 | | |
562 | 66.2k | while (ptr < end) { |
563 | 59.1k | ptr = avpriv_find_start_code(ptr, end, &state); |
564 | 59.1k | if (state == 0x1B3 || state == 0x1B6) { |
565 | 3.27k | if (ptr - pkt->data > 4) { |
566 | 2.92k | *size = ptr - 4 - pkt->data; |
567 | 2.92k | *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE); |
568 | 2.92k | if (!*data) |
569 | 0 | return AVERROR(ENOMEM); |
570 | | |
571 | 2.92k | memcpy(*data, pkt->data, *size); |
572 | | |
573 | 2.92k | if (s->remove) { |
574 | 245 | pkt->data += *size; |
575 | 245 | pkt->size -= *size; |
576 | 245 | } |
577 | 2.92k | } |
578 | 3.27k | break; |
579 | 3.27k | } |
580 | 59.1k | } |
581 | 10.4k | return 0; |
582 | 10.4k | } |
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 | 16.8k | { |
605 | 16.8k | ExtractExtradataContext *s = ctx->priv_data; |
606 | 16.8k | int i; |
607 | | |
608 | 125k | for (i = 0; i < FF_ARRAY_ELEMS(extract_tab); i++) { |
609 | 125k | if (extract_tab[i].id == ctx->par_in->codec_id) { |
610 | 16.8k | s->extract = extract_tab[i].extract; |
611 | 16.8k | break; |
612 | 16.8k | } |
613 | 125k | } |
614 | 16.8k | if (!s->extract) |
615 | 0 | return AVERROR_BUG; |
616 | | |
617 | 16.8k | return 0; |
618 | 16.8k | } |
619 | | |
620 | | static int extract_extradata_filter(AVBSFContext *ctx, AVPacket *pkt) |
621 | 125k | { |
622 | 125k | ExtractExtradataContext *s = ctx->priv_data; |
623 | 125k | uint8_t *extradata = NULL; |
624 | 125k | int extradata_size; |
625 | 125k | int ret = 0; |
626 | | |
627 | 125k | ret = ff_bsf_get_packet_ref(ctx, pkt); |
628 | 125k | if (ret < 0) |
629 | 54.2k | return ret; |
630 | | |
631 | 71.1k | ret = s->extract(ctx, pkt, &extradata, &extradata_size); |
632 | 71.1k | if (ret < 0) |
633 | 6.11k | goto fail; |
634 | | |
635 | 64.9k | if (extradata) { |
636 | 16.5k | memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
637 | 16.5k | ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, |
638 | 16.5k | extradata, extradata_size); |
639 | 16.5k | if (ret < 0) { |
640 | 0 | av_freep(&extradata); |
641 | 0 | goto fail; |
642 | 0 | } |
643 | 16.5k | } |
644 | | |
645 | 64.9k | return 0; |
646 | | |
647 | 6.11k | fail: |
648 | 6.11k | av_packet_unref(pkt); |
649 | 6.11k | return ret; |
650 | 64.9k | } |
651 | | |
652 | | static void extract_extradata_close(AVBSFContext *ctx) |
653 | 16.8k | { |
654 | 16.8k | ExtractExtradataContext *s = ctx->priv_data; |
655 | 16.8k | ff_av1_packet_uninit(&s->av1_pkt); |
656 | 16.8k | ff_h2645_packet_uninit(&s->h2645_pkt); |
657 | 16.8k | } |
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 | | }; |