Coverage Report

Created: 2026-06-30 07:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/codec/dav1d.c
Line
Count
Source
1
/*****************************************************************************
2
 * dav1d.c: dav1d decoder (AV1) module
3
 *****************************************************************************
4
 * Copyright (C) 2016 VLC authors and VideoLAN
5
 *
6
 * Authors: Adrien Maglo <magsoft@videolan.org>
7
 * Based on aom.c by: Tristan Matthews <tmatth@videolan.org>
8
 *
9
 * This program is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation; either version 2.1 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program; if not, write to the Free Software Foundation,
21
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22
 *****************************************************************************/
23
24
/*****************************************************************************
25
 * Preamble
26
 *****************************************************************************/
27
#ifdef HAVE_CONFIG_H
28
# include "config.h"
29
#endif
30
31
32
#include <vlc_common.h>
33
#include <vlc_plugin.h>
34
#include <vlc_codec.h>
35
#include <vlc_timestamp_helper.h>
36
37
#include <errno.h>
38
#include <dav1d/dav1d.h>
39
40
#include "../packetizer/iso_color_tables.h"
41
#include "../packetizer/av1_obu.h"
42
#include "cc.h"
43
44
/****************************************************************************
45
 * Local prototypes
46
 ****************************************************************************/
47
static int OpenDecoder(vlc_object_t *);
48
static void CloseDecoder(vlc_object_t *);
49
50
/*****************************************************************************
51
 * Module descriptor
52
 *****************************************************************************/
53
54
#define THREAD_FRAMES_TEXT N_("Frames Threads")
55
#define THREAD_FRAMES_LONGTEXT N_( "Max number of threads used for frame decoding, default 0=auto" )
56
#define THREAD_TILES_TEXT N_("Tiles Threads")
57
#define THREAD_TILES_LONGTEXT N_( "Max number of threads used for tile decoding, default 0=auto" )
58
59
60
166
vlc_module_begin ()
61
83
    set_shortname("dav1d")
62
83
    set_description(N_("Dav1d video decoder"))
63
83
    set_capability("video decoder", 10000)
64
166
    set_callbacks(OpenDecoder, CloseDecoder)
65
83
    set_subcategory(SUBCAT_INPUT_VCODEC)
66
67
83
#if DAV1D_API_VERSION_MAJOR >= 6
68
83
    add_integer_with_range("dav1d-thread-frames", 0, 0, DAV1D_MAX_THREADS,
69
83
                THREAD_FRAMES_TEXT, THREAD_FRAMES_LONGTEXT)
70
83
    add_obsolete_string("dav1d-thread-tiles") // unused with dav1d 1.0
71
#else
72
    add_integer_with_range("dav1d-thread-frames", 0, 0, DAV1D_MAX_FRAME_THREADS,
73
                THREAD_FRAMES_TEXT, THREAD_FRAMES_LONGTEXT)
74
    add_integer_with_range("dav1d-thread-tiles", 0, 0, DAV1D_MAX_TILE_THREADS,
75
                THREAD_TILES_TEXT, THREAD_TILES_LONGTEXT)
76
#endif
77
83
    add_bool( "dav1d-all-layers", false, "Display all spatial layers", NULL )
78
83
vlc_module_end ()
79
80
/*****************************************************************************
81
 * decoder_sys_t: libaom decoder descriptor
82
 *****************************************************************************/
83
typedef struct
84
{
85
    Dav1dSettings s;
86
    Dav1dContext *c;
87
    cc_data_t cc;
88
} decoder_sys_t;
89
90
struct user_data_s
91
{
92
    vlc_tick_t dts;
93
};
94
95
static void FreeUserData_Handler(const uint8_t *p, void *userdata)
96
96.5k
{
97
96.5k
    VLC_UNUSED(p);
98
96.5k
    free(userdata);
99
96.5k
}
100
101
static vlc_fourcc_t FindVlcChroma(const Dav1dPicture *img)
102
4.15k
{
103
4.15k
    static const vlc_fourcc_t chroma_table_rgb[] = { VLC_CODEC_GBR_PLANAR, VLC_CODEC_GBR_PLANAR_10L, VLC_CODEC_GBR_PLANAR_12L };
104
4.15k
    static const vlc_fourcc_t chroma_table[][3] = {
105
4.15k
        [DAV1D_PIXEL_LAYOUT_I400] = { VLC_CODEC_GREY, VLC_CODEC_GREY_10L, VLC_CODEC_GREY_12L },
106
4.15k
        [DAV1D_PIXEL_LAYOUT_I420] = { VLC_CODEC_I420, VLC_CODEC_I420_10L,  VLC_CODEC_I420_12L },
107
4.15k
        [DAV1D_PIXEL_LAYOUT_I422] = { VLC_CODEC_I422, VLC_CODEC_I422_10L,  VLC_CODEC_I422_12L },
108
4.15k
        [DAV1D_PIXEL_LAYOUT_I444] = { VLC_CODEC_I444, VLC_CODEC_I444_10L,  VLC_CODEC_I444_12L },
109
4.15k
    };
110
111
    // AV1 signals RGB with the combination of the identity matrix, the BT.709 primaries and the sRGB/YCC transfer function.
112
    // See: "5.5.2. Color config syntax" from https://aomediacodec.github.io/av1-spec/av1-spec.pdf
113
4.15k
    if( img->p.layout == DAV1D_PIXEL_LAYOUT_I444 &&
114
435
        img->seq_hdr->mtrx == DAV1D_MC_IDENTITY &&
115
48
        img->seq_hdr->pri == DAV1D_COLOR_PRI_BT709 &&
116
40
        img->seq_hdr->trc == DAV1D_TRC_SRGB )
117
40
    {
118
40
        if( img->seq_hdr->hbd >= (int)ARRAY_SIZE(chroma_table_rgb) )
119
0
            return 0;
120
40
        return chroma_table_rgb[img->seq_hdr->hbd];
121
40
    }
122
123
4.11k
    if( img->seq_hdr->layout < 0 || img->seq_hdr->layout >= (int)ARRAY_SIZE(chroma_table) )
124
0
        return 0;
125
4.11k
    if( img->seq_hdr->hbd >= (int)ARRAY_SIZE(chroma_table[0]) )
126
0
        return 0;
127
128
4.11k
    return chroma_table[img->seq_hdr->layout][img->seq_hdr->hbd];
129
4.11k
}
130
131
static void UpdateDecoderOutput(decoder_t *dec, const Dav1dSequenceHeader *seq_hdr)
132
4.15k
{
133
4.15k
    video_format_t *v = &dec->fmt_out.video;
134
135
4.15k
    if( !v->i_sar_num || !v->i_sar_den )
136
7
    {
137
7
        v->i_sar_num = 1;
138
7
        v->i_sar_den = 1;
139
7
    }
140
141
4.15k
    if(dec->fmt_in->video.primaries == COLOR_PRIMARIES_UNDEF && seq_hdr)
142
3.65k
    {
143
3.65k
        v->primaries = iso_23001_8_cp_to_vlc_primaries(seq_hdr->pri);
144
3.65k
        v->transfer = iso_23001_8_tc_to_vlc_xfer(seq_hdr->trc);
145
3.65k
        v->space = iso_23001_8_mc_to_vlc_coeffs(seq_hdr->mtrx);
146
3.65k
        v->color_range = seq_hdr->color_range ? COLOR_RANGE_FULL : COLOR_RANGE_LIMITED;
147
3.65k
    }
148
4.15k
}
149
150
static int NewPicture(Dav1dPicture *img, void *cookie)
151
4.15k
{
152
4.15k
    decoder_t *dec = cookie;
153
4.15k
    decoder_sys_t *p_sys = dec->p_sys;
154
155
4.15k
    video_format_t *v = &dec->fmt_out.video;
156
157
4.15k
    v->i_visible_width  = img->seq_hdr->max_width;
158
4.15k
    v->i_visible_height = img->seq_hdr->max_height;
159
160
4.15k
    UpdateDecoderOutput(dec, img->seq_hdr);
161
162
4.15k
    const Dav1dMasteringDisplay *md = img->mastering_display;
163
4.15k
    if( dec->fmt_in->video.mastering.max_luminance == 0 && md )
164
0
    {
165
0
        const uint8_t RGB2GBR[3] = {2,0,1};
166
0
        for( size_t i=0;i<6; i++ )
167
0
        {
168
0
            v->mastering.primaries[i] =
169
0
                    50000 * (double) md->primaries[RGB2GBR[i >> 1]][i % 2]
170
0
                          / (double)(1 << 16);
171
0
        }
172
0
        v->mastering.min_luminance = 10000 * (double)md->min_luminance
173
0
                                           / (double) (1<<14);
174
0
        v->mastering.max_luminance = 10000 * (double) md->max_luminance
175
0
                                           / (double) (1<<8);
176
0
        v->mastering.white_point[0] = 50000 * (double)md->white_point[0]
177
0
                                            / (double) (1<<16);
178
0
        v->mastering.white_point[1] = 50000 * (double)md->white_point[1]
179
0
                                            / (double) (1<<16);
180
0
    }
181
182
4.15k
    const Dav1dContentLightLevel *cll = img->content_light;
183
4.15k
    if( dec->fmt_in->video.lighting.MaxCLL == 0 && cll )
184
0
    {
185
0
        v->lighting.MaxCLL = cll->max_content_light_level;
186
0
        v->lighting.MaxFALL = cll->max_frame_average_light_level;
187
0
    }
188
189
4.15k
    v->projection_mode = dec->fmt_in->video.projection_mode;
190
4.15k
    v->multiview_mode = dec->fmt_in->video.multiview_mode;
191
4.15k
    v->pose = dec->fmt_in->video.pose;
192
4.15k
    dec->fmt_out.i_codec = FindVlcChroma(img);
193
4.15k
    if (unlikely(dec->fmt_out.i_codec == 0))
194
0
        return -1;
195
196
4.15k
    v->i_width  = (img->seq_hdr->max_width + 0x7F) & ~0x7F;
197
4.15k
    v->i_height = (img->seq_hdr->max_height + 0x7F) & ~0x7F;
198
4.15k
    v->i_chroma = dec->fmt_out.i_codec;
199
200
4.15k
#if DAV1D_API_VERSION_MAJOR >= 6
201
4.15k
    dec->i_extra_picture_buffers = p_sys->s.max_frame_delay;
202
#else
203
    dec->i_extra_picture_buffers = (p_sys->s.n_frame_threads - 1);
204
#endif
205
4.15k
    if (img->seq_hdr->super_res)
206
        // dav1d seems to buffer more pictures when using super resolution
207
1.05k
        dec->i_extra_picture_buffers += dec->i_extra_picture_buffers > 1 ? 2 : 1;
208
209
4.15k
    if (decoder_UpdateVideoFormat(dec) == 0)
210
4.15k
    {
211
4.15k
        picture_t *pic;
212
4.15k
        pic = decoder_NewPicture(dec);
213
4.15k
        if (unlikely(pic == NULL))
214
3
            return -1;
215
216
4.15k
        img->data[0] = pic->p[0].p_pixels;
217
4.15k
        img->stride[0] = pic->p[0].i_pitch;
218
4.15k
        img->data[1] = pic->p[1].p_pixels;
219
4.15k
        img->data[2] = pic->p[2].p_pixels;
220
4.15k
        assert(pic->p[1].i_pitch == pic->p[2].i_pitch);
221
4.15k
        img->stride[1] = pic->p[1].i_pitch;
222
223
4.15k
        img->allocator_data = pic;
224
4.15k
        return 0;
225
4.15k
    }
226
0
    return -1;
227
4.15k
}
228
229
static void ExtractCaptions(decoder_t *dec, const Dav1dPicture *img)
230
2.04k
{
231
2.04k
    decoder_sys_t *p_sys = dec->p_sys;
232
2.04k
    const struct user_data_s *userdata = (struct user_data_s *) img->m.user_data.data;
233
2.04k
    const Dav1dITUTT35 *itu_t35 = img->itut_t35;
234
2.04k
    if(itu_t35 && itu_t35->country_code == 0xb5 &&
235
0
       itu_t35->payload_size > 9 &&
236
0
       !memcmp(itu_t35->payload, "\x00\x0x31GA94\x03", 7))
237
0
    {
238
0
        cc_Extract(&p_sys->cc, CC_PAYLOAD_GA94, true,
239
0
                   &itu_t35->payload[7], itu_t35->payload_size - 7);
240
0
        if(p_sys->cc.b_reorder || p_sys->cc.i_data)
241
0
        {
242
0
            block_t *p_cc = block_Alloc(p_sys->cc.i_data);
243
0
            if(p_cc)
244
0
            {
245
0
                memcpy(p_cc->p_buffer, p_sys->cc.p_data, p_sys->cc.i_data);
246
0
                if(p_sys->cc.b_reorder || userdata == NULL)
247
0
                    p_cc->i_dts = p_cc->i_pts = img->m.timestamp;
248
0
                else
249
0
                    p_cc->i_pts = p_cc->i_dts = userdata->dts;
250
0
                decoder_cc_desc_t desc;
251
0
                desc.i_608_channels = p_sys->cc.i_608channels;
252
0
                desc.i_708_channels = p_sys->cc.i_708channels;
253
0
                desc.i_reorder_depth = 4;
254
0
                decoder_QueueCc(dec, p_cc, &desc);
255
0
            }
256
0
            cc_Flush(&p_sys->cc);
257
0
        }
258
0
    }
259
2.04k
}
260
261
static void FreePicture(Dav1dPicture *data, void *cookie)
262
4.15k
{
263
4.15k
    picture_t *pic = data->allocator_data;
264
4.15k
    decoder_t *dec = cookie;
265
4.15k
    VLC_UNUSED(dec);
266
4.15k
    picture_Release(pic);
267
4.15k
}
268
269
/****************************************************************************
270
 * Flush: clears decoder between seeks
271
 ****************************************************************************/
272
273
static void FlushDecoder(decoder_t *dec)
274
5.13k
{
275
5.13k
    decoder_sys_t *p_sys = dec->p_sys;
276
5.13k
    dav1d_flush(p_sys->c);
277
5.13k
    cc_Flush(&p_sys->cc);
278
5.13k
}
279
280
static void release_block(const uint8_t *buf, void *b)
281
401k
{
282
401k
    VLC_UNUSED(buf);
283
401k
    block_t *block = b;
284
401k
    block_Release(block);
285
401k
}
286
287
/****************************************************************************
288
 * Decode: the whole thing
289
 ****************************************************************************/
290
static int Decode(decoder_t *dec, block_t *block)
291
854k
{
292
854k
    decoder_sys_t *p_sys = dec->p_sys;
293
294
854k
    if (block && block->i_flags & (BLOCK_FLAG_CORRUPTED))
295
0
    {
296
0
        block_Release(block);
297
0
        return VLCDEC_SUCCESS;
298
0
    }
299
300
854k
    bool b_eos = false;
301
854k
    Dav1dData data;
302
854k
    Dav1dData *p_data = NULL;
303
304
854k
    if (block)
305
401k
    {
306
401k
        p_data = &data;
307
401k
        if (unlikely(dav1d_data_wrap(&data, block->p_buffer, block->i_buffer,
308
401k
                                     release_block, block) != 0))
309
0
        {
310
0
            block_Release(block);
311
0
            return VLCDEC_ECRITICAL;
312
0
        }
313
314
401k
        p_data->m.timestamp = block->i_pts == VLC_TICK_INVALID ? block->i_dts : block->i_pts;
315
401k
        if(block->i_dts != p_data->m.timestamp)
316
96.5k
        {
317
96.5k
            struct user_data_s *userdata = malloc(sizeof(*userdata));
318
96.5k
            if(unlikely(userdata == NULL ||
319
96.5k
                        0 != dav1d_data_wrap_user_data(&data, (const uint8_t *) userdata,
320
96.5k
                                                       FreeUserData_Handler, userdata)))
321
0
            {
322
0
                free(userdata);
323
0
                dav1d_data_unref(&data);
324
0
                return VLCDEC_ECRITICAL;
325
0
            }
326
96.5k
            userdata->dts = block->i_dts;
327
96.5k
        }
328
329
401k
        b_eos = (block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE);
330
401k
    }
331
332
854k
    bool b_draining = false;
333
854k
    int i_ret = VLCDEC_SUCCESS;
334
854k
    int res;
335
1.30M
    do {
336
1.30M
        if( p_data )
337
402k
        {
338
402k
            res = dav1d_send_data(p_sys->c, p_data);
339
402k
            if (res < 0 && res != DAV1D_ERR(EAGAIN))
340
46.4k
            {
341
46.4k
                msg_Err(dec, "Decoder feed error %d!", res);
342
                /* bitstream decoding errors (typically DAV1D_ERR(EINVAL), are assumed
343
                 * to be recoverable. Other errors returned from this function are either
344
                 * unexpected within the VLC configuration, or considered critical failures:
345
                 * - EAGAIN is handled above.
346
                 * - ENOMEM means out-of-memory and is unrecoverable.
347
                 * - ENOPROTOOPT is a build or configuration error (invalid demuxer/muxer or unsupported bitdepth) and is unrecoverable.
348
                 * - ERANGE means frame size limits exceeded. VLC doesn't use this so we can ignore this, but unless size changes, it would be unrecoverable.
349
                 * - EINVAL is any other bitstream error which is basically what this is about.
350
                 * - EIO means file count not be opened and is unrecoverable.
351
                 * - ENOENT  is actually only returned by dav1d_parse_sequence_header(), which is outside this context (I think?).
352
                 * - read() can return other values but it's OK to consider these critical for now. */
353
46.4k
                i_ret = res == DAV1D_ERR(EINVAL) ? VLCDEC_SUCCESS : VLCDEC_ECRITICAL;
354
46.4k
                break;
355
46.4k
            }
356
402k
        }
357
358
1.30M
        bool b_output_error = false;
359
1.25M
        do
360
1.26M
        {
361
1.26M
            Dav1dPicture img = { 0 };
362
1.26M
            res = dav1d_get_picture(p_sys->c, &img);
363
1.26M
            if (res == 0)
364
2.04k
            {
365
2.04k
                picture_t *_pic = img.allocator_data;
366
2.04k
                picture_t *pic = picture_Clone(_pic);
367
2.04k
                if (unlikely(pic == NULL))
368
0
                {
369
0
                    i_ret = VLC_EGENERIC;
370
0
                    picture_Release(_pic);
371
0
                    b_output_error = true;
372
0
                    break;
373
0
                }
374
2.04k
                pic->b_progressive = true; /* codec does not support interlacing */
375
2.04k
                pic->date = img.m.timestamp;
376
2.04k
                decoder_QueueVideo(dec, pic);
377
2.04k
                ExtractCaptions(dec, &img);
378
2.04k
                dav1d_picture_unref(&img);
379
380
                /* if not draining then break here and don't get further
381
                 * decoded frames. this allows for proper frame threading
382
                 * as otherwise all frames would be drained directly */
383
2.04k
                if(p_data != NULL && !b_eos)
384
772
                    break;
385
2.04k
            }
386
1.25M
            else if (res == DAV1D_ERR(EAGAIN))
387
1.25M
            {
388
                /* the decoder needs more data to be able to output something.
389
                 * if there is more data pending, continue the loop below or
390
                 * otherwise break and first read more data */
391
1.25M
                if (p_data && p_data->sz != 0)
392
4
                    res = 0;
393
1.25M
                break;
394
1.25M
            }
395
1.54k
            else
396
1.54k
            {
397
1.54k
                msg_Warn(dec, "Decoder error %d!", res);
398
1.54k
                b_output_error = true;
399
1.54k
                break;
400
1.54k
            }
401
1.26M
        } while(res == 0);
402
403
1.25M
        if(b_output_error)
404
1.54k
            break;
405
406
        /* on drain, we must ignore the 1st EAGAIN */
407
1.25M
        if(!b_draining && (res == DAV1D_ERR(EAGAIN) || res == 0)
408
806k
                       && (p_data == NULL||b_eos))
409
451k
        {
410
451k
            b_draining = true;
411
451k
            res = 0;
412
451k
        }
413
1.25M
    } while (res == 0 && ((p_data && p_data->sz != 0) || b_draining));
414
415
854k
    if(p_data && p_data->sz > 0)
416
46.5k
        dav1d_data_unref(p_data);
417
418
854k
    return i_ret;
419
854k
}
420
421
/*****************************************************************************
422
 * OpenDecoder: probe the decoder
423
 *****************************************************************************/
424
static int OpenDecoder(vlc_object_t *p_this)
425
217k
{
426
217k
    decoder_t *dec = (decoder_t *)p_this;
427
428
217k
    if (dec->fmt_in->i_codec != VLC_CODEC_AV1)
429
212k
        return VLC_EGENERIC;
430
431
5.13k
    decoder_sys_t *p_sys = vlc_obj_malloc(p_this, sizeof(*p_sys));
432
5.13k
    if (!p_sys)
433
0
        return VLC_ENOMEM;
434
435
5.13k
    dav1d_default_settings(&p_sys->s);
436
5.13k
#if DAV1D_API_VERSION_MAJOR >= 6
437
5.13k
    p_sys->s.n_threads = var_InheritInteger(p_this, "dav1d-thread-frames");
438
5.13k
    if (p_sys->s.n_threads == 0)
439
5.13k
        p_sys->s.n_threads = __MAX(1, vlc_GetCPUCount());
440
441
5.13k
#if DAV1D_API_VERSION_MAJOR > 6 || DAV1D_API_VERSION_MINOR >= 7
442
    // after dav1d 1.0.0
443
5.13k
    p_sys->s.max_frame_delay = dav1d_get_frame_delay( &p_sys->s );
444
#else // 1.0.0
445
    // corresponds to c->n_fc when max_frame_delay is 0 in dav1d 1.0.0
446
    static const uint8_t fc_lut[49] = {
447
        1,                                     /*     1 */
448
        2, 2, 2,                               /*  2- 4 */
449
        3, 3, 3, 3, 3,                         /*  5- 9 */
450
        4, 4, 4, 4, 4, 4, 4,                   /* 10-16 */
451
        5, 5, 5, 5, 5, 5, 5, 5, 5,             /* 17-25 */
452
        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,       /* 26-36 */
453
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* 37-49 */
454
    };
455
    if (p_sys->s.n_threads >= 50)
456
        p_sys->s.max_frame_delay = 8;
457
    else
458
        p_sys->s.max_frame_delay = fc_lut[p_sys->s.n_threads - 1];
459
#endif
460
461
#else // before dav1d 1.0.0
462
    p_sys->s.n_tile_threads = var_InheritInteger(p_this, "dav1d-thread-tiles");
463
    if (p_sys->s.n_tile_threads == 0)
464
        p_sys->s.n_tile_threads = VLC_CLIP(vlc_GetCPUCount(), 1, 4);
465
    p_sys->s.n_frame_threads = var_InheritInteger(p_this, "dav1d-thread-frames");
466
    if (p_sys->s.n_frame_threads == 0)
467
        p_sys->s.n_frame_threads = __MAX(1, vlc_GetCPUCount());
468
#endif
469
5.13k
    p_sys->s.all_layers = var_InheritBool( p_this, "dav1d-all-layers" );
470
5.13k
    p_sys->s.allocator.cookie = dec;
471
5.13k
    p_sys->s.allocator.alloc_picture_callback = NewPicture;
472
5.13k
    p_sys->s.allocator.release_picture_callback = FreePicture;
473
474
5.13k
    av1_OBU_sequence_header_t *sequence_hdr = NULL;
475
5.13k
    if (dec->fmt_in->i_extra > 4)
476
4.10k
    {
477
        // in ISOBMFF/WebM/Matroska the first 4 bytes are from the AV1CodecConfigurationRecord
478
        // and then one or more OBU
479
4.10k
        const uint8_t *obu_start = ((const uint8_t*) dec->fmt_in->p_extra) + 4;
480
4.10k
        int obu_size = dec->fmt_in->i_extra - 4;
481
4.10k
        if (AV1_OBUIsValid(obu_start, obu_size) && AV1_OBUGetType(obu_start) == AV1_OBU_SEQUENCE_HEADER)
482
4.09k
            sequence_hdr = AV1_OBU_parse_sequence_header(obu_start, obu_size);
483
4.10k
    }
484
485
5.13k
    dec->fmt_out.video.i_frame_rate = dec->fmt_in->video.i_frame_rate;
486
5.13k
    dec->fmt_out.video.i_frame_rate_base = dec->fmt_in->video.i_frame_rate_base;
487
488
5.13k
    bool super_res = false;
489
5.13k
    if (!sequence_hdr)
490
1.10k
    {
491
1.10k
        dec->fmt_out.i_codec = VLC_CODEC_I420;
492
1.10k
        dec->fmt_out.video.i_width = dec->fmt_in->video.i_width;
493
1.10k
        dec->fmt_out.video.i_height = dec->fmt_in->video.i_height;
494
1.10k
    }
495
4.02k
    else
496
4.02k
    {
497
        // use the sequence header to get a better chroma to start with
498
4.02k
        dec->fmt_out.i_codec = AV1_get_chroma(sequence_hdr);
499
500
4.02k
        AV1_get_frame_max_dimensions(sequence_hdr, &dec->fmt_out.video.i_width, &dec->fmt_out.video.i_height);
501
502
4.02k
        if (dec->fmt_out.video.transfer == TRANSFER_FUNC_UNDEF)
503
4.02k
            AV1_get_colorimetry(sequence_hdr, &dec->fmt_out.video.primaries, &dec->fmt_out.video.transfer,
504
4.02k
                                &dec->fmt_out.video.space, &dec->fmt_out.video.color_range);
505
4.02k
        super_res = AV1_get_super_res(sequence_hdr);
506
4.02k
    }
507
5.13k
    dec->fmt_out.video.i_visible_width  = dec->fmt_out.video.i_width;
508
5.13k
    dec->fmt_out.video.i_visible_height = dec->fmt_out.video.i_height;
509
510
5.13k
    if (dav1d_open(&p_sys->c, &p_sys->s) < 0)
511
0
    {
512
0
        msg_Err(p_this, "Could not open the Dav1d decoder");
513
0
        return VLC_EGENERIC;
514
0
    }
515
516
5.13k
#if DAV1D_API_VERSION_MAJOR >= 6
517
5.13k
    msg_Dbg(p_this, "Using dav1d version %s with %d threads",
518
5.13k
            dav1d_version(), p_sys->s.n_threads);
519
520
5.13k
    dec->i_extra_picture_buffers = p_sys->s.max_frame_delay;
521
#else
522
    msg_Dbg(p_this, "Using dav1d version %s with %d/%d frame/tile threads",
523
            dav1d_version(), p_sys->s.n_frame_threads, p_sys->s.n_tile_threads);
524
525
    dec->i_extra_picture_buffers = (p_sys->s.n_frame_threads - 1);
526
#endif
527
5.13k
    if (super_res)
528
        // dav1d seems to buffer more pictures when using super resolution
529
697
        dec->i_extra_picture_buffers += dec->i_extra_picture_buffers > 1 ? 2 : 1;
530
5.13k
    dec->fmt_out.video.i_width  = (dec->fmt_out.video.i_width + 0x7F) & ~0x7F;
531
5.13k
    dec->fmt_out.video.i_height = (dec->fmt_out.video.i_height + 0x7F) & ~0x7F;
532
533
5.13k
    dec->p_sys = p_sys;
534
535
5.13k
    if (dec->fmt_in->video.i_sar_num > 0 && dec->fmt_in->video.i_sar_den > 0) {
536
738
        dec->fmt_out.video.i_sar_num = dec->fmt_in->video.i_sar_num;
537
738
        dec->fmt_out.video.i_sar_den = dec->fmt_in->video.i_sar_den;
538
738
    }
539
5.13k
    dec->fmt_out.video.primaries   = dec->fmt_in->video.primaries;
540
5.13k
    dec->fmt_out.video.transfer    = dec->fmt_in->video.transfer;
541
5.13k
    dec->fmt_out.video.space       = dec->fmt_in->video.space;
542
5.13k
    dec->fmt_out.video.color_range = dec->fmt_in->video.color_range;
543
5.13k
    dec->fmt_out.video.mastering   = dec->fmt_in->video.mastering;
544
5.13k
    dec->fmt_out.video.lighting    = dec->fmt_in->video.lighting;
545
546
5.13k
    if (sequence_hdr != NULL)
547
4.02k
    {
548
        // we have the proper chroma, make sure we can use it
549
4.02k
        AV1_release_sequence_header(sequence_hdr);
550
551
4.02k
        if (decoder_UpdateVideoFormat(dec) != 0)
552
0
        {
553
0
            CloseDecoder(VLC_OBJECT(dec));
554
0
            return VLC_EGENERIC;
555
0
        }
556
4.02k
    }
557
5.13k
    dec->pf_decode = Decode;
558
5.13k
    dec->pf_flush = FlushDecoder;
559
560
5.13k
    cc_Init(&p_sys->cc);
561
562
5.13k
    return VLC_SUCCESS;
563
5.13k
}
564
565
/*****************************************************************************
566
 * CloseDecoder: decoder destruction
567
 *****************************************************************************/
568
static void CloseDecoder(vlc_object_t *p_this)
569
5.13k
{
570
5.13k
    decoder_t *dec = (decoder_t *)p_this;
571
5.13k
    decoder_sys_t *p_sys = dec->p_sys;
572
573
    /* Flush decoder */
574
5.13k
    FlushDecoder(dec);
575
576
5.13k
    dav1d_close(&p_sys->c);
577
5.13k
}