FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/cbs.c
Date: 2025-09-17 11:09:43
Exec Total Coverage
Lines: 405 490 82.7%
Functions: 52 66 78.8%
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_JPEG
50 &CBS_FUNC(type_jpeg),
51 #endif
52 #if CBS_MPEG2
53 &CBS_FUNC(type_mpeg2),
54 #endif
55 #if CBS_VP8
56 &CBS_FUNC(type_vp8),
57 #endif
58 #if CBS_VP9
59 &CBS_FUNC(type_vp9),
60 #endif
61 };
62
63 const enum AVCodecID CBS_FUNC(all_codec_ids)[] = {
64 #if CBS_APV
65 AV_CODEC_ID_APV,
66 #endif
67 #if CBS_AV1
68 AV_CODEC_ID_AV1,
69 #endif
70 #if CBS_H264
71 AV_CODEC_ID_H264,
72 #endif
73 #if CBS_H265
74 AV_CODEC_ID_H265,
75 #endif
76 #if CBS_H266
77 AV_CODEC_ID_H266,
78 #endif
79 #if CBS_JPEG
80 AV_CODEC_ID_MJPEG,
81 #endif
82 #if CBS_MPEG2
83 AV_CODEC_ID_MPEG2VIDEO,
84 #endif
85 #if CBS_VP8
86 AV_CODEC_ID_VP8,
87 #endif
88 #if CBS_VP9
89 AV_CODEC_ID_VP9,
90 #endif
91 AV_CODEC_ID_NONE
92 };
93
94 933 av_cold int CBS_FUNC(init)(CodedBitstreamContext **ctx_ptr,
95 enum AVCodecID codec_id, void *log_ctx)
96 {
97 CodedBitstreamContext *ctx;
98 const CodedBitstreamType *type;
99 int i;
100
101 933 type = NULL;
102
1/2
✓ Branch 0 taken 6228 times.
✗ Branch 1 not taken.
6228 for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) {
103
2/2
✓ Branch 0 taken 933 times.
✓ Branch 1 taken 5295 times.
6228 if (cbs_type_table[i]->codec_id == codec_id) {
104 933 type = cbs_type_table[i];
105 933 break;
106 }
107 }
108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 933 times.
933 if (!type)
109 return AVERROR(EINVAL);
110
111 933 ctx = av_mallocz(sizeof(*ctx));
112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 933 times.
933 if (!ctx)
113 return AVERROR(ENOMEM);
114
115 933 ctx->log_ctx = log_ctx;
116 933 ctx->codec = type; /* Must be before any error */
117
118
1/2
✓ Branch 0 taken 933 times.
✗ Branch 1 not taken.
933 if (type->priv_data_size) {
119 933 ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 933 times.
933 if (!ctx->priv_data) {
121 av_freep(&ctx);
122 return AVERROR(ENOMEM);
123 }
124
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 840 times.
933 if (type->priv_class) {
125 93 *(const AVClass **)ctx->priv_data = type->priv_class;
126 93 av_opt_set_defaults(ctx->priv_data);
127 }
128 }
129
130 933 ctx->decompose_unit_types = NULL;
131
132 933 ctx->trace_enable = 0;
133 933 ctx->trace_level = AV_LOG_TRACE;
134 933 ctx->trace_context = ctx;
135
136 933 *ctx_ptr = ctx;
137 933 return 0;
138 }
139
140 1 av_cold void CBS_FUNC(flush)(CodedBitstreamContext *ctx)
141 {
142
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ctx->codec->flush)
143 1 ctx->codec->flush(ctx);
144 1 }
145
146 1220 av_cold void CBS_FUNC(close)(CodedBitstreamContext **ctx_ptr)
147 {
148 1220 CodedBitstreamContext *ctx = *ctx_ptr;
149
150
2/2
✓ Branch 0 taken 287 times.
✓ Branch 1 taken 933 times.
1220 if (!ctx)
151 287 return;
152
153
2/2
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 537 times.
933 if (ctx->codec->close)
154 396 ctx->codec->close(ctx);
155
156 933 av_freep(&ctx->write_buffer);
157
158
3/4
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 840 times.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
933 if (ctx->codec->priv_class && ctx->priv_data)
159 93 av_opt_free(ctx->priv_data);
160
161 933 av_freep(&ctx->priv_data);
162 933 av_freep(ctx_ptr);
163 }
164
165 52498 static void cbs_unit_uninit(CodedBitstreamUnit *unit)
166 {
167 52498 av_refstruct_unref(&unit->content_ref);
168 52498 unit->content = NULL;
169
170 52498 av_buffer_unref(&unit->data_ref);
171 52498 unit->data = NULL;
172 52498 unit->data_size = 0;
173 52498 unit->data_bit_padding = 0;
174 52498 }
175
176 17626 void CBS_FUNC(fragment_reset)(CodedBitstreamFragment *frag)
177 {
178 int i;
179
180
2/2
✓ Branch 0 taken 52426 times.
✓ Branch 1 taken 17626 times.
70052 for (i = 0; i < frag->nb_units; i++)
181 52426 cbs_unit_uninit(&frag->units[i]);
182 17626 frag->nb_units = 0;
183
184 17626 av_buffer_unref(&frag->data_ref);
185 17626 frag->data = NULL;
186 17626 frag->data_size = 0;
187 17626 frag->data_bit_padding = 0;
188 17626 }
189
190 1678 av_cold void CBS_FUNC(fragment_free)(CodedBitstreamFragment *frag)
191 {
192 1678 CBS_FUNC(fragment_reset)(frag);
193
194 1678 av_freep(&frag->units);
195 1678 frag->nb_units_allocated = 0;
196 1678 }
197
198 #if CBS_READ
199 15964 static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
200 CodedBitstreamFragment *frag)
201 {
202 int err, i, j;
203
204
2/2
✓ Branch 0 taken 52485 times.
✓ Branch 1 taken 15963 times.
68448 for (i = 0; i < frag->nb_units; i++) {
205 52485 CodedBitstreamUnit *unit = &frag->units[i];
206
207
2/2
✓ Branch 0 taken 11569 times.
✓ Branch 1 taken 40916 times.
52485 if (ctx->decompose_unit_types) {
208
2/2
✓ Branch 0 taken 80338 times.
✓ Branch 1 taken 3890 times.
84228 for (j = 0; j < ctx->nb_decompose_unit_types; j++) {
209
2/2
✓ Branch 0 taken 7679 times.
✓ Branch 1 taken 72659 times.
80338 if (ctx->decompose_unit_types[j] == unit->type)
210 7679 break;
211 }
212
2/2
✓ Branch 0 taken 3890 times.
✓ Branch 1 taken 7679 times.
11569 if (j >= ctx->nb_decompose_unit_types)
213 3890 continue;
214 }
215
216 48595 av_refstruct_unref(&unit->content_ref);
217 48595 unit->content = NULL;
218
219
2/4
✓ Branch 0 taken 48595 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48595 times.
48595 av_assert0(unit->data && unit->data_ref);
220
221 48595 err = ctx->codec->read_unit(ctx, unit);
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48595 times.
48595 if (err == AVERROR(ENOSYS)) {
223 av_log(ctx->log_ctx, AV_LOG_VERBOSE,
224 "Decomposition unimplemented for unit %d "
225 "(type %"PRIu32").\n", i, unit->type);
226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48595 times.
48595 } else if (err == AVERROR(EAGAIN)) {
227 av_log(ctx->log_ctx, AV_LOG_VERBOSE,
228 "Skipping decomposition of unit %d "
229 "(type %"PRIu32").\n", i, unit->type);
230 av_refstruct_unref(&unit->content_ref);
231 unit->content = NULL;
232
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 48594 times.
48595 } else if (err < 0) {
233 1 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
234 "(type %"PRIu32"): %s.\n",
235 1 i, unit->type, av_err2str(err));
236 1 return err;
237 }
238 }
239
240 15963 return 0;
241 }
242
243 4073 static int cbs_fill_fragment_data(CodedBitstreamFragment *frag,
244 const uint8_t *data, size_t size)
245 {
246
2/4
✓ Branch 0 taken 4073 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4073 times.
4073 av_assert0(!frag->data && !frag->data_ref);
247
248 4073 frag->data_ref =
249 4073 av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4073 times.
4073 if (!frag->data_ref)
251 return AVERROR(ENOMEM);
252
253 4073 frag->data = frag->data_ref->data;
254 4073 frag->data_size = size;
255
256 4073 memcpy(frag->data, data, size);
257 4073 memset(frag->data + size, 0,
258 AV_INPUT_BUFFER_PADDING_SIZE);
259
260 4073 return 0;
261 }
262
263 15964 static int cbs_read_data(CodedBitstreamContext *ctx,
264 CodedBitstreamFragment *frag,
265 const AVBufferRef *buf,
266 const uint8_t *data, size_t size,
267 int header)
268 {
269 int err;
270
271
2/2
✓ Branch 0 taken 11891 times.
✓ Branch 1 taken 4073 times.
15964 if (buf) {
272 11891 frag->data_ref = av_buffer_ref(buf);
273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11891 times.
11891 if (!frag->data_ref)
274 return AVERROR(ENOMEM);
275
276 11891 frag->data = (uint8_t *)data;
277 11891 frag->data_size = size;
278
279 } else {
280 4073 err = cbs_fill_fragment_data(frag, data, size);
281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4073 times.
4073 if (err < 0)
282 return err;
283 }
284
285 15964 err = ctx->codec->split_fragment(ctx, frag, header);
286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15964 times.
15964 if (err < 0)
287 return err;
288
289 15964 return cbs_read_fragment_content(ctx, frag);
290 }
291
292 97 int CBS_FUNC(read_extradata)(CodedBitstreamContext *ctx,
293 CodedBitstreamFragment *frag,
294 const AVCodecParameters *par)
295 {
296 194 return cbs_read_data(ctx, frag, NULL,
297 97 par->extradata,
298 97 par->extradata_size, 1);
299 }
300
301 130 int CBS_FUNC(read_extradata_from_codec)(CodedBitstreamContext *ctx,
302 CodedBitstreamFragment *frag,
303 const AVCodecContext *avctx)
304 {
305 260 return cbs_read_data(ctx, frag, NULL,
306 130 avctx->extradata,
307 130 avctx->extradata_size, 1);
308 }
309
310 11864 int CBS_FUNC(read_packet)(CodedBitstreamContext *ctx,
311 CodedBitstreamFragment *frag,
312 const AVPacket *pkt)
313 {
314 23728 return cbs_read_data(ctx, frag, pkt->buf,
315 11864 pkt->data, pkt->size, 0);
316 }
317
318 1 int CBS_FUNC(read_packet_side_data)(CodedBitstreamContext *ctx,
319 CodedBitstreamFragment *frag,
320 const AVPacket *pkt)
321 {
322 size_t side_data_size;
323 const uint8_t *side_data =
324 1 av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
325 &side_data_size);
326
327 1 return cbs_read_data(ctx, frag, NULL,
328 side_data, side_data_size, 1);
329 }
330
331 3872 int CBS_FUNC(read)(CodedBitstreamContext *ctx,
332 CodedBitstreamFragment *frag,
333 const AVBufferRef *buf,
334 const uint8_t *data, size_t size)
335 {
336 3872 return cbs_read_data(ctx, frag, buf,
337 data, size, 0);
338 }
339 #endif
340
341 #if CBS_WRITE
342 /**
343 * Allocate a new internal data buffer of the given size in the unit.
344 *
345 * The data buffer will have input padding.
346 */
347 31946 static int cbs_alloc_unit_data(CodedBitstreamUnit *unit,
348 size_t size)
349 {
350
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);
351
352 31946 unit->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31946 times.
31946 if (!unit->data_ref)
354 return AVERROR(ENOMEM);
355
356 31946 unit->data = unit->data_ref->data;
357 31946 unit->data_size = size;
358
359 31946 memset(unit->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
360
361 31946 return 0;
362 }
363
364 31946 static int cbs_write_unit_data(CodedBitstreamContext *ctx,
365 CodedBitstreamUnit *unit)
366 {
367 PutBitContext pbc;
368 int ret;
369
370
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 31833 times.
31946 if (!ctx->write_buffer) {
371 // Initial write buffer size is 1MB.
372 113 ctx->write_buffer_size = 1024 * 1024;
373
374 113 reallocate_and_try_again:
375 113 ret = av_reallocp(&ctx->write_buffer, ctx->write_buffer_size);
376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 113 times.
113 if (ret < 0) {
377 av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a "
378 "sufficiently large write buffer (last attempt "
379 "%"SIZE_SPECIFIER" bytes).\n", ctx->write_buffer_size);
380 return ret;
381 }
382 }
383
384 31946 init_put_bits(&pbc, ctx->write_buffer, ctx->write_buffer_size);
385
386 31946 ret = ctx->codec->write_unit(ctx, unit, &pbc);
387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31946 times.
31946 if (ret < 0) {
388 if (ret == AVERROR(ENOSPC)) {
389 // Overflow.
390 if (ctx->write_buffer_size == INT_MAX / 8)
391 return AVERROR(ENOMEM);
392 ctx->write_buffer_size = FFMIN(2 * ctx->write_buffer_size, INT_MAX / 8);
393 goto reallocate_and_try_again;
394 }
395 // Write failed for some other reason.
396 return ret;
397 }
398
399 // Overflow but we didn't notice.
400
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31946 times.
31946 av_assert0(put_bits_count(&pbc) <= 8 * ctx->write_buffer_size);
401
402
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 31894 times.
31946 if (put_bits_count(&pbc) % 8)
403 52 unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8;
404 else
405 31894 unit->data_bit_padding = 0;
406
407 31946 flush_put_bits(&pbc);
408
409 31946 ret = cbs_alloc_unit_data(unit, put_bytes_output(&pbc));
410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31946 times.
31946 if (ret < 0)
411 return ret;
412
413 31946 memcpy(unit->data, ctx->write_buffer, unit->data_size);
414
415 31946 return 0;
416 }
417
418 7888 int CBS_FUNC(write_fragment_data)(CodedBitstreamContext *ctx,
419 CodedBitstreamFragment *frag)
420 {
421 int err, i;
422
423
2/2
✓ Branch 0 taken 31946 times.
✓ Branch 1 taken 7888 times.
39834 for (i = 0; i < frag->nb_units; i++) {
424 31946 CodedBitstreamUnit *unit = &frag->units[i];
425
426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31946 times.
31946 if (!unit->content)
427 continue;
428
429 31946 av_buffer_unref(&unit->data_ref);
430 31946 unit->data = NULL;
431
432 31946 err = cbs_write_unit_data(ctx, unit);
433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31946 times.
31946 if (err < 0) {
434 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
435 "(type %"PRIu32").\n", i, unit->type);
436 return err;
437 }
438
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);
439 }
440
441 7888 av_buffer_unref(&frag->data_ref);
442 7888 frag->data = NULL;
443
444 7888 err = ctx->codec->assemble_fragment(ctx, frag);
445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7888 times.
7888 if (err < 0) {
446 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
447 return err;
448 }
449
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);
450
451 7888 return 0;
452 }
453
454 96 int CBS_FUNC(write_extradata)(CodedBitstreamContext *ctx,
455 AVCodecParameters *par,
456 CodedBitstreamFragment *frag)
457 {
458 int err;
459
460 96 err = CBS_FUNC(write_fragment_data)(ctx, frag);
461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (err < 0)
462 return err;
463
464 96 av_freep(&par->extradata);
465 96 par->extradata_size = 0;
466
467
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 95 times.
96 if (!frag->data_size)
468 1 return 0;
469
470 95 par->extradata = av_malloc(frag->data_size +
471 AV_INPUT_BUFFER_PADDING_SIZE);
472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 if (!par->extradata)
473 return AVERROR(ENOMEM);
474
475 95 memcpy(par->extradata, frag->data, frag->data_size);
476 95 memset(par->extradata + frag->data_size, 0,
477 AV_INPUT_BUFFER_PADDING_SIZE);
478 95 par->extradata_size = frag->data_size;
479
480 95 return 0;
481 }
482
483 7791 int CBS_FUNC(write_packet)(CodedBitstreamContext *ctx,
484 AVPacket *pkt,
485 CodedBitstreamFragment *frag)
486 {
487 AVBufferRef *buf;
488 int err;
489
490 7791 err = CBS_FUNC(write_fragment_data)(ctx, frag);
491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7791 times.
7791 if (err < 0)
492 return err;
493
494 7791 buf = av_buffer_ref(frag->data_ref);
495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7791 times.
7791 if (!buf)
496 return AVERROR(ENOMEM);
497
498 7791 av_buffer_unref(&pkt->buf);
499
500 7791 pkt->buf = buf;
501 7791 pkt->data = frag->data;
502 7791 pkt->size = frag->data_size;
503
504 7791 return 0;
505 }
506 #endif
507
508
509 103198 void CBS_FUNC(trace_header)(CodedBitstreamContext *ctx,
510 const char *name)
511 {
512 #if CBS_TRACE
513
2/2
✓ Branch 0 taken 66414 times.
✓ Branch 1 taken 36781 times.
103195 if (!ctx->trace_enable)
514 66414 return;
515
516 36781 av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
517 #endif
518 3 }
519
520 973411 void CBS_FUNC(trace_read_log)(void *trace_context,
521 GetBitContext *gbc, int length,
522 const char *str, const int *subscripts,
523 int64_t value)
524 {
525 #if CBS_TRACE
526 973411 CodedBitstreamContext *ctx = trace_context;
527 char name[256];
528 char bits[256];
529 size_t name_len, bits_len;
530 int pad, subs, i, j, k, n;
531 int position;
532
533
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);
534
535 973411 position = get_bits_count(gbc);
536
537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 973411 times.
973411 av_assert0(length < 256);
538
2/2
✓ Branch 0 taken 3711164 times.
✓ Branch 1 taken 973411 times.
4684575 for (i = 0; i < length; i++)
539
2/2
✓ Branch 1 taken 1437909 times.
✓ Branch 2 taken 2273255 times.
3711164 bits[i] = get_bits1(gbc) ? '1' : '0';
540 973411 bits[length] = 0;
541
542
2/2
✓ Branch 0 taken 392788 times.
✓ Branch 1 taken 580623 times.
973411 subs = subscripts ? subscripts[0] : 0;
543 973411 n = 0;
544
2/2
✓ Branch 0 taken 21479487 times.
✓ Branch 1 taken 973411 times.
22452898 for (i = j = 0; str[i];) {
545
2/2
✓ Branch 0 taken 692863 times.
✓ Branch 1 taken 20786624 times.
21479487 if (str[i] == '[') {
546
2/2
✓ Branch 0 taken 691206 times.
✓ Branch 1 taken 1657 times.
692863 if (n < subs) {
547 691206 ++n;
548 691206 k = snprintf(name + j, sizeof(name) - j, "[%d", subscripts[n]);
549
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));
550 691206 j += k;
551
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++);
552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 691206 times.
691206 av_assert0(str[i] == ']');
553 } else {
554
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] != ']')
555 3314 name[j++] = str[i++];
556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1657 times.
1657 av_assert0(str[i] == ']');
557 }
558 } else {
559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20786624 times.
20786624 av_assert0(j + 1 < sizeof(name));
560 20786624 name[j++] = str[i++];
561 }
562 }
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 973411 times.
973411 av_assert0(j + 1 < sizeof(name));
564 973411 name[j] = 0;
565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 973411 times.
973411 av_assert0(n == subs);
566
567 973411 name_len = strlen(name);
568 973411 bits_len = length;
569
570
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 973397 times.
973411 if (name_len + bits_len > 60)
571 14 pad = bits_len + 2;
572 else
573 973397 pad = 61 - name_len;
574
575 973411 av_log(ctx->log_ctx, ctx->trace_level, "%-10d %s%*s = %"PRId64"\n",
576 position, name, pad, bits, value);
577 #endif
578 973411 }
579
580 973411 void CBS_FUNC(trace_write_log)(void *trace_context,
581 PutBitContext *pbc, int length,
582 const char *str, const int *subscripts,
583 int64_t value)
584 {
585 #if CBS_TRACE
586 973411 CodedBitstreamContext *ctx = trace_context;
587
588 // Ensure that the syntax element is written to the output buffer,
589 // make a GetBitContext pointed at the start position, then call the
590 // read log function which can read the bits back to log them.
591
592 GetBitContext gbc;
593 int position;
594
595
2/2
✓ Branch 0 taken 973172 times.
✓ Branch 1 taken 239 times.
973411 if (length > 0) {
596 PutBitContext flush;
597 973172 flush = *pbc;
598 973172 flush_put_bits(&flush);
599 }
600
601 973411 position = put_bits_count(pbc);
602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 973411 times.
973411 av_assert0(position >= length);
603
604 973411 init_get_bits(&gbc, pbc->buf, position);
605
606 973411 skip_bits_long(&gbc, position - length);
607
608 973411 CBS_FUNC(trace_read_log)(ctx, &gbc, length, str, subscripts, value);
609 #endif
610 973411 }
611
612 #if CBS_READ
613 2424941 static av_always_inline int cbs_read_unsigned(CodedBitstreamContext *ctx,
614 GetBitContext *gbc,
615 int width, const char *name,
616 const int *subscripts,
617 uint32_t *write_to,
618 uint32_t range_min,
619 uint32_t range_max)
620 {
621 uint32_t value;
622
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2424779 times.
2424779 CBS_TRACE_READ_START();
624
625
2/4
✓ Branch 0 taken 2424941 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2424941 times.
2424941 av_assert0(width > 0 && width <= 32);
626
627
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2424940 times.
2424941 if (get_bits_left(gbc) < width) {
628 1 av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
629 "%s: bitstream ended.\n", name);
630 1 return AVERROR_INVALIDDATA;
631 }
632
633 2424940 value = get_bits_long(gbc, width);
634
635
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2424778 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2424778 CBS_TRACE_READ_END();
636
637
2/4
✓ Branch 0 taken 2424940 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2424940 times.
2424940 if (value < range_min || value > range_max) {
638 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
639 "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
640 name, value, range_min, range_max);
641 return AVERROR_INVALIDDATA;
642 }
643
644 2424940 *write_to = value;
645 2424940 return 0;
646 }
647
648 1841223 int CBS_FUNC(read_unsigned)(CodedBitstreamContext *ctx, GetBitContext *gbc,
649 int width, const char *name,
650 const int *subscripts, uint32_t *write_to,
651 uint32_t range_min, uint32_t range_max)
652 {
653 1841223 return cbs_read_unsigned(ctx, gbc, width, name, subscripts,
654 write_to, range_min, range_max);
655 }
656
657 583718 int CBS_FUNC(read_simple_unsigned)(CodedBitstreamContext *ctx, GetBitContext *gbc,
658 int width, const char *name, uint32_t *write_to)
659 {
660 583718 return cbs_read_unsigned(ctx, gbc, width, name, NULL,
661 write_to, 0, UINT32_MAX);
662 }
663 #endif
664
665 #if CBS_WRITE
666 943391 int CBS_FUNC(write_unsigned)(CodedBitstreamContext *ctx, PutBitContext *pbc,
667 int width, const char *name,
668 const int *subscripts, uint32_t value,
669 uint32_t range_min, uint32_t range_max)
670 {
671
2/2
✓ Branch 0 taken 734550 times.
✓ Branch 1 taken 208841 times.
943391 CBS_TRACE_WRITE_START();
672
673
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);
674
675
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) {
676 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
677 "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
678 name, value, range_min, range_max);
679 return AVERROR_INVALIDDATA;
680 }
681
682
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 943391 times.
943391 if (put_bits_left(pbc) < width)
683 return AVERROR(ENOSPC);
684
685 943391 put_bits63(pbc, width, value);
686
687
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();
688
689 943391 return 0;
690 }
691
692 267528 int CBS_FUNC(write_simple_unsigned)(CodedBitstreamContext *ctx, PutBitContext *pbc,
693 int width, const char *name, uint32_t value)
694 {
695 535056 return CBS_FUNC(write_unsigned)(ctx, pbc, width, name, NULL,
696 267528 value, 0, MAX_UINT_BITS(width));
697 }
698 #endif
699
700 #if CBS_READ
701 50 int CBS_FUNC(read_signed)(CodedBitstreamContext *ctx, GetBitContext *gbc,
702 int width, const char *name,
703 const int *subscripts, int32_t *write_to,
704 int32_t range_min, int32_t range_max)
705 {
706 int32_t value;
707
708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 CBS_TRACE_READ_START();
709
710
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);
711
712
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 if (get_bits_left(gbc) < width) {
713 av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
714 "%s: bitstream ended.\n", name);
715 return AVERROR_INVALIDDATA;
716 }
717
718 50 value = get_sbits_long(gbc, width);
719
720
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
50 CBS_TRACE_READ_END();
721
722
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) {
723 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
724 "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
725 name, value, range_min, range_max);
726 return AVERROR_INVALIDDATA;
727 }
728
729 50 *write_to = value;
730 50 return 0;
731 }
732 #endif
733
734 #if CBS_WRITE
735 50 int CBS_FUNC(write_signed)(CodedBitstreamContext *ctx, PutBitContext *pbc,
736 int width, const char *name,
737 const int *subscripts, int32_t value,
738 int32_t range_min, int32_t range_max)
739 {
740
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 CBS_TRACE_WRITE_START();
741
742
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);
743
744
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) {
745 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
746 "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
747 name, value, range_min, range_max);
748 return AVERROR_INVALIDDATA;
749 }
750
751
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 if (put_bits_left(pbc) < width)
752 return AVERROR(ENOSPC);
753
754 50 put_bits63(pbc, width, zero_extend(value, width));
755
756
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();
757
758 50 return 0;
759 }
760 #endif
761
762
763 52498 static int cbs_insert_unit(CodedBitstreamFragment *frag,
764 int position)
765 {
766 CodedBitstreamUnit *units;
767
768
2/2
✓ Branch 0 taken 49632 times.
✓ Branch 1 taken 2866 times.
52498 if (frag->nb_units < frag->nb_units_allocated) {
769 49632 units = frag->units;
770
771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49632 times.
49632 if (position < frag->nb_units)
772 memmove(units + position + 1, units + position,
773 (frag->nb_units - position) * sizeof(*units));
774 } else {
775 2866 units = av_malloc_array(frag->nb_units*2 + 1, sizeof(*units));
776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2866 times.
2866 if (!units)
777 return AVERROR(ENOMEM);
778
779 2866 frag->nb_units_allocated = 2*frag->nb_units_allocated + 1;
780
781
2/2
✓ Branch 0 taken 1489 times.
✓ Branch 1 taken 1377 times.
2866 if (position > 0)
782 1489 memcpy(units, frag->units, position * sizeof(*units));
783
784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2866 times.
2866 if (position < frag->nb_units)
785 memcpy(units + position + 1, frag->units + position,
786 (frag->nb_units - position) * sizeof(*units));
787
788 2866 av_free(frag->units);
789 2866 frag->units = units;
790 }
791
792 52498 memset(units + position, 0, sizeof(*units));
793
794 52498 ++frag->nb_units;
795
796 52498 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 52485 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 52485 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 52485 times.
52485 av_assert0(position >= 0 && position <= frag->nb_units);
840
841
1/2
✓ Branch 0 taken 52485 times.
✗ Branch 1 not taken.
52485 if (data_buf)
842 52485 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 52485 times.
52485 if (!data_ref) {
846 if (!data_buf)
847 av_free(data);
848 return AVERROR(ENOMEM);
849 }
850
851 52485 err = cbs_insert_unit(frag, position);
852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52485 times.
52485 if (err < 0) {
853 av_buffer_unref(&data_ref);
854 return err;
855 }
856
857 52485 unit = &frag->units[position];
858 52485 unit->type = type;
859 52485 unit->data = data;
860 52485 unit->data_size = data_size;
861 52485 unit->data_ref = data_ref;
862
863 52485 return 0;
864 }
865
866 52485 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 52485 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 42937 static void cbs_default_free_unit_content(AVRefStructOpaque opaque, void *content)
893 {
894 42937 const CodedBitstreamUnitTypeDescriptor *desc = opaque.c;
895
896
2/2
✓ Branch 0 taken 50906 times.
✓ Branch 1 taken 42937 times.
93843 for (int i = 0; i < desc->type.ref.nb_offsets; i++) {
897 50906 void **ptr = (void**)((char*)content + desc->type.ref.offsets[i]);
898 50906 av_buffer_unref((AVBufferRef**)(ptr + 1));
899 }
900 42937 }
901
902 static const CodedBitstreamUnitTypeDescriptor
903 48901 *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 48901 times.
48901 if (!ctx->codec->unit_types)
910 return NULL;
911
912 277696 for (i = 0;; i++) {
913 277696 desc = &ctx->codec->unit_types[i];
914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 277696 times.
277696 if (desc->nb_unit_types == 0)
915 break;
916
2/2
✓ Branch 0 taken 36402 times.
✓ Branch 1 taken 241294 times.
277696 if (desc->nb_unit_types == CBS_UNIT_TYPE_RANGE) {
917
1/2
✓ Branch 0 taken 36402 times.
✗ Branch 1 not taken.
36402 if (unit->type >= desc->unit_type.range.start &&
918
2/2
✓ Branch 0 taken 24835 times.
✓ Branch 1 taken 11567 times.
36402 unit->type <= desc->unit_type.range.end)
919 24835 return desc;
920 } else {
921
2/2
✓ Branch 0 taken 255340 times.
✓ Branch 1 taken 217228 times.
472568 for (j = 0; j < desc->nb_unit_types; j++) {
922
2/2
✓ Branch 0 taken 24066 times.
✓ Branch 1 taken 231274 times.
255340 if (desc->unit_type.list[j] == unit->type)
923 24066 return desc;
924 }
925 }
926 }
927 return NULL;
928 }
929
930 48901 static void *cbs_alloc_content(const CodedBitstreamUnitTypeDescriptor *desc)
931 {
932 48901 return av_refstruct_alloc_ext_c(desc->content_size, 0,
933 48901 (AVRefStructOpaque){ .c = desc },
934
2/2
✓ Branch 0 taken 5964 times.
✓ Branch 1 taken 42937 times.
48901 desc->content_type == CBS_CONTENT_TYPE_COMPLEX
935 ? desc->type.complex.content_free
936 : cbs_default_free_unit_content);
937 }
938
939 48595 int CBS_FUNC(alloc_unit_content)(CodedBitstreamContext *ctx,
940 CodedBitstreamUnit *unit)
941 {
942 const CodedBitstreamUnitTypeDescriptor *desc;
943
944
2/4
✓ Branch 0 taken 48595 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48595 times.
48595 av_assert0(!unit->content && !unit->content_ref);
945
946 48595 desc = cbs_find_unit_type_desc(ctx, unit);
947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48595 times.
48595 if (!desc)
948 return AVERROR(ENOSYS);
949
950 48595 unit->content_ref = cbs_alloc_content(desc);
951
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48595 times.
48595 if (!unit->content_ref)
952 return AVERROR(ENOMEM);
953 48595 unit->content = unit->content_ref;
954
955 48595 return 0;
956 }
957
958 306 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 306 times.
306 av_assert0(unit->content);
967 306 src = unit->content;
968
969 306 copy = cbs_alloc_content(desc);
970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 306 times.
306 if (!copy)
971 return AVERROR(ENOMEM);
972 306 memcpy(copy, src, desc->content_size);
973
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 306 times.
612 for (int i = 0; i < desc->type.ref.nb_offsets; i++) {
974 306 void **ptr = (void**)(copy + desc->type.ref.offsets[i]);
975 /* Zero all the AVBufferRefs as they are owned by src. */
976 306 *(ptr + 1) = NULL;
977 }
978
979
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 306 times.
612 for (i = 0; i < desc->type.ref.nb_offsets; i++) {
980 306 const uint8_t *const *src_ptr = (const uint8_t* const*)(src + desc->type.ref.offsets[i]);
981 306 const AVBufferRef *src_buf = *(AVBufferRef**)(src_ptr + 1);
982 306 uint8_t **copy_ptr = (uint8_t**)(copy + desc->type.ref.offsets[i]);
983 306 AVBufferRef **copy_buf = (AVBufferRef**)(copy_ptr + 1);
984
985
1/2
✓ Branch 0 taken 306 times.
✗ Branch 1 not taken.
306 if (!*src_ptr) {
986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 306 times.
306 av_assert0(!src_buf);
987 306 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 306 *clonep = copy;
1004
1005 306 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 306 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 306 desc = cbs_find_unit_type_desc(ctx, unit);
1025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 306 times.
306 if (!desc)
1026 return AVERROR(ENOSYS);
1027
1028
1/3
✓ Branch 0 taken 306 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
306 switch (desc->content_type) {
1029 306 case CBS_CONTENT_TYPE_INTERNAL_REFS:
1030 306 err = cbs_clone_noncomplex_unit_content(&new_content, unit, desc);
1031 306 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 306 times.
306 if (err < 0)
1044 return err;
1045
1046 306 unit->content_ref = new_content;
1047 306 unit->content = new_content;
1048 306 return 0;
1049 }
1050
1051 15814 int CBS_FUNC(make_unit_refcounted)(CodedBitstreamContext *ctx,
1052 CodedBitstreamUnit *unit)
1053 {
1054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15814 times.
15814 av_assert0(unit->content);
1055
1/2
✓ Branch 0 taken 15814 times.
✗ Branch 1 not taken.
15814 if (unit->content_ref)
1056 15814 return 0;
1057 return cbs_clone_unit_content(ctx, unit);
1058 }
1059
1060 306 int CBS_FUNC(make_unit_writable)(CodedBitstreamContext *ctx,
1061 CodedBitstreamUnit *unit)
1062 {
1063 306 void *ref = unit->content_ref;
1064 int err;
1065
1066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 306 times.
306 av_assert0(unit->content);
1067
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))
1068 return 0;
1069
1070 306 err = cbs_clone_unit_content(ctx, unit);
1071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 306 times.
306 if (err < 0)
1072 return err;
1073 306 av_refstruct_unref(&ref);
1074 306 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