/src/ffmpeg/libavcodec/bsf/vvc_mp4toannexb.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * H.266/VVC MP4 to Annex B byte stream format filter |
3 | | * Copyright (c) 2022, Thomas Siedel |
4 | | * |
5 | | * This file is part of FFmpeg. |
6 | | * |
7 | | * FFmpeg is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * FFmpeg is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with FFmpeg; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | #include <string.h> |
23 | | |
24 | | #include "libavutil/intreadwrite.h" |
25 | | #include "libavutil/mem.h" |
26 | | |
27 | | #include "bsf.h" |
28 | | #include "bsf_internal.h" |
29 | | #include "bytestream.h" |
30 | | #include "defs.h" |
31 | | #include "vvc.h" |
32 | | |
33 | 1.83k | #define MIN_VVCC_LENGTH 23 |
34 | | |
35 | | typedef struct VVCBSFContext { |
36 | | uint8_t length_size; |
37 | | int extradata_parsed; |
38 | | } VVCBSFContext; |
39 | | |
40 | | static int vvc_extradata_to_annexb(AVBSFContext *ctx) |
41 | 710 | { |
42 | 710 | GetByteContext gb; |
43 | 710 | int length_size, num_arrays, i, j; |
44 | 710 | int ret = 0; |
45 | 710 | int temp = 0; |
46 | 710 | int ptl_present; |
47 | | |
48 | 710 | uint8_t *new_extradata = NULL; |
49 | 710 | size_t new_extradata_size = 0; |
50 | | |
51 | 710 | int max_picture_width = 0; |
52 | 710 | int max_picture_height = 0; |
53 | 710 | int avg_frame_rate = 0; |
54 | | |
55 | 710 | bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size); |
56 | 710 | temp = bytestream2_get_byte(&gb); |
57 | 710 | length_size = ((temp & 6) >> 1) + 1; |
58 | 710 | ptl_present = temp & 1; |
59 | 710 | if (ptl_present) { |
60 | 424 | int num_bytes_constraint_info; |
61 | 424 | int general_profile_idc; |
62 | 424 | int general_tier_flag; |
63 | 424 | int general_level_idc; |
64 | 424 | int ptl_frame_only_constraint_flag; |
65 | 424 | int ptl_multi_layer_enabled_flag; |
66 | 424 | int ptl_num_sub_profiles; |
67 | 424 | int temp3, temp4, temp5; |
68 | 424 | int temp2 = bytestream2_get_be16(&gb); |
69 | 424 | int ols_idx = (temp2 >> 7) & 0x1ff; |
70 | 424 | int num_sublayers = (temp2 >> 4) & 0x7; |
71 | 424 | int constant_frame_rate = (temp2 >> 2) & 0x3; |
72 | 424 | int chroma_format_idc = temp2 & 0x3; |
73 | 424 | int bit_depth_minus8 = (bytestream2_get_byte(&gb) >> 5) & 0x7; |
74 | 424 | av_log(ctx, AV_LOG_DEBUG, |
75 | 424 | "bit_depth_minus8 %d chroma_format_idc %d\n", bit_depth_minus8, |
76 | 424 | chroma_format_idc); |
77 | 424 | av_log(ctx, AV_LOG_DEBUG, "constant_frame_rate %d, ols_idx %d\n", |
78 | 424 | constant_frame_rate, ols_idx); |
79 | | // VvcPTLRecord(num_sublayers) native_ptl |
80 | 424 | temp3 = bytestream2_get_byte(&gb); |
81 | 424 | num_bytes_constraint_info = (temp3) & 0x3f; |
82 | 424 | temp4 = bytestream2_get_byte(&gb); |
83 | 424 | general_profile_idc = (temp4 >> 1) & 0x7f; |
84 | 424 | general_tier_flag = (temp4) & 1; |
85 | 424 | general_level_idc = bytestream2_get_byte(&gb); |
86 | 424 | av_log(ctx, AV_LOG_DEBUG, |
87 | 424 | "general_profile_idc %d, general_tier_flag %d, general_level_idc %d, num_sublayers %d num_bytes_constraint_info %d\n", |
88 | 424 | general_profile_idc, general_tier_flag, general_level_idc, |
89 | 424 | num_sublayers, num_bytes_constraint_info); |
90 | | |
91 | 424 | temp5 = bytestream2_get_byte(&gb); |
92 | 424 | ptl_frame_only_constraint_flag = (temp5 >> 7) & 0x1; |
93 | 424 | ptl_multi_layer_enabled_flag = (temp5 >> 6) & 0x1; |
94 | 10.4k | for (i = 0; i < num_bytes_constraint_info - 1; i++) { |
95 | | // unsigned int(8*num_bytes_constraint_info - 2) general_constraint_info; |
96 | 10.0k | bytestream2_get_byte(&gb); |
97 | 10.0k | } |
98 | | |
99 | 424 | av_log(ctx, AV_LOG_DEBUG, |
100 | 424 | "ptl_multi_layer_enabled_flag %d, ptl_frame_only_constraint_flag %d\n", |
101 | 424 | ptl_multi_layer_enabled_flag, ptl_frame_only_constraint_flag); |
102 | | |
103 | 424 | if (num_sublayers > 1) { |
104 | 270 | int temp6 = bytestream2_get_byte(&gb); |
105 | 270 | uint8_t ptl_sublayer_level_present_flag[8] = { 0 }; |
106 | | //uint8_t sublayer_level_idc[8] = {0}; |
107 | 1.44k | for (i = num_sublayers - 2; i >= 0; i--) { |
108 | 1.17k | ptl_sublayer_level_present_flag[i] = |
109 | 1.17k | (temp6 >> (7 - (num_sublayers - 2 - i))) & 0x01; |
110 | 1.17k | } |
111 | | // for (j=num_sublayers; j<=8 && num_sublayers > 1; j++) |
112 | | // bit(1) ptl_reserved_zero_bit = 0; |
113 | 1.44k | for (i = num_sublayers - 2; i >= 0; i--) { |
114 | 1.17k | if (ptl_sublayer_level_present_flag[i]) { |
115 | | //sublayer_level_idc[i] = bytestream2_get_byte(&gb); |
116 | 443 | } |
117 | 1.17k | } |
118 | 270 | } |
119 | | |
120 | 424 | ptl_num_sub_profiles = bytestream2_get_byte(&gb); |
121 | 32.6k | for (j = 0; j < ptl_num_sub_profiles; j++) { |
122 | | // unsigned int(32) general_sub_profile_idc[j]; |
123 | 32.2k | bytestream2_get_be16(&gb); |
124 | 32.2k | bytestream2_get_be16(&gb); |
125 | 32.2k | } |
126 | | |
127 | 424 | max_picture_width = bytestream2_get_be16(&gb); // unsigned_int(16) max_picture_width; |
128 | 424 | max_picture_height = bytestream2_get_be16(&gb); // unsigned_int(16) max_picture_height; |
129 | 424 | avg_frame_rate = bytestream2_get_be16(&gb); // unsigned int(16) avg_frame_rate; } |
130 | 424 | av_log(ctx, AV_LOG_DEBUG, |
131 | 424 | "max_picture_width %d, max_picture_height %d, avg_frame_rate %d\n", |
132 | 424 | max_picture_width, max_picture_height, avg_frame_rate); |
133 | 424 | } |
134 | | |
135 | 710 | num_arrays = bytestream2_get_byte(&gb); |
136 | | |
137 | 2.13k | for (i = 0; i < num_arrays; i++) { |
138 | 1.66k | int cnt; |
139 | 1.66k | int type = bytestream2_get_byte(&gb) & 0x1f; |
140 | | |
141 | 1.66k | if (type == VVC_OPI_NUT || type == VVC_DCI_NUT) |
142 | 981 | cnt = 1; |
143 | 686 | else |
144 | 686 | cnt = bytestream2_get_be16(&gb); |
145 | | |
146 | 1.66k | av_log(ctx, AV_LOG_DEBUG, "nalu_type %d cnt %d\n", type, cnt); |
147 | | |
148 | 1.66k | if (!(type == VVC_OPI_NUT || type == VVC_DCI_NUT || |
149 | 1.66k | type == VVC_VPS_NUT || type == VVC_SPS_NUT || type == VVC_PPS_NUT |
150 | 1.66k | || type == VVC_PREFIX_SEI_NUT || type == VVC_SUFFIX_SEI_NUT)) { |
151 | 135 | av_log(ctx, AV_LOG_ERROR, |
152 | 135 | "Invalid NAL unit type in extradata: %d\n", type); |
153 | 135 | ret = AVERROR_INVALIDDATA; |
154 | 135 | goto fail; |
155 | 135 | } |
156 | | |
157 | 3.34k | for (j = 0; j < cnt; j++) { |
158 | 1.92k | const int nalu_len = bytestream2_get_be16(&gb); |
159 | | |
160 | 1.92k | if (!nalu_len || |
161 | 1.92k | nalu_len > bytestream2_get_bytes_left(&gb) || |
162 | 1.92k | 4 + AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - new_extradata_size) { |
163 | 107 | ret = AVERROR_INVALIDDATA; |
164 | 107 | goto fail; |
165 | 107 | } |
166 | 1.81k | ret = av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 |
167 | 1.81k | + AV_INPUT_BUFFER_PADDING_SIZE); |
168 | 1.81k | if (ret < 0) |
169 | 0 | goto fail; |
170 | | |
171 | 1.81k | AV_WB32(new_extradata + new_extradata_size, 1); // add the startcode |
172 | 1.81k | bytestream2_get_buffer(&gb, new_extradata + new_extradata_size + 4, |
173 | 1.81k | nalu_len); |
174 | 1.81k | new_extradata_size += 4 + nalu_len; |
175 | 1.81k | memset(new_extradata + new_extradata_size, 0, |
176 | 1.81k | AV_INPUT_BUFFER_PADDING_SIZE); |
177 | 1.81k | } |
178 | 1.53k | } |
179 | | |
180 | 468 | av_freep(&ctx->par_out->extradata); |
181 | 468 | ctx->par_out->extradata = new_extradata; |
182 | 468 | ctx->par_out->extradata_size = new_extradata_size; |
183 | | |
184 | 468 | if (!new_extradata_size) |
185 | 414 | av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n"); |
186 | | |
187 | 468 | return length_size; |
188 | 242 | fail: |
189 | 242 | av_freep(&new_extradata); |
190 | 242 | return ret; |
191 | 710 | } |
192 | | |
193 | | static int vvc_mp4toannexb_init(AVBSFContext *ctx) |
194 | 919 | { |
195 | 919 | VVCBSFContext *s = ctx->priv_data; |
196 | 919 | int ret; |
197 | | |
198 | 919 | if (ctx->par_in->extradata_size < MIN_VVCC_LENGTH || |
199 | 919 | AV_RB24(ctx->par_in->extradata) == 1 || |
200 | 919 | AV_RB32(ctx->par_in->extradata) == 1) { |
201 | 209 | av_log(ctx, AV_LOG_VERBOSE, |
202 | 209 | "The input looks like it is Annex B already\n"); |
203 | 710 | } else { |
204 | 710 | ret = vvc_extradata_to_annexb(ctx); |
205 | 710 | if (ret < 0) |
206 | 242 | return ret; |
207 | 468 | s->length_size = ret; |
208 | 468 | s->extradata_parsed = 1; |
209 | 468 | } |
210 | | |
211 | 677 | return 0; |
212 | 919 | } |
213 | | |
214 | | static int vvc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) |
215 | 31.5k | { |
216 | 31.5k | VVCBSFContext *s = ctx->priv_data; |
217 | 31.5k | AVPacket *in; |
218 | 31.5k | GetByteContext gb; |
219 | | |
220 | 31.5k | int is_irap = 0; |
221 | 31.5k | int added_extra = 0; |
222 | 31.5k | int i, ret = 0; |
223 | | |
224 | 31.5k | ret = ff_bsf_get_packet(ctx, &in); |
225 | 31.5k | if (ret < 0) |
226 | 7.12k | return ret; |
227 | | |
228 | 24.4k | if (!s->extradata_parsed) { |
229 | 4.84k | av_packet_move_ref(out, in); |
230 | 4.84k | av_packet_free(&in); |
231 | 4.84k | return 0; |
232 | 4.84k | } |
233 | | |
234 | 19.5k | bytestream2_init(&gb, in->data, in->size); |
235 | | |
236 | | /* check if this packet contains an IRAP. The extradata will need to be added before any potential PH_NUT */ |
237 | 175k | while (bytestream2_get_bytes_left(&gb)) { |
238 | 174k | uint32_t nalu_size = 0; |
239 | 174k | int nalu_type; |
240 | | |
241 | 174k | if (bytestream2_get_bytes_left(&gb) < s->length_size) { |
242 | 2.25k | ret = AVERROR_INVALIDDATA; |
243 | 2.25k | goto fail; |
244 | 2.25k | } |
245 | | |
246 | 363k | for (i = 0; i < s->length_size; i++) |
247 | 191k | nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); |
248 | | |
249 | 171k | if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) { |
250 | 11.5k | ret = AVERROR_INVALIDDATA; |
251 | 11.5k | goto fail; |
252 | 11.5k | } |
253 | | |
254 | 160k | nalu_type = (bytestream2_peek_be16(&gb) >> 3) & 0x1f; |
255 | 160k | is_irap = nalu_type >= VVC_IDR_W_RADL && nalu_type <= VVC_RSV_IRAP_11; |
256 | 160k | if (is_irap) { |
257 | 4.32k | break; |
258 | 4.32k | } |
259 | 156k | bytestream2_seek(&gb, nalu_size, SEEK_CUR); |
260 | 156k | } |
261 | | |
262 | 5.73k | bytestream2_seek(&gb, 0, SEEK_SET); |
263 | 672k | while (bytestream2_get_bytes_left(&gb)) { |
264 | 671k | uint32_t nalu_size = 0; |
265 | 671k | int nalu_type; |
266 | 671k | int add_extradata, extra_size, prev_size; |
267 | | |
268 | 671k | if (bytestream2_get_bytes_left(&gb) < s->length_size) { |
269 | 635 | ret = AVERROR_INVALIDDATA; |
270 | 635 | goto fail; |
271 | 635 | } |
272 | | |
273 | 1.35M | for (i = 0; i < s->length_size; i++) |
274 | 683k | nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); |
275 | | |
276 | 670k | if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) { |
277 | 3.50k | ret = AVERROR_INVALIDDATA; |
278 | 3.50k | goto fail; |
279 | 3.50k | } |
280 | | |
281 | 666k | nalu_type = (bytestream2_peek_be16(&gb) >> 3) & 0x1f; |
282 | | |
283 | | /* prepend extradata to IRAP frames */ |
284 | 666k | add_extradata = is_irap && nalu_type != VVC_AUD_NUT && !added_extra; |
285 | 666k | extra_size = add_extradata * ctx->par_out->extradata_size; |
286 | 666k | added_extra |= add_extradata; |
287 | | |
288 | 666k | if (FFMIN(INT_MAX, SIZE_MAX) < 4ULL + nalu_size + extra_size) { |
289 | 0 | ret = AVERROR_INVALIDDATA; |
290 | 0 | goto fail; |
291 | 0 | } |
292 | | |
293 | 666k | prev_size = out->size; |
294 | | |
295 | 666k | ret = av_grow_packet(out, 4 + nalu_size + extra_size); |
296 | 666k | if (ret < 0) |
297 | 0 | goto fail; |
298 | | |
299 | 666k | if (extra_size) |
300 | 830 | memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size); |
301 | 666k | AV_WB32(out->data + prev_size + extra_size, 1); |
302 | 666k | bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, |
303 | 666k | nalu_size); |
304 | 666k | } |
305 | | |
306 | 1.60k | ret = av_packet_copy_props(out, in); |
307 | 1.60k | if (ret < 0) |
308 | 0 | goto fail; |
309 | | |
310 | 19.5k | fail: |
311 | 19.5k | if (ret < 0) |
312 | 17.9k | av_packet_unref(out); |
313 | 19.5k | av_packet_free(&in); |
314 | | |
315 | 19.5k | return ret; |
316 | 1.60k | } |
317 | | |
318 | | static const enum AVCodecID codec_ids[] = { |
319 | | AV_CODEC_ID_VVC, AV_CODEC_ID_NONE, |
320 | | }; |
321 | | |
322 | | const FFBitStreamFilter ff_vvc_mp4toannexb_bsf = { |
323 | | .p.name = "vvc_mp4toannexb", |
324 | | .p.codec_ids = codec_ids, |
325 | | .priv_data_size = sizeof(VVCBSFContext), |
326 | | .init = vvc_mp4toannexb_init, |
327 | | .filter = vvc_mp4toannexb_filter, |
328 | | }; |