1 /*****************************************************************************
2 * av1_obu: AV1 OBU parser
3 *****************************************************************************
4 * Copyright (C) 2018 VideoLabs, VLC authors and VideoLAN
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.
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.
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 *****************************************************************************/
23 static inline uint64_t leb128(const uint8_t *p_buf
, size_t i_buf
, uint8_t *pi_len
)
27 for(size_t i
=0; i
<8; i
++)
31 i_val
|= ((uint64_t)(p_buf
[i
] & 0x7F) << (i
* 7));
32 if((p_buf
[i
] & 0x80) == 0)
38 return *pi_len
? i_val
: 0;
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,
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,
57 static inline enum av1_obu_type_e
AV1_OBUGetType(const uint8_t *p_buf
)
59 return (enum av1_obu_type_e
)((p_buf
[0] >> 3) & 0x0F);
62 static inline bool AV1_OBUHasSizeField(const uint8_t *p_buf
)
64 return p_buf
[0] & 0x02;
67 static inline bool AV1_OBUHasExtensionField(const uint8_t *p_buf
)
69 return p_buf
[0] & 0x04;
72 static inline bool AV1_OBUIsValid(const uint8_t *p_buf
, size_t i_buf
)
74 return (i_buf
> 0 && (p_buf
[0] & 0x81) == 0);
77 static inline bool AV1_OBUIsBaseLayer(const uint8_t *p_buf
, size_t i_buf
)
79 return !AV1_OBUHasExtensionField(p_buf
) || (i_buf
< 2) || !(p_buf
[1] >> 3);
82 static uint32_t AV1_OBUSize(const uint8_t *p_buf
, size_t i_buf
, uint8_t *pi_len
)
84 if(!AV1_OBUHasSizeField(p_buf
))
86 if(AV1_OBUHasExtensionField(p_buf
) && i_buf
< 2)
88 return i_buf
- 1 - AV1_OBUHasExtensionField(p_buf
);
91 if(AV1_OBUHasExtensionField(p_buf
))
98 /* skip extension header */
102 uint64_t i_size
= leb128(&p_buf
[1], i_buf
- 1, pi_len
);
103 if(i_size
> (INT64_C(1) << 32) - 1)
111 static bool AV1_OBUSkipHeader(const uint8_t **pp_buf
, size_t *pi_buf
)
115 size_t i_header
= 1 + !!AV1_OBUHasExtensionField(*pp_buf
);
116 if(AV1_OBUHasSizeField(*pp_buf
))
119 (void) AV1_OBUSize(*pp_buf
, *pi_buf
, &i_len
);
124 if(i_header
> *pi_buf
)
131 /* METADATA properties */
132 enum av1_obu_metadata_type_e
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,
145 static inline enum av1_obu_metadata_type_e
146 AV1_OBUGetMetadataType(const uint8_t *p_buf
, size_t i_buf
)
148 if(!AV1_OBUSkipHeader(&p_buf
, &i_buf
) || i_buf
< 1)
149 return AV1_METADATA_TYPE_RESERVED
;
152 uint64_t i_type
= leb128(p_buf
, i_buf
, &i_len
);
153 if(i_len
== 0 || i_type
> ((INT64_C(1) << 32) - 1))
154 return AV1_METADATA_TYPE_RESERVED
;
155 return (enum av1_obu_metadata_type_e
) i_type
;
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 vlc_fourcc_t
AV1_get_chroma(const av1_OBU_sequence_header_t
*);
174 /* FRAME_HEADER properties */
175 typedef struct av1_OBU_frame_header_t av1_OBU_frame_header_t
;
176 enum av1_frame_type_e
178 AV1_FRAME_TYPE_KEY
= 0,
179 AV1_FRAME_TYPE_INTER
= 1,
180 AV1_FRAME_TYPE_INTRA_ONLY
= 2,
181 AV1_FRAME_TYPE_SWITCH
= 3,
184 av1_OBU_frame_header_t
* AV1_OBU_parse_frame_header(const uint8_t *p_data
, size_t i_data
,
185 const av1_OBU_sequence_header_t
*);
186 void AV1_release_frame_header(av1_OBU_frame_header_t
*);
187 enum av1_frame_type_e
AV1_get_frame_type(const av1_OBU_frame_header_t
*);
188 bool AV1_get_frame_visibility(const av1_OBU_frame_header_t
*);
192 /* ISOBMFF Mapping */
194 size_t AV1_create_DecoderConfigurationRecord(uint8_t **,
195 const av1_OBU_sequence_header_t
*,
196 size_t, const uint8_t *[], const size_t []);
202 const uint8_t *p_head
;
203 const uint8_t *p_tail
;
204 } AV1_OBU_iterator_ctx_t
;
206 static inline void AV1_OBU_iterator_init(AV1_OBU_iterator_ctx_t
*p_ctx
,
207 const uint8_t *p_data
, size_t i_data
)
209 p_ctx
->p_head
= p_data
;
210 p_ctx
->p_tail
= p_data
+ i_data
;
213 static inline bool AV1_OBU_iterate_next(AV1_OBU_iterator_ctx_t
*p_ctx
,
214 const uint8_t **pp_start
, size_t *pi_size
)
216 const size_t i_remain
= p_ctx
->p_tail
- p_ctx
->p_head
;
217 if(!AV1_OBUIsValid(p_ctx
->p_head
, i_remain
))
219 if(!AV1_OBUHasSizeField(p_ctx
->p_head
))
221 *pp_start
= p_ctx
->p_head
;
223 p_ctx
->p_head
= p_ctx
->p_tail
;
227 uint8_t i_obu_size_len
;
228 const uint32_t i_obu_size
= AV1_OBUSize(p_ctx
->p_head
, i_remain
, &i_obu_size_len
);
229 const size_t i_obu
= i_obu_size
+ i_obu_size_len
+ !!AV1_OBUHasExtensionField(p_ctx
->p_head
) + 1;
230 if(i_obu_size_len
== 0 || i_obu
> i_remain
)
233 *pp_start
= p_ctx
->p_head
;
234 p_ctx
->p_head
+= i_obu
;