FFmpeg coverage


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