Coverage Report

Created: 2026-07-12 08:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/packetizer/av1.c
Line
Count
Source
1
/*****************************************************************************
2
 * av1.c: AV1 video packetizer
3
 *****************************************************************************
4
 * Copyright (C) 2018 VideoLabs, VLC authors and VideoLAN
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this program; if not, write to the Free Software Foundation,
18
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19
 *****************************************************************************/
20
21
/*****************************************************************************
22
 * Preamble
23
 *****************************************************************************/
24
25
#ifdef HAVE_CONFIG_H
26
# include "config.h"
27
#endif
28
29
#include <vlc_common.h>
30
#include <vlc_plugin.h>
31
#include <vlc_codec.h>
32
#include <vlc_block.h>
33
#include <vlc_bits.h>
34
35
#include <vlc_block_helper.h>
36
37
#include "av1.h"
38
#include "av1_obu.h"
39
40
//#define DEBUG_AV1_PACKETIZER
41
42
/****************************************************************************
43
 * Local prototypes
44
 ****************************************************************************/
45
typedef struct
46
{
47
    struct
48
    {
49
        block_t *p_chain;
50
        block_t **pp_chain_last;
51
    } obus;
52
53
    block_t *p_sequence_header_block;
54
    av1_OBU_sequence_header_t *p_sequence_header;
55
    bool b_sequence_header_changed;
56
    struct
57
    {
58
        bool b_has_visible_frame;
59
        struct
60
        {
61
            block_t *p_chain;
62
            block_t **pp_chain_last;
63
        } pre, frame, post;
64
        vlc_tick_t dts;
65
        vlc_tick_t pts;
66
    } tu;
67
    uint32_t i_seen;
68
    int i_next_block_flags;
69
70
} av1_sys_t;
71
72
644k
#define BLOCK_FLAG_DROP (1 << BLOCK_FLAG_PRIVATE_SHIFT)
73
74
/****************************************************************************
75
 * Helpers
76
 ****************************************************************************/
77
static inline void InitQueue(block_t **pp_head, block_t ***ppp_tail)
78
353k
{
79
353k
    *pp_head = NULL;
80
353k
    *ppp_tail = pp_head;
81
353k
}
82
83
static bool block_Differs(const block_t *a, const block_t *b)
84
15.2k
{
85
15.2k
    return (a->i_buffer != b->i_buffer ||
86
12.9k
            memcmp(a->p_buffer, b->p_buffer, a->i_buffer));
87
15.2k
}
88
89
353k
#define INITQ(name) InitQueue(&p_sys->name.p_chain, &p_sys->name.pp_chain_last)
90
380k
#define PUSHQ(name,b) \
91
380k
{\
92
380k
    block_ChainLastAppend(&p_sys->name.pp_chain_last, b);\
93
380k
    if(p_sys->tu.dts == VLC_TICK_INVALID)\
94
380k
    {\
95
325k
        p_sys->tu.dts = b->i_dts;\
96
325k
        p_sys->tu.pts = b->i_pts;\
97
325k
    }\
98
380k
}
99
100
static void UpdateDecoderFormat(decoder_t *p_dec)
101
312k
{
102
312k
    av1_sys_t *p_sys = p_dec->p_sys;
103
312k
    if(!p_sys->p_sequence_header)
104
68.9k
        return;
105
106
243k
    if(p_dec->fmt_in->i_profile < AV1_PROFILE_MAIN)
107
243k
    {
108
243k
        int val[3];
109
243k
        AV1_get_profile_level(p_sys->p_sequence_header, &val[0], &val[1], &val[2]);
110
243k
        if(p_dec->fmt_out.i_profile != val[0] || p_dec->fmt_out.i_level != val[1])
111
2.05k
        {
112
2.05k
            p_dec->fmt_out.i_profile = val[0];
113
2.05k
            p_dec->fmt_out.i_level = val[1];
114
2.05k
        }
115
243k
    }
116
117
243k
    unsigned wnum, hden;
118
243k
    AV1_get_frame_max_dimensions(p_sys->p_sequence_header, &wnum, &hden);
119
243k
    if((!p_dec->fmt_in->video.i_visible_height ||
120
211k
        !p_dec->fmt_in->video.i_visible_width ||
121
211k
        p_sys->b_sequence_header_changed) &&
122
33.2k
       (p_dec->fmt_out.video.i_visible_width != wnum ||
123
31.1k
        p_dec->fmt_out.video.i_visible_width != hden))
124
15.6k
    {
125
15.6k
        p_dec->fmt_out.video.i_width =
126
15.6k
        p_dec->fmt_out.video.i_visible_width = wnum;
127
15.6k
        p_dec->fmt_out.video.i_height =
128
15.6k
        p_dec->fmt_out.video.i_visible_height = hden;
129
15.6k
    }
130
131
243k
    if((!p_dec->fmt_in->video.i_frame_rate ||
132
185k
        !p_dec->fmt_in->video.i_frame_rate_base) &&
133
63.5k
        AV1_get_frame_rate(p_sys->p_sequence_header, &wnum, &hden) &&
134
295
        (p_dec->fmt_out.video.i_frame_rate != wnum ||
135
273
         p_dec->fmt_out.video.i_frame_rate_base != hden))
136
22
    {
137
22
        p_dec->fmt_out.video.i_frame_rate = wnum;
138
22
        p_dec->fmt_out.video.i_frame_rate_base = hden;
139
22
    }
140
141
243k
    video_color_primaries_t prim;
142
243k
    video_color_space_t space;
143
243k
    video_transfer_func_t xfer;
144
243k
    video_color_range_t full;
145
243k
    if(p_dec->fmt_in->video.primaries == COLOR_PRIMARIES_UNDEF &&
146
243k
       AV1_get_colorimetry(p_sys->p_sequence_header, &prim, &xfer, &space, &full) &&
147
16.6k
       prim != COLOR_PRIMARIES_UNDEF &&
148
1.08k
       (p_dec->fmt_out.video.primaries != prim ||
149
961
        p_dec->fmt_out.video.transfer != xfer ||
150
902
        p_dec->fmt_out.video.space != space))
151
187
    {
152
187
        p_dec->fmt_out.video.primaries = prim;
153
187
        p_dec->fmt_out.video.transfer = xfer;
154
187
        p_dec->fmt_out.video.space = space;
155
187
        p_dec->fmt_out.video.color_range = full;
156
187
    }
157
158
243k
    if (p_sys->b_sequence_header_changed && p_dec->fmt_out.p_extra)
159
2.82k
    {
160
2.82k
        free(p_dec->fmt_out.p_extra);
161
2.82k
        p_dec->fmt_out.i_extra = 0;
162
2.82k
        p_dec->fmt_out.p_extra = NULL;
163
2.82k
    }
164
165
243k
    if(p_dec->fmt_out.i_extra <= 4)
166
3.40k
    {
167
3.40k
        free(p_dec->fmt_out.p_extra);
168
3.40k
        p_dec->fmt_out.i_extra =
169
3.40k
                AV1_create_DecoderConfigurationRecord((uint8_t **)&p_dec->fmt_out.p_extra,
170
3.40k
                                                      p_sys->p_sequence_header,
171
3.40k
                                                      1,
172
3.40k
                                                      (const uint8_t **)&p_sys->p_sequence_header_block->p_buffer,
173
3.40k
                                                      &p_sys->p_sequence_header_block->i_buffer);
174
3.40k
    }
175
243k
    p_sys->b_sequence_header_changed = false;
176
243k
}
177
178
static block_t * OutputQueues(decoder_t *p_dec, bool b_valid)
179
314k
{
180
314k
    av1_sys_t *p_sys = p_dec->p_sys;
181
314k
    block_t *p_output = NULL;
182
314k
    block_t **pp_output_last = &p_output;
183
314k
    uint32_t i_flags = 0; /* Because block_ChainGather does not merge flags or times */
184
185
314k
    if(p_sys->tu.pre.p_chain)
186
310k
    {
187
310k
        block_ChainLastAppend(&pp_output_last, p_sys->tu.pre.p_chain);
188
310k
        INITQ(tu.pre);
189
310k
    }
190
191
314k
    if(p_sys->tu.frame.p_chain)
192
39.6k
    {
193
39.6k
        i_flags |= p_sys->tu.frame.p_chain->i_flags;
194
39.6k
        block_ChainLastAppend(&pp_output_last, p_sys->tu.frame.p_chain);
195
39.6k
        INITQ(tu.frame);
196
39.6k
    }
197
198
314k
    if(p_sys->tu.post.p_chain)
199
0
    {
200
0
        block_ChainLastAppend(&pp_output_last, p_sys->tu.post.p_chain);
201
0
        INITQ(tu.post);
202
0
    }
203
204
314k
    if(p_output)
205
312k
    {
206
312k
        p_output->i_dts = p_sys->tu.dts;
207
312k
        p_output->i_pts = p_sys->tu.pts;
208
312k
        p_output->i_flags |= i_flags;
209
312k
        if(!b_valid)
210
19.9k
            p_output->i_flags |= BLOCK_FLAG_DROP;
211
292k
        else
212
292k
        {
213
292k
            p_output->i_flags |= p_sys->i_next_block_flags;
214
292k
            p_sys->i_next_block_flags = 0;
215
292k
        }
216
312k
    }
217
218
314k
    p_sys->tu.b_has_visible_frame = false;
219
314k
    p_sys->tu.dts = VLC_TICK_INVALID;
220
314k
    p_sys->tu.pts = VLC_TICK_INVALID;
221
314k
    p_sys->i_seen = 0;
222
223
314k
    return p_output;
224
314k
}
225
226
/****************************************************************************
227
 * Packetizer Helpers
228
 ****************************************************************************/
229
static block_t *GatherAndValidateChain(decoder_t *p_dec, block_t *p_outputchain)
230
312k
{
231
312k
    block_t *p_output = NULL;
232
312k
    av1_sys_t *p_sys = p_dec->p_sys;
233
312k
    VLC_UNUSED(p_sys);
234
235
312k
    if(p_outputchain)
236
312k
    {
237
#ifdef DEBUG_AV1_PACKETIZER
238
        msg_Dbg(p_dec, "TU output %" PRId64, p_outputchain->i_dts);
239
        for(block_t *p = p_outputchain; p; p=p->p_next)
240
        {
241
            enum av1_obu_type_e OBUtype = AV1_OBUGetType(p->p_buffer);
242
            if(OBUtype == AV1_OBU_FRAME || OBUtype == AV1_OBU_FRAME_HEADER)
243
            {
244
                av1_OBU_frame_header_t *p_fh = NULL;
245
                if(AV1_OBUIsBaseLayer(p->p_buffer, p->i_buffer) && p_sys->p_sequence_header)
246
                {
247
                    p_fh = AV1_OBU_parse_frame_header(p->p_buffer, p->i_buffer,
248
                                                      p_sys->p_sequence_header);
249
                    if(p_fh)
250
                    {
251
                        msg_Dbg(p_dec,"OBU TYPE %d sz %zu dts %" PRId64 " type %d %d",
252
                                OBUtype, p->i_buffer, p->i_dts,
253
                                AV1_get_frame_type(p_fh),
254
                                AV1_get_frame_visibility(p_fh));
255
                    }
256
                    AV1_release_frame_header(p_fh);
257
                }
258
            }
259
            else msg_Dbg(p_dec, "OBU TYPE %d sz %zu dts %" PRId64, OBUtype, p->i_buffer, p->i_dts);
260
        }
261
#endif
262
312k
        if(p_outputchain->i_flags & BLOCK_FLAG_DROP)
263
19.9k
            p_output = p_outputchain; /* Avoid useless gather */
264
292k
        else
265
292k
            p_output = block_ChainGather(p_outputchain);
266
312k
    }
267
268
312k
    if(p_output && (p_output->i_flags & BLOCK_FLAG_DROP))
269
19.9k
    {
270
19.9k
        block_ChainRelease(p_output); /* Chain! see above */
271
19.9k
        p_output = NULL;
272
19.9k
    }
273
274
312k
    return p_output;
275
312k
}
276
277
static block_t *ParseOBUBlock(decoder_t *p_dec, block_t *p_obu)
278
538k
{
279
538k
    av1_sys_t *p_sys = p_dec->p_sys;
280
281
538k
    block_t * p_output = NULL;
282
538k
    enum av1_obu_type_e OBUtype = AV1_OBUGetType(p_obu->p_buffer);
283
538k
    const bool b_base_layer = AV1_OBUIsBaseLayer(p_obu->p_buffer, p_obu->i_buffer);
284
285
538k
    switch(OBUtype)
286
538k
    {
287
18.9k
        case AV1_OBU_SEQUENCE_HEADER:
288
18.9k
        {
289
18.9k
            if(p_sys->tu.frame.p_chain || p_sys->tu.post.p_chain)
290
1.66k
                p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL);
291
292
18.9k
            if(b_base_layer)
293
15.8k
            {
294
                /* Save a copy for Extradata */
295
15.8k
                if(!p_sys->p_sequence_header_block ||
296
15.2k
                   block_Differs(p_sys->p_sequence_header_block, p_obu))
297
11.9k
                {
298
11.9k
                    if(p_sys->p_sequence_header_block)
299
11.2k
                        block_Release(p_sys->p_sequence_header_block);
300
11.9k
                    p_sys->p_sequence_header_block = block_Duplicate(p_obu);
301
11.9k
                }
302
303
15.8k
                av1_OBU_sequence_header_t *new_seq_header;
304
15.8k
                new_seq_header = AV1_OBU_parse_sequence_header(p_obu->p_buffer, p_obu->i_buffer);
305
15.8k
                if (likely(new_seq_header))
306
9.66k
                {
307
9.66k
                    if (!p_sys->p_sequence_header ||
308
9.07k
                        !AV1_sequence_header_equal(p_sys->p_sequence_header, new_seq_header))
309
6.06k
                    {
310
6.06k
                        if (p_sys->p_sequence_header)
311
5.47k
                        {
312
5.47k
                            AV1_release_sequence_header(p_sys->p_sequence_header);
313
5.47k
                            p_sys->b_sequence_header_changed = true;
314
5.47k
                        }
315
6.06k
                        p_sys->p_sequence_header = new_seq_header;
316
6.06k
                    }
317
3.59k
                    else AV1_release_sequence_header(new_seq_header);
318
9.66k
                }
319
15.8k
            }
320
18.9k
            PUSHQ(tu.pre, p_obu);
321
18.9k
        } break;
322
323
309k
        case AV1_OBU_TEMPORAL_DELIMITER:
324
309k
        {
325
309k
            p_output = OutputQueues(p_dec, p_sys->p_sequence_header_block != NULL);
326
309k
            PUSHQ(tu.pre, p_obu);
327
309k
        } break;
328
329
21.5k
        case AV1_OBU_FRAME:
330
30.3k
        case AV1_OBU_FRAME_HEADER:
331
30.3k
        {
332
30.3k
            if(b_base_layer)
333
20.8k
            {
334
20.8k
                av1_OBU_frame_header_t *p_fh = NULL;
335
20.8k
                if(p_sys->p_sequence_header)
336
17.6k
                {
337
17.6k
                    p_fh = AV1_OBU_parse_frame_header(p_obu->p_buffer, p_obu->i_buffer,
338
17.6k
                                                      p_sys->p_sequence_header);
339
17.6k
                    if(p_fh)
340
17.6k
                    {
341
17.6k
                        if((p_sys->i_seen & AV1_OBU_TEMPORAL_DELIMITER) && p_sys->tu.b_has_visible_frame)
342
1.35k
                            p_output = OutputQueues(p_dec, true);
343
344
17.6k
                        switch(AV1_get_frame_type(p_fh))
345
17.6k
                        {
346
13.2k
                            case AV1_FRAME_TYPE_KEY:
347
14.3k
                            case AV1_FRAME_TYPE_INTRA_ONLY:
348
14.3k
                                p_obu->i_flags |= BLOCK_FLAG_TYPE_I;
349
14.3k
                                break;
350
2.98k
                            case AV1_FRAME_TYPE_INTER:
351
2.98k
                                p_obu->i_flags |= BLOCK_FLAG_TYPE_P;
352
2.98k
                                break;
353
282
                            default:
354
282
                                break;
355
17.6k
                        }
356
357
17.6k
                        p_sys->tu.b_has_visible_frame |= AV1_get_frame_visibility(p_fh);
358
17.6k
                        AV1_release_frame_header(p_fh);
359
17.6k
                    }
360
17.6k
                    else msg_Warn(p_dec, "could not parse frame header");
361
17.6k
                }
362
20.8k
            }
363
364
30.3k
            if(!p_output && p_sys->tu.post.p_chain)
365
0
                p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL);
366
367
30.3k
            PUSHQ(tu.frame, p_obu);
368
30.3k
        } break;
369
370
6.58k
        case AV1_OBU_METADATA:
371
6.58k
        {
372
6.58k
            if(p_sys->tu.frame.p_chain || p_sys->tu.post.p_chain)
373
25
                p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL);
374
6.58k
            PUSHQ(tu.pre, p_obu);
375
6.58k
        } break;
376
377
7.11k
        case AV1_OBU_TILE_GROUP:
378
15.4k
        case AV1_OBU_TILE_LIST:
379
15.4k
            if(p_sys->tu.post.p_chain)
380
0
                p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL);
381
15.4k
            PUSHQ(tu.frame, p_obu);
382
15.4k
            break;
383
384
8.22k
        case AV1_OBU_REDUNDANT_FRAME_HEADER:
385
14.4k
        case AV1_OBU_PADDING:
386
158k
        default:
387
158k
            block_Release(p_obu);
388
158k
            break;
389
538k
    }
390
391
538k
    if(b_base_layer)
392
480k
        p_sys->i_seen |= 1 << OBUtype;
393
394
538k
    return p_output;
395
538k
}
396
397
/****************************************************************************
398
 * Flush
399
 ****************************************************************************/
400
static void PacketizeFlush(decoder_t *p_dec)
401
609
{
402
609
    av1_sys_t *p_sys = p_dec->p_sys;
403
404
609
    block_ChainRelease(OutputQueues(p_dec, false));
405
406
609
    if(p_sys->p_sequence_header)
407
590
    {
408
590
        AV1_release_sequence_header(p_sys->p_sequence_header);
409
590
        p_sys->p_sequence_header = NULL;
410
590
        p_sys->b_sequence_header_changed = true;
411
590
    }
412
609
    if(p_sys->p_sequence_header_block)
413
603
    {
414
603
        block_Release(p_sys->p_sequence_header_block);
415
603
        p_sys->p_sequence_header_block = NULL;
416
603
    }
417
418
609
    block_ChainRelease(p_sys->obus.p_chain);
419
609
    INITQ(obus);
420
421
609
    p_sys->tu.dts = VLC_TICK_INVALID;
422
609
    p_sys->tu.pts = VLC_TICK_INVALID;
423
609
    p_sys->tu.b_has_visible_frame = false;
424
609
    p_sys->i_seen = 0;
425
609
    p_sys->i_next_block_flags = BLOCK_FLAG_DISCONTINUITY;
426
609
}
427
428
/****************************************************************************
429
 * Packetize
430
 ****************************************************************************/
431
static block_t *PacketizeOBU(decoder_t *p_dec, block_t **pp_block)
432
1.22M
{
433
1.22M
    av1_sys_t *p_sys = p_dec->p_sys;
434
435
1.22M
    block_t *p_block = pp_block ? *pp_block : NULL;
436
1.22M
    if(p_block)
437
935k
    {
438
935k
        if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
439
0
        {
440
            /* First always drain complete blocks before discontinuity */
441
0
            block_t *p_drain = PacketizeOBU( p_dec, NULL );
442
0
            if(p_drain)
443
0
                return p_drain;
444
445
0
            PacketizeFlush( p_dec );
446
447
0
            if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
448
0
            {
449
0
                block_Release( p_block );
450
0
                return NULL;
451
0
            }
452
0
        }
453
454
935k
        if(!AV1_OBUIsValid(p_block->p_buffer, p_block->i_buffer))
455
624k
        {
456
624k
            msg_Warn(p_dec,"fed with invalid OBU");
457
624k
            block_Release(p_block);
458
624k
            return NULL;
459
624k
        }
460
311k
        *pp_block = NULL;
461
311k
        block_ChainLastAppend(&p_sys->obus.pp_chain_last, p_block);
462
311k
    }
463
464
604k
    block_t *p_output = NULL;
465
934k
    while(p_sys->obus.p_chain)
466
641k
    {
467
641k
        block_t *p_frag = p_sys->obus.p_chain;
468
469
641k
        AV1_OBU_iterator_ctx_t it;
470
641k
        AV1_OBU_iterator_init(&it, p_frag->p_buffer, p_frag->i_buffer);
471
641k
        const uint8_t *p_obu; size_t i_obu;
472
473
641k
        if(!AV1_OBU_iterate_next(&it, &p_obu, &i_obu))
474
102k
        {
475
102k
            msg_Warn(p_dec,"Invalid OBU header in sequence, discarding");
476
            /* frag is not OBU, drop */
477
102k
            p_sys->obus.p_chain = p_frag->p_next;
478
102k
            if(p_frag->p_next == NULL)
479
98.7k
                p_sys->obus.pp_chain_last = &p_sys->obus.p_chain;
480
4.06k
            else
481
4.06k
                p_frag->p_next = NULL;
482
102k
            block_Release(p_frag);
483
102k
            continue;
484
102k
        }
485
486
538k
        block_t *p_obublock;
487
538k
        if(i_obu == p_frag->i_buffer)
488
208k
        {
489
208k
            p_sys->obus.p_chain = p_frag->p_next;
490
208k
            if(p_frag->p_next == NULL)
491
194k
                p_sys->obus.pp_chain_last = &p_sys->obus.p_chain;
492
14.2k
            else
493
14.2k
                p_frag->p_next = NULL;
494
208k
            p_obublock = p_frag;
495
208k
        }
496
330k
        else
497
330k
        {
498
330k
            p_obublock = block_Alloc(i_obu);
499
330k
            memcpy(p_obublock->p_buffer, p_frag->p_buffer, i_obu);
500
330k
            p_frag->i_buffer -= i_obu;
501
330k
            p_frag->p_buffer += i_obu;
502
330k
            p_obublock->i_dts = p_frag->i_dts;
503
330k
            p_obublock->i_pts = p_frag->i_pts;
504
330k
            p_obublock->i_flags = p_frag->i_flags;
505
330k
            p_frag->i_flags = 0;
506
330k
            p_frag->i_dts = VLC_TICK_INVALID;
507
330k
            p_frag->i_pts = VLC_TICK_INVALID;
508
330k
        }
509
510
538k
        p_output = ParseOBUBlock(p_dec, p_obublock);
511
538k
        if(p_output)
512
311k
            break;
513
538k
    }
514
515
516
604k
    if(!p_output && pp_block == NULL)
517
1.21k
        p_output = OutputQueues(p_dec, p_sys->p_sequence_header_block != NULL);
518
519
604k
    if(p_output)
520
312k
    {
521
312k
        p_output = GatherAndValidateChain(p_dec, p_output);
522
312k
        UpdateDecoderFormat(p_dec);
523
312k
    }
524
525
604k
    return p_output;
526
1.22M
}
527
528
/*****************************************************************************
529
 * Close
530
 *****************************************************************************/
531
static void Close(vlc_object_t *p_this)
532
609
{
533
609
    decoder_t *p_dec = (decoder_t*)p_this;
534
609
    av1_sys_t *p_sys = p_dec->p_sys;
535
536
609
    PacketizeFlush(p_dec);
537
538
609
    free(p_sys);
539
609
}
540
541
/*****************************************************************************
542
 * Open
543
 *****************************************************************************/
544
static int Open(vlc_object_t *p_this)
545
9.48k
{
546
9.48k
    decoder_t *p_dec = (decoder_t*)p_this;
547
9.48k
    av1_sys_t *p_sys;
548
549
9.48k
    if (p_dec->fmt_in->i_codec != VLC_CODEC_AV1)
550
8.87k
        return VLC_EGENERIC;
551
552
609
    p_dec->p_sys = p_sys = calloc(1, sizeof(av1_sys_t));
553
609
    if (!p_dec->p_sys)
554
0
        return VLC_ENOMEM;
555
556
609
    INITQ(obus);
557
609
    p_sys->p_sequence_header_block = NULL;
558
609
    p_sys->p_sequence_header = NULL;
559
609
    p_sys->b_sequence_header_changed = false;
560
609
    p_sys->tu.b_has_visible_frame = false;
561
609
    p_sys->tu.dts = VLC_TICK_INVALID;
562
609
    p_sys->tu.pts = VLC_TICK_INVALID;
563
609
    p_sys->i_seen = 0;
564
609
    p_sys->i_next_block_flags = 0;
565
609
    INITQ(tu.pre);
566
609
    INITQ(tu.frame);
567
609
    INITQ(tu.post);
568
569
    /* Copy properties */
570
609
    es_format_Copy(&p_dec->fmt_out, p_dec->fmt_in);
571
609
    p_dec->fmt_out.b_packetized = true;
572
573
609
    p_dec->pf_packetize = PacketizeOBU;
574
609
    p_dec->pf_flush = PacketizeFlush;
575
576
609
    return VLC_SUCCESS;
577
609
}
578
579
/*****************************************************************************
580
 * Module descriptor
581
 *****************************************************************************/
582
583
168
vlc_module_begin ()
584
84
    set_subcategory(SUBCAT_SOUT_PACKETIZER)
585
84
    set_description(N_("AV1 video packetizer"))
586
84
    set_capability("video packetizer", 50)
587
168
    set_callbacks(Open, Close)
588
84
vlc_module_end ()