FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/cbs.c
Date: 2026-06-16 12:54:33
Exec Total Coverage
Lines: 405 490 82.7%
Functions: 53 66 80.3%
Branches: 199 329 60.5%

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