FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/cbs.c
Date: 2025-04-22 22:59:17
Exec Total Coverage
Lines: 407 494 82.4%
Functions: 46 66 69.7%
Branches: 204 335 60.9%

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 <string.h>
20
21 #include "libavutil/avassert.h"
22 #include "libavutil/buffer.h"
23 #include "libavutil/common.h"
24 #include "libavutil/mem.h"
25 #include "libavutil/opt.h"
26
27 #include "avcodec.h"
28 #include "cbs.h"
29 #include "cbs_internal.h"
30 #include "libavutil/refstruct.h"
31
32
33 static const CodedBitstreamType *const cbs_type_table[] = {
34 #if CBS_AV1
35 &CBS_FUNC(type_av1),
36 #endif
37 #if CBS_H264
38 &CBS_FUNC(type_h264),
39 #endif
40 #if CBS_H265
41 &CBS_FUNC(type_h265),
42 #endif
43 #if CBS_H266
44 &CBS_FUNC(type_h266),
45 #endif
46 #if CBS_JPEG
47 &CBS_FUNC(type_jpeg),
48 #endif
49 #if CBS_MPEG2
50 &CBS_FUNC(type_mpeg2),
51 #endif
52 #if CBS_VP8
53 &CBS_FUNC(type_vp8),
54 #endif
55 #if CBS_VP9
56 &CBS_FUNC(type_vp9),
57 #endif
58 };
59
60 const enum AVCodecID CBS_FUNC(all_codec_ids)[] = {
61 #if CBS_AV1
62 AV_CODEC_ID_AV1,
63 #endif
64 #if CBS_H264
65 AV_CODEC_ID_H264,
66 #endif
67 #if CBS_H265
68 AV_CODEC_ID_H265,
69 #endif
70 #if CBS_H266
71 AV_CODEC_ID_H266,
72 #endif
73 #if CBS_JPEG
74 AV_CODEC_ID_MJPEG,
75 #endif
76 #if CBS_MPEG2
77 AV_CODEC_ID_MPEG2VIDEO,
78 #endif
79 #if CBS_VP8
80 AV_CODEC_ID_VP8,
81 #endif
82 #if CBS_VP9
83 AV_CODEC_ID_VP9,
84 #endif
85 AV_CODEC_ID_NONE
86 };
87
88 415 av_cold int CBS_FUNC(init)(CodedBitstreamContext **ctx_ptr,
89 enum AVCodecID codec_id, void *log_ctx)
90 {
91 CodedBitstreamContext *ctx;
92 const CodedBitstreamType *type;
93 int i;
94
95 415 type = NULL;
96
1/2
✓ Branch 0 taken 1371 times.
✗ Branch 1 not taken.
1371 for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) {
97
2/2
✓ Branch 0 taken 415 times.
✓ Branch 1 taken 956 times.
1371 if (cbs_type_table[i]->codec_id == codec_id) {
98 415 type = cbs_type_table[i];
99 415 break;
100 }
101 }
102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 415 times.
415 if (!type)
103 return AVERROR(EINVAL);
104
105 415 ctx = av_mallocz(sizeof(*ctx));
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 415 times.
415 if (!ctx)
107 return AVERROR(ENOMEM);
108
109 415 ctx->log_ctx = log_ctx;
110 415 ctx->codec = type; /* Must be before any error */
111
112
1/2
✓ Branch 0 taken 415 times.
✗ Branch 1 not taken.
415 if (type->priv_data_size) {
113 415 ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 415 times.
415 if (!ctx->priv_data) {
115 av_freep(&ctx);
116 return AVERROR(ENOMEM);
117 }
118
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 322 times.
415 if (type->priv_class) {
119 93 *(const AVClass **)ctx->priv_data = type->priv_class;
120 93 av_opt_set_defaults(ctx->priv_data);
121 }
122 }
123
124 415 ctx->decompose_unit_types = NULL;
125
126 415 ctx->trace_enable = 0;
127 415 ctx->trace_level = AV_LOG_TRACE;
128 415 ctx->trace_context = ctx;
129
130 415 *ctx_ptr = ctx;
131 415 return 0;
132 }
133
134 1 av_cold void CBS_FUNC(flush)(CodedBitstreamContext *ctx)
135 {
136
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ctx->codec->flush)
137 1 ctx->codec->flush(ctx);
138 1 }
139
140 691 av_cold void CBS_FUNC(close)(CodedBitstreamContext **ctx_ptr)
141 {
142 691 CodedBitstreamContext *ctx = *ctx_ptr;
143
144
2/2
✓ Branch 0 taken 276 times.
✓ Branch 1 taken 415 times.
691 if (!ctx)
145 276 return;
146
147
2/2
✓ Branch 0 taken 381 times.
✓ Branch 1 taken 34 times.
415 if (ctx->codec->close)
148 381 ctx->codec->close(ctx);
149
150 415 av_freep(&ctx->write_buffer);
151
152
3/4
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 322 times.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
415 if (ctx->codec->priv_class && ctx->priv_data)
153 93 av_opt_free(ctx->priv_data);
154
155 415 av_freep(&ctx->priv_data);
156 415 av_freep(ctx_ptr);
157 }
158
159 49467 static void cbs_unit_uninit(CodedBitstreamUnit *unit)
160 {
161 49467 av_refstruct_unref(&unit->content_ref);
162 49467 unit->content = NULL;
163
164 49467 av_buffer_unref(&unit->data_ref);
165 49467 unit->data = NULL;
166 49467 unit->data_size = 0;
167 49467 unit->data_bit_padding = 0;
168 49467 }
169
170 14445 void CBS_FUNC(fragment_reset)(CodedBitstreamFragment *frag)
171 {
172 int i;
173
174
2/2
✓ Branch 0 taken 49395 times.
✓ Branch 1 taken 14445 times.
63840 for (i = 0; i < frag->nb_units; i++)
175 49395 cbs_unit_uninit(&frag->units[i]);
176 14445 frag->nb_units = 0;
177
178 14445 av_buffer_unref(&frag->data_ref);
179 14445 frag->data = NULL;
180 14445 frag->data_size = 0;
181 14445 frag->data_bit_padding = 0;
182 14445 }
183
184 1154 av_cold void CBS_FUNC(fragment_free)(CodedBitstreamFragment *frag)
185 {
186 1154 CBS_FUNC(fragment_reset)(frag);
187
188 1154 av_freep(&frag->units);
189 1154 frag->nb_units_allocated = 0;
190 1154 }
191
192 #if CBS_READ
193 13306 static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
194 CodedBitstreamFragment *frag)
195 {
196 int err, i, j;
197
198
2/2
✓ Branch 0 taken 49454 times.
✓ Branch 1 taken 13305 times.
62759 for (i = 0; i < frag->nb_units; i++) {
199 49454 CodedBitstreamUnit *unit = &frag->units[i];
200
201
2/2
✓ Branch 0 taken 11244 times.
✓ Branch 1 taken 38210 times.
49454 if (ctx->decompose_unit_types) {
202
2/2
✓ Branch 0 taken 78016 times.
✓ Branch 1 taken 3726 times.
81742 for (j = 0; j < ctx->nb_decompose_unit_types; j++) {
203
2/2
✓ Branch 0 taken 7518 times.
✓ Branch 1 taken 70498 times.
78016 if (ctx->decompose_unit_types[j] == unit->type)
204 7518 break;
205 }
206
2/2
✓ Branch 0 taken 3726 times.
✓ Branch 1 taken 7518 times.
11244 if (j >= ctx->nb_decompose_unit_types)
207 3726 continue;
208 }
209
210 45728 av_refstruct_unref(&unit->content_ref);
211 45728 unit->content = NULL;
212
213
2/4
✓ Branch 0 taken 45728 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 45728 times.
45728 av_assert0(unit->data && unit->data_ref);
214
215 45728 err = ctx->codec->read_unit(ctx, unit);
216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45728 times.
45728 if (err == AVERROR(ENOSYS)) {
217 av_log(ctx->log_ctx, AV_LOG_VERBOSE,
218 "Decomposition unimplemented for unit %d "
219 "(type %"PRIu32").\n", i, unit->type);
220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45728 times.
45728 } else if (err == AVERROR(EAGAIN)) {
221 av_log(ctx->log_ctx, AV_LOG_VERBOSE,
222 "Skipping decomposition of unit %d "
223 "(type %"PRIu32").\n", i, unit->type);
224 av_refstruct_unref(&unit->content_ref);
225 unit->content = NULL;
226
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 45727 times.
45728 } else if (err < 0) {
227 1 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
228 "(type %"PRIu32").\n", i, unit->type);
229 1 return err;
230 }
231 }
232
233 13305 return 0;
234 }
235
236 3963 static int cbs_fill_fragment_data(CodedBitstreamFragment *frag,
237 const uint8_t *data, size_t size)
238 {
239
2/4
✓ Branch 0 taken 3963 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3963 times.
3963 av_assert0(!frag->data && !frag->data_ref);
240
241 3963 frag->data_ref =
242 3963 av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3963 times.
3963 if (!frag->data_ref)
244 return AVERROR(ENOMEM);
245
246 3963 frag->data = frag->data_ref->data;
247 3963 frag->data_size = size;
248
249 3963 memcpy(frag->data, data, size);
250 3963 memset(frag->data + size, 0,
251 AV_INPUT_BUFFER_PADDING_SIZE);
252
253 3963 return 0;
254 }
255
256 13306 static int cbs_read_data(CodedBitstreamContext *ctx,
257 CodedBitstreamFragment *frag,
258 AVBufferRef *buf,
259 const uint8_t *data, size_t size,
260 int header)
261 {
262 int err;
263
264
2/2
✓ Branch 0 taken 9343 times.
✓ Branch 1 taken 3963 times.
13306 if (buf) {
265 9343 frag->data_ref = av_buffer_ref(buf);
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9343 times.
9343 if (!frag->data_ref)
267 return AVERROR(ENOMEM);
268
269 9343 frag->data = (uint8_t *)data;
270 9343 frag->data_size = size;
271
272 } else {
273 3963 err = cbs_fill_fragment_data(frag, data, size);
274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3963 times.
3963 if (err < 0)
275 return err;
276 }
277
278 13306 err = ctx->codec->split_fragment(ctx, frag, header);
279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13306 times.
13306 if (err < 0)
280 return err;
281
282 13306 return cbs_read_fragment_content(ctx, frag);
283 }
284
285 94 int CBS_FUNC(read_extradata)(CodedBitstreamContext *ctx,
286 CodedBitstreamFragment *frag,
287 const AVCodecParameters *par)
288 {
289 188 return cbs_read_data(ctx, frag, NULL,
290 94 par->extradata,
291 94 par->extradata_size, 1);
292 }
293
294 124 int CBS_FUNC(read_extradata_from_codec)(CodedBitstreamContext *ctx,
295 CodedBitstreamFragment *frag,
296 const AVCodecContext *avctx)
297 {
298 248 return cbs_read_data(ctx, frag, NULL,
299 124 avctx->extradata,
300 124 avctx->extradata_size, 1);
301 }
302
303 9343 int CBS_FUNC(read_packet)(CodedBitstreamContext *ctx,
304 CodedBitstreamFragment *frag,
305 const AVPacket *pkt)
306 {
307 18686 return cbs_read_data(ctx, frag, pkt->buf,
308 9343 pkt->data, pkt->size, 0);
309 }
310
311 2 int CBS_FUNC(read_packet_side_data)(CodedBitstreamContext *ctx,
312 CodedBitstreamFragment *frag,
313 const AVPacket *pkt)
314 {
315 size_t side_data_size;
316 const uint8_t *side_data =
317 2 av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
318 &side_data_size);
319
320 2 return cbs_read_data(ctx, frag, NULL,
321 side_data, side_data_size, 1);
322 }
323
324 3743 int CBS_FUNC(read)(CodedBitstreamContext *ctx,
325 CodedBitstreamFragment *frag,
326 const uint8_t *data, size_t size)
327 {
328 3743 return cbs_read_data(ctx, frag, NULL,
329 data, size, 0);
330 }
331 #endif
332
333 #if CBS_WRITE
334 /**
335 * Allocate a new internal data buffer of the given size in the unit.
336 *
337 * The data buffer will have input padding.
338 */
339 31837 static int cbs_alloc_unit_data(CodedBitstreamUnit *unit,
340 size_t size)
341 {
342
2/4
✓ Branch 0 taken 31837 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 31837 times.
31837 av_assert0(!unit->data && !unit->data_ref);
343
344 31837 unit->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31837 times.
31837 if (!unit->data_ref)
346 return AVERROR(ENOMEM);
347
348 31837 unit->data = unit->data_ref->data;
349 31837 unit->data_size = size;
350
351 31837 memset(unit->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
352
353 31837 return 0;
354 }
355
356 31837 static int cbs_write_unit_data(CodedBitstreamContext *ctx,
357 CodedBitstreamUnit *unit)
358 {
359 PutBitContext pbc;
360 int ret;
361
362
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 31729 times.
31837 if (!ctx->write_buffer) {
363 // Initial write buffer size is 1MB.
364 108 ctx->write_buffer_size = 1024 * 1024;
365
366 108 reallocate_and_try_again:
367 108 ret = av_reallocp(&ctx->write_buffer, ctx->write_buffer_size);
368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (ret < 0) {
369 av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a "
370 "sufficiently large write buffer (last attempt "
371 "%"SIZE_SPECIFIER" bytes).\n", ctx->write_buffer_size);
372 return ret;
373 }
374 }
375
376 31837 init_put_bits(&pbc, ctx->write_buffer, ctx->write_buffer_size);
377
378 31837 ret = ctx->codec->write_unit(ctx, unit, &pbc);
379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31837 times.
31837 if (ret < 0) {
380 if (ret == AVERROR(ENOSPC)) {
381 // Overflow.
382 if (ctx->write_buffer_size == INT_MAX / 8)
383 return AVERROR(ENOMEM);
384 ctx->write_buffer_size = FFMIN(2 * ctx->write_buffer_size, INT_MAX / 8);
385 goto reallocate_and_try_again;
386 }
387 // Write failed for some other reason.
388 return ret;
389 }
390
391 // Overflow but we didn't notice.
392
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31837 times.
31837 av_assert0(put_bits_count(&pbc) <= 8 * ctx->write_buffer_size);
393
394
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 31785 times.
31837 if (put_bits_count(&pbc) % 8)
395 52 unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8;
396 else
397 31785 unit->data_bit_padding = 0;
398
399 31837 flush_put_bits(&pbc);
400
401 31837 ret = cbs_alloc_unit_data(unit, put_bytes_output(&pbc));
402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31837 times.
31837 if (ret < 0)
403 return ret;
404
405 31837 memcpy(unit->data, ctx->write_buffer, unit->data_size);
406
407 31837 return 0;
408 }
409
410 7801 int CBS_FUNC(write_fragment_data)(CodedBitstreamContext *ctx,
411 CodedBitstreamFragment *frag)
412 {
413 int err, i;
414
415
2/2
✓ Branch 0 taken 31837 times.
✓ Branch 1 taken 7801 times.
39638 for (i = 0; i < frag->nb_units; i++) {
416 31837 CodedBitstreamUnit *unit = &frag->units[i];
417
418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31837 times.
31837 if (!unit->content)
419 continue;
420
421 31837 av_buffer_unref(&unit->data_ref);
422 31837 unit->data = NULL;
423
424 31837 err = cbs_write_unit_data(ctx, unit);
425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31837 times.
31837 if (err < 0) {
426 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
427 "(type %"PRIu32").\n", i, unit->type);
428 return err;
429 }
430
2/4
✓ Branch 0 taken 31837 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 31837 times.
31837 av_assert0(unit->data && unit->data_ref);
431 }
432
433 7801 av_buffer_unref(&frag->data_ref);
434 7801 frag->data = NULL;
435
436 7801 err = ctx->codec->assemble_fragment(ctx, frag);
437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7801 times.
7801 if (err < 0) {
438 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
439 return err;
440 }
441
2/4
✓ Branch 0 taken 7801 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7801 times.
7801 av_assert0(frag->data && frag->data_ref);
442
443 7801 return 0;
444 }
445
446 93 int CBS_FUNC(write_extradata)(CodedBitstreamContext *ctx,
447 AVCodecParameters *par,
448 CodedBitstreamFragment *frag)
449 {
450 int err;
451
452 93 err = CBS_FUNC(write_fragment_data)(ctx, frag);
453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if (err < 0)
454 return err;
455
456 93 av_freep(&par->extradata);
457 93 par->extradata_size = 0;
458
459
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 92 times.
93 if (!frag->data_size)
460 1 return 0;
461
462 92 par->extradata = av_malloc(frag->data_size +
463 AV_INPUT_BUFFER_PADDING_SIZE);
464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
92 if (!par->extradata)
465 return AVERROR(ENOMEM);
466
467 92 memcpy(par->extradata, frag->data, frag->data_size);
468 92 memset(par->extradata + frag->data_size, 0,
469 AV_INPUT_BUFFER_PADDING_SIZE);
470 92 par->extradata_size = frag->data_size;
471
472 92 return 0;
473 }
474
475 7706 int CBS_FUNC(write_packet)(CodedBitstreamContext *ctx,
476 AVPacket *pkt,
477 CodedBitstreamFragment *frag)
478 {
479 AVBufferRef *buf;
480 int err;
481
482 7706 err = CBS_FUNC(write_fragment_data)(ctx, frag);
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7706 times.
7706 if (err < 0)
484 return err;
485
486 7706 buf = av_buffer_ref(frag->data_ref);
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7706 times.
7706 if (!buf)
488 return AVERROR(ENOMEM);
489
490 7706 av_buffer_unref(&pkt->buf);
491
492 7706 pkt->buf = buf;
493 7706 pkt->data = frag->data;
494 7706 pkt->size = frag->data_size;
495
496 7706 return 0;
497 }
498 #endif
499
500
501 100029 void CBS_FUNC(trace_header)(CodedBitstreamContext *ctx,
502 const char *name)
503 {
504 #if CBS_TRACE
505
2/2
✓ Branch 0 taken 63377 times.
✓ Branch 1 taken 36652 times.
100029 if (!ctx->trace_enable)
506 63377 return;
507
508 36652 av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
509 #endif
510 }
511
512 967438 void CBS_FUNC(trace_read_log)(void *trace_context,
513 GetBitContext *gbc, int length,
514 const char *str, const int *subscripts,
515 int64_t value)
516 {
517 #if CBS_TRACE
518 967438 CodedBitstreamContext *ctx = trace_context;
519 char name[256];
520 char bits[256];
521 size_t name_len, bits_len;
522 int pad, subs, i, j, k, n;
523 int position;
524
525
2/4
✓ Branch 0 taken 967438 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 967438 times.
967438 av_assert0(value >= INT_MIN && value <= UINT32_MAX);
526
527 967438 position = get_bits_count(gbc);
528
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 967438 times.
967438 av_assert0(length < 256);
530
2/2
✓ Branch 0 taken 3682132 times.
✓ Branch 1 taken 967438 times.
4649570 for (i = 0; i < length; i++)
531
2/2
✓ Branch 1 taken 1426487 times.
✓ Branch 2 taken 2255645 times.
3682132 bits[i] = get_bits1(gbc) ? '1' : '0';
532 967438 bits[length] = 0;
533
534
2/2
✓ Branch 0 taken 389981 times.
✓ Branch 1 taken 577457 times.
967438 subs = subscripts ? subscripts[0] : 0;
535 967438 n = 0;
536
2/2
✓ Branch 0 taken 21340813 times.
✓ Branch 1 taken 967438 times.
22308251 for (i = j = 0; str[i];) {
537
2/2
✓ Branch 0 taken 690056 times.
✓ Branch 1 taken 20650757 times.
21340813 if (str[i] == '[') {
538
2/2
✓ Branch 0 taken 688399 times.
✓ Branch 1 taken 1657 times.
690056 if (n < subs) {
539 688399 ++n;
540 688399 k = snprintf(name + j, sizeof(name) - j, "[%d", subscripts[n]);
541
2/4
✓ Branch 0 taken 688399 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 688399 times.
688399 av_assert0(k > 0 && j + k < sizeof(name));
542 688399 j += k;
543
3/4
✓ Branch 0 taken 2578767 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1890368 times.
✓ Branch 3 taken 688399 times.
2578767 for (++i; str[i] && str[i] != ']'; i++);
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 688399 times.
688399 av_assert0(str[i] == ']');
545 } else {
546
3/4
✓ Branch 0 taken 4971 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3314 times.
✓ Branch 3 taken 1657 times.
4971 while (str[i] && str[i] != ']')
547 3314 name[j++] = str[i++];
548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1657 times.
1657 av_assert0(str[i] == ']');
549 }
550 } else {
551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20650757 times.
20650757 av_assert0(j + 1 < sizeof(name));
552 20650757 name[j++] = str[i++];
553 }
554 }
555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 967438 times.
967438 av_assert0(j + 1 < sizeof(name));
556 967438 name[j] = 0;
557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 967438 times.
967438 av_assert0(n == subs);
558
559 967438 name_len = strlen(name);
560 967438 bits_len = length;
561
562
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 967424 times.
967438 if (name_len + bits_len > 60)
563 14 pad = bits_len + 2;
564 else
565 967424 pad = 61 - name_len;
566
567 967438 av_log(ctx->log_ctx, ctx->trace_level, "%-10d %s%*s = %"PRId64"\n",
568 position, name, pad, bits, value);
569 #endif
570 967438 }
571
572 967438 void CBS_FUNC(trace_write_log)(void *trace_context,
573 PutBitContext *pbc, int length,
574 const char *str, const int *subscripts,
575 int64_t value)
576 {
577 #if CBS_TRACE
578 967438 CodedBitstreamContext *ctx = trace_context;
579
580 // Ensure that the syntax element is written to the output buffer,
581 // make a GetBitContext pointed at the start position, then call the
582 // read log function which can read the bits back to log them.
583
584 GetBitContext gbc;
585 int position;
586
587
2/2
✓ Branch 0 taken 967199 times.
✓ Branch 1 taken 239 times.
967438 if (length > 0) {
588 PutBitContext flush;
589 967199 flush = *pbc;
590 967199 flush_put_bits(&flush);
591 }
592
593 967438 position = put_bits_count(pbc);
594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 967438 times.
967438 av_assert0(position >= length);
595
596 967438 init_get_bits(&gbc, pbc->buf, position);
597
598 967438 skip_bits_long(&gbc, position - length);
599
600 967438 CBS_FUNC(trace_read_log)(ctx, &gbc, length, str, subscripts, value);
601 #endif
602 967438 }
603
604 #if CBS_READ
605 2308390 static av_always_inline int cbs_read_unsigned(CodedBitstreamContext *ctx,
606 GetBitContext *gbc,
607 int width, const char *name,
608 const int *subscripts,
609 uint32_t *write_to,
610 uint32_t range_min,
611 uint32_t range_max)
612 {
613 uint32_t value;
614
615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2308390 times.
2308390 CBS_TRACE_READ_START();
616
617
2/4
✓ Branch 0 taken 2308390 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2308390 times.
2308390 av_assert0(width > 0 && width <= 32);
618
619
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2308389 times.
2308390 if (get_bits_left(gbc) < width) {
620 1 av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
621 "%s: bitstream ended.\n", name);
622 1 return AVERROR_INVALIDDATA;
623 }
624
625 2308389 value = get_bits_long(gbc, width);
626
627
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2308389 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2308389 CBS_TRACE_READ_END();
628
629
2/4
✓ Branch 0 taken 2308389 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2308389 times.
2308389 if (value < range_min || value > range_max) {
630 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
631 "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
632 name, value, range_min, range_max);
633 return AVERROR_INVALIDDATA;
634 }
635
636 2308389 *write_to = value;
637 2308389 return 0;
638 }
639
640 1785754 int CBS_FUNC(read_unsigned)(CodedBitstreamContext *ctx, GetBitContext *gbc,
641 int width, const char *name,
642 const int *subscripts, uint32_t *write_to,
643 uint32_t range_min, uint32_t range_max)
644 {
645 1785754 return cbs_read_unsigned(ctx, gbc, width, name, subscripts,
646 write_to, range_min, range_max);
647 }
648
649 522636 int CBS_FUNC(read_simple_unsigned)(CodedBitstreamContext *ctx, GetBitContext *gbc,
650 int width, const char *name, uint32_t *write_to)
651 {
652 522636 return cbs_read_unsigned(ctx, gbc, width, name, NULL,
653 write_to, 0, UINT32_MAX);
654 }
655 #endif
656
657 #if CBS_WRITE
658 936431 int CBS_FUNC(write_unsigned)(CodedBitstreamContext *ctx, PutBitContext *pbc,
659 int width, const char *name,
660 const int *subscripts, uint32_t value,
661 uint32_t range_min, uint32_t range_max)
662 {
663
2/2
✓ Branch 0 taken 729264 times.
✓ Branch 1 taken 207167 times.
936431 CBS_TRACE_WRITE_START();
664
665
2/4
✓ Branch 0 taken 936431 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 936431 times.
936431 av_assert0(width > 0 && width <= 32);
666
667
2/4
✓ Branch 0 taken 936431 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 936431 times.
936431 if (value < range_min || value > range_max) {
668 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
669 "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
670 name, value, range_min, range_max);
671 return AVERROR_INVALIDDATA;
672 }
673
674
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 936431 times.
936431 if (put_bits_left(pbc) < width)
675 return AVERROR(ENOSPC);
676
677
2/2
✓ Branch 0 taken 935451 times.
✓ Branch 1 taken 980 times.
936431 if (width < 32)
678 935451 put_bits(pbc, width, value);
679 else
680 980 put_bits32(pbc, value);
681
682
3/4
✓ Branch 0 taken 729264 times.
✓ Branch 1 taken 207167 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 729264 times.
936431 CBS_TRACE_WRITE_END();
683
684 936431 return 0;
685 }
686
687 266171 int CBS_FUNC(write_simple_unsigned)(CodedBitstreamContext *ctx, PutBitContext *pbc,
688 int width, const char *name, uint32_t value)
689 {
690 532342 return CBS_FUNC(write_unsigned)(ctx, pbc, width, name, NULL,
691 266171 value, 0, MAX_UINT_BITS(width));
692 }
693 #endif
694
695 #if CBS_READ
696 50 int CBS_FUNC(read_signed)(CodedBitstreamContext *ctx, GetBitContext *gbc,
697 int width, const char *name,
698 const int *subscripts, int32_t *write_to,
699 int32_t range_min, int32_t range_max)
700 {
701 int32_t value;
702
703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 CBS_TRACE_READ_START();
704
705
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
50 av_assert0(width > 0 && width <= 32);
706
707
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 if (get_bits_left(gbc) < width) {
708 av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
709 "%s: bitstream ended.\n", name);
710 return AVERROR_INVALIDDATA;
711 }
712
713 50 value = get_sbits_long(gbc, width);
714
715
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
50 CBS_TRACE_READ_END();
716
717
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
50 if (value < range_min || value > range_max) {
718 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
719 "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
720 name, value, range_min, range_max);
721 return AVERROR_INVALIDDATA;
722 }
723
724 50 *write_to = value;
725 50 return 0;
726 }
727 #endif
728
729 #if CBS_WRITE
730 50 int CBS_FUNC(write_signed)(CodedBitstreamContext *ctx, PutBitContext *pbc,
731 int width, const char *name,
732 const int *subscripts, int32_t value,
733 int32_t range_min, int32_t range_max)
734 {
735
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 CBS_TRACE_WRITE_START();
736
737
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
50 av_assert0(width > 0 && width <= 32);
738
739
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
50 if (value < range_min || value > range_max) {
740 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
741 "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
742 name, value, range_min, range_max);
743 return AVERROR_INVALIDDATA;
744 }
745
746
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 if (put_bits_left(pbc) < width)
747 return AVERROR(ENOSPC);
748
749
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if (width < 32)
750 50 put_sbits(pbc, width, value);
751 else
752 put_bits32(pbc, value);
753
754
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
50 CBS_TRACE_WRITE_END();
755
756 50 return 0;
757 }
758 #endif
759
760
761 49467 static int cbs_insert_unit(CodedBitstreamFragment *frag,
762 int position)
763 {
764 CodedBitstreamUnit *units;
765
766
2/2
✓ Branch 0 taken 47153 times.
✓ Branch 1 taken 2314 times.
49467 if (frag->nb_units < frag->nb_units_allocated) {
767 47153 units = frag->units;
768
769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47153 times.
47153 if (position < frag->nb_units)
770 memmove(units + position + 1, units + position,
771 (frag->nb_units - position) * sizeof(*units));
772 } else {
773 2314 units = av_malloc_array(frag->nb_units*2 + 1, sizeof(*units));
774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2314 times.
2314 if (!units)
775 return AVERROR(ENOMEM);
776
777 2314 frag->nb_units_allocated = 2*frag->nb_units_allocated + 1;
778
779
2/2
✓ Branch 0 taken 1445 times.
✓ Branch 1 taken 869 times.
2314 if (position > 0)
780 1445 memcpy(units, frag->units, position * sizeof(*units));
781
782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2314 times.
2314 if (position < frag->nb_units)
783 memcpy(units + position + 1, frag->units + position,
784 (frag->nb_units - position) * sizeof(*units));
785 }
786
787 49467 memset(units + position, 0, sizeof(*units));
788
789
2/2
✓ Branch 0 taken 2314 times.
✓ Branch 1 taken 47153 times.
49467 if (units != frag->units) {
790 2314 av_free(frag->units);
791 2314 frag->units = units;
792 }
793
794 49467 ++frag->nb_units;
795
796 49467 return 0;
797 }
798
799 13 int CBS_FUNC(insert_unit_content)(CodedBitstreamFragment *frag,
800 int position,
801 CodedBitstreamUnitType type,
802 void *content,
803 void *content_ref)
804 {
805 CodedBitstreamUnit *unit;
806 int err;
807
808
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (position == -1)
809 13 position = frag->nb_units;
810
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 av_assert0(position >= 0 && position <= frag->nb_units);
811
812 13 err = cbs_insert_unit(frag, position);
813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (err < 0)
814 return err;
815
816
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (content_ref) {
817 // Create our own reference out of the user-supplied one.
818 13 content_ref = av_refstruct_ref(content_ref);
819 }
820
821 13 unit = &frag->units[position];
822 13 unit->type = type;
823 13 unit->content = content;
824 13 unit->content_ref = content_ref;
825
826 13 return 0;
827 }
828
829 49454 static int cbs_insert_unit_data(CodedBitstreamFragment *frag,
830 CodedBitstreamUnitType type,
831 uint8_t *data, size_t data_size,
832 AVBufferRef *data_buf,
833 int position)
834 {
835 CodedBitstreamUnit *unit;
836 AVBufferRef *data_ref;
837 int err;
838
839
2/4
✓ Branch 0 taken 49454 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49454 times.
49454 av_assert0(position >= 0 && position <= frag->nb_units);
840
841
1/2
✓ Branch 0 taken 49454 times.
✗ Branch 1 not taken.
49454 if (data_buf)
842 49454 data_ref = av_buffer_ref(data_buf);
843 else
844 data_ref = av_buffer_create(data, data_size, NULL, NULL, 0);
845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49454 times.
49454 if (!data_ref) {
846 if (!data_buf)
847 av_free(data);
848 return AVERROR(ENOMEM);
849 }
850
851 49454 err = cbs_insert_unit(frag, position);
852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49454 times.
49454 if (err < 0) {
853 av_buffer_unref(&data_ref);
854 return err;
855 }
856
857 49454 unit = &frag->units[position];
858 49454 unit->type = type;
859 49454 unit->data = data;
860 49454 unit->data_size = data_size;
861 49454 unit->data_ref = data_ref;
862
863 49454 return 0;
864 }
865
866 49454 int CBS_FUNC(append_unit_data)(CodedBitstreamFragment *frag,
867 CodedBitstreamUnitType type,
868 uint8_t *data, size_t data_size,
869 AVBufferRef *data_buf)
870 {
871 49454 return cbs_insert_unit_data(frag, type,
872 data, data_size, data_buf,
873 frag->nb_units);
874 }
875
876 72 void CBS_FUNC(delete_unit)(CodedBitstreamFragment *frag,
877 int position)
878 {
879
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
72 av_assert0(0 <= position && position < frag->nb_units
880 && "Unit to be deleted not in fragment.");
881
882 72 cbs_unit_uninit(&frag->units[position]);
883
884 72 --frag->nb_units;
885
886
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (frag->nb_units > 0)
887 72 memmove(frag->units + position,
888 72 frag->units + position + 1,
889 72 (frag->nb_units - position) * sizeof(*frag->units));
890 72 }
891
892 40218 static void cbs_default_free_unit_content(AVRefStructOpaque opaque, void *content)
893 {
894 40218 const CodedBitstreamUnitTypeDescriptor *desc = opaque.c;
895
896
2/2
✓ Branch 0 taken 48172 times.
✓ Branch 1 taken 40218 times.
88390 for (int i = 0; i < desc->type.ref.nb_offsets; i++) {
897 48172 void **ptr = (void**)((char*)content + desc->type.ref.offsets[i]);
898 48172 av_buffer_unref((AVBufferRef**)(ptr + 1));
899 }
900 40218 }
901
902 static const CodedBitstreamUnitTypeDescriptor
903 46035 *cbs_find_unit_type_desc(CodedBitstreamContext *ctx,
904 CodedBitstreamUnit *unit)
905 {
906 const CodedBitstreamUnitTypeDescriptor *desc;
907 int i, j;
908
909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46035 times.
46035 if (!ctx->codec->unit_types)
910 return NULL;
911
912 270872 for (i = 0;; i++) {
913 270872 desc = &ctx->codec->unit_types[i];
914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 270872 times.
270872 if (desc->nb_unit_types == 0)
915 break;
916
2/2
✓ Branch 0 taken 35795 times.
✓ Branch 1 taken 235077 times.
270872 if (desc->nb_unit_types == CBS_UNIT_TYPE_RANGE) {
917
1/2
✓ Branch 0 taken 35795 times.
✗ Branch 1 not taken.
35795 if (unit->type >= desc->unit_type.range.start &&
918
2/2
✓ Branch 0 taken 24514 times.
✓ Branch 1 taken 11281 times.
35795 unit->type <= desc->unit_type.range.end)
919 24514 return desc;
920 } else {
921
2/2
✓ Branch 0 taken 249012 times.
✓ Branch 1 taken 213556 times.
462568 for (j = 0; j < desc->nb_unit_types; j++) {
922
2/2
✓ Branch 0 taken 21521 times.
✓ Branch 1 taken 227491 times.
249012 if (desc->unit_type.list[j] == unit->type)
923 21521 return desc;
924 }
925 }
926 }
927 return NULL;
928 }
929
930 46035 static void *cbs_alloc_content(const CodedBitstreamUnitTypeDescriptor *desc)
931 {
932 46035 return av_refstruct_alloc_ext_c(desc->content_size, 0,
933 46035 (AVRefStructOpaque){ .c = desc },
934
2/2
✓ Branch 0 taken 5817 times.
✓ Branch 1 taken 40218 times.
46035 desc->content_type == CBS_CONTENT_TYPE_COMPLEX
935 ? desc->type.complex.content_free
936 : cbs_default_free_unit_content);
937 }
938
939 45728 int CBS_FUNC(alloc_unit_content)(CodedBitstreamContext *ctx,
940 CodedBitstreamUnit *unit)
941 {
942 const CodedBitstreamUnitTypeDescriptor *desc;
943
944
2/4
✓ Branch 0 taken 45728 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 45728 times.
45728 av_assert0(!unit->content && !unit->content_ref);
945
946 45728 desc = cbs_find_unit_type_desc(ctx, unit);
947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45728 times.
45728 if (!desc)
948 return AVERROR(ENOSYS);
949
950 45728 unit->content_ref = cbs_alloc_content(desc);
951
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45728 times.
45728 if (!unit->content_ref)
952 return AVERROR(ENOMEM);
953 45728 unit->content = unit->content_ref;
954
955 45728 return 0;
956 }
957
958 307 static int cbs_clone_noncomplex_unit_content(void **clonep,
959 const CodedBitstreamUnit *unit,
960 const CodedBitstreamUnitTypeDescriptor *desc)
961 {
962 const uint8_t *src;
963 uint8_t *copy;
964 int err, i;
965
966
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 307 times.
307 av_assert0(unit->content);
967 307 src = unit->content;
968
969 307 copy = cbs_alloc_content(desc);
970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 307 times.
307 if (!copy)
971 return AVERROR(ENOMEM);
972 307 memcpy(copy, src, desc->content_size);
973
2/2
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 307 times.
614 for (int i = 0; i < desc->type.ref.nb_offsets; i++) {
974 307 void **ptr = (void**)(copy + desc->type.ref.offsets[i]);
975 /* Zero all the AVBufferRefs as they are owned by src. */
976 307 *(ptr + 1) = NULL;
977 }
978
979
2/2
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 307 times.
614 for (i = 0; i < desc->type.ref.nb_offsets; i++) {
980 307 const uint8_t *const *src_ptr = (const uint8_t* const*)(src + desc->type.ref.offsets[i]);
981 307 const AVBufferRef *src_buf = *(AVBufferRef**)(src_ptr + 1);
982 307 uint8_t **copy_ptr = (uint8_t**)(copy + desc->type.ref.offsets[i]);
983 307 AVBufferRef **copy_buf = (AVBufferRef**)(copy_ptr + 1);
984
985
1/2
✓ Branch 0 taken 307 times.
✗ Branch 1 not taken.
307 if (!*src_ptr) {
986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 307 times.
307 av_assert0(!src_buf);
987 307 continue;
988 }
989 if (!src_buf) {
990 // We can't handle a non-refcounted pointer here - we don't
991 // have enough information to handle whatever structure lies
992 // at the other end of it.
993 err = AVERROR(EINVAL);
994 goto fail;
995 }
996
997 *copy_buf = av_buffer_ref(src_buf);
998 if (!*copy_buf) {
999 err = AVERROR(ENOMEM);
1000 goto fail;
1001 }
1002 }
1003 307 *clonep = copy;
1004
1005 307 return 0;
1006
1007 fail:
1008 av_refstruct_unref(&copy);
1009 return err;
1010 }
1011
1012 /*
1013 * On success, unit->content and unit->content_ref are updated with
1014 * the new content; unit is untouched on failure.
1015 * Any old content_ref is simply overwritten and not freed.
1016 */
1017 307 static int cbs_clone_unit_content(CodedBitstreamContext *ctx,
1018 CodedBitstreamUnit *unit)
1019 {
1020 const CodedBitstreamUnitTypeDescriptor *desc;
1021 void *new_content;
1022 int err;
1023
1024 307 desc = cbs_find_unit_type_desc(ctx, unit);
1025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 307 times.
307 if (!desc)
1026 return AVERROR(ENOSYS);
1027
1028
1/3
✓ Branch 0 taken 307 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
307 switch (desc->content_type) {
1029 307 case CBS_CONTENT_TYPE_INTERNAL_REFS:
1030 307 err = cbs_clone_noncomplex_unit_content(&new_content, unit, desc);
1031 307 break;
1032
1033 case CBS_CONTENT_TYPE_COMPLEX:
1034 if (!desc->type.complex.content_clone)
1035 return AVERROR_PATCHWELCOME;
1036 err = desc->type.complex.content_clone(&new_content, unit);
1037 break;
1038
1039 default:
1040 av_assert0(0 && "Invalid content type.");
1041 }
1042
1043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 307 times.
307 if (err < 0)
1044 return err;
1045
1046 307 unit->content_ref = new_content;
1047 307 unit->content = new_content;
1048 307 return 0;
1049 }
1050
1051 15541 int CBS_FUNC(make_unit_refcounted)(CodedBitstreamContext *ctx,
1052 CodedBitstreamUnit *unit)
1053 {
1054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15541 times.
15541 av_assert0(unit->content);
1055
1/2
✓ Branch 0 taken 15541 times.
✗ Branch 1 not taken.
15541 if (unit->content_ref)
1056 15541 return 0;
1057 return cbs_clone_unit_content(ctx, unit);
1058 }
1059
1060 307 int CBS_FUNC(make_unit_writable)(CodedBitstreamContext *ctx,
1061 CodedBitstreamUnit *unit)
1062 {
1063 307 void *ref = unit->content_ref;
1064 int err;
1065
1066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 307 times.
307 av_assert0(unit->content);
1067
2/4
✓ Branch 0 taken 307 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 307 times.
307 if (ref && av_refstruct_exclusive(ref))
1068 return 0;
1069
1070 307 err = cbs_clone_unit_content(ctx, unit);
1071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 307 times.
307 if (err < 0)
1072 return err;
1073 307 av_refstruct_unref(&ref);
1074 307 return 0;
1075 }
1076
1077 696 void CBS_FUNC(discard_units)(CodedBitstreamContext *ctx,
1078 CodedBitstreamFragment *frag,
1079 enum AVDiscard skip,
1080 int flags)
1081 {
1082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 696 times.
696 if (!ctx->codec->discarded_unit)
1083 return;
1084
1085
2/2
✓ Branch 0 taken 1292 times.
✓ Branch 1 taken 134 times.
1426 for (int i = frag->nb_units - 1; i >= 0; i--) {
1086
2/2
✓ Branch 1 taken 562 times.
✓ Branch 2 taken 730 times.
1292 if (ctx->codec->discarded_unit(ctx, &frag->units[i], skip)) {
1087 // discard all units
1088
1/2
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
562 if (!(flags & DISCARD_FLAG_KEEP_NON_VCL)) {
1089 562 CBS_FUNC(fragment_free)(frag);
1090 562 return;
1091 }
1092
1093 CBS_FUNC(delete_unit)(frag, i);
1094 }
1095 }
1096 }
1097