Coverage Report

Created: 2026-06-09 09:09

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