/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 |