FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/cbs_h266.c
Date: 2026-03-13 22:30:28
Exec Total Coverage
Lines: 246 297 82.8%
Functions: 11 11 100.0%
Branches: 110 170 64.7%

Line Branch Exec 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 "libavutil/intmath.h"
20 #include "libavutil/mem.h"
21 #include "libavutil/refstruct.h"
22 #include "bytestream.h"
23 #include "cbs.h"
24 #include "cbs_internal.h"
25 #include "cbs_h2645.h"
26 #include "cbs_h266.h"
27 #include "cbs_sei.h"
28 #include "get_bits.h"
29
30 #define HEADER(name) do { \
31 ff_cbs_trace_header(ctx, name); \
32 } while (0)
33
34 #define CHECK(call) do { \
35 err = (call); \
36 if (err < 0) \
37 return err; \
38 } while (0)
39
40 #define FUNC_NAME2(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
41 #define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name)
42 #define FUNC_H266(name) FUNC_NAME1(READWRITE, h266, name)
43 #define FUNC_NAME2_EXPORT(rw, codec, name) ff_cbs_ ## codec ## _ ## rw ## _ ## name
44 #define FUNC_NAME1_EXPORT(rw, codec, name) FUNC_NAME2_EXPORT(rw, codec, name)
45 #define FUNC_SEI(name) FUNC_NAME1_EXPORT(READWRITE, sei, name)
46
47 #define SEI_FUNC(name, args) \
48 static int FUNC_H266(name) args; \
49 static int FUNC_H266(name ## _internal)(CodedBitstreamContext *ctx, \
50 RWContext *rw, void *cur, \
51 SEIMessageState *state) \
52 { \
53 return FUNC_H266(name)(ctx, rw, cur, state); \
54 } \
55 static int FUNC_H266(name) args
56
57 #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
58
59 #define u(width, name, range_min, range_max) \
60 xu(width, name, current->name, range_min, range_max, 0, )
61 #define flag(name) ub(1, name)
62 #define ue(name, range_min, range_max) \
63 xue(name, current->name, range_min, range_max, 0, )
64 #define i(width, name, range_min, range_max) \
65 xi(width, name, current->name, range_min, range_max, 0, )
66 #define ib(width, name) \
67 xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), 0, )
68 #define se(name, range_min, range_max) \
69 xse(name, current->name, range_min, range_max, 0, )
70
71 #define us(width, name, range_min, range_max, subs, ...) \
72 xu(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
73 #define ubs(width, name, subs, ...) \
74 xu(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__)
75 #define flags(name, subs, ...) \
76 xu(1, name, current->name, 0, 1, subs, __VA_ARGS__)
77 #define ues(name, range_min, range_max, subs, ...) \
78 xue(name, current->name, range_min, range_max, subs, __VA_ARGS__)
79 #define is(width, name, range_min, range_max, subs, ...) \
80 xi(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
81 #define ibs(width, name, subs, ...) \
82 xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), subs, __VA_ARGS__)
83 #define ses(name, range_min, range_max, subs, ...) \
84 xse(name, current->name, range_min, range_max, subs, __VA_ARGS__)
85
86 #define fixed(width, name, value) do { \
87 av_unused uint32_t fixed_value = value; \
88 xu(width, name, fixed_value, value, value, 0, ); \
89 } while (0)
90
91
92 #define READ
93 #define READWRITE read
94 #define RWContext GetBitContext
95
96 #define ub(width, name) do { \
97 uint32_t value; \
98 CHECK(ff_cbs_read_simple_unsigned(ctx, rw, width, #name, \
99 &value)); \
100 current->name = value; \
101 } while (0)
102 #define xu(width, name, var, range_min, range_max, subs, ...) do { \
103 uint32_t value; \
104 CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
105 SUBSCRIPTS(subs, __VA_ARGS__), \
106 &value, range_min, range_max)); \
107 var = value; \
108 } while (0)
109 #define xue(name, var, range_min, range_max, subs, ...) do { \
110 uint32_t value; \
111 CHECK(ff_cbs_read_ue_golomb(ctx, rw, #name, \
112 SUBSCRIPTS(subs, __VA_ARGS__), \
113 &value, range_min, range_max)); \
114 var = value; \
115 } while (0)
116 #define xi(width, name, var, range_min, range_max, subs, ...) do { \
117 int32_t value; \
118 CHECK(ff_cbs_read_signed(ctx, rw, width, #name, \
119 SUBSCRIPTS(subs, __VA_ARGS__), \
120 &value, range_min, range_max)); \
121 var = value; \
122 } while (0)
123 #define xse(name, var, range_min, range_max, subs, ...) do { \
124 int32_t value; \
125 CHECK(ff_cbs_read_se_golomb(ctx, rw, #name, \
126 SUBSCRIPTS(subs, __VA_ARGS__), \
127 &value, range_min, range_max)); \
128 var = value; \
129 } while (0)
130
131
132 #define infer(name, value) do { \
133 current->name = value; \
134 } while (0)
135
136 #define more_rbsp_data(var) ((var) = ff_cbs_h2645_read_more_rbsp_data(rw))
137
138 #define bit_position(rw) (get_bits_count(rw))
139 #define byte_alignment(rw) (get_bits_count(rw) % 8)
140
141 #define allocate(name, size) do { \
142 name ## _ref = av_buffer_allocz(size + \
143 AV_INPUT_BUFFER_PADDING_SIZE); \
144 if (!name ## _ref) \
145 return AVERROR(ENOMEM); \
146 name = name ## _ref->data; \
147 } while (0)
148
149 #define FUNC(name) FUNC_H266(name)
150 #include "cbs_h266_syntax_template.c"
151 #undef FUNC
152
153
154 #undef READ
155 #undef READWRITE
156 #undef RWContext
157 #undef ub
158 #undef xu
159 #undef xi
160 #undef xue
161 #undef xse
162 #undef infer
163 #undef more_rbsp_data
164 #undef bit_position
165 #undef byte_alignment
166 #undef allocate
167 #undef allocate_struct
168
169
170 #define WRITE
171 #define READWRITE write
172 #define RWContext PutBitContext
173
174 #define ub(width, name) do { \
175 uint32_t value = current->name; \
176 CHECK(ff_cbs_write_simple_unsigned(ctx, rw, width, #name, \
177 value)); \
178 } while (0)
179 #define xu(width, name, var, range_min, range_max, subs, ...) do { \
180 uint32_t value = var; \
181 CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
182 SUBSCRIPTS(subs, __VA_ARGS__), \
183 value, range_min, range_max)); \
184 } while (0)
185 #define xue(name, var, range_min, range_max, subs, ...) do { \
186 uint32_t value = var; \
187 CHECK(ff_cbs_write_ue_golomb(ctx, rw, #name, \
188 SUBSCRIPTS(subs, __VA_ARGS__), \
189 value, range_min, range_max)); \
190 } while (0)
191 #define xi(width, name, var, range_min, range_max, subs, ...) do { \
192 int32_t value = var; \
193 CHECK(ff_cbs_write_signed(ctx, rw, width, #name, \
194 SUBSCRIPTS(subs, __VA_ARGS__), \
195 value, range_min, range_max)); \
196 } while (0)
197 #define xse(name, var, range_min, range_max, subs, ...) do { \
198 int32_t value = var; \
199 CHECK(ff_cbs_write_se_golomb(ctx, rw, #name, \
200 SUBSCRIPTS(subs, __VA_ARGS__), \
201 value, range_min, range_max)); \
202 } while (0)
203
204 #define infer(name, value) do { \
205 if (current->name != (value)) { \
206 av_log(ctx->log_ctx, AV_LOG_ERROR, \
207 "%s does not match inferred value: " \
208 "%"PRId64", but should be %"PRId64".\n", \
209 #name, (int64_t)current->name, (int64_t)(value)); \
210 return AVERROR_INVALIDDATA; \
211 } \
212 } while (0)
213
214 #define more_rbsp_data(var) (var)
215
216 #define bit_position(rw) (put_bits_count(rw))
217 #define byte_alignment(rw) (put_bits_count(rw) % 8)
218
219 #define allocate(name, size) do { \
220 if (!name) { \
221 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s must be set " \
222 "for writing.\n", #name); \
223 return AVERROR_INVALIDDATA; \
224 } \
225 } while (0)
226
227 #define FUNC(name) FUNC_H266(name)
228 #include "cbs_h266_syntax_template.c"
229 #undef FUNC
230
231 #undef WRITE
232 #undef READWRITE
233 #undef RWContext
234 #undef ub
235 #undef xu
236 #undef xi
237 #undef xue
238 #undef xse
239 #undef u
240 #undef i
241 #undef flag
242 #undef ue
243 #undef se
244 #undef infer
245 #undef more_rbsp_data
246 #undef bit_position
247 #undef byte_alignment
248 #undef allocate
249
250
251
252 6511 static int cbs_h266_split_fragment(CodedBitstreamContext *ctx,
253 CodedBitstreamFragment *frag,
254 int header)
255 {
256 6511 enum AVCodecID codec_id = ctx->codec->codec_id;
257 6511 CodedBitstreamH266Context *priv = ctx->priv_data;
258 6511 CodedBitstreamH2645Context *h2645 = &priv->common;
259 GetByteContext gbc;
260 int err;
261
262
2/4
✓ Branch 0 taken 6511 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6511 times.
6511 av_assert0(frag->data && frag->nb_units == 0);
263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6511 times.
6511 if (frag->data_size == 0)
264 return 0;
265
266
4/4
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 6388 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 118 times.
6516 if(header && frag->data[0]) {
267 // VVCC header.
268 int ptl_present_flag, num_arrays;
269 int b, i, j;
270
271 5 h2645->mp4 = 1;
272
273 5 bytestream2_init(&gbc, frag->data, frag->data_size);
274
275 5 b = bytestream2_get_byte(&gbc);
276 5 h2645->nal_length_size = ((b >> 1) & 3) + 1;
277 5 ptl_present_flag = b & 1;
278
279
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if(ptl_present_flag) {
280 int num_sublayers, num_bytes_constraint_info, num_sub_profiles;
281 5 num_sublayers = (bytestream2_get_be16u(&gbc) >> 4) & 7;
282 5 bytestream2_skip(&gbc, 1);
283
284 // begin VvcPTLRecord(num_sublayers);
285 5 num_bytes_constraint_info = bytestream2_get_byte(&gbc) & 0x3f;
286 5 bytestream2_skip(&gbc, 2 + num_bytes_constraint_info);
287
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if(num_sublayers > 1) {
288 2 int count_present_flags = 0;
289 2 b = bytestream2_get_byte(&gbc);
290
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for(i = num_sublayers - 2; i >= 0; i--) {
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if((b >> (7 - (num_sublayers - 2 - i))) & 0x01)
292 count_present_flags++;
293 }
294 2 bytestream2_skip(&gbc, count_present_flags);
295 }
296 5 num_sub_profiles = bytestream2_get_byte(&gbc);
297 5 bytestream2_skip(&gbc, num_sub_profiles * 4);
298 // end VvcPTLRecord(num_sublayers);
299
300 5 bytestream2_skip(&gbc, 3 * 2);
301 }
302
303 5 num_arrays = bytestream2_get_byte(&gbc);
304
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
18 for(j = 0; j < num_arrays; j++) {
305 size_t start, end, size;
306 13 int nal_unit_type = bytestream2_get_byte(&gbc) & 0x1f;
307 13 unsigned int num_nalus = 1;
308
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
13 if(nal_unit_type != VVC_DCI_NUT && nal_unit_type != VVC_OPI_NUT)
309 13 num_nalus = bytestream2_get_be16(&gbc);
310
311 13 start = bytestream2_tell(&gbc);
312
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
26 for(i = 0; i < num_nalus; i++) {
313
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if (bytestream2_get_bytes_left(&gbc) < 2)
314 return AVERROR_INVALIDDATA;
315 13 size = bytestream2_get_be16(&gbc);
316
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if (bytestream2_get_bytes_left(&gbc) < size)
317 return AVERROR_INVALIDDATA;
318 13 bytestream2_skip(&gbc, size);
319 }
320 13 end = bytestream2_tell(&gbc);
321
322 13 err = ff_h2645_packet_split(&h2645->read_packet,
323 13 frag->data + start, end - start,
324 ctx->log_ctx, 2, AV_CODEC_ID_VVC,
325 H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (err < 0) {
327 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split "
328 "VVCC array %d (%d NAL units of type %d).\n",
329 i, num_nalus, nal_unit_type);
330 return err;
331 }
332 13 err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (err < 0)
334 return err;
335 }
336 } else {
337
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 6476 times.
6506 int flags = (H2645_FLAG_IS_NALFF * !!h2645->mp4) | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF;
338 // Annex B, or later MP4 with already-known parameters.
339
340 6506 err = ff_h2645_packet_split(&h2645->read_packet,
341 6506 frag->data, frag->data_size,
342 ctx->log_ctx,
343 h2645->nal_length_size,
344 codec_id, flags);
345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6506 times.
6506 if (err < 0)
346 return err;
347
348 6506 err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6506 times.
6506 if (err < 0)
350 return err;
351 }
352
353 6511 return 0;
354 }
355
356 #define cbs_h266_replace_ps(ps_name, ps_var, id_element) \
357 static int cbs_h266_replace_ ## ps_var(CodedBitstreamContext *ctx, \
358 CodedBitstreamUnit *unit) \
359 { \
360 CodedBitstreamH266Context *priv = ctx->priv_data; \
361 H266Raw ## ps_name *ps_var = unit->content; \
362 unsigned int id = ps_var->id_element; \
363 int err = ff_cbs_make_unit_refcounted(ctx, unit); \
364 if (err < 0) \
365 return err; \
366 av_assert0(unit->content_ref); \
367 av_refstruct_replace(&priv->ps_var[id], unit->content_ref); \
368 return 0; \
369 }
370
371
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
26 cbs_h266_replace_ps(VPS, vps, vps_video_parameter_set_id)
372
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1905 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1905 times.
1905 cbs_h266_replace_ps(PPS, pps, pps_pic_parameter_set_id)
373
374 1274 static int cbs_h266_replace_sps(CodedBitstreamContext *ctx,
375 CodedBitstreamUnit *unit)
376 {
377 1274 CodedBitstreamH266Context *priv = ctx->priv_data;
378 1274 H266RawSPS *sps = unit->content;
379 1274 unsigned int id = sps->sps_seq_parameter_set_id;
380 1274 int err = ff_cbs_make_unit_refcounted(ctx, unit);
381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1274 times.
1274 if (err < 0)
382 return err;
383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1274 times.
1274 av_assert0(unit->content_ref);
384
4/4
✓ Branch 0 taken 1040 times.
✓ Branch 1 taken 234 times.
✓ Branch 2 taken 786 times.
✓ Branch 3 taken 254 times.
1274 if (priv->sps[id] && memcmp(priv->sps[id], unit->content_ref, sizeof(*priv->sps[id]))) {
385
2/2
✓ Branch 0 taken 50304 times.
✓ Branch 1 taken 786 times.
51090 for (unsigned int i = 0; i < VVC_MAX_PPS_COUNT; i++) {
386
3/4
✓ Branch 0 taken 786 times.
✓ Branch 1 taken 49518 times.
✓ Branch 2 taken 786 times.
✗ Branch 3 not taken.
50304 if (priv->pps[i] && priv->pps[i]->pps_seq_parameter_set_id == id)
387 786 av_refstruct_unref(&priv->pps[i]);
388 }
389 }
390 1274 av_refstruct_replace(&priv->sps[id], unit->content_ref);
391 1274 return 0;
392 }
393
394 8550 static int cbs_h266_replace_ph(CodedBitstreamContext *ctx,
395 CodedBitstreamUnit *unit,
396 H266RawPictureHeader *ph)
397 {
398 8550 CodedBitstreamH266Context *h266 = ctx->priv_data;
399 int err;
400
401 8550 err = ff_cbs_make_unit_refcounted(ctx, unit);
402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8550 times.
8550 if (err < 0)
403 return err;
404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8550 times.
8550 av_assert0(unit->content_ref);
405 8550 av_refstruct_replace(&h266->ph_ref, unit->content_ref);
406 8550 h266->ph = ph;
407 8550 return 0;
408 }
409
410 15524 static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx,
411 CodedBitstreamUnit *unit)
412 {
413 GetBitContext gbc;
414 int err;
415 15524 CodedBitstreamH266Context *h266 = ctx->priv_data;
416
417 15524 err = init_get_bits8(&gbc, unit->data, unit->data_size);
418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15524 times.
15524 if (err < 0)
419 return err;
420
421 15524 err = ff_cbs_alloc_unit_content(ctx, unit);
422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15524 times.
15524 if (err < 0)
423 return err;
424
425
10/11
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 939 times.
✓ Branch 4 taken 1514 times.
✓ Branch 5 taken 659 times.
✓ Branch 6 taken 218 times.
✓ Branch 7 taken 8823 times.
✓ Branch 8 taken 53 times.
✓ Branch 9 taken 3290 times.
✗ Branch 10 not taken.
15524 switch (unit->type) {
426 4 case VVC_DCI_NUT:
427 {
428 4 err = cbs_h266_read_dci(ctx, &gbc, unit->content);
429
430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
431 return err;
432 }
433 4 break;
434 2 case VVC_OPI_NUT:
435 {
436 2 err = cbs_h266_read_opi(ctx, &gbc, unit->content);
437
438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
439 return err;
440 }
441 2 break;
442 22 case VVC_VPS_NUT:
443 {
444 22 H266RawVPS *vps = unit->content;
445
446 22 err = cbs_h266_read_vps(ctx, &gbc, vps);
447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (err < 0)
448 return err;
449
450 22 err = cbs_h266_replace_vps(ctx, unit);
451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (err < 0)
452 return err;
453 }
454 22 break;
455 939 case VVC_SPS_NUT:
456 {
457 939 H266RawSPS *sps = unit->content;
458
459 939 err = cbs_h266_read_sps(ctx, &gbc, sps);
460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 939 times.
939 if (err < 0)
461 return err;
462
463 939 err = cbs_h266_replace_sps(ctx, unit);
464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 939 times.
939 if (err < 0)
465 return err;
466 }
467 939 break;
468
469 1514 case VVC_PPS_NUT:
470 {
471 1514 H266RawPPS *pps = unit->content;
472
473 1514 err = cbs_h266_read_pps(ctx, &gbc, pps);
474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1514 times.
1514 if (err < 0)
475 return err;
476
477 1514 err = cbs_h266_replace_pps(ctx, unit);
478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1514 times.
1514 if (err < 0)
479 return err;
480 }
481 1514 break;
482
483 659 case VVC_PREFIX_APS_NUT:
484 case VVC_SUFFIX_APS_NUT:
485 {
486 659 err = cbs_h266_read_aps(ctx, &gbc, unit->content,
487 659 unit->type == VVC_PREFIX_APS_NUT);
488
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 659 times.
659 if (err < 0)
490 return err;
491 }
492 659 break;
493 218 case VVC_PH_NUT:
494 {
495 218 H266RawPH *ph = unit->content;
496 218 err = cbs_h266_read_ph(ctx, &gbc, ph);
497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 218 times.
218 if (err < 0)
498 return err;
499 218 err = cbs_h266_replace_ph(ctx, unit, &ph->ph_picture_header);
500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 218 times.
218 if (err < 0)
501 return err;
502 }
503 218 break;
504
505 8823 case VVC_TRAIL_NUT:
506 case VVC_STSA_NUT:
507 case VVC_RADL_NUT:
508 case VVC_RASL_NUT:
509 case VVC_IDR_W_RADL:
510 case VVC_IDR_N_LP:
511 case VVC_CRA_NUT:
512 case VVC_GDR_NUT:
513 {
514 8823 H266RawSlice *slice = unit->content;
515 int pos, len;
516
517 8823 err = cbs_h266_read_slice_header(ctx, &gbc, &slice->header);
518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8823 times.
8823 if (err < 0)
519 return err;
520
521
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8823 times.
8823 if (!ff_cbs_h2645_read_more_rbsp_data(&gbc))
522 return AVERROR_INVALIDDATA;
523
524 8823 pos = get_bits_count(&gbc);
525 8823 len = unit->data_size;
526
527
2/2
✓ Branch 0 taken 6202 times.
✓ Branch 1 taken 2621 times.
8823 if (slice->header.sh_picture_header_in_slice_header_flag) {
528 6202 err = cbs_h266_replace_ph(ctx, unit, &slice->header.sh_picture_header);
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6202 times.
6202 if (err < 0)
530 return err;
531 6202 slice->ph_ref = NULL;
532 } else {
533 2621 slice->ph_ref = av_refstruct_ref(h266->ph_ref);
534 }
535 8823 slice->ph = h266->ph;
536 8823 slice->pps = av_refstruct_ref(h266->pps[slice->ph->ph_pic_parameter_set_id]);
537 8823 slice->sps = av_refstruct_ref(h266->sps[slice->pps->pps_seq_parameter_set_id]);
538
539 8823 slice->header_size = pos / 8;
540 8823 slice->data_size = len - pos / 8;
541 8823 slice->data_ref = av_buffer_ref(unit->data_ref);
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8823 times.
8823 if (!slice->data_ref)
543 return AVERROR(ENOMEM);
544 8823 slice->data = unit->data + pos / 8;
545 8823 slice->data_bit_start = pos % 8;
546 }
547 8823 break;
548
549 53 case VVC_AUD_NUT:
550 {
551 53 err = cbs_h266_read_aud(ctx, &gbc, unit->content);
552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (err < 0)
553 return err;
554 }
555 53 break;
556
557 3290 case VVC_PREFIX_SEI_NUT:
558 case VVC_SUFFIX_SEI_NUT:
559 {
560 3290 err = cbs_h266_read_sei(ctx, &gbc, unit->content,
561 3290 unit->type == VVC_PREFIX_SEI_NUT);
562
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3290 times.
3290 if (err < 0)
564 return err;
565 }
566 3290 break;
567
568 default:
569 return AVERROR(ENOSYS);
570 }
571 15524 return 0;
572 }
573
574 5777 static int cbs_h266_write_nal_unit(CodedBitstreamContext *ctx,
575 CodedBitstreamUnit *unit,
576 PutBitContext *pbc)
577 {
578 int err;
579
580
10/11
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 335 times.
✓ Branch 4 taken 391 times.
✓ Branch 5 taken 228 times.
✓ Branch 6 taken 27 times.
✓ Branch 7 taken 2588 times.
✓ Branch 8 taken 12 times.
✓ Branch 9 taken 2190 times.
✗ Branch 10 not taken.
5777 switch (unit->type) {
581 1 case VVC_DCI_NUT:
582 {
583 1 H266RawDCI *dci = unit->content;
584
585 1 err = cbs_h266_write_dci(ctx, pbc, dci);
586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0)
587 return err;
588 }
589 1 break;
590 1 case VVC_OPI_NUT:
591 {
592 1 H266RawOPI *opi = unit->content;
593
594 1 err = cbs_h266_write_opi(ctx, pbc, opi);
595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0)
596 return err;
597 }
598 1 break;
599 4 case VVC_VPS_NUT:
600 {
601 4 H266RawVPS *vps = unit->content;
602
603 4 err = cbs_h266_write_vps(ctx, pbc, vps);
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
605 return err;
606
607 4 err = cbs_h266_replace_vps(ctx, unit);
608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err < 0)
609 return err;
610 }
611 4 break;
612 335 case VVC_SPS_NUT:
613 {
614 335 H266RawSPS *sps = unit->content;
615
616 335 err = cbs_h266_write_sps(ctx, pbc, sps);
617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 335 times.
335 if (err < 0)
618 return err;
619
620 335 err = cbs_h266_replace_sps(ctx, unit);
621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 335 times.
335 if (err < 0)
622 return err;
623 }
624 335 break;
625
626 391 case VVC_PPS_NUT:
627 {
628 391 H266RawPPS *pps = unit->content;
629
630 391 err = cbs_h266_write_pps(ctx, pbc, pps);
631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 391 times.
391 if (err < 0)
632 return err;
633
634 391 err = cbs_h266_replace_pps(ctx, unit);
635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 391 times.
391 if (err < 0)
636 return err;
637 }
638 391 break;
639
640 228 case VVC_PREFIX_APS_NUT:
641 case VVC_SUFFIX_APS_NUT:
642 {
643 228 err = cbs_h266_write_aps(ctx, pbc, unit->content,
644 228 unit->type == VVC_PREFIX_APS_NUT);
645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
228 if (err < 0)
646 return err;
647 }
648 228 break;
649 27 case VVC_PH_NUT:
650 {
651 27 H266RawPH *ph = unit->content;
652 27 err = cbs_h266_write_ph(ctx, pbc, ph);
653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (err < 0)
654 return err;
655
656 27 err = cbs_h266_replace_ph(ctx, unit, &ph->ph_picture_header);
657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (err < 0)
658 return err;
659 }
660 27 break;
661
662 2588 case VVC_TRAIL_NUT:
663 case VVC_STSA_NUT:
664 case VVC_RADL_NUT:
665 case VVC_RASL_NUT:
666 case VVC_IDR_W_RADL:
667 case VVC_IDR_N_LP:
668 case VVC_CRA_NUT:
669 case VVC_GDR_NUT:
670 {
671 2588 H266RawSlice *slice = unit->content;
672
673 2588 err = cbs_h266_write_slice_header(ctx, pbc, &slice->header);
674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2588 times.
2588 if (err < 0)
675 return err;
676
677
2/2
✓ Branch 0 taken 2103 times.
✓ Branch 1 taken 485 times.
2588 if (slice->header.sh_picture_header_in_slice_header_flag) {
678 2103 err = cbs_h266_replace_ph(ctx, unit, &slice->header.sh_picture_header);
679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2103 times.
2103 if (err < 0)
680 return err;
681 }
682
683
1/2
✓ Branch 0 taken 2588 times.
✗ Branch 1 not taken.
2588 if (slice->data) {
684 2588 err = ff_cbs_h2645_write_slice_data(ctx, pbc, slice->data,
685 slice->data_size,
686 slice->data_bit_start);
687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2588 times.
2588 if (err < 0)
688 return err;
689 } else {
690 // No slice data - that was just the header.
691 }
692 }
693 2588 break;
694
695 12 case VVC_AUD_NUT:
696 {
697 12 err = cbs_h266_write_aud(ctx, pbc, unit->content);
698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (err < 0)
699 return err;
700 }
701 12 break;
702
703 2190 case VVC_PREFIX_SEI_NUT:
704 case VVC_SUFFIX_SEI_NUT:
705 {
706 2190 err = cbs_h266_write_sei(ctx, pbc, unit->content,
707 2190 unit->type == VVC_PREFIX_SEI_NUT);
708
709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2190 times.
2190 if (err < 0)
710 return err;
711 }
712 2190 break;
713
714 default:
715 av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for "
716 "NAL unit type %"PRIu32".\n", unit->type);
717 return AVERROR_PATCHWELCOME;
718 }
719
720 5777 return 0;
721 }
722
723 212 static av_cold void cbs_h266_flush(CodedBitstreamContext *ctx)
724 {
725 212 CodedBitstreamH266Context *h266 = ctx->priv_data;
726
727
2/2
✓ Branch 0 taken 3392 times.
✓ Branch 1 taken 212 times.
3604 for (int i = 0; i < FF_ARRAY_ELEMS(h266->vps); i++)
728 3392 av_refstruct_unref(&h266->vps[i]);
729
2/2
✓ Branch 0 taken 3392 times.
✓ Branch 1 taken 212 times.
3604 for (int i = 0; i < FF_ARRAY_ELEMS(h266->sps); i++)
730 3392 av_refstruct_unref(&h266->sps[i]);
731
2/2
✓ Branch 0 taken 13568 times.
✓ Branch 1 taken 212 times.
13780 for (int i = 0; i < FF_ARRAY_ELEMS(h266->pps); i++)
732 13568 av_refstruct_unref(&h266->pps[i]);
733 212 av_refstruct_unref(&h266->ph_ref);
734 212 }
735
736 212 static av_cold void cbs_h266_close(CodedBitstreamContext *ctx)
737 {
738 212 CodedBitstreamH266Context *h266 = ctx->priv_data;
739
740 212 cbs_h266_flush(ctx);
741 212 ff_h2645_packet_uninit(&h266->common.read_packet);
742 212 }
743
744 8823 static void cbs_h266_free_slice(AVRefStructOpaque unused, void *content)
745 {
746 8823 H266RawSlice *slice = content;
747 8823 av_buffer_unref(&slice->data_ref);
748 8823 av_refstruct_unref(&slice->sps);
749 8823 av_refstruct_unref(&slice->pps);
750 8823 av_refstruct_unref(&slice->ph_ref);
751 8823 }
752
753
754 3290 static void cbs_h266_free_sei(AVRefStructOpaque unused, void *content)
755 {
756 3290 H266RawSEI *sei = content;
757 3290 ff_cbs_sei_free_message_list(&sei->message_list);
758 3290 }
759
760 static CodedBitstreamUnitTypeDescriptor cbs_h266_unit_types[] = {
761 CBS_UNIT_TYPE_INTERNAL_REF(VVC_DCI_NUT, H266RawDCI, extension_data.data),
762 CBS_UNIT_TYPE_INTERNAL_REF(VVC_OPI_NUT, H266RawOPI, extension_data.data),
763 CBS_UNIT_TYPE_INTERNAL_REF(VVC_VPS_NUT, H266RawVPS, extension_data.data),
764 {
765 .nb_unit_types = 1,
766 .unit_type.list[0] = VVC_SPS_NUT,
767 .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS,
768 .content_size = sizeof(H266RawSPS),
769 .type.ref = {
770 .nb_offsets = 2,
771 .offsets = { offsetof(H266RawSPS, extension_data.data),
772 offsetof(H266RawSPS, vui.extension_data.data) }
773 },
774 },
775 CBS_UNIT_TYPE_INTERNAL_REF(VVC_PPS_NUT, H266RawPPS, extension_data.data),
776 CBS_UNIT_TYPE_INTERNAL_REF(VVC_PREFIX_APS_NUT, H266RawAPS, extension_data.data),
777 CBS_UNIT_TYPE_INTERNAL_REF(VVC_SUFFIX_APS_NUT, H266RawAPS, extension_data.data),
778
779 CBS_UNIT_TYPE_POD(VVC_PH_NUT , H266RawPH),
780 CBS_UNIT_TYPE_POD(VVC_AUD_NUT, H266RawAUD),
781
782 CBS_UNIT_TYPES_COMPLEX((VVC_TRAIL_NUT, VVC_STSA_NUT, VVC_RADL_NUT),
783 H266RawSlice, cbs_h266_free_slice),
784 CBS_UNIT_TYPES_COMPLEX((VVC_RASL_NUT, VVC_IDR_W_RADL, VVC_IDR_N_LP),
785 H266RawSlice, cbs_h266_free_slice),
786 CBS_UNIT_TYPES_COMPLEX((VVC_CRA_NUT, VVC_GDR_NUT),
787 H266RawSlice, cbs_h266_free_slice),
788
789 CBS_UNIT_TYPES_COMPLEX((VVC_PREFIX_SEI_NUT, VVC_SUFFIX_SEI_NUT),
790 H266RawSEI, cbs_h266_free_sei),
791
792 CBS_UNIT_TYPE_END_OF_LIST
793 };
794
795 const CodedBitstreamType ff_cbs_type_h266 = {
796 .codec_id = AV_CODEC_ID_VVC,
797
798 .priv_data_size = sizeof(CodedBitstreamH266Context),
799
800 .unit_types = cbs_h266_unit_types,
801
802 .split_fragment = &cbs_h266_split_fragment,
803 .read_unit = &cbs_h266_read_nal_unit,
804 .write_unit = &cbs_h266_write_nal_unit,
805 .assemble_fragment = &ff_cbs_h2645_assemble_fragment,
806
807 .flush = &cbs_h266_flush,
808 .close = &cbs_h266_close,
809 };
810