Coverage Report

Created: 2026-11-12 07:28

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
1.51M
#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
886k
{
79
886k
    *pp_head = NULL;
80
886k
    *ppp_tail = pp_head;
81
886k
}
82
83
static bool block_Differs(const block_t *a, const block_t *b)
84
66.2k
{
85
66.2k
    return (a->i_buffer != b->i_buffer ||
86
50.4k
            memcmp(a->p_buffer, b->p_buffer, a->i_buffer));
87
66.2k
}
88
89
886k
#define INITQ(name) InitQueue(&p_sys->name.p_chain, &p_sys->name.pp_chain_last)
90
924k
#define PUSHQ(name,b) \
91
924k
{\
92
924k
    block_ChainLastAppend(&p_sys->name.pp_chain_last, b);\
93
924k
    if(p_sys->tu.dts == VLC_TICK_INVALID)\
94
924k
    {\
95
764k
        p_sys->tu.dts = b->i_dts;\
96
764k
        p_sys->tu.pts = b->i_pts;\
97
764k
    }\
98
924k
}
99
100
static void UpdateDecoderFormat(decoder_t *p_dec)
101
750k
{
102
750k
    av1_sys_t *p_sys = p_dec->p_sys;
103
750k
    if(!p_sys->p_sequence_header)
104
141k
        return;
105
106
609k
    if(p_dec->fmt_in->i_profile < AV1_PROFILE_MAIN)
107
609k
    {
108
609k
        int val[3];
109
609k
        AV1_get_profile_level(p_sys->p_sequence_header, &val[0], &val[1], &val[2]);
110
609k
        if(p_dec->fmt_out.i_profile != val[0] || p_dec->fmt_out.i_level != val[1])
111
23.1k
        {
112
23.1k
            p_dec->fmt_out.i_profile = val[0];
113
23.1k
            p_dec->fmt_out.i_level = val[1];
114
23.1k
        }
115
609k
    }
116
117
609k
    unsigned wnum, hden;
118
609k
    AV1_get_frame_max_dimensions(p_sys->p_sequence_header, &wnum, &hden);
119
609k
    if((!p_dec->fmt_in->video.i_visible_height ||
120
533k
        !p_dec->fmt_in->video.i_visible_width ||
121
522k
        p_sys->b_sequence_header_changed) &&
122
102k
       (p_dec->fmt_out.video.i_visible_width != wnum ||
123
86.3k
        p_dec->fmt_out.video.i_visible_width != hden))
124
80.6k
    {
125
80.6k
        p_dec->fmt_out.video.i_width =
126
80.6k
        p_dec->fmt_out.video.i_visible_width = wnum;
127
80.6k
        p_dec->fmt_out.video.i_height =
128
80.6k
        p_dec->fmt_out.video.i_visible_height = hden;
129
80.6k
    }
130
131
609k
    if((!p_dec->fmt_in->video.i_frame_rate ||
132
399k
        !p_dec->fmt_in->video.i_frame_rate_base) &&
133
238k
        AV1_get_frame_rate(p_sys->p_sequence_header, &wnum, &hden) &&
134
3.10k
        (p_dec->fmt_out.video.i_frame_rate != wnum ||
135
2.77k
         p_dec->fmt_out.video.i_frame_rate_base != hden))
136
330
    {
137
330
        p_dec->fmt_out.video.i_frame_rate = wnum;
138
330
        p_dec->fmt_out.video.i_frame_rate_base = hden;
139
330
    }
140
141
609k
    video_color_primaries_t prim;
142
609k
    video_color_space_t space;
143
609k
    video_transfer_func_t xfer;
144
609k
    video_color_range_t full;
145
609k
    if(p_dec->fmt_in->video.primaries == COLOR_PRIMARIES_UNDEF &&
146
609k
       AV1_get_colorimetry(p_sys->p_sequence_header, &prim, &xfer, &space, &full) &&
147
93.5k
       prim != COLOR_PRIMARIES_UNDEF &&
148
6.82k
       (p_dec->fmt_out.video.primaries != prim ||
149
6.40k
        p_dec->fmt_out.video.transfer != xfer ||
150
6.29k
        p_dec->fmt_out.video.space != space))
151
559
    {
152
559
        p_dec->fmt_out.video.primaries = prim;
153
559
        p_dec->fmt_out.video.transfer = xfer;
154
559
        p_dec->fmt_out.video.space = space;
155
559
        p_dec->fmt_out.video.color_range = full;
156
559
    }
157
158
609k
    if (p_sys->b_sequence_header_changed && p_dec->fmt_out.p_extra)
159
25.0k
    {
160
25.0k
        free(p_dec->fmt_out.p_extra);
161
25.0k
        p_dec->fmt_out.i_extra = 0;
162
25.0k
        p_dec->fmt_out.p_extra = NULL;
163
25.0k
    }
164
165
609k
    if(p_dec->fmt_out.i_extra <= 4)
166
32.6k
    {
167
32.6k
        free(p_dec->fmt_out.p_extra);
168
32.6k
        p_dec->fmt_out.i_extra =
169
32.6k
                AV1_create_DecoderConfigurationRecord((uint8_t **)&p_dec->fmt_out.p_extra,
170
32.6k
                                                      p_sys->p_sequence_header,
171
32.6k
                                                      1,
172
32.6k
                                                      (const uint8_t **)&p_sys->p_sequence_header_block->p_buffer,
173
32.6k
                                                      &p_sys->p_sequence_header_block->i_buffer);
174
32.6k
    }
175
609k
    p_sys->b_sequence_header_changed = false;
176
609k
}
177
178
static block_t * OutputQueues(decoder_t *p_dec, bool b_valid)
179
768k
{
180
768k
    av1_sys_t *p_sys = p_dec->p_sys;
181
768k
    block_t *p_output = NULL;
182
768k
    block_t **pp_output_last = &p_output;
183
768k
    uint32_t i_flags = 0; /* Because block_ChainGather does not merge flags or times */
184
185
768k
    if(p_sys->tu.pre.p_chain)
186
747k
    {
187
747k
        block_ChainLastAppend(&pp_output_last, p_sys->tu.pre.p_chain);
188
747k
        INITQ(tu.pre);
189
747k
    }
190
191
768k
    if(p_sys->tu.frame.p_chain)
192
95.2k
    {
193
95.2k
        i_flags |= p_sys->tu.frame.p_chain->i_flags;
194
95.2k
        block_ChainLastAppend(&pp_output_last, p_sys->tu.frame.p_chain);
195
95.2k
        INITQ(tu.frame);
196
95.2k
    }
197
198
768k
    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
768k
    if(p_output)
205
750k
    {
206
750k
        p_output->i_dts = p_sys->tu.dts;
207
750k
        p_output->i_pts = p_sys->tu.pts;
208
750k
        p_output->i_flags |= i_flags;
209
750k
        if(!b_valid)
210
17.3k
            p_output->i_flags |= BLOCK_FLAG_DROP;
211
733k
        else
212
733k
        {
213
733k
            p_output->i_flags |= p_sys->i_next_block_flags;
214
733k
            p_sys->i_next_block_flags = 0;
215
733k
        }
216
750k
    }
217
218
768k
    p_sys->tu.b_has_visible_frame = false;
219
768k
    p_sys->tu.dts = VLC_TICK_INVALID;
220
768k
    p_sys->tu.pts = VLC_TICK_INVALID;
221
768k
    p_sys->i_seen = 0;
222
223
768k
    return p_output;
224
768k
}
225
226
/****************************************************************************
227
 * Packetizer Helpers
228
 ****************************************************************************/
229
static block_t *GatherAndValidateChain(decoder_t *p_dec, block_t *p_outputchain)
230
750k
{
231
750k
    block_t *p_output = NULL;
232
750k
    av1_sys_t *p_sys = p_dec->p_sys;
233
750k
    VLC_UNUSED(p_sys);
234
235
750k
    if(p_outputchain)
236
750k
    {
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
750k
        if(p_outputchain->i_flags & BLOCK_FLAG_DROP)
263
17.3k
            p_output = p_outputchain; /* Avoid useless gather */
264
733k
        else
265
733k
            p_output = block_ChainGather(p_outputchain);
266
750k
    }
267
268
750k
    if(p_output && (p_output->i_flags & BLOCK_FLAG_DROP))
269
17.3k
    {
270
17.3k
        block_ChainRelease(p_output); /* Chain! see above */
271
17.3k
        p_output = NULL;
272
17.3k
    }
273
274
750k
    return p_output;
275
750k
}
276
277
static block_t *ParseOBUBlock(decoder_t *p_dec, block_t *p_obu)
278
1.40M
{
279
1.40M
    av1_sys_t *p_sys = p_dec->p_sys;
280
281
1.40M
    block_t * p_output = NULL;
282
1.40M
    enum av1_obu_type_e OBUtype = AV1_OBUGetType(p_obu->p_buffer);
283
1.40M
    const bool b_base_layer = AV1_OBUIsBaseLayer(p_obu->p_buffer, p_obu->i_buffer);
284
285
1.40M
    switch(OBUtype)
286
1.40M
    {
287
82.0k
        case AV1_OBU_SEQUENCE_HEADER:
288
82.0k
        {
289
82.0k
            if(p_sys->tu.frame.p_chain || p_sys->tu.post.p_chain)
290
17.2k
                p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL);
291
292
82.0k
            if(b_base_layer)
293
73.9k
            {
294
                /* Save a copy for Extradata */
295
73.9k
                if(!p_sys->p_sequence_header_block ||
296
66.2k
                   block_Differs(p_sys->p_sequence_header_block, p_obu))
297
62.9k
                {
298
62.9k
                    if(p_sys->p_sequence_header_block)
299
55.3k
                        block_Release(p_sys->p_sequence_header_block);
300
62.9k
                    p_sys->p_sequence_header_block = block_Duplicate(p_obu);
301
62.9k
                }
302
303
73.9k
                av1_OBU_sequence_header_t *new_seq_header;
304
73.9k
                new_seq_header = AV1_OBU_parse_sequence_header(p_obu->p_buffer, p_obu->i_buffer);
305
73.9k
                if (likely(new_seq_header))
306
55.6k
                {
307
55.6k
                    if (!p_sys->p_sequence_header ||
308
48.0k
                        !AV1_sequence_header_equal(p_sys->p_sequence_header, new_seq_header))
309
41.5k
                    {
310
41.5k
                        if (p_sys->p_sequence_header)
311
33.8k
                        {
312
33.8k
                            AV1_release_sequence_header(p_sys->p_sequence_header);
313
33.8k
                            p_sys->b_sequence_header_changed = true;
314
33.8k
                        }
315
41.5k
                        p_sys->p_sequence_header = new_seq_header;
316
41.5k
                    }
317
14.1k
                    else AV1_release_sequence_header(new_seq_header);
318
55.6k
                }
319
73.9k
            }
320
82.0k
            PUSHQ(tu.pre, p_obu);
321
82.0k
        } break;
322
323
723k
        case AV1_OBU_TEMPORAL_DELIMITER:
324
723k
        {
325
723k
            p_output = OutputQueues(p_dec, p_sys->p_sequence_header_block != NULL);
326
723k
            PUSHQ(tu.pre, p_obu);
327
723k
        } break;
328
329
61.6k
        case AV1_OBU_FRAME:
330
78.2k
        case AV1_OBU_FRAME_HEADER:
331
78.2k
        {
332
78.2k
            if(b_base_layer)
333
55.4k
            {
334
55.4k
                av1_OBU_frame_header_t *p_fh = NULL;
335
55.4k
                if(p_sys->p_sequence_header)
336
51.0k
                {
337
51.0k
                    p_fh = AV1_OBU_parse_frame_header(p_obu->p_buffer, p_obu->i_buffer,
338
51.0k
                                                      p_sys->p_sequence_header);
339
51.0k
                    if(p_fh)
340
51.0k
                    {
341
51.0k
                        if((p_sys->i_seen & AV1_OBU_TEMPORAL_DELIMITER) && p_sys->tu.b_has_visible_frame)
342
2.82k
                            p_output = OutputQueues(p_dec, true);
343
344
51.0k
                        switch(AV1_get_frame_type(p_fh))
345
51.0k
                        {
346
43.3k
                            case AV1_FRAME_TYPE_KEY:
347
44.3k
                            case AV1_FRAME_TYPE_INTRA_ONLY:
348
44.3k
                                p_obu->i_flags |= BLOCK_FLAG_TYPE_I;
349
44.3k
                                break;
350
5.94k
                            case AV1_FRAME_TYPE_INTER:
351
5.94k
                                p_obu->i_flags |= BLOCK_FLAG_TYPE_P;
352
5.94k
                                break;
353
667
                            default:
354
667
                                break;
355
51.0k
                        }
356
357
51.0k
                        p_sys->tu.b_has_visible_frame |= AV1_get_frame_visibility(p_fh);
358
51.0k
                        AV1_release_frame_header(p_fh);
359
51.0k
                    }
360
51.0k
                    else msg_Warn(p_dec, "could not parse frame header");
361
51.0k
                }
362
55.4k
            }
363
364
78.2k
            if(!p_output && p_sys->tu.post.p_chain)
365
0
                p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL);
366
367
78.2k
            PUSHQ(tu.frame, p_obu);
368
78.2k
        } break;
369
370
11.4k
        case AV1_OBU_METADATA:
371
11.4k
        {
372
11.4k
            if(p_sys->tu.frame.p_chain || p_sys->tu.post.p_chain)
373
78
                p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL);
374
11.4k
            PUSHQ(tu.pre, p_obu);
375
11.4k
        } break;
376
377
15.0k
        case AV1_OBU_TILE_GROUP:
378
28.7k
        case AV1_OBU_TILE_LIST:
379
28.7k
            if(p_sys->tu.post.p_chain)
380
0
                p_output = OutputQueues(p_dec, p_sys->p_sequence_header != NULL);
381
28.7k
            PUSHQ(tu.frame, p_obu);
382
28.7k
            break;
383
384
13.0k
        case AV1_OBU_REDUNDANT_FRAME_HEADER:
385
23.6k
        case AV1_OBU_PADDING:
386
485k
        default:
387
485k
            block_Release(p_obu);
388
485k
            break;
389
1.40M
    }
390
391
1.40M
    if(b_base_layer)
392
1.30M
        p_sys->i_seen |= 1 << OBUtype;
393
394
1.40M
    return p_output;
395
1.40M
}
396
397
/****************************************************************************
398
 * Flush
399
 ****************************************************************************/
400
static void PacketizeFlush(decoder_t *p_dec)
401
8.73k
{
402
8.73k
    av1_sys_t *p_sys = p_dec->p_sys;
403
404
8.73k
    block_ChainRelease(OutputQueues(p_dec, false));
405
406
8.73k
    if(p_sys->p_sequence_header)
407
7.65k
    {
408
7.65k
        AV1_release_sequence_header(p_sys->p_sequence_header);
409
7.65k
        p_sys->p_sequence_header = NULL;
410
7.65k
        p_sys->b_sequence_header_changed = true;
411
7.65k
    }
412
8.73k
    if(p_sys->p_sequence_header_block)
413
7.67k
    {
414
7.67k
        block_Release(p_sys->p_sequence_header_block);
415
7.67k
        p_sys->p_sequence_header_block = NULL;
416
7.67k
    }
417
418
8.73k
    block_ChainRelease(p_sys->obus.p_chain);
419
8.73k
    INITQ(obus);
420
421
8.73k
    p_sys->tu.dts = VLC_TICK_INVALID;
422
8.73k
    p_sys->tu.pts = VLC_TICK_INVALID;
423
8.73k
    p_sys->tu.b_has_visible_frame = false;
424
8.73k
    p_sys->i_seen = 0;
425
8.73k
    p_sys->i_next_block_flags = BLOCK_FLAG_DISCONTINUITY;
426
8.73k
}
427
428
/****************************************************************************
429
 * Packetize
430
 ****************************************************************************/
431
static block_t *PacketizeOBU(decoder_t *p_dec, block_t **pp_block)
432
2.49M
{
433
2.49M
    av1_sys_t *p_sys = p_dec->p_sys;
434
435
2.49M
    block_t *p_block = pp_block ? *pp_block : NULL;
436
2.49M
    if(p_block)
437
1.75M
    {
438
1.75M
        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
1.75M
        if(!AV1_OBUIsValid(p_block->p_buffer, p_block->i_buffer))
455
993k
        {
456
993k
            msg_Warn(p_dec,"fed with invalid OBU");
457
993k
            block_Release(p_block);
458
993k
            return NULL;
459
993k
        }
460
764k
        *pp_block = NULL;
461
764k
        block_ChainLastAppend(&p_sys->obus.pp_chain_last, p_block);
462
764k
    }
463
464
1.50M
    block_t *p_output = NULL;
465
2.33M
    while(p_sys->obus.p_chain)
466
1.57M
    {
467
1.57M
        block_t *p_frag = p_sys->obus.p_chain;
468
469
1.57M
        AV1_OBU_iterator_ctx_t it;
470
1.57M
        AV1_OBU_iterator_init(&it, p_frag->p_buffer, p_frag->i_buffer);
471
1.57M
        const uint8_t *p_obu; size_t i_obu;
472
473
1.57M
        if(!AV1_OBU_iterate_next(&it, &p_obu, &i_obu))
474
164k
        {
475
164k
            msg_Warn(p_dec,"Invalid OBU header in sequence, discarding");
476
            /* frag is not OBU, drop */
477
164k
            p_sys->obus.p_chain = p_frag->p_next;
478
164k
            if(p_frag->p_next == NULL)
479
161k
                p_sys->obus.pp_chain_last = &p_sys->obus.p_chain;
480
3.27k
            else
481
3.27k
                p_frag->p_next = NULL;
482
164k
            block_Release(p_frag);
483
164k
            continue;
484
164k
        }
485
486
1.40M
        block_t *p_obublock;
487
1.40M
        if(i_obu == p_frag->i_buffer)
488
599k
        {
489
599k
            p_sys->obus.p_chain = p_frag->p_next;
490
599k
            if(p_frag->p_next == NULL)
491
586k
                p_sys->obus.pp_chain_last = &p_sys->obus.p_chain;
492
13.2k
            else
493
13.2k
                p_frag->p_next = NULL;
494
599k
            p_obublock = p_frag;
495
599k
        }
496
809k
        else
497
809k
        {
498
809k
            p_obublock = block_Alloc(i_obu);
499
809k
            memcpy(p_obublock->p_buffer, p_frag->p_buffer, i_obu);
500
809k
            p_frag->i_buffer -= i_obu;
501
809k
            p_frag->p_buffer += i_obu;
502
809k
            p_obublock->i_dts = p_frag->i_dts;
503
809k
            p_obublock->i_pts = p_frag->i_pts;
504
809k
            p_obublock->i_flags = p_frag->i_flags;
505
809k
            p_frag->i_flags = 0;
506
809k
            p_frag->i_dts = VLC_TICK_INVALID;
507
809k
            p_frag->i_pts = VLC_TICK_INVALID;
508
809k
        }
509
510
1.40M
        p_output = ParseOBUBlock(p_dec, p_obublock);
511
1.40M
        if(p_output)
512
742k
            break;
513
1.40M
    }
514
515
516
1.50M
    if(!p_output && pp_block == NULL)
517
16.4k
        p_output = OutputQueues(p_dec, p_sys->p_sequence_header_block != NULL);
518
519
1.50M
    if(p_output)
520
750k
    {
521
750k
        p_output = GatherAndValidateChain(p_dec, p_output);
522
750k
        UpdateDecoderFormat(p_dec);
523
750k
    }
524
525
1.50M
    return p_output;
526
2.49M
}
527
528
/*****************************************************************************
529
 * Close
530
 *****************************************************************************/
531
static void Close(vlc_object_t *p_this)
532
8.73k
{
533
8.73k
    decoder_t *p_dec = (decoder_t*)p_this;
534
8.73k
    av1_sys_t *p_sys = p_dec->p_sys;
535
536
8.73k
    PacketizeFlush(p_dec);
537
538
8.73k
    free(p_sys);
539
8.73k
}
540
541
/*****************************************************************************
542
 * Open
543
 *****************************************************************************/
544
static int Open(vlc_object_t *p_this)
545
47.2k
{
546
47.2k
    decoder_t *p_dec = (decoder_t*)p_this;
547
47.2k
    av1_sys_t *p_sys;
548
549
47.2k
    if (p_dec->fmt_in->i_codec != VLC_CODEC_AV1)
550
38.5k
        return VLC_EGENERIC;
551
552
8.73k
    p_dec->p_sys = p_sys = calloc(1, sizeof(av1_sys_t));
553
8.73k
    if (!p_dec->p_sys)
554
0
        return VLC_ENOMEM;
555
556
8.73k
    INITQ(obus);
557
8.73k
    p_sys->p_sequence_header_block = NULL;
558
8.73k
    p_sys->p_sequence_header = NULL;
559
8.73k
    p_sys->b_sequence_header_changed = false;
560
8.73k
    p_sys->tu.b_has_visible_frame = false;
561
8.73k
    p_sys->tu.dts = VLC_TICK_INVALID;
562
8.73k
    p_sys->tu.pts = VLC_TICK_INVALID;
563
8.73k
    p_sys->i_seen = 0;
564
8.73k
    p_sys->i_next_block_flags = 0;
565
8.73k
    INITQ(tu.pre);
566
8.73k
    INITQ(tu.frame);
567
8.73k
    INITQ(tu.post);
568
569
    /* Copy properties */
570
8.73k
    es_format_Copy(&p_dec->fmt_out, p_dec->fmt_in);
571
8.73k
    p_dec->fmt_out.b_packetized = true;
572
573
8.73k
    p_dec->pf_packetize = PacketizeOBU;
574
8.73k
    p_dec->pf_flush = PacketizeFlush;
575
576
8.73k
    return VLC_SUCCESS;
577
8.73k
}
578
579
/*****************************************************************************
580
 * Module descriptor
581
 *****************************************************************************/
582
583
178
vlc_module_begin ()
584
89
    set_subcategory(SUBCAT_SOUT_PACKETIZER)
585
89
    set_description(N_("AV1 video packetizer"))
586
89
    set_capability("video packetizer", 50)
587
178
    set_callbacks(Open, Close)
588
89
vlc_module_end ()