2 * EVC helper functions for muxers
3 * Copyright (c) 2022 Dawid Kozinski <d.kozinski@samsung.com>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/mem.h"
23 #include "libavcodec/get_bits.h"
24 #include "libavcodec/golomb.h"
25 #include "libavcodec/evc.h"
29 // @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.1
38 // @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3
39 typedef struct EVCNALUnitArray
{
40 uint8_t array_completeness
; // when equal to 1 indicates that all NAL units of the given type are in the following array
41 uint8_t NAL_unit_type
; // indicates the type of the NAL units in the following array
42 uint16_t numNalus
; // indicates the number of NAL units of the indicated type
43 uint16_t *nalUnitLength
; // indicates the length in bytes of the NAL unit
44 uint8_t **nalUnit
; // contains an SPS, PPS, APS or a SEI NAL unit, as specified in ISO/IEC 23094-1
48 * @brief Specifies the decoder configuration information for ISO/IEC 23094-1 video content.
49 * @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.2
50 * Carriage of network abstraction layer (NAL) unit structured video in the ISO base media file format
52 typedef struct EVCDecoderConfigurationRecord
{
53 uint8_t configurationVersion
; // 8 bits
54 uint8_t profile_idc
; // 8 bits
55 uint8_t level_idc
; // 8 bits
56 uint32_t toolset_idc_h
; // 32 bits
57 uint32_t toolset_idc_l
; // 32 bits
58 uint8_t chroma_format_idc
; // 2 bits
59 uint8_t bit_depth_luma_minus8
; // 3 bits
60 uint8_t bit_depth_chroma_minus8
; // 3 bits
61 uint16_t pic_width_in_luma_samples
; // 16 bits
62 uint16_t pic_height_in_luma_samples
; // 16 bits
63 uint8_t lengthSizeMinusOne
; // 2 bits
64 uint8_t num_of_arrays
; // 8 bits
65 EVCNALUnitArray arrays
[NB_ARRAYS
];
66 } EVCDecoderConfigurationRecord
;
73 typedef struct NALUList
{
75 unsigned nalus_array_size
;
76 unsigned nb_nalus
; ///< valid entries in nalus
79 // @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax)
80 static int evcc_parse_sps(const uint8_t *bs
, int bs_size
, EVCDecoderConfigurationRecord
*evcc
)
83 unsigned sps_seq_parameter_set_id
;
86 bs
+= EVC_NALU_HEADER_SIZE
;
87 bs_size
-= EVC_NALU_HEADER_SIZE
;
89 ret
= init_get_bits8(&gb
, bs
, bs_size
);
93 sps_seq_parameter_set_id
= get_ue_golomb_long(&gb
);
95 if (sps_seq_parameter_set_id
>= EVC_MAX_SPS_COUNT
)
96 return AVERROR_INVALIDDATA
;
98 // the Baseline profile is indicated by profile_idc eqal to 0
99 // the Main profile is indicated by profile_idc eqal to 1
100 evcc
->profile_idc
= get_bits(&gb
, 8);
102 evcc
->level_idc
= get_bits(&gb
, 8);
104 evcc
->toolset_idc_h
= get_bits_long(&gb
, 32);
105 evcc
->toolset_idc_l
= get_bits_long(&gb
, 32);
111 evcc
->chroma_format_idc
= get_ue_golomb_long(&gb
);
112 if (evcc
->chroma_format_idc
> 3)
113 return AVERROR_INVALIDDATA
;
115 evcc
->pic_width_in_luma_samples
= get_ue_golomb_long(&gb
);
116 evcc
->pic_height_in_luma_samples
= get_ue_golomb_long(&gb
);
118 evcc
->bit_depth_luma_minus8
= get_ue_golomb_long(&gb
);
119 evcc
->bit_depth_chroma_minus8
= get_ue_golomb_long(&gb
);
120 // EVCDecoderConfigurationRecord can't store values > 7. Limit it to bit depth 14.
121 if (evcc
->bit_depth_luma_minus8
> 6 || evcc
->bit_depth_chroma_minus8
> 6)
122 return AVERROR_INVALIDDATA
;
127 // @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3
128 static int evcc_array_add_nal_unit(const uint8_t *nal_buf
, uint32_t nal_size
,
129 uint8_t nal_type
, int ps_array_completeness
,
130 EVCNALUnitArray
*array
)
133 uint16_t numNalus
= array
->numNalus
;
135 ret
= av_reallocp_array(&array
->nalUnit
, numNalus
+ 1, sizeof(uint8_t *));
139 ret
= av_reallocp_array(&array
->nalUnitLength
, numNalus
+ 1, sizeof(uint16_t));
143 array
->nalUnit
[numNalus
] = (uint8_t *)nal_buf
;
144 array
->nalUnitLength
[numNalus
] = nal_size
;
145 array
->NAL_unit_type
= nal_type
;
149 * When the sample entry name is 'evc1', the default and mandatory value of
150 * array_completeness is 1 for arrays of all types of parameter sets, and 0
151 * for all other arrays.
153 if (nal_type
== EVC_SPS_NUT
|| nal_type
== EVC_PPS_NUT
|| nal_type
== EVC_APS_NUT
)
154 array
->array_completeness
= ps_array_completeness
;
159 static void evcc_init(EVCDecoderConfigurationRecord
*evcc
)
161 memset(evcc
, 0, sizeof(EVCDecoderConfigurationRecord
));
162 evcc
->configurationVersion
= 1;
163 evcc
->lengthSizeMinusOne
= 3; // 4 bytes
166 static void evcc_close(EVCDecoderConfigurationRecord
*evcc
)
168 for (unsigned i
= 0; i
< FF_ARRAY_ELEMS(evcc
->arrays
); i
++) {
169 EVCNALUnitArray
*const array
= &evcc
->arrays
[i
];
171 av_freep(&array
->nalUnit
);
172 av_freep(&array
->nalUnitLength
);
176 static int evcc_write(AVIOContext
*pb
, EVCDecoderConfigurationRecord
*evcc
)
180 av_log(NULL
, AV_LOG_TRACE
, "configurationVersion: %"PRIu8
"\n",
181 evcc
->configurationVersion
);
182 av_log(NULL
, AV_LOG_TRACE
, "profile_idc: %"PRIu8
"\n",
184 av_log(NULL
, AV_LOG_TRACE
, "level_idc: %"PRIu8
"\n",
186 av_log(NULL
, AV_LOG_TRACE
, "toolset_idc_h: %"PRIu32
"\n",
187 evcc
->toolset_idc_h
);
188 av_log(NULL
, AV_LOG_TRACE
, "toolset_idc_l: %"PRIu32
"\n",
189 evcc
->toolset_idc_l
);
190 av_log(NULL
, AV_LOG_TRACE
, "chroma_format_idc: %"PRIu8
"\n",
191 evcc
->chroma_format_idc
);
192 av_log(NULL
, AV_LOG_TRACE
, "bit_depth_luma_minus8: %"PRIu8
"\n",
193 evcc
->bit_depth_luma_minus8
);
194 av_log(NULL
, AV_LOG_TRACE
, "bit_depth_chroma_minus8: %"PRIu8
"\n",
195 evcc
->bit_depth_chroma_minus8
);
196 av_log(NULL
, AV_LOG_TRACE
, "pic_width_in_luma_samples: %"PRIu16
"\n",
197 evcc
->pic_width_in_luma_samples
);
198 av_log(NULL
, AV_LOG_TRACE
, "pic_height_in_luma_samples: %"PRIu16
"\n",
199 evcc
->pic_height_in_luma_samples
);
200 av_log(NULL
, AV_LOG_TRACE
, "lengthSizeMinusOne: %"PRIu8
"\n",
201 evcc
->lengthSizeMinusOne
);
202 av_log(NULL
, AV_LOG_TRACE
, "num_of_arrays: %"PRIu8
"\n",
203 evcc
->num_of_arrays
);
204 for (unsigned i
= 0; i
< FF_ARRAY_ELEMS(evcc
->arrays
); i
++) {
205 const EVCNALUnitArray
*const array
= &evcc
->arrays
[i
];
207 if(array
->numNalus
== 0)
210 av_log(NULL
, AV_LOG_TRACE
, "array_completeness[%u]: %"PRIu8
"\n",
211 i
, array
->array_completeness
);
212 av_log(NULL
, AV_LOG_TRACE
, "NAL_unit_type[%u]: %"PRIu8
"\n",
213 i
, array
->NAL_unit_type
);
214 av_log(NULL
, AV_LOG_TRACE
, "numNalus[%u]: %"PRIu16
"\n",
216 for ( unsigned j
= 0; j
< array
->numNalus
; j
++)
217 av_log(NULL
, AV_LOG_TRACE
,
218 "nalUnitLength[%u][%u]: %"PRIu16
"\n",
219 i
, j
, array
->nalUnitLength
[j
]);
223 * We need at least one SPS.
225 sps_count
= evcc
->arrays
[SPS_INDEX
].numNalus
;
226 if (!sps_count
|| sps_count
> EVC_MAX_SPS_COUNT
)
227 return AVERROR_INVALIDDATA
;
229 /* unsigned int(8) configurationVersion = 1; */
230 avio_w8(pb
, evcc
->configurationVersion
);
232 /* unsigned int(8) profile_idc */
233 avio_w8(pb
, evcc
->profile_idc
);
235 /* unsigned int(8) level_idc */
236 avio_w8(pb
, evcc
->level_idc
);
238 /* unsigned int(32) toolset_idc_h */
239 avio_wb32(pb
, evcc
->toolset_idc_h
);
241 /* unsigned int(32) toolset_idc_l */
242 avio_wb32(pb
, evcc
->toolset_idc_l
);
245 * unsigned int(2) chroma_format_idc;
246 * unsigned int(3) bit_depth_luma_minus8;
247 * unsigned int(3) bit_depth_chroma_minus8;
249 avio_w8(pb
, evcc
->chroma_format_idc
<< 6 |
250 evcc
->bit_depth_luma_minus8
<< 3 |
251 evcc
->bit_depth_chroma_minus8
);
253 /* unsigned int(16) pic_width_in_luma_samples; */
254 avio_wb16(pb
, evcc
->pic_width_in_luma_samples
);
256 /* unsigned int(16) pic_height_in_luma_samples; */
257 avio_wb16(pb
, evcc
->pic_height_in_luma_samples
);
260 * unsigned int(6) reserved = '000000'b;
261 * unsigned int(2) lengthSizeMinusOne;
263 avio_w8(pb
, evcc
->lengthSizeMinusOne
& 0x3);
265 /* unsigned int(8) numOfArrays; */
266 avio_w8(pb
, evcc
->num_of_arrays
);
268 for (unsigned i
= 0; i
< FF_ARRAY_ELEMS(evcc
->arrays
); i
++) {
269 const EVCNALUnitArray
*const array
= &evcc
->arrays
[i
];
271 if (!array
->numNalus
)
275 * bit(1) array_completeness;
276 * unsigned int(1) reserved = 0;
277 * unsigned int(6) NAL_unit_type;
279 avio_w8(pb
, array
->array_completeness
<< 7 |
280 array
->NAL_unit_type
& 0x3f);
282 /* unsigned int(16) numNalus; */
283 avio_wb16(pb
, array
->numNalus
);
285 for (unsigned j
= 0; j
< array
->numNalus
; j
++) {
286 /* unsigned int(16) nalUnitLength; */
287 avio_wb16(pb
, array
->nalUnitLength
[j
]);
289 /* bit(8*nalUnitLength) nalUnit; */
290 avio_write(pb
, array
->nalUnit
[j
],
291 array
->nalUnitLength
[j
]);
298 int ff_isom_write_evcc(AVIOContext
*pb
, const uint8_t *data
,
299 int size
, int ps_array_completeness
)
301 EVCDecoderConfigurationRecord evcc
;
304 int bytes_to_read
= size
;
305 unsigned array_index
;
310 /* We can't write a valid evcC from the provided data */
311 return AVERROR_INVALIDDATA
;
312 } else if (*data
== 1) {
313 /* Data is already evcC-formatted */
314 avio_write(pb
, data
, size
);
320 while (bytes_to_read
> EVC_NALU_LENGTH_PREFIX_SIZE
) {
321 nalu_size
= evc_read_nal_unit_length(data
, EVC_NALU_LENGTH_PREFIX_SIZE
);
322 if (nalu_size
== 0) break;
324 data
+= EVC_NALU_LENGTH_PREFIX_SIZE
;
325 bytes_to_read
-= EVC_NALU_LENGTH_PREFIX_SIZE
;
327 if (bytes_to_read
< nalu_size
) break;
329 nalu_type
= evc_get_nalu_type(data
, bytes_to_read
);
330 if (nalu_type
< EVC_NOIDR_NUT
|| nalu_type
> EVC_UNSPEC_NUT62
) {
331 ret
= AVERROR_INVALIDDATA
;
335 // @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3
336 // NAL_unit_type indicates the type of the NAL units in the following array (which shall be all of that type);
337 // - it takes a value as defined in ISO/IEC 23094-1;
338 // - it is restricted to take one of the values indicating a SPS, PPS, APS, or SEI NAL unit.
341 array_index
= SPS_INDEX
;
344 array_index
= PPS_INDEX
;
347 array_index
= APS_INDEX
;
350 array_index
= SEI_INDEX
;
357 if( (array_index
== SPS_INDEX
) ||
358 (array_index
== PPS_INDEX
) ||
359 (array_index
== APS_INDEX
) ||
360 (array_index
== SEI_INDEX
) ) {
362 ret
= evcc_array_add_nal_unit(data
, nalu_size
, nalu_type
, ps_array_completeness
, &(evcc
.arrays
[array_index
]));
366 if (evcc
.arrays
[array_index
].numNalus
== 1)
367 evcc
.num_of_arrays
++;
369 if(nalu_type
== EVC_SPS_NUT
) {
370 ret
= evcc_parse_sps(data
, nalu_size
, &evcc
);
377 bytes_to_read
-= nalu_size
;
380 ret
= evcc_write(pb
, &evcc
);