FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc_parser.c
Date: 2024-02-16 17:37:06
Exec Total Coverage
Lines: 220 252 87.3%
Functions: 14 14 100.0%
Branches: 130 163 79.8%

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 "cbs.h"
24 #include "cbs_h266.h"
25 #include "parser.h"
26
27 #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes
28 #define IS_IDR(nut) (nut == VVC_IDR_W_RADL || nut == VVC_IDR_N_LP)
29 #define IS_H266_SLICE(nut) (nut <= VVC_RASL_NUT || (nut >= VVC_IDR_W_RADL && nut <= VVC_GDR_NUT))
30
31 typedef struct PuInfo {
32 const H266RawPPS *pps;
33 const H266RawSPS *sps;
34 const H266RawPictureHeader *ph;
35 const H266RawSlice *slice;
36 int pic_type;
37 } PuInfo;
38
39 typedef struct AuDetector {
40 uint8_t prev_layer_id;
41 int prev_tid0_poc;
42 int prev_poc;
43 } AuDetector;
44
45 typedef struct VVCParserContext {
46 ParseContext pc;
47 CodedBitstreamContext *cbc;
48
49 CodedBitstreamFragment picture_unit;
50
51 AVPacket au;
52 AVPacket last_au;
53
54 AuDetector au_detector;
55
56 int parsed_extradata;
57 } VVCParserContext;
58
59 static const enum AVPixelFormat pix_fmts_8bit[] = {
60 AV_PIX_FMT_GRAY8, AV_PIX_FMT_YUV420P,
61 AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P
62 };
63
64 static const enum AVPixelFormat pix_fmts_10bit[] = {
65 AV_PIX_FMT_GRAY10, AV_PIX_FMT_YUV420P10,
66 AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10
67 };
68
69 2928 static int get_format(const H266RawSPS *sps)
70 {
71
2/3
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2924 times.
✗ Branch 2 not taken.
2928 switch (sps->sps_bitdepth_minus8) {
72 4 case 0:
73 4 return pix_fmts_8bit[sps->sps_chroma_format_idc];
74 2924 case 2:
75 2924 return pix_fmts_10bit[sps->sps_chroma_format_idc];
76 }
77 return AV_PIX_FMT_NONE;
78 }
79
80 /**
81 * Find the end of the current frame in the bitstream.
82 * @return the position of the first byte of the next frame, or END_NOT_FOUND
83 */
84 9959 static int find_frame_end(AVCodecParserContext *s, const uint8_t *buf,
85 int buf_size)
86 {
87 9959 VVCParserContext *ctx = s->priv_data;
88 9959 ParseContext *pc = &ctx->pc;
89 int i;
90
91
2/2
✓ Branch 0 taken 7091047 times.
✓ Branch 1 taken 7030 times.
7098077 for (i = 0; i < buf_size; i++) {
92 int nut, code_len;
93
94 7091047 pc->state64 = (pc->state64 << 8) | buf[i];
95
96
2/2
✓ Branch 0 taken 7079748 times.
✓ Branch 1 taken 11299 times.
7091047 if (((pc->state64 >> 3 * 8) & 0xFFFFFF) != START_CODE)
97 7079748 continue;
98
99
2/2
✓ Branch 0 taken 6397 times.
✓ Branch 1 taken 4902 times.
11299 code_len = ((pc->state64 >> 3 * 8) & 0xFFFFFFFF) == 0x01 ? 4 : 3;
100
101 11299 nut = (pc->state64 >> (8 + 3)) & 0x1F;
102 // 7.4.2.4.3 and 7.4.2.4.4
103
5/6
✓ Branch 0 taken 5209 times.
✓ Branch 1 taken 6090 times.
✓ Branch 2 taken 1985 times.
✓ Branch 3 taken 3224 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1985 times.
11299 if ((nut >= VVC_OPI_NUT && nut <= VVC_PREFIX_APS_NUT &&
104
2/2
✓ Branch 0 taken 9270 times.
✓ Branch 1 taken 44 times.
9314 nut != VVC_PH_NUT) || nut == VVC_AUD_NUT
105
4/4
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 9146 times.
✓ Branch 2 taken 116 times.
✓ Branch 3 taken 8 times.
9270 || (nut == VVC_PREFIX_SEI_NUT && !pc->frame_start_found)
106
2/4
✓ Branch 0 taken 9262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9262 times.
✗ Branch 3 not taken.
9262 || nut == VVC_RSV_NVCL_26 || nut == VVC_UNSPEC_28
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9262 times.
9262 || nut == VVC_UNSPEC_29) {
108
2/2
✓ Branch 0 taken 709 times.
✓ Branch 1 taken 1328 times.
2037 if (pc->frame_start_found) {
109 709 pc->frame_start_found = 0;
110 709 return i - (code_len + 2);
111 }
112
7/8
✓ Branch 0 taken 9182 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 3672 times.
✓ Branch 3 taken 5510 times.
✓ Branch 4 taken 3672 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 580 times.
✓ Branch 7 taken 3092 times.
9262 } else if (nut == VVC_PH_NUT || IS_H266_SLICE(nut)) {
113 6170 int sh_picture_header_in_slice_header_flag = buf[i] >> 7;
114
115
4/4
✓ Branch 0 taken 6090 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 5120 times.
✓ Branch 3 taken 970 times.
6170 if (nut == VVC_PH_NUT || sh_picture_header_in_slice_header_flag) {
116
2/2
✓ Branch 0 taken 2980 times.
✓ Branch 1 taken 2220 times.
5200 if (!pc->frame_start_found) {
117 2980 pc->frame_start_found = 1;
118 } else { // First slice of next frame found
119 2220 pc->frame_start_found = 0;
120 2220 return i - (code_len + 2);
121 }
122 }
123 }
124 }
125 7030 return END_NOT_FOUND;
126 }
127
128 2980 static int get_pict_type(const CodedBitstreamFragment *pu)
129 {
130 2980 int has_p = 0;
131
2/2
✓ Branch 0 taken 6010 times.
✓ Branch 1 taken 1418 times.
7428 for (int i = 0; i < pu->nb_units; i++) {
132 6010 CodedBitstreamUnit *unit = &pu->units[i];
133
5/6
✓ Branch 0 taken 3382 times.
✓ Branch 1 taken 2628 times.
✓ Branch 2 taken 3382 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 580 times.
✓ Branch 5 taken 2802 times.
6010 if (IS_H266_SLICE(unit->type)) {
134 3208 const H266RawSlice *slice = unit->content;
135 3208 uint8_t type = slice->header.sh_slice_type;
136
2/2
✓ Branch 0 taken 1562 times.
✓ Branch 1 taken 1646 times.
3208 if (type == VVC_SLICE_TYPE_B) {
137 1562 return AV_PICTURE_TYPE_B;
138 }
139
2/2
✓ Branch 0 taken 1068 times.
✓ Branch 1 taken 578 times.
1646 if (type == VVC_SLICE_TYPE_P) {
140 1068 has_p = 1;
141 }
142 }
143 }
144
2/2
✓ Branch 0 taken 1068 times.
✓ Branch 1 taken 350 times.
1418 return has_p ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
145 }
146
147 2928 static void set_parser_ctx(AVCodecParserContext *s, AVCodecContext *avctx,
148 const PuInfo *pu)
149 {
150 static const uint8_t h266_sub_width_c[] = {
151 1, 2, 2, 1
152 };
153 static const uint8_t h266_sub_height_c[] = {
154 1, 2, 1, 1
155 };
156 2928 const H266RawSPS *sps = pu->sps;
157 2928 const H266RawPPS *pps = pu->pps;
158 2928 const H266RawNALUnitHeader *nal = &pu->slice->header.nal_unit_header;
159
160 2928 s->pict_type = pu->pic_type;
161 2928 s->format = get_format(sps);
162 2928 s->picture_structure = AV_PICTURE_STRUCTURE_FRAME;
163
164 8778 s->key_frame = nal->nal_unit_type == VVC_IDR_W_RADL ||
165
2/2
✓ Branch 0 taken 2600 times.
✓ Branch 1 taken 322 times.
2922 nal->nal_unit_type == VVC_IDR_N_LP ||
166
4/4
✓ Branch 0 taken 2922 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2582 times.
✓ Branch 3 taken 18 times.
8432 nal->nal_unit_type == VVC_CRA_NUT ||
167
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2580 times.
2582 nal->nal_unit_type == VVC_GDR_NUT;
168
169 2928 s->coded_width = pps->pps_pic_width_in_luma_samples;
170 2928 s->coded_height = pps->pps_pic_height_in_luma_samples;
171 2928 s->width = pps->pps_pic_width_in_luma_samples -
172 2928 (pps->pps_conf_win_left_offset + pps->pps_conf_win_right_offset) *
173 2928 h266_sub_width_c[sps->sps_chroma_format_idc];
174 2928 s->height = pps->pps_pic_height_in_luma_samples -
175 2928 (pps->pps_conf_win_top_offset + pps->pps_conf_win_bottom_offset) *
176 2928 h266_sub_height_c[sps->sps_chroma_format_idc];;
177
178 2928 avctx->profile = sps->profile_tier_level.general_profile_idc;
179 2928 avctx->level = sps->profile_tier_level.general_level_idc;
180
181 2928 avctx->colorspace = (enum AVColorSpace) sps->vui.vui_matrix_coeffs;
182 2928 avctx->color_primaries = (enum AVColorPrimaries) sps->vui.vui_colour_primaries;
183 2928 avctx->color_trc = (enum AVColorTransferCharacteristic) sps->vui.vui_transfer_characteristics;
184 2928 avctx->color_range =
185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2928 times.
2928 sps->vui.vui_full_range_flag ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
186
187 2928 avctx->has_b_frames = (sps->sps_max_sublayers_minus1 + 1) > 2 ? 2 :
188 sps->sps_max_sublayers_minus1;
189 2928 avctx->max_b_frames = sps->sps_max_sublayers_minus1;
190
191
1/2
✓ Branch 0 taken 2928 times.
✗ Branch 1 not taken.
2928 if (sps->sps_ptl_dpb_hrd_params_present_flag &&
192
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 2808 times.
2928 sps->sps_timing_hrd_params_present_flag) {
193 120 int num = sps->sps_general_timing_hrd_parameters.num_units_in_tick;
194 120 int den = sps->sps_general_timing_hrd_parameters.time_scale;
195
196
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)
197 120 av_reduce(&avctx->framerate.den, &avctx->framerate.num,
198 num, den, 1 << 30);
199 }
200 2928 }
201
202 //8.3.1 Decoding process for picture order count.
203 //VTM did not follow the spec, and it's much simpler than spec.
204 //We follow the VTM.
205 2980 static void get_slice_poc(VVCParserContext *s, int *poc,
206 const H266RawSPS *sps,
207 const H266RawPictureHeader *ph,
208 const H266RawSliceHeader *slice, void *log_ctx)
209 {
210 int poc_msb, max_poc_lsb, poc_lsb;
211 2980 AuDetector *d = &s->au_detector;
212 2980 max_poc_lsb = 1 << (sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4);
213 2980 poc_lsb = ph->ph_pic_order_cnt_lsb;
214
4/4
✓ Branch 0 taken 2974 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 326 times.
✓ Branch 3 taken 2648 times.
2980 if (IS_IDR(slice->nal_unit_header.nal_unit_type)) {
215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332 times.
332 if (ph->ph_poc_msb_cycle_present_flag)
216 poc_msb = ph->ph_poc_msb_cycle_val * max_poc_lsb;
217 else
218 332 poc_msb = 0;
219 } else {
220 2648 int prev_poc = d->prev_tid0_poc;
221 2648 int prev_poc_lsb = prev_poc & (max_poc_lsb - 1);
222 2648 int prev_poc_msb = prev_poc - prev_poc_lsb;
223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2648 times.
2648 if (ph->ph_poc_msb_cycle_present_flag) {
224 poc_msb = ph->ph_poc_msb_cycle_val * max_poc_lsb;
225 } else {
226
2/2
✓ Branch 0 taken 1056 times.
✓ Branch 1 taken 1592 times.
2648 if ((poc_lsb < prev_poc_lsb) && ((prev_poc_lsb - poc_lsb) >=
227
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1052 times.
1056 (max_poc_lsb / 2)))
228 4 poc_msb = prev_poc_msb + (unsigned)max_poc_lsb;
229
2/2
✓ Branch 0 taken 1574 times.
✓ Branch 1 taken 1070 times.
2644 else if ((poc_lsb > prev_poc_lsb) && ((poc_lsb - prev_poc_lsb) >
230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1574 times.
1574 (max_poc_lsb / 2)))
231 poc_msb = prev_poc_msb - (unsigned)max_poc_lsb;
232 else
233 2644 poc_msb = prev_poc_msb;
234 }
235 }
236
237 2980 *poc = poc_msb + poc_lsb;
238 2980 }
239
240 51 static void au_detector_init(AuDetector *d)
241 {
242 51 d->prev_layer_id = UINT8_MAX;
243 51 d->prev_poc = INT_MAX;
244 51 d->prev_tid0_poc = INT_MAX;
245 51 }
246
247 2980 static int is_au_start(VVCParserContext *s, const PuInfo *pu, void *log_ctx)
248 {
249 //7.4.2.4.3
250 2980 AuDetector *d = &s->au_detector;
251 2980 const H266RawSPS *sps = pu->sps;
252 2980 const H266RawNALUnitHeader *nal = &pu->slice->header.nal_unit_header;
253 2980 const H266RawPictureHeader *ph = pu->ph;
254 2980 const H266RawSlice *slice = pu->slice;
255 int ret, poc, nut;
256
257 2980 get_slice_poc(s, &poc, sps, ph, &slice->header, log_ctx);
258
259
3/4
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 2928 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 52 times.
2980 ret = (nal->nuh_layer_id <= d->prev_layer_id) || (poc != d->prev_poc);
260
261 2980 nut = nal->nal_unit_type;
262 2980 d->prev_layer_id = nal->nuh_layer_id;
263 2980 d->prev_poc = poc;
264
2/2
✓ Branch 0 taken 1570 times.
✓ Branch 1 taken 1410 times.
2980 if (nal->nuh_temporal_id_plus1 == 1 &&
265
2/4
✓ Branch 0 taken 1570 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1570 times.
✗ Branch 3 not taken.
1570 !ph->ph_non_ref_pic_flag && nut != VVC_RADL_NUT
266
1/2
✓ Branch 0 taken 1570 times.
✗ Branch 1 not taken.
1570 && nut != VVC_RASL_NUT) {
267 1570 d->prev_tid0_poc = poc;
268 }
269 2980 return ret;
270 }
271
272 2980 static int get_pu_info(PuInfo *info, const CodedBitstreamH266Context *h266,
273 const CodedBitstreamFragment *pu, void *logctx)
274 {
275 const H266RawNALUnitHeader *nal;
276 int ret;
277
278 2980 memset(info, 0, sizeof(*info));
279
1/2
✓ Branch 0 taken 4362 times.
✗ Branch 1 not taken.
4362 for (int i = 0; i < pu->nb_units; i++) {
280 4362 nal = pu->units[i].content;
281
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 3894 times.
4362 if (!nal)
282 468 continue;
283
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 3840 times.
3894 if ( nal->nal_unit_type == VVC_PH_NUT ) {
284 54 const H266RawPH *ph = pu->units[i].content;
285 54 info->ph = &ph->ph_picture_header;
286
5/6
✓ Branch 0 taken 1212 times.
✓ Branch 1 taken 2628 times.
✓ Branch 2 taken 1212 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 352 times.
✓ Branch 5 taken 860 times.
3840 } else if (IS_H266_SLICE(nal->nal_unit_type)) {
287 2980 info->slice = pu->units[i].content;
288
2/2
✓ Branch 0 taken 2926 times.
✓ Branch 1 taken 54 times.
2980 if (info->slice->header.sh_picture_header_in_slice_header_flag)
289 2926 info->ph = &info->slice->header.sh_picture_header;
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2980 times.
2980 if (!info->ph) {
291 av_log(logctx, AV_LOG_ERROR,
292 "can't find picture header in picture unit.\n");
293 ret = AVERROR_INVALIDDATA;
294 goto error;
295 }
296 2980 break;
297 }
298 }
299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2980 times.
2980 if (!info->slice) {
300 av_log(logctx, AV_LOG_ERROR, "can't find slice in picture unit.\n");
301 ret = AVERROR_INVALIDDATA;
302 goto error;
303 }
304 2980 info->pps = h266->pps[info->ph->ph_pic_parameter_set_id];
305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2980 times.
2980 if (!info->pps) {
306 av_log(logctx, AV_LOG_ERROR, "PPS id %d is not avaliable.\n",
307 info->ph->ph_pic_parameter_set_id);
308 ret = AVERROR_INVALIDDATA;
309 goto error;
310 }
311 2980 info->sps = h266->sps[info->pps->pps_seq_parameter_set_id];
312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2980 times.
2980 if (!info->sps) {
313 av_log(logctx, AV_LOG_ERROR, "SPS id %d is not avaliable.\n",
314 info->pps->pps_seq_parameter_set_id);
315 ret = AVERROR_INVALIDDATA;
316 goto error;
317 }
318 2980 info->pic_type = get_pict_type(pu);
319 2980 return 0;
320 error:
321 memset(info, 0, sizeof(*info));
322 return ret;
323 }
324
325 2980 static int append_au(AVPacket *pkt, const uint8_t *buf, int buf_size)
326 {
327 2980 int offset = pkt->size;
328 int ret;
329
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2980 times.
2980 if ((ret = av_grow_packet(pkt, buf_size)) < 0)
330 goto end;
331 2980 memcpy(pkt->data + offset, buf, buf_size);
332 2980 end:
333 2980 return ret;
334 }
335
336 /**
337 * Parse NAL units of found picture and decode some basic information.
338 *
339 * @param s parser context.
340 * @param avctx codec context.
341 * @param buf buffer with field/frame data.
342 * @param buf_size size of the buffer.
343 * @return < 0 for error, == 0 for a complete au, > 0 is not a completed au.
344 */
345 2984 static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
346 int buf_size, AVCodecContext *avctx)
347 {
348 2984 VVCParserContext *ctx = s->priv_data;
349 2984 const CodedBitstreamH266Context *h266 = ctx->cbc->priv_data;
350
351 2984 CodedBitstreamFragment *pu = &ctx->picture_unit;
352 int ret;
353 PuInfo info;
354
355
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2980 times.
2984 if (!buf_size) {
356
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (ctx->au.size) {
357 4 av_packet_move_ref(&ctx->last_au, &ctx->au);
358 4 return 0;
359 }
360 return 1;
361 }
362
363
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2980 times.
2980 if ((ret = ff_cbs_read(ctx->cbc, pu, buf, buf_size)) < 0) {
364 av_log(avctx, AV_LOG_ERROR, "Failed to parse picture unit.\n");
365 goto end;
366 }
367
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2980 times.
2980 if ((ret = get_pu_info(&info, h266, pu, avctx)) < 0)
368 goto end;
369
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2980 times.
2980 if (append_au(&ctx->au, buf, buf_size) < 0) {
370 ret = AVERROR(ENOMEM);
371 goto end;
372 }
373
2/2
✓ Branch 1 taken 2928 times.
✓ Branch 2 taken 52 times.
2980 if (is_au_start(ctx, &info, avctx)) {
374 2928 set_parser_ctx(s, avctx, &info);
375 2928 av_packet_move_ref(&ctx->last_au, &ctx->au);
376 } else {
377 52 ret = 1; //not a completed au
378 }
379 2980 end:
380 2980 ff_cbs_fragment_reset(pu);
381 2980 return ret;
382 }
383
384 /**
385 * Combine PU to AU
386 *
387 * @param s parser context.
388 * @param avctx codec context.
389 * @param buf buffer to a PU.
390 * @param buf_size size of the buffer.
391 * @return < 0 for error, == 0 a complete au, > 0 not a completed au.
392 */
393 2984 static int combine_au(AVCodecParserContext *s, AVCodecContext *avctx,
394 const uint8_t **buf, int *buf_size)
395 {
396 2984 VVCParserContext *ctx = s->priv_data;
397 int ret;
398
399 2984 ctx->cbc->log_ctx = avctx;
400
401 2984 av_packet_unref(&ctx->last_au);
402 2984 ret = parse_nal_units(s, *buf, *buf_size, avctx);
403
2/2
✓ Branch 0 taken 2932 times.
✓ Branch 1 taken 52 times.
2984 if (ret == 0) {
404
1/2
✓ Branch 0 taken 2932 times.
✗ Branch 1 not taken.
2932 if (ctx->last_au.size) {
405 2932 *buf = ctx->last_au.data;
406 2932 *buf_size = ctx->last_au.size;
407 } else {
408 ret = 1; //no output
409 }
410 }
411 2984 ctx->cbc->log_ctx = NULL;
412 2984 return ret;
413 }
414
415 9959 static int vvc_parser_parse(AVCodecParserContext *s, AVCodecContext *avctx,
416 const uint8_t **poutbuf, int *poutbuf_size,
417 const uint8_t *buf, int buf_size)
418 {
419 int next, ret;
420 9959 VVCParserContext *ctx = s->priv_data;
421 9959 ParseContext *pc = &ctx->pc;
422 9959 CodedBitstreamFragment *pu = &ctx->picture_unit;
423
424 9959 int is_dummy_buf = !buf_size;
425 9959 int flush = !buf_size;
426 9959 const uint8_t *dummy_buf = buf;
427
428 9959 *poutbuf = NULL;
429 9959 *poutbuf_size = 0;
430
431
4/4
✓ Branch 0 taken 7800 times.
✓ Branch 1 taken 2159 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 7749 times.
9959 if (avctx->extradata_size && !ctx->parsed_extradata) {
432 51 ctx->parsed_extradata = 1;
433
434 51 ret = ff_cbs_read_extradata_from_codec(ctx->cbc, pu, avctx);
435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (ret < 0)
436 av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata.\n");
437
438 51 ff_cbs_fragment_reset(pu);
439 }
440
441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9959 times.
9959 if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
442 next = buf_size;
443 } else {
444 9959 next = find_frame_end(s, buf, buf_size);
445
2/2
✓ Branch 1 taken 6928 times.
✓ Branch 2 taken 3031 times.
9959 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0)
446 6928 return buf_size;
447 }
448
449 3031 is_dummy_buf &= (dummy_buf == buf);
450
451
2/2
✓ Branch 0 taken 2980 times.
✓ Branch 1 taken 51 times.
3031 if (!is_dummy_buf) {
452 2980 ret = combine_au(s, avctx, &buf, &buf_size);
453
4/4
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 2928 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 48 times.
2980 if (ret > 0 && flush) {
454 4 buf_size = 0;
455 4 ret = combine_au(s, avctx, &buf, &buf_size);
456 }
457
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2932 times.
2980 if (ret != 0)
458 48 return next;
459 }
460
461 2983 *poutbuf = buf;
462 2983 *poutbuf_size = buf_size;
463
464 2983 return next;
465 }
466
467 static const CodedBitstreamUnitType decompose_unit_types[] = {
468 VVC_TRAIL_NUT,
469 VVC_STSA_NUT,
470 VVC_RADL_NUT,
471 VVC_RASL_NUT,
472 VVC_IDR_W_RADL,
473 VVC_IDR_N_LP,
474 VVC_CRA_NUT,
475 VVC_GDR_NUT,
476 VVC_VPS_NUT,
477 VVC_SPS_NUT,
478 VVC_PPS_NUT,
479 VVC_PH_NUT,
480 VVC_AUD_NUT,
481 };
482
483 51 static av_cold int vvc_parser_init(AVCodecParserContext *s)
484 {
485 51 VVCParserContext *ctx = s->priv_data;
486 int ret;
487
488 51 ret = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_VVC, NULL);
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (ret < 0)
490 return ret;
491 51 au_detector_init(&ctx->au_detector);
492
493 51 ctx->cbc->decompose_unit_types = decompose_unit_types;
494 51 ctx->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types);
495
496 51 return ret;
497 }
498
499 51 static av_cold void vvc_parser_close(AVCodecParserContext *s)
500 {
501 51 VVCParserContext *ctx = s->priv_data;
502
503 51 av_packet_unref(&ctx->au);
504 51 av_packet_unref(&ctx->last_au);
505 51 ff_cbs_fragment_free(&ctx->picture_unit);
506
507 51 ff_cbs_close(&ctx->cbc);
508 51 av_freep(&ctx->pc.buffer);
509 51 }
510
511 const AVCodecParser ff_vvc_parser = {
512 .codec_ids = { AV_CODEC_ID_VVC },
513 .priv_data_size = sizeof(VVCParserContext),
514 .parser_init = vvc_parser_init,
515 .parser_close = vvc_parser_close,
516 .parser_parse = vvc_parser_parse,
517 };
518