Coverage Report

Created: 2025-07-18 07:04

/src/vlc/modules/packetizer/av1_obu.h
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * av1_obu: AV1 OBU parser
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
#ifndef VLC_AV1_OBU_H
21
#define VLC_AV1_OBU_H
22
23
static inline uint64_t leb128(const uint8_t *p_buf, size_t i_buf, uint8_t *pi_len)
24
0
{
25
0
    uint64_t i_val = 0;
26
0
    *pi_len = 0;
27
0
    for(size_t i=0; i<8; i++)
28
0
    {
29
0
        if(i >= i_buf)
30
0
            break;
31
0
        i_val |= ((uint64_t)(p_buf[i] & 0x7F) << (i * 7));
32
0
        if((p_buf[i] & 0x80) == 0)
33
0
        {
34
0
            *pi_len = i + 1;
35
0
            break;
36
0
        }
37
0
    }
38
0
    return *pi_len ? i_val : 0;
39
0
}
Unexecuted instantiation: mp4.c:leb128
Unexecuted instantiation: mkv.cpp:leb128(unsigned char const*, unsigned long, unsigned char*)
40
41
enum av1_obu_type_e
42
{
43
    AV1_OBU_RESERVED_0             = 0,
44
    AV1_OBU_SEQUENCE_HEADER        = 1,
45
    AV1_OBU_TEMPORAL_DELIMITER     = 2,
46
    AV1_OBU_FRAME_HEADER           = 3,
47
    AV1_OBU_TILE_GROUP             = 4,
48
    AV1_OBU_METADATA               = 5,
49
    AV1_OBU_FRAME                  = 6,
50
    AV1_OBU_REDUNDANT_FRAME_HEADER = 7,
51
    AV1_OBU_TILE_LIST              = 8,
52
    AV1_OBU_RESERVED_START_9       = 9,
53
    AV1_OBU_RESERVED_END_14        = 14,
54
    AV1_OBU_PADDING                = 15,
55
};
56
57
static inline enum av1_obu_type_e AV1_OBUGetType(const uint8_t *p_buf)
58
0
{
59
0
    return (enum av1_obu_type_e)((p_buf[0] >> 3) & 0x0F);
60
0
}
Unexecuted instantiation: mp4.c:AV1_OBUGetType
Unexecuted instantiation: mkv.cpp:AV1_OBUGetType(unsigned char const*)
61
62
static inline bool AV1_OBUHasSizeField(const uint8_t *p_buf)
63
0
{
64
0
    return p_buf[0] & 0x02;
65
0
}
Unexecuted instantiation: mp4.c:AV1_OBUHasSizeField
Unexecuted instantiation: mkv.cpp:AV1_OBUHasSizeField(unsigned char const*)
66
67
static inline bool AV1_OBUHasExtensionField(const uint8_t *p_buf)
68
0
{
69
0
    return p_buf[0] & 0x04;
70
0
}
Unexecuted instantiation: mp4.c:AV1_OBUHasExtensionField
Unexecuted instantiation: mkv.cpp:AV1_OBUHasExtensionField(unsigned char const*)
71
72
static inline bool AV1_OBUIsValid(const uint8_t *p_buf, size_t i_buf)
73
0
{
74
0
    return (i_buf > 0 && (p_buf[0] & 0x81) == 0);
75
0
}
Unexecuted instantiation: mp4.c:AV1_OBUIsValid
Unexecuted instantiation: mkv.cpp:AV1_OBUIsValid(unsigned char const*, unsigned long)
76
77
static inline bool AV1_OBUIsBaseLayer(const uint8_t *p_buf, size_t i_buf)
78
0
{
79
0
    return !AV1_OBUHasExtensionField(p_buf) || (i_buf < 2) || !(p_buf[1] >> 3);
80
0
}
Unexecuted instantiation: mp4.c:AV1_OBUIsBaseLayer
Unexecuted instantiation: mkv.cpp:AV1_OBUIsBaseLayer(unsigned char const*, unsigned long)
81
82
static uint32_t AV1_OBUSize(const uint8_t *p_buf, size_t i_buf, uint8_t *pi_len)
83
0
{
84
0
    if(!AV1_OBUHasSizeField(p_buf))
85
0
    {
86
0
        if(AV1_OBUHasExtensionField(p_buf) && i_buf < 2)
87
0
            return false;
88
0
        return i_buf - 1 - AV1_OBUHasExtensionField(p_buf);
89
0
    }
90
91
0
    if(AV1_OBUHasExtensionField(p_buf))
92
0
    {
93
0
        if(i_buf == 1)
94
0
        {
95
0
            *pi_len = 0;
96
0
            return 0;
97
0
        }
98
        /* skip extension header */
99
0
        p_buf += 1;
100
0
        i_buf -= 1;
101
0
    }
102
0
    uint64_t i_size = leb128(&p_buf[1], i_buf - 1, pi_len);
103
0
    if(i_size > (INT64_C(1) << 32) - 1)
104
0
    {
105
0
        *pi_len = 0;
106
0
        return 0;
107
0
    }
108
0
    return i_size;
109
0
}
Unexecuted instantiation: mp4.c:AV1_OBUSize
Unexecuted instantiation: mkv.cpp:AV1_OBUSize(unsigned char const*, unsigned long, unsigned char*)
110
111
static bool AV1_OBUSkipHeader(const uint8_t **pp_buf, size_t *pi_buf)
112
0
{
113
0
    if(*pi_buf < 1)
114
0
        return false;
115
0
    size_t i_header = 1 + !!AV1_OBUHasExtensionField(*pp_buf);
116
0
    if(AV1_OBUHasSizeField(*pp_buf))
117
0
    {
118
0
        uint8_t i_len;
119
0
        (void) AV1_OBUSize(*pp_buf, *pi_buf, &i_len);
120
0
        if(i_len == 0)
121
0
            return false;
122
0
        i_header += i_len;
123
0
    }
124
0
    if(i_header > *pi_buf)
125
0
        return false;
126
0
    *pp_buf += i_header;
127
0
    *pi_buf -= i_header;
128
0
    return true;
129
0
}
Unexecuted instantiation: mp4.c:AV1_OBUSkipHeader
Unexecuted instantiation: mkv.cpp:AV1_OBUSkipHeader(unsigned char const**, unsigned long*)
130
131
/* METADATA properties */
132
enum av1_obu_metadata_type_e
133
{
134
    AV1_METADATA_TYPE_RESERVED             = 0,
135
    AV1_METADATA_TYPE_HDR_CLL              = 1,
136
    AV1_METADATA_TYPE_HDR_MDCV             = 2,
137
    AV1_METADATA_TYPE_SCALABILITY          = 3,
138
    AV1_METADATA_TYPE_ITUT_T35             = 4,
139
    AV1_METADATA_TYPE_TIMECODE             = 5,
140
    AV1_METADATA_TYPE_USER_PRIVATE_START_6 = 6,
141
    AV1_METADATA_TYPE_USER_PRIVATE_END_31  = 31,
142
    AV1_METADATA_TYPE_RESERVED_START_32    = 32,
143
};
144
145
static inline enum av1_obu_metadata_type_e
146
        AV1_OBUGetMetadataType(const uint8_t *p_buf, size_t i_buf)
147
0
{
148
0
    if(!AV1_OBUSkipHeader(&p_buf, &i_buf) || i_buf < 1)
149
0
        return AV1_METADATA_TYPE_RESERVED;
150
0
151
0
    uint8_t i_len;
152
0
    uint64_t i_type = leb128(p_buf, i_buf, &i_len);
153
0
    if(i_len == 0 || i_type > ((INT64_C(1) << 32) - 1))
154
0
        return AV1_METADATA_TYPE_RESERVED;
155
0
    return (enum av1_obu_metadata_type_e) i_type;
156
0
}
Unexecuted instantiation: mp4.c:AV1_OBUGetMetadataType
Unexecuted instantiation: mkv.cpp:AV1_OBUGetMetadataType(unsigned char const*, unsigned long)
157
158
159
160
/* SEQUENCE_HEADER properties */
161
typedef struct av1_OBU_sequence_header_t av1_OBU_sequence_header_t;
162
av1_OBU_sequence_header_t * AV1_OBU_parse_sequence_header(const uint8_t *, size_t);
163
void AV1_release_sequence_header(av1_OBU_sequence_header_t *);
164
void AV1_get_frame_max_dimensions(const av1_OBU_sequence_header_t *, unsigned *, unsigned *);
165
void AV1_get_profile_level(const av1_OBU_sequence_header_t *, int *, int *, int *);
166
bool AV1_get_colorimetry( const av1_OBU_sequence_header_t *,
167
                          video_color_primaries_t *, video_transfer_func_t *,
168
                          video_color_space_t *, video_color_range_t *);
169
bool AV1_get_frame_rate(const av1_OBU_sequence_header_t *, unsigned *, unsigned *);
170
bool AV1_get_super_res(const av1_OBU_sequence_header_t *);
171
vlc_fourcc_t AV1_get_chroma(const av1_OBU_sequence_header_t *);
172
173
bool AV1_sequence_header_equal(const av1_OBU_sequence_header_t *,const av1_OBU_sequence_header_t *);
174
175
176
177
/* FRAME_HEADER properties */
178
typedef struct av1_OBU_frame_header_t av1_OBU_frame_header_t;
179
enum av1_frame_type_e
180
{
181
    AV1_FRAME_TYPE_KEY        = 0,
182
    AV1_FRAME_TYPE_INTER      = 1,
183
    AV1_FRAME_TYPE_INTRA_ONLY = 2,
184
    AV1_FRAME_TYPE_SWITCH     = 3,
185
};
186
187
av1_OBU_frame_header_t * AV1_OBU_parse_frame_header(const uint8_t *p_data, size_t i_data,
188
                                                    const av1_OBU_sequence_header_t *);
189
void AV1_release_frame_header(av1_OBU_frame_header_t *);
190
enum av1_frame_type_e AV1_get_frame_type(const av1_OBU_frame_header_t *);
191
bool AV1_get_frame_visibility(const av1_OBU_frame_header_t *);
192
193
194
195
/* ISOBMFF Mapping */
196
197
size_t AV1_create_DecoderConfigurationRecord(uint8_t **,
198
                                             const av1_OBU_sequence_header_t *,
199
                                             size_t, const uint8_t *[], const size_t []);
200
201
/* OBU Iterator */
202
203
typedef struct
204
{
205
    const uint8_t *p_head;
206
    const uint8_t *p_tail;
207
} AV1_OBU_iterator_ctx_t;
208
209
static inline void AV1_OBU_iterator_init(AV1_OBU_iterator_ctx_t *p_ctx,
210
                                         const uint8_t *p_data, size_t i_data)
211
0
{
212
0
    p_ctx->p_head = p_data;
213
0
    p_ctx->p_tail = p_data + i_data;
214
0
}
Unexecuted instantiation: mp4.c:AV1_OBU_iterator_init
Unexecuted instantiation: mkv.cpp:AV1_OBU_iterator_init(AV1_OBU_iterator_ctx_t*, unsigned char const*, unsigned long)
215
216
static inline bool AV1_OBU_iterate_next(AV1_OBU_iterator_ctx_t *p_ctx,
217
                                        const uint8_t **pp_start, size_t *pi_size)
218
0
{
219
0
    const size_t i_remain = p_ctx->p_tail - p_ctx->p_head;
220
0
    if(!AV1_OBUIsValid(p_ctx->p_head, i_remain))
221
0
        return false;
222
0
    if(!AV1_OBUHasSizeField(p_ctx->p_head))
223
0
    {
224
0
        *pp_start = p_ctx->p_head;
225
0
        *pi_size = i_remain;
226
0
        p_ctx->p_head = p_ctx->p_tail;
227
0
        return true;
228
0
    }
229
230
0
    uint8_t i_obu_size_len;
231
0
    const uint32_t i_obu_size = AV1_OBUSize(p_ctx->p_head, i_remain, &i_obu_size_len);
232
0
    const size_t i_obu = i_obu_size + i_obu_size_len + !!AV1_OBUHasExtensionField(p_ctx->p_head) + 1;
233
0
    if(i_obu_size_len == 0 || i_obu > i_remain)
234
0
        return false;
235
0
    *pi_size = i_obu;
236
0
    *pp_start = p_ctx->p_head;
237
0
    p_ctx->p_head += i_obu;
238
0
    return true;
239
0
}
Unexecuted instantiation: mp4.c:AV1_OBU_iterate_next
Unexecuted instantiation: mkv.cpp:AV1_OBU_iterate_next(AV1_OBU_iterator_ctx_t*, unsigned char const**, unsigned long*)
240
241
#endif