GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/cbs.c Lines: 248 374 66.3 %
Date: 2020-07-11 02:49:52 Branches: 117 270 43.3 %

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 "config.h"
22
23
#include "libavutil/avassert.h"
24
#include "libavutil/buffer.h"
25
#include "libavutil/common.h"
26
27
#include "cbs.h"
28
#include "cbs_internal.h"
29
30
31
static const CodedBitstreamType *cbs_type_table[] = {
32
#if CONFIG_CBS_AV1
33
    &ff_cbs_type_av1,
34
#endif
35
#if CONFIG_CBS_H264
36
    &ff_cbs_type_h264,
37
#endif
38
#if CONFIG_CBS_H265
39
    &ff_cbs_type_h265,
40
#endif
41
#if CONFIG_CBS_JPEG
42
    &ff_cbs_type_jpeg,
43
#endif
44
#if CONFIG_CBS_MPEG2
45
    &ff_cbs_type_mpeg2,
46
#endif
47
#if CONFIG_CBS_VP9
48
    &ff_cbs_type_vp9,
49
#endif
50
};
51
52
const enum AVCodecID ff_cbs_all_codec_ids[] = {
53
#if CONFIG_CBS_AV1
54
    AV_CODEC_ID_AV1,
55
#endif
56
#if CONFIG_CBS_H264
57
    AV_CODEC_ID_H264,
58
#endif
59
#if CONFIG_CBS_H265
60
    AV_CODEC_ID_H265,
61
#endif
62
#if CONFIG_CBS_JPEG
63
    AV_CODEC_ID_MJPEG,
64
#endif
65
#if CONFIG_CBS_MPEG2
66
    AV_CODEC_ID_MPEG2VIDEO,
67
#endif
68
#if CONFIG_CBS_VP9
69
    AV_CODEC_ID_VP9,
70
#endif
71
    AV_CODEC_ID_NONE
72
};
73
74
126
int ff_cbs_init(CodedBitstreamContext **ctx_ptr,
75
                enum AVCodecID codec_id, void *log_ctx)
76
{
77
    CodedBitstreamContext *ctx;
78
    const CodedBitstreamType *type;
79
    int i;
80
81
126
    type = NULL;
82
318
    for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) {
83
318
        if (cbs_type_table[i]->codec_id == codec_id) {
84
126
            type = cbs_type_table[i];
85
126
            break;
86
        }
87
    }
88
126
    if (!type)
89
        return AVERROR(EINVAL);
90
91
126
    ctx = av_mallocz(sizeof(*ctx));
92
126
    if (!ctx)
93
        return AVERROR(ENOMEM);
94
95
126
    ctx->log_ctx = log_ctx;
96
126
    ctx->codec   = type;
97
98
126
    if (type->priv_data_size) {
99
126
        ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
100
126
        if (!ctx->priv_data) {
101
            av_freep(&ctx);
102
            return AVERROR(ENOMEM);
103
        }
104
    }
105
106
126
    ctx->decompose_unit_types = NULL;
107
108
126
    ctx->trace_enable = 0;
109
126
    ctx->trace_level  = AV_LOG_TRACE;
110
111
126
    *ctx_ptr = ctx;
112
126
    return 0;
113
}
114
115
126
void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
116
{
117
126
    CodedBitstreamContext *ctx = *ctx_ptr;
118
119
126
    if (!ctx)
120
        return;
121
122

126
    if (ctx->codec && ctx->codec->close)
123
109
        ctx->codec->close(ctx);
124
125
126
    av_freep(&ctx->write_buffer);
126
126
    av_freep(&ctx->priv_data);
127
126
    av_freep(ctx_ptr);
128
}
129
130
25566
static void cbs_unit_uninit(CodedBitstreamUnit *unit)
131
{
132
25566
    av_buffer_unref(&unit->content_ref);
133
25566
    unit->content = NULL;
134
135
25566
    av_buffer_unref(&unit->data_ref);
136
25566
    unit->data             = NULL;
137
25566
    unit->data_size        = 0;
138
25566
    unit->data_bit_padding = 0;
139
25566
}
140
141
5552
void ff_cbs_fragment_reset(CodedBitstreamFragment *frag)
142
{
143
    int i;
144
145
31118
    for (i = 0; i < frag->nb_units; i++)
146
25566
        cbs_unit_uninit(&frag->units[i]);
147
5552
    frag->nb_units = 0;
148
149
5552
    av_buffer_unref(&frag->data_ref);
150
5552
    frag->data             = NULL;
151
5552
    frag->data_size        = 0;
152
5552
    frag->data_bit_padding = 0;
153
5552
}
154
155
92
void ff_cbs_fragment_free(CodedBitstreamFragment *frag)
156
{
157
92
    ff_cbs_fragment_reset(frag);
158
159
92
    av_freep(&frag->units);
160
92
    frag->nb_units_allocated = 0;
161
92
}
162
163
5459
static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
164
                                     CodedBitstreamFragment *frag)
165
{
166
    int err, i, j;
167
168
31012
    for (i = 0; i < frag->nb_units; i++) {
169
25553
        CodedBitstreamUnit *unit = &frag->units[i];
170
171
25553
        if (ctx->decompose_unit_types) {
172
3135
            for (j = 0; j < ctx->nb_decompose_unit_types; j++) {
173
3123
                if (ctx->decompose_unit_types[j] == unit->type)
174
1036
                    break;
175
            }
176
1048
            if (j >= ctx->nb_decompose_unit_types)
177
12
                continue;
178
        }
179
180
25541
        av_buffer_unref(&unit->content_ref);
181
25541
        unit->content = NULL;
182
183

25541
        av_assert0(unit->data && unit->data_ref);
184
185
25541
        err = ctx->codec->read_unit(ctx, unit);
186
25541
        if (err == AVERROR(ENOSYS)) {
187
            av_log(ctx->log_ctx, AV_LOG_VERBOSE,
188
                   "Decomposition unimplemented for unit %d "
189
                   "(type %"PRIu32").\n", i, unit->type);
190
25541
        } else if (err < 0) {
191
            av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
192
                   "(type %"PRIu32").\n", i, unit->type);
193
            return err;
194
        }
195
    }
196
197
5459
    return 0;
198
}
199
200
445
static int cbs_fill_fragment_data(CodedBitstreamFragment *frag,
201
                                  const uint8_t *data, size_t size)
202
{
203

445
    av_assert0(!frag->data && !frag->data_ref);
204
205
445
    frag->data_ref =
206
445
        av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
207
445
    if (!frag->data_ref)
208
        return AVERROR(ENOMEM);
209
210
445
    frag->data      = frag->data_ref->data;
211
445
    frag->data_size = size;
212
213
445
    memcpy(frag->data, data, size);
214
445
    memset(frag->data + size, 0,
215
           AV_INPUT_BUFFER_PADDING_SIZE);
216
217
445
    return 0;
218
}
219
220
54
int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
221
                          CodedBitstreamFragment *frag,
222
                          const AVCodecParameters *par)
223
{
224
    int err;
225
226
54
    err = cbs_fill_fragment_data(frag, par->extradata,
227
54
                                 par->extradata_size);
228
54
    if (err < 0)
229
        return err;
230
231
54
    err = ctx->codec->split_fragment(ctx, frag, 1);
232
54
    if (err < 0)
233
        return err;
234
235
54
    return cbs_read_fragment_content(ctx, frag);
236
}
237
238
5014
int ff_cbs_read_packet(CodedBitstreamContext *ctx,
239
                       CodedBitstreamFragment *frag,
240
                       const AVPacket *pkt)
241
{
242
    int err;
243
244
5014
    if (pkt->buf) {
245
5014
        frag->data_ref = av_buffer_ref(pkt->buf);
246
5014
        if (!frag->data_ref)
247
            return AVERROR(ENOMEM);
248
249
5014
        frag->data      = pkt->data;
250
5014
        frag->data_size = pkt->size;
251
252
    } else {
253
        err = cbs_fill_fragment_data(frag, pkt->data, pkt->size);
254
        if (err < 0)
255
            return err;
256
    }
257
258
5014
    err = ctx->codec->split_fragment(ctx, frag, 0);
259
5014
    if (err < 0)
260
        return err;
261
262
5014
    return cbs_read_fragment_content(ctx, frag);
263
}
264
265
391
int ff_cbs_read(CodedBitstreamContext *ctx,
266
                CodedBitstreamFragment *frag,
267
                const uint8_t *data, size_t size)
268
{
269
    int err;
270
271
391
    err = cbs_fill_fragment_data(frag, data, size);
272
391
    if (err < 0)
273
        return err;
274
275
391
    err = ctx->codec->split_fragment(ctx, frag, 0);
276
391
    if (err < 0)
277
        return err;
278
279
391
    return cbs_read_fragment_content(ctx, frag);
280
}
281
282
24505
static int cbs_write_unit_data(CodedBitstreamContext *ctx,
283
                               CodedBitstreamUnit *unit)
284
{
285
    PutBitContext pbc;
286
    int ret;
287
288
24505
    if (!ctx->write_buffer) {
289
        // Initial write buffer size is 1MB.
290
69
        ctx->write_buffer_size = 1024 * 1024;
291
292
69
    reallocate_and_try_again:
293
69
        ret = av_reallocp(&ctx->write_buffer, ctx->write_buffer_size);
294
69
        if (ret < 0) {
295
            av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a "
296
                   "sufficiently large write buffer (last attempt "
297
                   "%"SIZE_SPECIFIER" bytes).\n", ctx->write_buffer_size);
298
            return ret;
299
        }
300
    }
301
302
24505
    init_put_bits(&pbc, ctx->write_buffer, ctx->write_buffer_size);
303
304
24505
    ret = ctx->codec->write_unit(ctx, unit, &pbc);
305
24505
    if (ret < 0) {
306
        if (ret == AVERROR(ENOSPC)) {
307
            // Overflow.
308
            if (ctx->write_buffer_size == INT_MAX / 8)
309
                return AVERROR(ENOMEM);
310
            ctx->write_buffer_size = FFMIN(2 * ctx->write_buffer_size, INT_MAX / 8);
311
            goto reallocate_and_try_again;
312
        }
313
        // Write failed for some other reason.
314
        return ret;
315
    }
316
317
    // Overflow but we didn't notice.
318
24505
    av_assert0(put_bits_count(&pbc) <= 8 * ctx->write_buffer_size);
319
320
24505
    if (put_bits_count(&pbc) % 8)
321
52
        unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8;
322
    else
323
24453
        unit->data_bit_padding = 0;
324
325
24505
    flush_put_bits(&pbc);
326
327
24505
    ret = ff_cbs_alloc_unit_data(unit, put_bits_count(&pbc) / 8);
328
24505
    if (ret < 0)
329
        return ret;
330
331
24505
    memcpy(unit->data, ctx->write_buffer, unit->data_size);
332
333
24505
    return 0;
334
}
335
336
5056
int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
337
                               CodedBitstreamFragment *frag)
338
{
339
    int err, i;
340
341
29561
    for (i = 0; i < frag->nb_units; i++) {
342
24505
        CodedBitstreamUnit *unit = &frag->units[i];
343
344
24505
        if (!unit->content)
345
            continue;
346
347
24505
        av_buffer_unref(&unit->data_ref);
348
24505
        unit->data = NULL;
349
350
24505
        err = cbs_write_unit_data(ctx, unit);
351
24505
        if (err < 0) {
352
            av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
353
                   "(type %"PRIu32").\n", i, unit->type);
354
            return err;
355
        }
356

24505
        av_assert0(unit->data && unit->data_ref);
357
    }
358
359
5056
    av_buffer_unref(&frag->data_ref);
360
5056
    frag->data = NULL;
361
362
5056
    err = ctx->codec->assemble_fragment(ctx, frag);
363
5056
    if (err < 0) {
364
        av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
365
        return err;
366
    }
367

5056
    av_assert0(frag->data && frag->data_ref);
368
369
5056
    return 0;
370
}
371
372
54
int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
373
                           AVCodecParameters *par,
374
                           CodedBitstreamFragment *frag)
375
{
376
    int err;
377
378
54
    err = ff_cbs_write_fragment_data(ctx, frag);
379
54
    if (err < 0)
380
        return err;
381
382
54
    av_freep(&par->extradata);
383
384
54
    par->extradata = av_malloc(frag->data_size +
385
                               AV_INPUT_BUFFER_PADDING_SIZE);
386
54
    if (!par->extradata)
387
        return AVERROR(ENOMEM);
388
389
54
    memcpy(par->extradata, frag->data, frag->data_size);
390
54
    memset(par->extradata + frag->data_size, 0,
391
           AV_INPUT_BUFFER_PADDING_SIZE);
392
54
    par->extradata_size = frag->data_size;
393
394
54
    return 0;
395
}
396
397
5002
int ff_cbs_write_packet(CodedBitstreamContext *ctx,
398
                        AVPacket *pkt,
399
                        CodedBitstreamFragment *frag)
400
{
401
    AVBufferRef *buf;
402
    int err;
403
404
5002
    err = ff_cbs_write_fragment_data(ctx, frag);
405
5002
    if (err < 0)
406
        return err;
407
408
5002
    buf = av_buffer_ref(frag->data_ref);
409
5002
    if (!buf)
410
        return AVERROR(ENOMEM);
411
412
5002
    av_buffer_unref(&pkt->buf);
413
414
5002
    pkt->buf  = buf;
415
5002
    pkt->data = frag->data;
416
5002
    pkt->size = frag->data_size;
417
418
5002
    return 0;
419
}
420
421
422
59969
void ff_cbs_trace_header(CodedBitstreamContext *ctx,
423
                         const char *name)
424
{
425
59969
    if (!ctx->trace_enable)
426
59969
        return;
427
428
    av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
429
}
430
431
void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, int position,
432
                                 const char *str, const int *subscripts,
433
                                 const char *bits, int64_t value)
434
{
435
    char name[256];
436
    size_t name_len, bits_len;
437
    int pad, subs, i, j, k, n;
438
439
    if (!ctx->trace_enable)
440
        return;
441
442
    av_assert0(value >= INT_MIN && value <= UINT32_MAX);
443
444
    subs = subscripts ? subscripts[0] : 0;
445
    n = 0;
446
    for (i = j = 0; str[i];) {
447
        if (str[i] == '[') {
448
            if (n < subs) {
449
                ++n;
450
                k = snprintf(name + j, sizeof(name) - j, "[%d", subscripts[n]);
451
                av_assert0(k > 0 && j + k < sizeof(name));
452
                j += k;
453
                for (++i; str[i] && str[i] != ']'; i++);
454
                av_assert0(str[i] == ']');
455
            } else {
456
                while (str[i] && str[i] != ']')
457
                    name[j++] = str[i++];
458
                av_assert0(str[i] == ']');
459
            }
460
        } else {
461
            av_assert0(j + 1 < sizeof(name));
462
            name[j++] = str[i++];
463
        }
464
    }
465
    av_assert0(j + 1 < sizeof(name));
466
    name[j] = 0;
467
    av_assert0(n == subs);
468
469
    name_len = strlen(name);
470
    bits_len = strlen(bits);
471
472
    if (name_len + bits_len > 60)
473
        pad = bits_len + 2;
474
    else
475
        pad = 61 - name_len;
476
477
    av_log(ctx->log_ctx, ctx->trace_level, "%-10d  %s%*s = %"PRId64"\n",
478
           position, name, pad, bits, value);
479
}
480
481
463893
int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc,
482
                         int width, const char *name,
483
                         const int *subscripts, uint32_t *write_to,
484
                         uint32_t range_min, uint32_t range_max)
485
{
486
    uint32_t value;
487
    int position;
488
489

463893
    av_assert0(width > 0 && width <= 32);
490
491
463893
    if (get_bits_left(gbc) < width) {
492
        av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
493
               "%s: bitstream ended.\n", name);
494
        return AVERROR_INVALIDDATA;
495
    }
496
497
463893
    if (ctx->trace_enable)
498
        position = get_bits_count(gbc);
499
500
463893
    value = get_bits_long(gbc, width);
501
502
463893
    if (ctx->trace_enable) {
503
        char bits[33];
504
        int i;
505
        for (i = 0; i < width; i++)
506
            bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
507
        bits[i] = 0;
508
509
        ff_cbs_trace_syntax_element(ctx, position, name, subscripts,
510
                                    bits, value);
511
    }
512
513

463893
    if (value < range_min || value > range_max) {
514
        av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
515
               "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
516
               name, value, range_min, range_max);
517
        return AVERROR_INVALIDDATA;
518
    }
519
520
463893
    *write_to = value;
521
463893
    return 0;
522
}
523
524
404485
int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
525
                          int width, const char *name,
526
                          const int *subscripts, uint32_t value,
527
                          uint32_t range_min, uint32_t range_max)
528
{
529

404485
    av_assert0(width > 0 && width <= 32);
530
531

404485
    if (value < range_min || value > range_max) {
532
        av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
533
               "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
534
               name, value, range_min, range_max);
535
        return AVERROR_INVALIDDATA;
536
    }
537
538
404485
    if (put_bits_left(pbc) < width)
539
        return AVERROR(ENOSPC);
540
541
404485
    if (ctx->trace_enable) {
542
        char bits[33];
543
        int i;
544
        for (i = 0; i < width; i++)
545
            bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
546
        bits[i] = 0;
547
548
        ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
549
                                    name, subscripts, bits, value);
550
    }
551
552
404485
    if (width < 32)
553
403881
        put_bits(pbc, width, value);
554
    else
555
604
        put_bits32(pbc, value);
556
557
404485
    return 0;
558
}
559
560
50
int ff_cbs_read_signed(CodedBitstreamContext *ctx, GetBitContext *gbc,
561
                       int width, const char *name,
562
                       const int *subscripts, int32_t *write_to,
563
                       int32_t range_min, int32_t range_max)
564
{
565
    int32_t value;
566
    int position;
567
568

50
    av_assert0(width > 0 && width <= 32);
569
570
50
    if (get_bits_left(gbc) < width) {
571
        av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
572
               "%s: bitstream ended.\n", name);
573
        return AVERROR_INVALIDDATA;
574
    }
575
576
50
    if (ctx->trace_enable)
577
        position = get_bits_count(gbc);
578
579
50
    value = get_sbits_long(gbc, width);
580
581
50
    if (ctx->trace_enable) {
582
        char bits[33];
583
        int i;
584
        for (i = 0; i < width; i++)
585
            bits[i] = value & (1U << (width - i - 1)) ? '1' : '0';
586
        bits[i] = 0;
587
588
        ff_cbs_trace_syntax_element(ctx, position, name, subscripts,
589
                                    bits, value);
590
    }
591
592

50
    if (value < range_min || value > range_max) {
593
        av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
594
               "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
595
               name, value, range_min, range_max);
596
        return AVERROR_INVALIDDATA;
597
    }
598
599
50
    *write_to = value;
600
50
    return 0;
601
}
602
603
50
int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
604
                        int width, const char *name,
605
                        const int *subscripts, int32_t value,
606
                        int32_t range_min, int32_t range_max)
607
{
608

50
    av_assert0(width > 0 && width <= 32);
609
610

50
    if (value < range_min || value > range_max) {
611
        av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
612
               "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
613
               name, value, range_min, range_max);
614
        return AVERROR_INVALIDDATA;
615
    }
616
617
50
    if (put_bits_left(pbc) < width)
618
        return AVERROR(ENOSPC);
619
620
50
    if (ctx->trace_enable) {
621
        char bits[33];
622
        int i;
623
        for (i = 0; i < width; i++)
624
            bits[i] = value & (1U << (width - i - 1)) ? '1' : '0';
625
        bits[i] = 0;
626
627
        ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
628
                                    name, subscripts, bits, value);
629
    }
630
631
50
    if (width < 32)
632
50
        put_sbits(pbc, width, value);
633
    else
634
        put_bits32(pbc, value);
635
636
50
    return 0;
637
}
638
639
640
25541
int ff_cbs_alloc_unit_content(CodedBitstreamUnit *unit,
641
                              size_t size,
642
                              void (*free)(void *opaque, uint8_t *data))
643
{
644

25541
    av_assert0(!unit->content && !unit->content_ref);
645
646
25541
    unit->content = av_mallocz(size);
647
25541
    if (!unit->content)
648
        return AVERROR(ENOMEM);
649
650
25541
    unit->content_ref = av_buffer_create(unit->content, size,
651
                                         free, NULL, 0);
652
25541
    if (!unit->content_ref) {
653
        av_freep(&unit->content);
654
        return AVERROR(ENOMEM);
655
    }
656
657
25541
    return 0;
658
}
659
660
24505
int ff_cbs_alloc_unit_data(CodedBitstreamUnit *unit,
661
                           size_t size)
662
{
663

24505
    av_assert0(!unit->data && !unit->data_ref);
664
665
24505
    unit->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
666
24505
    if (!unit->data_ref)
667
        return AVERROR(ENOMEM);
668
669
24505
    unit->data      = unit->data_ref->data;
670
24505
    unit->data_size = size;
671
672
24505
    memset(unit->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
673
674
24505
    return 0;
675
}
676
677
25566
static int cbs_insert_unit(CodedBitstreamFragment *frag,
678
                           int position)
679
{
680
    CodedBitstreamUnit *units;
681
682
25566
    if (frag->nb_units < frag->nb_units_allocated) {
683
25296
        units = frag->units;
684
685
25296
        if (position < frag->nb_units)
686
            memmove(units + position + 1, units + position,
687
                    (frag->nb_units - position) * sizeof(*units));
688
    } else {
689
270
        units = av_malloc_array(frag->nb_units*2 + 1, sizeof(*units));
690
270
        if (!units)
691
            return AVERROR(ENOMEM);
692
693
270
        frag->nb_units_allocated = 2*frag->nb_units_allocated + 1;
694
695
270
        if (position > 0)
696
179
            memcpy(units, frag->units, position * sizeof(*units));
697
698
270
        if (position < frag->nb_units)
699
            memcpy(units + position + 1, frag->units + position,
700
                   (frag->nb_units - position) * sizeof(*units));
701
    }
702
703
25566
    memset(units + position, 0, sizeof(*units));
704
705
25566
    if (units != frag->units) {
706
270
        av_free(frag->units);
707
270
        frag->units = units;
708
    }
709
710
25566
    ++frag->nb_units;
711
712
25566
    return 0;
713
}
714
715
13
int ff_cbs_insert_unit_content(CodedBitstreamFragment *frag,
716
                               int position,
717
                               CodedBitstreamUnitType type,
718
                               void *content,
719
                               AVBufferRef *content_buf)
720
{
721
    CodedBitstreamUnit *unit;
722
    AVBufferRef *content_ref;
723
    int err;
724
725
13
    if (position == -1)
726
13
        position = frag->nb_units;
727

13
    av_assert0(position >= 0 && position <= frag->nb_units);
728
729
13
    if (content_buf) {
730
13
        content_ref = av_buffer_ref(content_buf);
731
13
        if (!content_ref)
732
            return AVERROR(ENOMEM);
733
    } else {
734
        content_ref = NULL;
735
    }
736
737
13
    err = cbs_insert_unit(frag, position);
738
13
    if (err < 0) {
739
        av_buffer_unref(&content_ref);
740
        return err;
741
    }
742
743
13
    unit = &frag->units[position];
744
13
    unit->type        = type;
745
13
    unit->content     = content;
746
13
    unit->content_ref = content_ref;
747
748
13
    return 0;
749
}
750
751
25553
int ff_cbs_insert_unit_data(CodedBitstreamFragment *frag,
752
                            int position,
753
                            CodedBitstreamUnitType type,
754
                            uint8_t *data, size_t data_size,
755
                            AVBufferRef *data_buf)
756
{
757
    CodedBitstreamUnit *unit;
758
    AVBufferRef *data_ref;
759
    int err;
760
761
25553
    if (position == -1)
762
16710
        position = frag->nb_units;
763

25553
    av_assert0(position >= 0 && position <= frag->nb_units);
764
765
25553
    if (data_buf)
766
25553
        data_ref = av_buffer_ref(data_buf);
767
    else
768
        data_ref = av_buffer_create(data, data_size, NULL, NULL, 0);
769
25553
    if (!data_ref) {
770
        if (!data_buf)
771
            av_free(data);
772
        return AVERROR(ENOMEM);
773
    }
774
775
25553
    err = cbs_insert_unit(frag, position);
776
25553
    if (err < 0) {
777
        av_buffer_unref(&data_ref);
778
        return err;
779
    }
780
781
25553
    unit = &frag->units[position];
782
25553
    unit->type      = type;
783
25553
    unit->data      = data;
784
25553
    unit->data_size = data_size;
785
25553
    unit->data_ref  = data_ref;
786
787
25553
    return 0;
788
}
789
790
void ff_cbs_delete_unit(CodedBitstreamFragment *frag,
791
                        int position)
792
{
793
    av_assert0(0 <= position && position < frag->nb_units
794
                             && "Unit to be deleted not in fragment.");
795
796
    cbs_unit_uninit(&frag->units[position]);
797
798
    --frag->nb_units;
799
800
    if (frag->nb_units > 0)
801
        memmove(frag->units + position,
802
                frag->units + position + 1,
803
                (frag->nb_units - position) * sizeof(*frag->units));
804
}