Coverage Report

Created: 2026-02-14 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/cbs_vp9.c
Line
Count
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 "libavutil/avassert.h"
20
21
#include "cbs.h"
22
#include "cbs_internal.h"
23
#include "cbs_vp9.h"
24
25
26
static int cbs_vp9_read_s(CodedBitstreamContext *ctx, GetBitContext *gbc,
27
                          int width, const char *name,
28
                          const int *subscripts, int32_t *write_to)
29
3.39M
{
30
3.39M
    uint32_t magnitude;
31
3.39M
    int sign;
32
3.39M
    int32_t value;
33
34
3.39M
    CBS_TRACE_READ_START();
35
36
3.39M
    if (get_bits_left(gbc) < width + 1) {
37
9.42k
        av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid signed value at "
38
9.42k
               "%s: bitstream ended.\n", name);
39
9.42k
        return AVERROR_INVALIDDATA;
40
9.42k
    }
41
42
3.38M
    magnitude = get_bits(gbc, width);
43
3.38M
    sign      = get_bits1(gbc);
44
3.38M
    value     = sign ? -(int32_t)magnitude : magnitude;
45
46
3.38M
    CBS_TRACE_READ_END();
47
48
3.38M
    *write_to = value;
49
3.38M
    return 0;
50
3.38M
}
51
52
static int cbs_vp9_write_s(CodedBitstreamContext *ctx, PutBitContext *pbc,
53
                           int width, const char *name,
54
                           const int *subscripts, int32_t value)
55
15.8k
{
56
15.8k
    uint32_t magnitude;
57
15.8k
    int sign;
58
59
15.8k
    CBS_TRACE_WRITE_START();
60
61
15.8k
    if (put_bits_left(pbc) < width + 1)
62
0
        return AVERROR(ENOSPC);
63
64
15.8k
    sign      = value < 0;
65
15.8k
    magnitude = sign ? -value : value;
66
67
15.8k
    put_bits(pbc, width, magnitude);
68
15.8k
    put_bits(pbc, 1, sign);
69
70
15.8k
    CBS_TRACE_WRITE_END();
71
72
15.8k
    return 0;
73
15.8k
}
74
75
static int cbs_vp9_read_increment(CodedBitstreamContext *ctx, GetBitContext *gbc,
76
                                  uint32_t range_min, uint32_t range_max,
77
                                  const char *name, uint32_t *write_to)
78
2.85M
{
79
2.85M
    uint32_t value;
80
81
2.85M
    CBS_TRACE_READ_START();
82
83
2.85M
    av_assert0(range_min <= range_max && range_max - range_min < 32);
84
85
2.97M
    for (value = range_min; value < range_max;) {
86
2.19M
        if (get_bits_left(gbc) < 1) {
87
3.96k
            av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid increment value at "
88
3.96k
                   "%s: bitstream ended.\n", name);
89
3.96k
            return AVERROR_INVALIDDATA;
90
3.96k
        }
91
2.18M
        if (get_bits1(gbc))
92
124k
            ++value;
93
2.06M
        else
94
2.06M
            break;
95
2.18M
    }
96
97
2.85M
    CBS_TRACE_READ_END_NO_SUBSCRIPTS();
98
99
2.85M
    *write_to = value;
100
2.85M
    return 0;
101
2.85M
}
102
103
static int cbs_vp9_write_increment(CodedBitstreamContext *ctx, PutBitContext *pbc,
104
                                   uint32_t range_min, uint32_t range_max,
105
                                   const char *name, uint32_t value)
106
21.2k
{
107
21.2k
    int len;
108
109
21.2k
    CBS_TRACE_WRITE_START();
110
111
21.2k
    av_assert0(range_min <= range_max && range_max - range_min < 8);
112
21.2k
    if (value < range_min || value > range_max) {
113
504
        av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
114
504
               "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
115
504
               name, value, range_min, range_max);
116
504
        return AVERROR_INVALIDDATA;
117
504
    }
118
119
20.7k
    if (value == range_max)
120
6.07k
        len = range_max - range_min;
121
14.6k
    else
122
14.6k
        len = value - range_min + 1;
123
20.7k
    if (put_bits_left(pbc) < len)
124
0
        return AVERROR(ENOSPC);
125
126
20.7k
    if (len > 0)
127
15.9k
        put_bits(pbc, len, (1 << len) - 1 - (value != range_max));
128
129
20.7k
    CBS_TRACE_WRITE_END_NO_SUBSCRIPTS();
130
131
20.7k
    return 0;
132
20.7k
}
133
134
static int cbs_vp9_read_le(CodedBitstreamContext *ctx, GetBitContext *gbc,
135
                           int width, const char *name,
136
                           const int *subscripts, uint32_t *write_to)
137
94.9k
{
138
94.9k
    uint32_t value;
139
94.9k
    int b;
140
141
94.9k
    CBS_TRACE_READ_START();
142
143
94.9k
    av_assert0(width % 8 == 0);
144
145
94.9k
    if (get_bits_left(gbc) < width) {
146
8.23k
        av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid le value at "
147
8.23k
               "%s: bitstream ended.\n", name);
148
8.23k
        return AVERROR_INVALIDDATA;
149
8.23k
    }
150
151
86.7k
    value = 0;
152
244k
    for (b = 0; b < width; b += 8)
153
157k
        value |= get_bits(gbc, 8) << b;
154
155
86.7k
    CBS_TRACE_READ_END();
156
157
86.7k
    *write_to = value;
158
86.7k
    return 0;
159
86.7k
}
160
161
static int cbs_vp9_write_le(CodedBitstreamContext *ctx, PutBitContext *pbc,
162
                            int width, const char *name,
163
                            const int *subscripts, uint32_t value)
164
6.15k
{
165
6.15k
    int b;
166
167
6.15k
    CBS_TRACE_WRITE_START();
168
169
6.15k
    av_assert0(width % 8 == 0);
170
171
6.15k
    if (put_bits_left(pbc) < width)
172
0
        return AVERROR(ENOSPC);
173
174
13.4k
    for (b = 0; b < width; b += 8)
175
7.25k
        put_bits(pbc, 8, value >> b & 0xff);
176
177
6.15k
    CBS_TRACE_WRITE_END();
178
179
6.15k
    return 0;
180
6.15k
}
181
182
2.19M
#define HEADER(name) do { \
183
2.19M
        ff_cbs_trace_header(ctx, name); \
184
2.19M
    } while (0)
185
186
110M
#define CHECK(call) do { \
187
110M
        err = (call); \
188
110M
        if (err < 0) \
189
110M
            return err; \
190
110M
    } while (0)
191
192
#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
193
#define FUNC_VP9(rw, name) FUNC_NAME(rw, vp9, name)
194
#define FUNC(name) FUNC_VP9(READWRITE, name)
195
196
#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
197
198
#define s(width, name) \
199
        xs(width, name, current->name, 0, )
200
#define fs(width, name, subs, ...) \
201
21.3M
        xf(width, name, current->name, subs, __VA_ARGS__)
202
#define ss(width, name, subs, ...) \
203
852k
        xs(width, name, current->name, subs, __VA_ARGS__)
204
205
#define READ
206
#define READWRITE read
207
#define RWContext GetBitContext
208
209
43.3M
#define f(width, name) do { \
210
43.3M
        uint32_t value; \
211
43.3M
        CHECK(ff_cbs_read_simple_unsigned(ctx, rw, width, #name, \
212
43.3M
                                          &value)); \
213
43.3M
        current->name = value; \
214
43.1M
    } while (0)
215
39.5M
#define xf(width, name, var, subs, ...) do { \
216
39.5M
        uint32_t value; \
217
39.5M
        CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
218
39.5M
                                   SUBSCRIPTS(subs, __VA_ARGS__), \
219
39.5M
                                   &value, 0, (1 << width) - 1)); \
220
39.5M
        var = value; \
221
39.4M
    } while (0)
222
3.39M
#define xs(width, name, var, subs, ...) do { \
223
3.39M
        int32_t value; \
224
3.39M
        CHECK(cbs_vp9_read_s(ctx, rw, width, #name, \
225
3.39M
                             SUBSCRIPTS(subs, __VA_ARGS__), &value)); \
226
3.39M
        var = value; \
227
3.38M
    } while (0)
228
229
230
2.85M
#define increment(name, min, max) do { \
231
2.85M
        uint32_t value; \
232
2.85M
        CHECK(cbs_vp9_read_increment(ctx, rw, min, max, #name, &value)); \
233
2.85M
        current->name = value; \
234
2.85M
    } while (0)
235
236
94.9k
#define fle(width, name, subs, ...) do { \
237
94.9k
        CHECK(cbs_vp9_read_le(ctx, rw, width, #name, \
238
94.9k
                              SUBSCRIPTS(subs, __VA_ARGS__), &current->name)); \
239
94.9k
    } while (0)
240
241
4.36M
#define delta_q(name) do { \
242
4.36M
        uint8_t delta_coded; \
243
4.36M
        int8_t delta_q; \
244
4.36M
        xf(1, name.delta_coded, delta_coded, 0, ); \
245
4.36M
        if (delta_coded) \
246
4.36M
            xs(4, name.delta_q, delta_q, 0, ); \
247
4.36M
        else \
248
4.36M
            delta_q = 0; \
249
4.36M
        current->name = delta_q; \
250
4.35M
    } while (0)
251
252
8.37M
#define prob(name, subs, ...) do { \
253
8.37M
        uint8_t prob_coded; \
254
8.37M
        uint8_t prob; \
255
8.37M
        xf(1, name.prob_coded, prob_coded, subs, __VA_ARGS__); \
256
8.37M
        if (prob_coded) \
257
8.36M
            xf(8, name.prob, prob, subs, __VA_ARGS__); \
258
8.36M
        else \
259
8.36M
            prob = 255; \
260
8.36M
        current->name = prob; \
261
8.36M
    } while (0)
262
263
6.30M
#define fixed(width, name, value) do { \
264
6.30M
        av_unused uint32_t fixed_value; \
265
6.30M
        CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
266
6.30M
                                   0, &fixed_value, value, value)); \
267
6.30M
    } while (0)
268
269
14.4M
#define infer(name, value) do { \
270
14.4M
        current->name = value; \
271
14.4M
    } while (0)
272
273
6.78M
#define byte_alignment(rw) (get_bits_count(rw) % 8)
274
275
#include "cbs_vp9_syntax_template.c"
276
277
#undef READ
278
#undef READWRITE
279
#undef RWContext
280
#undef f
281
#undef xf
282
#undef xs
283
#undef increment
284
#undef fle
285
#undef delta_q
286
#undef prob
287
#undef fixed
288
#undef infer
289
#undef byte_alignment
290
291
292
#define WRITE
293
#define READWRITE write
294
#define RWContext PutBitContext
295
296
295k
#define f(width, name) do { \
297
295k
        CHECK(ff_cbs_write_simple_unsigned(ctx, rw, width, #name, \
298
295k
                                           current->name)); \
299
295k
    } while (0)
300
189k
#define xf(width, name, var, subs, ...) do { \
301
189k
        CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
302
189k
                                    SUBSCRIPTS(subs, __VA_ARGS__), \
303
189k
                                    var, 0, (1 << width) - 1)); \
304
189k
    } while (0)
305
15.8k
#define xs(width, name, var, subs, ...) do { \
306
15.8k
        CHECK(cbs_vp9_write_s(ctx, rw, width, #name, \
307
15.8k
                              SUBSCRIPTS(subs, __VA_ARGS__), var)); \
308
15.8k
    } while (0)
309
310
21.2k
#define increment(name, min, max) do { \
311
21.2k
        CHECK(cbs_vp9_write_increment(ctx, rw, min, max, #name, current->name)); \
312
21.2k
    } while (0)
313
314
6.15k
#define fle(width, name, subs, ...) do { \
315
6.15k
        CHECK(cbs_vp9_write_le(ctx, rw, width, #name, \
316
6.15k
                               SUBSCRIPTS(subs, __VA_ARGS__), current->name)); \
317
6.15k
    } while (0)
318
319
32.6k
#define delta_q(name) do { \
320
32.6k
        xf(1, name.delta_coded, !!current->name, 0, ); \
321
32.6k
        if (current->name) \
322
32.6k
            xs(4, name.delta_q, current->name, 0, ); \
323
32.6k
    } while (0)
324
325
12.0k
#define prob(name, subs, ...) do { \
326
12.0k
        xf(1, name.prob_coded, current->name != 255, subs, __VA_ARGS__); \
327
12.0k
        if (current->name != 255) \
328
12.0k
            xf(8, name.prob, current->name, subs, __VA_ARGS__); \
329
12.0k
    } while (0)
330
331
43.7k
#define fixed(width, name, value) do { \
332
43.7k
        CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
333
43.7k
                                    0, value, value, value)); \
334
43.7k
    } while (0)
335
336
156k
#define infer(name, value) do { \
337
156k
        if (current->name != (value)) { \
338
0
            av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \
339
0
                   "%s does not match inferred value: " \
340
0
                   "%"PRId64", but should be %"PRId64".\n", \
341
0
                   #name, (int64_t)current->name, (int64_t)(value)); \
342
0
        } \
343
156k
    } while (0)
344
345
43.8k
#define byte_alignment(rw) (put_bits_count(rw) % 8)
346
347
#include "cbs_vp9_syntax_template.c"
348
349
#undef WRITE
350
#undef READWRITE
351
#undef RWContext
352
#undef f
353
#undef xf
354
#undef xs
355
#undef increment
356
#undef fle
357
#undef delta_q
358
#undef prob
359
#undef fixed
360
#undef infer
361
#undef byte_alignment
362
363
364
static int cbs_vp9_split_fragment(CodedBitstreamContext *ctx,
365
                                  CodedBitstreamFragment *frag,
366
                                  int header)
367
1.15M
{
368
1.15M
    uint8_t superframe_header;
369
1.15M
    int err;
370
371
1.15M
    if (frag->data_size == 0)
372
4.65k
        return AVERROR_INVALIDDATA;
373
374
    // Last byte in the packet.
375
1.15M
    superframe_header = frag->data[frag->data_size - 1];
376
377
1.15M
    if ((superframe_header & 0xe0) == 0xc0) {
378
34.3k
        VP9RawSuperframeIndex sfi = {0};
379
34.3k
        GetBitContext gbc;
380
34.3k
        size_t index_size, pos;
381
34.3k
        int i;
382
383
34.3k
        index_size = 2 + (((superframe_header & 0x18) >> 3) + 1) *
384
34.3k
                          ((superframe_header & 0x07) + 1);
385
386
34.3k
        if (index_size > frag->data_size)
387
8.96k
            return AVERROR_INVALIDDATA;
388
389
25.3k
        err = init_get_bits(&gbc, frag->data + frag->data_size - index_size,
390
25.3k
                            8 * index_size);
391
25.3k
        if (err < 0)
392
0
            return err;
393
394
25.3k
        err = cbs_vp9_read_superframe_index(ctx, &gbc, &sfi);
395
25.3k
        if (err < 0)
396
9.32k
            return err;
397
398
16.0k
        pos = 0;
399
44.7k
        for (i = 0; i <= sfi.frames_in_superframe_minus_1; i++) {
400
37.3k
            if (pos + sfi.frame_sizes[i] + index_size > frag->data_size) {
401
8.62k
                av_log(ctx->log_ctx, AV_LOG_ERROR, "Frame %d too large "
402
8.62k
                       "in superframe: %"PRIu32" bytes.\n",
403
8.62k
                       i, sfi.frame_sizes[i]);
404
8.62k
                return AVERROR_INVALIDDATA;
405
8.62k
            }
406
407
28.7k
            err = ff_cbs_append_unit_data(frag, 0,
408
28.7k
                                          frag->data + pos,
409
28.7k
                                          sfi.frame_sizes[i],
410
28.7k
                                          frag->data_ref);
411
28.7k
            if (err < 0)
412
0
                return err;
413
414
28.7k
            pos += sfi.frame_sizes[i];
415
28.7k
        }
416
7.39k
        if (pos + index_size != frag->data_size) {
417
5.83k
            av_log(ctx->log_ctx, AV_LOG_WARNING, "Extra padding at "
418
5.83k
                   "end of superframe: %zu bytes.\n",
419
5.83k
                   frag->data_size - (pos + index_size));
420
5.83k
        }
421
422
7.39k
        return 0;
423
424
1.11M
    } else {
425
1.11M
        err = ff_cbs_append_unit_data(frag, 0,
426
1.11M
                                      frag->data, frag->data_size,
427
1.11M
                                      frag->data_ref);
428
1.11M
        if (err < 0)
429
0
            return err;
430
1.11M
    }
431
432
1.11M
    return 0;
433
1.15M
}
434
435
static int cbs_vp9_read_unit(CodedBitstreamContext *ctx,
436
                             CodedBitstreamUnit *unit)
437
2.15M
{
438
2.15M
    VP9RawFrame *frame;
439
2.15M
    GetBitContext gbc;
440
2.15M
    int err, pos;
441
442
2.15M
    err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
443
2.15M
    if (err < 0)
444
0
        return err;
445
446
2.15M
    err = ff_cbs_alloc_unit_content(ctx, unit);
447
2.15M
    if (err < 0)
448
0
        return err;
449
2.15M
    frame = unit->content;
450
451
2.15M
    err = cbs_vp9_read_frame(ctx, &gbc, frame);
452
2.15M
    if (err < 0)
453
626k
        return err;
454
455
1.52M
    pos = get_bits_count(&gbc);
456
1.52M
    av_assert0(pos % 8 == 0);
457
1.52M
    pos /= 8;
458
1.52M
    av_assert0(pos <= unit->data_size);
459
460
1.52M
    if (pos == unit->data_size) {
461
        // No data (e.g. a show-existing-frame frame).
462
1.45M
    } else {
463
1.45M
        frame->data_ref = av_buffer_ref(unit->data_ref);
464
1.45M
        if (!frame->data_ref)
465
0
            return AVERROR(ENOMEM);
466
467
1.45M
        frame->data      = unit->data      + pos;
468
1.45M
        frame->data_size = unit->data_size - pos;
469
1.45M
    }
470
471
1.52M
    return 0;
472
1.52M
}
473
474
static int cbs_vp9_write_unit(CodedBitstreamContext *ctx,
475
                              CodedBitstreamUnit *unit,
476
                              PutBitContext *pbc)
477
17.8k
{
478
17.8k
    VP9RawFrame *frame = unit->content;
479
17.8k
    int err;
480
481
17.8k
    err = cbs_vp9_write_frame(ctx, pbc, frame);
482
17.8k
    if (err < 0)
483
504
        return err;
484
485
    // Frame must be byte-aligned.
486
17.3k
    av_assert0(put_bits_count(pbc) % 8 == 0);
487
488
17.3k
    if (frame->data) {
489
7.10k
        if (frame->data_size > put_bits_left(pbc) / 8)
490
0
            return AVERROR(ENOSPC);
491
492
7.10k
        flush_put_bits(pbc);
493
7.10k
        memcpy(put_bits_ptr(pbc), frame->data, frame->data_size);
494
7.10k
        skip_put_bytes(pbc, frame->data_size);
495
7.10k
    }
496
497
17.3k
    return 0;
498
17.3k
}
499
500
static int cbs_vp9_assemble_fragment(CodedBitstreamContext *ctx,
501
                                     CodedBitstreamFragment *frag)
502
12.7k
{
503
12.7k
    int err;
504
505
12.7k
    if (frag->nb_units == 1) {
506
        // Output is just the content of the single frame.
507
508
11.2k
        CodedBitstreamUnit *frame = &frag->units[0];
509
510
11.2k
        frag->data_ref = av_buffer_ref(frame->data_ref);
511
11.2k
        if (!frag->data_ref)
512
0
            return AVERROR(ENOMEM);
513
514
11.2k
        frag->data      = frame->data;
515
11.2k
        frag->data_size = frame->data_size;
516
517
11.2k
    } else {
518
        // Build superframe out of frames.
519
520
1.58k
        VP9RawSuperframeIndex sfi;
521
1.58k
        PutBitContext pbc;
522
1.58k
        AVBufferRef *ref;
523
1.58k
        uint8_t *data;
524
1.58k
        size_t size, max, pos;
525
1.58k
        int i, size_len;
526
527
1.58k
        if (frag->nb_units > 8) {
528
0
            av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many frames to "
529
0
                   "make superframe: %d.\n", frag->nb_units);
530
0
            return AVERROR(EINVAL);
531
0
        }
532
533
1.58k
        max = 0;
534
7.74k
        for (i = 0; i < frag->nb_units; i++)
535
6.15k
            if (max < frag->units[i].data_size)
536
2.76k
                max = frag->units[i].data_size;
537
538
1.58k
        if (max < 2)
539
268
            size_len = 1;
540
1.31k
        else
541
1.31k
            size_len = av_log2(max) / 8 + 1;
542
1.58k
        av_assert0(size_len <= 4);
543
544
1.58k
        sfi.superframe_marker            = VP9_SUPERFRAME_MARKER;
545
1.58k
        sfi.bytes_per_framesize_minus_1  = size_len - 1;
546
1.58k
        sfi.frames_in_superframe_minus_1 = frag->nb_units - 1;
547
548
1.58k
        size = 2;
549
7.74k
        for (i = 0; i < frag->nb_units; i++) {
550
6.15k
            size += size_len + frag->units[i].data_size;
551
6.15k
            sfi.frame_sizes[i] = frag->units[i].data_size;
552
6.15k
        }
553
554
1.58k
        ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
555
1.58k
        if (!ref)
556
0
            return AVERROR(ENOMEM);
557
1.58k
        data = ref->data;
558
1.58k
        memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
559
560
1.58k
        pos = 0;
561
7.74k
        for (i = 0; i < frag->nb_units; i++) {
562
6.15k
            av_assert0(size - pos > frag->units[i].data_size);
563
6.15k
            memcpy(data + pos, frag->units[i].data,
564
6.15k
                   frag->units[i].data_size);
565
6.15k
            pos += frag->units[i].data_size;
566
6.15k
        }
567
1.58k
        av_assert0(size - pos == 2 + frag->nb_units * size_len);
568
569
1.58k
        init_put_bits(&pbc, data + pos, size - pos);
570
571
1.58k
        err = cbs_vp9_write_superframe_index(ctx, &pbc, &sfi);
572
1.58k
        if (err < 0) {
573
0
            av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write "
574
0
                   "superframe index.\n");
575
0
            av_buffer_unref(&ref);
576
0
            return err;
577
0
        }
578
579
1.58k
        av_assert0(put_bits_left(&pbc) == 0);
580
1.58k
        flush_put_bits(&pbc);
581
582
1.58k
        frag->data_ref  = ref;
583
1.58k
        frag->data      = data;
584
1.58k
        frag->data_size = size;
585
1.58k
    }
586
587
12.7k
    return 0;
588
12.7k
}
589
590
static av_cold void cbs_vp9_flush(CodedBitstreamContext *ctx)
591
105k
{
592
105k
    CodedBitstreamVP9Context *vp9 = ctx->priv_data;
593
594
105k
    memset(vp9->ref, 0, sizeof(vp9->ref));
595
105k
}
596
597
static CodedBitstreamUnitTypeDescriptor cbs_vp9_unit_types[] = {
598
    CBS_UNIT_TYPE_INTERNAL_REF(0, VP9RawFrame, data),
599
    CBS_UNIT_TYPE_END_OF_LIST
600
};
601
602
const CodedBitstreamType ff_cbs_type_vp9 = {
603
    .codec_id          = AV_CODEC_ID_VP9,
604
605
    .priv_data_size    = sizeof(CodedBitstreamVP9Context),
606
607
    .unit_types        = cbs_vp9_unit_types,
608
609
    .split_fragment    = &cbs_vp9_split_fragment,
610
    .read_unit         = &cbs_vp9_read_unit,
611
    .write_unit        = &cbs_vp9_write_unit,
612
613
    .flush             = &cbs_vp9_flush,
614
615
    .assemble_fragment = &cbs_vp9_assemble_fragment,
616
};