FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc_parser.c
Date: 2026-10-09 17:04:47
Exec Total Coverage
Lines: 219 250 87.6%
Functions: 14 14 100.0%
Branches: 130 161 80.7%

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