FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc_parser.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 218 250 87.2%
Functions: 14 14 100.0%
Branches: 131 163 80.4%

Line Branch Exec Source
1 /*
2 * H.266 / VVC parser
3 *
4 * Copyright (C) 2021 Nuo Mi <nuomi2021@gmail.com>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "libavutil/mem.h"
24 #include "cbs.h"
25 #include "cbs_h266.h"
26 #include "parser.h"
27
28 #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes
29 #define IS_IDR(nut) (nut == VVC_IDR_W_RADL || nut == VVC_IDR_N_LP)
30 #define IS_H266_SLICE(nut) (nut <= VVC_RASL_NUT || (nut >= VVC_IDR_W_RADL && nut <= VVC_GDR_NUT))
31
32 typedef struct PuInfo {
33 const H266RawPPS *pps;
34 const H266RawSPS *sps;
35 const H266RawPictureHeader *ph;
36 const H266RawSlice *slice;
37 int pic_type;
38 } PuInfo;
39
40 typedef struct AuDetector {
41 uint8_t prev_layer_id;
42 int prev_tid0_poc;
43 int prev_poc;
44 } AuDetector;
45
46 typedef struct VVCParserContext {
47 ParseContext pc;
48 CodedBitstreamContext *cbc;
49
50 CodedBitstreamFragment picture_unit;
51
52 AVPacket au;
53 AVPacket last_au;
54
55 AuDetector au_detector;
56
57 int parsed_extradata;
58 } VVCParserContext;
59
60 static const enum AVPixelFormat pix_fmts_8bit[] = {
61 AV_PIX_FMT_GRAY8, AV_PIX_FMT_YUV420P,
62 AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P
63 };
64
65 static const enum AVPixelFormat pix_fmts_10bit[] = {
66 AV_PIX_FMT_GRAY10, AV_PIX_FMT_YUV420P10,
67 AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10
68 };
69
70 2994 static int get_format(const H266RawSPS *sps)
71 {
72
2/3
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 2960 times.
✗ Branch 2 not taken.
2994 switch (sps->sps_bitdepth_minus8) {
73 34 case 0:
74 34 return pix_fmts_8bit[sps->sps_chroma_format_idc];
75 2960 case 2:
76 2960 return pix_fmts_10bit[sps->sps_chroma_format_idc];
77 }
78 return AV_PIX_FMT_NONE;
79 }
80
81 /**
82 * Find the end of the current frame in the bitstream.
83 * @return the position of the first byte of the next frame, or END_NOT_FOUND
84 */
85 10161 static int find_frame_end(AVCodecParserContext *s, const uint8_t *buf,
86 int buf_size)
87 {
88 10161 VVCParserContext *ctx = s->priv_data;
89 10161 ParseContext *pc = &ctx->pc;
90 int i;
91
92
2/2
✓ Branch 0 taken 7243257 times.
✓ Branch 1 taken 7186 times.
7250443 for (i = 0; i < buf_size; i++) {
93 int nut, code_len;
94
95 7243257 pc->state64 = (pc->state64 << 8) | buf[i];
96
97
2/2
✓ Branch 0 taken 7231575 times.
✓ Branch 1 taken 11682 times.
7243257 if (((pc->state64 >> 3 * 8) & 0xFFFFFF) != START_CODE)
98 7231575 continue;
99
100
2/2
✓ Branch 0 taken 6501 times.
✓ Branch 1 taken 5181 times.
11682 code_len = ((pc->state64 >> 3 * 8) & 0xFFFFFFFF) == 0x01 ? 4 : 3;
101
102 11682 nut = (pc->state64 >> (8 + 3)) & 0x1F;
103 // 7.4.2.4.3 and 7.4.2.4.4
104
5/6
✓ Branch 0 taken 5307 times.
✓ Branch 1 taken 6375 times.
✓ Branch 2 taken 2003 times.
✓ Branch 3 taken 3304 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2003 times.
11682 if ((nut >= VVC_OPI_NUT && nut <= VVC_PREFIX_APS_NUT &&
105
2/2
✓ Branch 0 taken 9636 times.
✓ Branch 1 taken 43 times.
9679 nut != VVC_PH_NUT) || nut == VVC_AUD_NUT
106
4/4
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 9512 times.
✓ Branch 2 taken 116 times.
✓ Branch 3 taken 8 times.
9636 || (nut == VVC_PREFIX_SEI_NUT && !pc->frame_start_found)
107
2/4
✓ Branch 0 taken 9628 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9628 times.
✗ Branch 3 not taken.
9628 || nut == VVC_RSV_NVCL_26 || nut == VVC_UNSPEC_28
108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9628 times.
9628 || nut == VVC_UNSPEC_29) {
109
2/2
✓ Branch 0 taken 713 times.
✓ Branch 1 taken 1341 times.
2054 if (pc->frame_start_found) {
110 713 pc->frame_start_found = 0;
111 713 return i - (code_len + 2);
112 }
113
7/8
✓ Branch 0 taken 9486 times.
✓ Branch 1 taken 142 times.
✓ Branch 2 taken 3702 times.
✓ Branch 3 taken 5784 times.
✓ Branch 4 taken 3702 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 591 times.
✓ Branch 7 taken 3111 times.
9628 } else if (nut == VVC_PH_NUT || IS_H266_SLICE(nut)) {
114 6517 int sh_picture_header_in_slice_header_flag = buf[i] >> 7;
115
116
4/4
✓ Branch 0 taken 6375 times.
✓ Branch 1 taken 142 times.
✓ Branch 2 taken 5149 times.
✓ Branch 3 taken 1226 times.
6517 if (nut == VVC_PH_NUT || sh_picture_header_in_slice_header_flag) {
117
2/2
✓ Branch 0 taken 3029 times.
✓ Branch 1 taken 2262 times.
5291 if (!pc->frame_start_found) {
118 3029 pc->frame_start_found = 1;
119 } else { // First slice of next frame found
120 2262 pc->frame_start_found = 0;
121 2262 return i - (code_len + 2);
122 }
123 }
124 }
125 }
126 7186 return END_NOT_FOUND;
127 }
128
129 3029 static int get_pict_type(const CodedBitstreamFragment *pu)
130 {
131 3029 int has_p = 0;
132
2/2
✓ Branch 0 taken 6113 times.
✓ Branch 1 taken 1423 times.
7536 for (int i = 0; i < pu->nb_units; i++) {
133 6113 CodedBitstreamUnit *unit = &pu->units[i];
134
5/6
✓ Branch 0 taken 3440 times.
✓ Branch 1 taken 2673 times.
✓ Branch 2 taken 3440 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 591 times.
✓ Branch 5 taken 2849 times.
6113 if (IS_H266_SLICE(unit->type)) {
135 3264 const H266RawSlice *slice = unit->content;
136 3264 uint8_t type = slice->header.sh_slice_type;
137
2/2
✓ Branch 0 taken 1606 times.
✓ Branch 1 taken 1658 times.
3264 if (type == VVC_SLICE_TYPE_B) {
138 1606 return AV_PICTURE_TYPE_B;
139 }
140
2/2
✓ Branch 0 taken 1068 times.
✓ Branch 1 taken 590 times.
1658 if (type == VVC_SLICE_TYPE_P) {
141 1068 has_p = 1;
142 }
143 }
144 }
145
2/2
✓ Branch 0 taken 1068 times.
✓ Branch 1 taken 355 times.
1423 return has_p ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
146 }
147
148 2994 static void set_parser_ctx(AVCodecParserContext *s, AVCodecContext *avctx,
149 const PuInfo *pu)
150 {
151 static const uint8_t h266_sub_width_c[] = {
152 1, 2, 2, 1
153 };
154 static const uint8_t h266_sub_height_c[] = {
155 1, 2, 1, 1
156 };
157 2994 const H266RawSPS *sps = pu->sps;
158 2994 const H266RawPPS *pps = pu->pps;
159 2994 const H266RawNALUnitHeader *nal = &pu->slice->header.nal_unit_header;
160
161 2994 s->pict_type = pu->pic_type;
162 2994 s->format = get_format(sps);
163 2994 s->picture_structure = AV_PICTURE_STRUCTURE_FRAME;
164
165 8973 s->key_frame = nal->nal_unit_type == VVC_IDR_W_RADL ||
166
2/2
✓ Branch 0 taken 2661 times.
✓ Branch 1 taken 324 times.
2985 nal->nal_unit_type == VVC_IDR_N_LP ||
167
4/4
✓ Branch 0 taken 2985 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 2643 times.
✓ Branch 3 taken 18 times.
8622 nal->nal_unit_type == VVC_CRA_NUT ||
168
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2641 times.
2643 nal->nal_unit_type == VVC_GDR_NUT;
169
170 2994 s->coded_width = pps->pps_pic_width_in_luma_samples;
171 2994 s->coded_height = pps->pps_pic_height_in_luma_samples;
172 2994 s->width = pps->pps_pic_width_in_luma_samples -
173 2994 (pps->pps_conf_win_left_offset + pps->pps_conf_win_right_offset) *
174 2994 h266_sub_width_c[sps->sps_chroma_format_idc];
175 2994 s->height = pps->pps_pic_height_in_luma_samples -
176 2994 (pps->pps_conf_win_top_offset + pps->pps_conf_win_bottom_offset) *
177 2994 h266_sub_height_c[sps->sps_chroma_format_idc];
178
179 2994 avctx->profile = sps->profile_tier_level.general_profile_idc;
180 2994 avctx->level = sps->profile_tier_level.general_level_idc;
181
182 2994 avctx->colorspace = (enum AVColorSpace) sps->vui.vui_matrix_coeffs;
183 2994 avctx->color_primaries = (enum AVColorPrimaries) sps->vui.vui_colour_primaries;
184 2994 avctx->color_trc = (enum AVColorTransferCharacteristic) sps->vui.vui_transfer_characteristics;
185 2994 avctx->color_range =
186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2994 times.
2994 sps->vui.vui_full_range_flag ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
187
188
1/2
✓ Branch 0 taken 2994 times.
✗ Branch 1 not taken.
2994 if (sps->sps_ptl_dpb_hrd_params_present_flag &&
189
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 2874 times.
2994 sps->sps_timing_hrd_params_present_flag) {
190 120 uint32_t num = sps->sps_general_timing_hrd_parameters.num_units_in_tick;
191 120 uint32_t den = sps->sps_general_timing_hrd_parameters.time_scale;
192
193
2/4
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 if (num != 0 && den != 0)
194 120 av_reduce(&avctx->framerate.den, &avctx->framerate.num,
195 num, den, 1 << 30);
196 }
197 2994 }
198
199 //8.3.1 Decoding process for picture order count.
200 //VTM did not follow the spec, and it's much simpler than spec.
201 //We follow the VTM.
202 3029 static void get_slice_poc(VVCParserContext *s, int *poc,
203 const H266RawSPS *sps,
204 const H266RawPictureHeader *ph,
205 const H266RawSliceHeader *slice, void *log_ctx)
206 {
207 int poc_msb, max_poc_lsb, poc_lsb;
208 3029 AuDetector *d = &s->au_detector;
209 3029 max_poc_lsb = 1 << (sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4);
210 3029 poc_lsb = ph->ph_pic_order_cnt_lsb;
211
4/4
✓ Branch 0 taken 3020 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 327 times.
✓ Branch 3 taken 2693 times.
3029 if (IS_IDR(slice->nal_unit_header.nal_unit_type)) {
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 if (ph->ph_poc_msb_cycle_present_flag)
213 poc_msb = ph->ph_poc_msb_cycle_val * max_poc_lsb;
214 else
215 336 poc_msb = 0;
216 } else {
217 2693 int prev_poc = d->prev_tid0_poc;
218 2693 int prev_poc_lsb = prev_poc & (max_poc_lsb - 1);
219 2693 int prev_poc_msb = prev_poc - prev_poc_lsb;
220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2693 times.
2693 if (ph->ph_poc_msb_cycle_present_flag) {
221 poc_msb = ph->ph_poc_msb_cycle_val * max_poc_lsb;
222 } else {
223
2/2
✓ Branch 0 taken 1053 times.
✓ Branch 1 taken 1640 times.
2693 if ((poc_lsb < prev_poc_lsb) && ((prev_poc_lsb - poc_lsb) >=
224
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1049 times.
1053 (max_poc_lsb / 2)))
225 4 poc_msb = prev_poc_msb + (unsigned)max_poc_lsb;
226
2/2
✓ Branch 0 taken 1623 times.
✓ Branch 1 taken 1066 times.
2689 else if ((poc_lsb > prev_poc_lsb) && ((poc_lsb - prev_poc_lsb) >
227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1623 times.
1623 (max_poc_lsb / 2)))
228 poc_msb = prev_poc_msb - (unsigned)max_poc_lsb;
229 else
230 2689 poc_msb = prev_poc_msb;
231 }
232 }
233
234 3029 *poc = poc_msb + poc_lsb;
235 3029 }
236
237 55 static void au_detector_init(AuDetector *d)
238 {
239 55 d->prev_layer_id = UINT8_MAX;
240 55 d->prev_poc = INT_MAX;
241 55 d->prev_tid0_poc = INT_MAX;
242 55 }
243
244 3029 static int is_au_start(VVCParserContext *s, const PuInfo *pu, void *log_ctx)
245 {
246 //7.4.2.4.3
247 3029 AuDetector *d = &s->au_detector;
248 3029 const H266RawSPS *sps = pu->sps;
249 3029 const H266RawNALUnitHeader *nal = &pu->slice->header.nal_unit_header;
250 3029 const H266RawPictureHeader *ph = pu->ph;
251 3029 const H266RawSlice *slice = pu->slice;
252 int ret, poc, nut;
253
254 3029 get_slice_poc(s, &poc, sps, ph, &slice->header, log_ctx);
255
256
3/4
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 2994 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 35 times.
3029 ret = (nal->nuh_layer_id <= d->prev_layer_id) || (poc != d->prev_poc);
257
258 3029 nut = nal->nal_unit_type;
259 3029 d->prev_layer_id = nal->nuh_layer_id;
260 3029 d->prev_poc = poc;
261
2/2
✓ Branch 0 taken 1603 times.
✓ Branch 1 taken 1426 times.
3029 if (nal->nuh_temporal_id_plus1 == 1 &&
262
3/4
✓ Branch 0 taken 1591 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1591 times.
✗ Branch 3 not taken.
1603 !ph->ph_non_ref_pic_flag && nut != VVC_RADL_NUT
263
1/2
✓ Branch 0 taken 1591 times.
✗ Branch 1 not taken.
1591 && nut != VVC_RASL_NUT) {
264 1591 d->prev_tid0_poc = poc;
265 }
266 3029 return ret;
267 }
268
269 3029 static int get_pu_info(PuInfo *info, const CodedBitstreamH266Context *h266,
270 const CodedBitstreamFragment *pu, void *logctx)
271 {
272 const H266RawNALUnitHeader *nal;
273 int ret;
274
275 3029 memset(info, 0, sizeof(*info));
276
1/2
✓ Branch 0 taken 4456 times.
✗ Branch 1 not taken.
4456 for (int i = 0; i < pu->nb_units; i++) {
277 4456 nal = pu->units[i].content;
278
2/2
✓ Branch 0 taken 474 times.
✓ Branch 1 taken 3982 times.
4456 if (!nal)
279 474 continue;
280
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 3896 times.
3982 if ( nal->nal_unit_type == VVC_PH_NUT ) {
281 86 const H266RawPH *ph = pu->units[i].content;
282 86 info->ph = &ph->ph_picture_header;
283
5/6
✓ Branch 0 taken 1223 times.
✓ Branch 1 taken 2673 times.
✓ Branch 2 taken 1223 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 356 times.
✓ Branch 5 taken 867 times.
3896 } else if (IS_H266_SLICE(nal->nal_unit_type)) {
284 3029 info->slice = pu->units[i].content;
285
2/2
✓ Branch 0 taken 2943 times.
✓ Branch 1 taken 86 times.
3029 if (info->slice->header.sh_picture_header_in_slice_header_flag)
286 2943 info->ph = &info->slice->header.sh_picture_header;
287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3029 times.
3029 if (!info->ph) {
288 av_log(logctx, AV_LOG_ERROR,
289 "can't find picture header in picture unit.\n");
290 ret = AVERROR_INVALIDDATA;
291 goto error;
292 }
293 3029 break;
294 }
295 }
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3029 times.
3029 if (!info->slice) {
297 av_log(logctx, AV_LOG_ERROR, "can't find slice in picture unit.\n");
298 ret = AVERROR_INVALIDDATA;
299 goto error;
300 }
301 3029 info->pps = h266->pps[info->ph->ph_pic_parameter_set_id];
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3029 times.
3029 if (!info->pps) {
303 av_log(logctx, AV_LOG_ERROR, "PPS id %d is not avaliable.\n",
304 info->ph->ph_pic_parameter_set_id);
305 ret = AVERROR_INVALIDDATA;
306 goto error;
307 }
308 3029 info->sps = h266->sps[info->pps->pps_seq_parameter_set_id];
309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3029 times.
3029 if (!info->sps) {
310 av_log(logctx, AV_LOG_ERROR, "SPS id %d is not avaliable.\n",
311 info->pps->pps_seq_parameter_set_id);
312 ret = AVERROR_INVALIDDATA;
313 goto error;
314 }
315 3029 info->pic_type = get_pict_type(pu);
316 3029 return 0;
317 error:
318 memset(info, 0, sizeof(*info));
319 return ret;
320 }
321
322 3029 static int append_au(AVPacket *pkt, const uint8_t *buf, int buf_size)
323 {
324 3029 int offset = pkt->size;
325 int ret;
326
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3029 times.
3029 if ((ret = av_grow_packet(pkt, buf_size)) < 0)
327 goto end;
328 3029 memcpy(pkt->data + offset, buf, buf_size);
329 3029 end:
330 3029 return ret;
331 }
332
333 /**
334 * Parse NAL units of found picture and decode some basic information.
335 *
336 * @param s parser context.
337 * @param avctx codec context.
338 * @param buf buffer with field/frame data.
339 * @param buf_size size of the buffer.
340 * @return < 0 for error, == 0 for a complete au, > 0 is not a completed au.
341 */
342 3032 static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
343 int buf_size, AVCodecContext *avctx)
344 {
345 3032 VVCParserContext *ctx = s->priv_data;
346 3032 const CodedBitstreamH266Context *h266 = ctx->cbc->priv_data;
347
348 3032 CodedBitstreamFragment *pu = &ctx->picture_unit;
349 int ret;
350 PuInfo info;
351
352
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3029 times.
3032 if (!buf_size) {
353
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ctx->au.size) {
354 3 av_packet_move_ref(&ctx->last_au, &ctx->au);
355 3 return 0;
356 }
357 return 1;
358 }
359
360
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3029 times.
3029 if ((ret = ff_cbs_read(ctx->cbc, pu, buf, buf_size)) < 0) {
361 av_log(avctx, AV_LOG_ERROR, "Failed to parse picture unit.\n");
362 goto end;
363 }
364
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3029 times.
3029 if ((ret = get_pu_info(&info, h266, pu, avctx)) < 0)
365 goto end;
366
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3029 times.
3029 if (append_au(&ctx->au, buf, buf_size) < 0) {
367 ret = AVERROR(ENOMEM);
368 goto end;
369 }
370
2/2
✓ Branch 1 taken 2994 times.
✓ Branch 2 taken 35 times.
3029 if (is_au_start(ctx, &info, avctx)) {
371 2994 set_parser_ctx(s, avctx, &info);
372 2994 av_packet_move_ref(&ctx->last_au, &ctx->au);
373 } else {
374 35 ret = 1; //not a completed au
375 }
376 3029 end:
377 3029 ff_cbs_fragment_reset(pu);
378 3029 return ret;
379 }
380
381 /**
382 * Combine PU to AU
383 *
384 * @param s parser context.
385 * @param avctx codec context.
386 * @param buf buffer to a PU.
387 * @param buf_size size of the buffer.
388 * @return < 0 for error, == 0 a complete au, > 0 not a completed au.
389 */
390 3032 static int combine_au(AVCodecParserContext *s, AVCodecContext *avctx,
391 const uint8_t **buf, int *buf_size)
392 {
393 3032 VVCParserContext *ctx = s->priv_data;
394 int ret;
395
396 3032 ctx->cbc->log_ctx = avctx;
397
398 3032 av_packet_unref(&ctx->last_au);
399 3032 ret = parse_nal_units(s, *buf, *buf_size, avctx);
400
2/2
✓ Branch 0 taken 2997 times.
✓ Branch 1 taken 35 times.
3032 if (ret == 0) {
401
1/2
✓ Branch 0 taken 2997 times.
✗ Branch 1 not taken.
2997 if (ctx->last_au.size) {
402 2997 *buf = ctx->last_au.data;
403 2997 *buf_size = ctx->last_au.size;
404 } else {
405 ret = 1; //no output
406 }
407 }
408 3032 ctx->cbc->log_ctx = NULL;
409 3032 return ret;
410 }
411
412 10161 static int vvc_parser_parse(AVCodecParserContext *s, AVCodecContext *avctx,
413 const uint8_t **poutbuf, int *poutbuf_size,
414 const uint8_t *buf, int buf_size)
415 {
416 int next, ret;
417 10161 VVCParserContext *ctx = s->priv_data;
418 10161 ParseContext *pc = &ctx->pc;
419 10161 CodedBitstreamFragment *pu = &ctx->picture_unit;
420
421 10161 int is_dummy_buf = !buf_size;
422 10161 int flush = !buf_size;
423 10161 const uint8_t *dummy_buf = buf;
424
425 10161 *poutbuf = NULL;
426 10161 *poutbuf_size = 0;
427
428
4/4
✓ Branch 0 taken 7951 times.
✓ Branch 1 taken 2210 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 7897 times.
10161 if (avctx->extradata_size && !ctx->parsed_extradata) {
429 54 ctx->parsed_extradata = 1;
430
431 54 ret = ff_cbs_read_extradata_from_codec(ctx->cbc, pu, avctx);
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (ret < 0)
433 av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata.\n");
434
435 54 ff_cbs_fragment_reset(pu);
436 }
437
438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10161 times.
10161 if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
439 next = buf_size;
440 } else {
441 10161 next = find_frame_end(s, buf, buf_size);
442
2/2
✓ Branch 1 taken 7078 times.
✓ Branch 2 taken 3083 times.
10161 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0)
443 7078 return buf_size;
444 }
445
446 3083 is_dummy_buf &= (dummy_buf == buf);
447
448
2/2
✓ Branch 0 taken 3029 times.
✓ Branch 1 taken 54 times.
3083 if (!is_dummy_buf) {
449 3029 ret = combine_au(s, avctx, &buf, &buf_size);
450
4/4
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 2994 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 32 times.
3029 if (ret > 0 && flush) {
451 3 buf_size = 0;
452 3 ret = combine_au(s, avctx, &buf, &buf_size);
453 }
454
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2997 times.
3029 if (ret != 0)
455 32 return next;
456 }
457
458 3051 *poutbuf = buf;
459 3051 *poutbuf_size = buf_size;
460
461 3051 return next;
462 }
463
464 static const CodedBitstreamUnitType decompose_unit_types[] = {
465 VVC_TRAIL_NUT,
466 VVC_STSA_NUT,
467 VVC_RADL_NUT,
468 VVC_RASL_NUT,
469 VVC_IDR_W_RADL,
470 VVC_IDR_N_LP,
471 VVC_CRA_NUT,
472 VVC_GDR_NUT,
473 VVC_VPS_NUT,
474 VVC_SPS_NUT,
475 VVC_PPS_NUT,
476 VVC_PH_NUT,
477 VVC_AUD_NUT,
478 };
479
480 55 static av_cold int vvc_parser_init(AVCodecParserContext *s)
481 {
482 55 VVCParserContext *ctx = s->priv_data;
483 int ret;
484
485 55 ret = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_VVC, NULL);
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (ret < 0)
487 return ret;
488 55 au_detector_init(&ctx->au_detector);
489
490 55 ctx->cbc->decompose_unit_types = decompose_unit_types;
491 55 ctx->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types);
492
493 55 return ret;
494 }
495
496 55 static av_cold void vvc_parser_close(AVCodecParserContext *s)
497 {
498 55 VVCParserContext *ctx = s->priv_data;
499
500 55 av_packet_unref(&ctx->au);
501 55 av_packet_unref(&ctx->last_au);
502 55 ff_cbs_fragment_free(&ctx->picture_unit);
503
504 55 ff_cbs_close(&ctx->cbc);
505 55 av_freep(&ctx->pc.buffer);
506 55 }
507
508 const AVCodecParser ff_vvc_parser = {
509 .codec_ids = { AV_CODEC_ID_VVC },
510 .priv_data_size = sizeof(VVCParserContext),
511 .parser_init = vvc_parser_init,
512 .parser_close = vvc_parser_close,
513 .parser_parse = vvc_parser_parse,
514 };
515