FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/hevc.c
Date: 2025-01-20 09:27:23
Exec Total Coverage
Lines: 462 646 71.5%
Functions: 22 25 88.0%
Branches: 182 364 50.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2014 Tim Walker <tdskywalker@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "libavcodec/get_bits.h"
22 #include "libavcodec/golomb.h"
23 #include "libavcodec/hevc/hevc.h"
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/mem.h"
26 #include "avc.h"
27 #include "avio.h"
28 #include "avio_internal.h"
29 #include "hevc.h"
30 #include "nal.h"
31
32 #define MAX_SPATIAL_SEGMENTATION 4096 // max. value of u(12) field
33
34 enum {
35 VPS_INDEX,
36 SPS_INDEX,
37 PPS_INDEX,
38 SEI_PREFIX_INDEX,
39 SEI_SUFFIX_INDEX,
40 NB_ARRAYS
41 };
42
43
44 #define FLAG_ARRAY_COMPLETENESS (1 << 0)
45 #define FLAG_IS_NALFF (1 << 1)
46 #define FLAG_IS_LHVC (1 << 2)
47
48 typedef struct HVCCNALUnit {
49 uint8_t nuh_layer_id;
50 uint8_t parameter_set_id;
51 uint16_t nalUnitLength;
52 const uint8_t *nalUnit;
53
54 // VPS
55 uint8_t vps_max_sub_layers_minus1;
56 } HVCCNALUnit;
57
58 typedef struct HVCCNALUnitArray {
59 uint8_t array_completeness;
60 uint8_t NAL_unit_type;
61 uint16_t numNalus;
62 HVCCNALUnit *nal;
63 } HVCCNALUnitArray;
64
65 typedef struct HEVCDecoderConfigurationRecord {
66 uint8_t configurationVersion;
67 uint8_t general_profile_space;
68 uint8_t general_tier_flag;
69 uint8_t general_profile_idc;
70 uint32_t general_profile_compatibility_flags;
71 uint64_t general_constraint_indicator_flags;
72 uint8_t general_level_idc;
73 uint16_t min_spatial_segmentation_idc;
74 uint8_t parallelismType;
75 uint8_t chromaFormat;
76 uint8_t bitDepthLumaMinus8;
77 uint8_t bitDepthChromaMinus8;
78 uint16_t avgFrameRate;
79 uint8_t constantFrameRate;
80 uint8_t numTemporalLayers;
81 uint8_t temporalIdNested;
82 uint8_t lengthSizeMinusOne;
83 uint8_t numOfArrays;
84 HVCCNALUnitArray arrays[NB_ARRAYS];
85
86 uint8_t alpha_layer_nuh_id;
87 } HEVCDecoderConfigurationRecord;
88
89 typedef struct HVCCProfileTierLevel {
90 uint8_t profile_space;
91 uint8_t tier_flag;
92 uint8_t profile_idc;
93 uint32_t profile_compatibility_flags;
94 uint64_t constraint_indicator_flags;
95 uint8_t level_idc;
96 } HVCCProfileTierLevel;
97
98 4 static void hvcc_update_ptl(HEVCDecoderConfigurationRecord *hvcc,
99 HVCCProfileTierLevel *ptl)
100 {
101 /*
102 * The value of general_profile_space in all the parameter sets must be
103 * identical.
104 */
105 4 hvcc->general_profile_space = ptl->profile_space;
106
107 /*
108 * The level indication general_level_idc must indicate a level of
109 * capability equal to or greater than the highest level indicated for the
110 * highest tier in all the parameter sets.
111 */
112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (hvcc->general_tier_flag < ptl->tier_flag)
113 hvcc->general_level_idc = ptl->level_idc;
114 else
115 4 hvcc->general_level_idc = FFMAX(hvcc->general_level_idc, ptl->level_idc);
116
117 /*
118 * The tier indication general_tier_flag must indicate a tier equal to or
119 * greater than the highest tier indicated in all the parameter sets.
120 */
121 4 hvcc->general_tier_flag = FFMAX(hvcc->general_tier_flag, ptl->tier_flag);
122
123 /*
124 * The profile indication general_profile_idc must indicate a profile to
125 * which the stream associated with this configuration record conforms.
126 *
127 * If the sequence parameter sets are marked with different profiles, then
128 * the stream may need examination to determine which profile, if any, the
129 * entire stream conforms to. If the entire stream is not examined, or the
130 * examination reveals that there is no profile to which the entire stream
131 * conforms, then the entire stream must be split into two or more
132 * sub-streams with separate configuration records in which these rules can
133 * be met.
134 *
135 * Note: set the profile to the highest value for the sake of simplicity.
136 */
137 4 hvcc->general_profile_idc = FFMAX(hvcc->general_profile_idc, ptl->profile_idc);
138
139 /*
140 * Each bit in general_profile_compatibility_flags may only be set if all
141 * the parameter sets set that bit.
142 */
143 4 hvcc->general_profile_compatibility_flags &= ptl->profile_compatibility_flags;
144
145 /*
146 * Each bit in general_constraint_indicator_flags may only be set if all
147 * the parameter sets set that bit.
148 */
149 4 hvcc->general_constraint_indicator_flags &= ptl->constraint_indicator_flags;
150 4 }
151
152 4 static void hvcc_parse_ptl(GetBitContext *gb,
153 HEVCDecoderConfigurationRecord *hvcc,
154 int profile_present_flag,
155 unsigned int max_sub_layers_minus1)
156 {
157 unsigned int i;
158 HVCCProfileTierLevel general_ptl;
159 uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS];
160 uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS];
161
162
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (profile_present_flag) {
163 4 general_ptl.profile_space = get_bits(gb, 2);
164 4 general_ptl.tier_flag = get_bits1(gb);
165 4 general_ptl.profile_idc = get_bits(gb, 5);
166 4 general_ptl.profile_compatibility_flags = get_bits_long(gb, 32);
167 4 general_ptl.constraint_indicator_flags = get_bits64(gb, 48);
168 4 general_ptl.level_idc = get_bits(gb, 8);
169 4 hvcc_update_ptl(hvcc, &general_ptl);
170 } else
171 skip_bits(gb, 8); // general_level_idc
172
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for (i = 0; i < max_sub_layers_minus1; i++) {
174 sub_layer_profile_present_flag[i] = get_bits1(gb);
175 sub_layer_level_present_flag[i] = get_bits1(gb);
176 }
177
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (max_sub_layers_minus1 > 0)
179 for (i = max_sub_layers_minus1; i < 8; i++)
180 skip_bits(gb, 2); // reserved_zero_2bits[i]
181
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for (i = 0; i < max_sub_layers_minus1; i++) {
183 if (sub_layer_profile_present_flag[i]) {
184 /*
185 * sub_layer_profile_space[i] u(2)
186 * sub_layer_tier_flag[i] u(1)
187 * sub_layer_profile_idc[i] u(5)
188 * sub_layer_profile_compatibility_flag[i][0..31] u(32)
189 * sub_layer_progressive_source_flag[i] u(1)
190 * sub_layer_interlaced_source_flag[i] u(1)
191 * sub_layer_non_packed_constraint_flag[i] u(1)
192 * sub_layer_frame_only_constraint_flag[i] u(1)
193 * sub_layer_reserved_zero_44bits[i] u(44)
194 */
195 skip_bits_long(gb, 32);
196 skip_bits_long(gb, 32);
197 skip_bits (gb, 24);
198 }
199
200 if (sub_layer_level_present_flag[i])
201 skip_bits(gb, 8);
202 }
203 4 }
204
205 2 static void skip_sub_layer_hrd_parameters(GetBitContext *gb,
206 unsigned int cpb_cnt_minus1,
207 uint8_t sub_pic_hrd_params_present_flag)
208 {
209 unsigned int i;
210
211
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (i = 0; i <= cpb_cnt_minus1; i++) {
212 2 get_ue_golomb_long(gb); // bit_rate_value_minus1
213 2 get_ue_golomb_long(gb); // cpb_size_value_minus1
214
215
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (sub_pic_hrd_params_present_flag) {
216 2 get_ue_golomb_long(gb); // cpb_size_du_value_minus1
217 2 get_ue_golomb_long(gb); // bit_rate_du_value_minus1
218 }
219
220 2 skip_bits1(gb); // cbr_flag
221 }
222 2 }
223
224 1 static int skip_hrd_parameters(GetBitContext *gb, uint8_t cprms_present_flag,
225 unsigned int max_sub_layers_minus1)
226 {
227 unsigned int i;
228 1 uint8_t sub_pic_hrd_params_present_flag = 0;
229 1 uint8_t nal_hrd_parameters_present_flag = 0;
230 1 uint8_t vcl_hrd_parameters_present_flag = 0;
231
232
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (cprms_present_flag) {
233 1 nal_hrd_parameters_present_flag = get_bits1(gb);
234 1 vcl_hrd_parameters_present_flag = get_bits1(gb);
235
236
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (nal_hrd_parameters_present_flag ||
237 vcl_hrd_parameters_present_flag) {
238 1 sub_pic_hrd_params_present_flag = get_bits1(gb);
239
240
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (sub_pic_hrd_params_present_flag)
241 /*
242 * tick_divisor_minus2 u(8)
243 * du_cpb_removal_delay_increment_length_minus1 u(5)
244 * sub_pic_cpb_params_in_pic_timing_sei_flag u(1)
245 * dpb_output_delay_du_length_minus1 u(5)
246 */
247 1 skip_bits(gb, 19);
248
249 /*
250 * bit_rate_scale u(4)
251 * cpb_size_scale u(4)
252 */
253 1 skip_bits(gb, 8);
254
255
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (sub_pic_hrd_params_present_flag)
256 1 skip_bits(gb, 4); // cpb_size_du_scale
257
258 /*
259 * initial_cpb_removal_delay_length_minus1 u(5)
260 * au_cpb_removal_delay_length_minus1 u(5)
261 * dpb_output_delay_length_minus1 u(5)
262 */
263 1 skip_bits(gb, 15);
264 }
265 }
266
267
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (i = 0; i <= max_sub_layers_minus1; i++) {
268 1 unsigned int cpb_cnt_minus1 = 0;
269 1 uint8_t low_delay_hrd_flag = 0;
270 1 uint8_t fixed_pic_rate_within_cvs_flag = 0;
271 1 uint8_t fixed_pic_rate_general_flag = get_bits1(gb);
272
273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!fixed_pic_rate_general_flag)
274 fixed_pic_rate_within_cvs_flag = get_bits1(gb);
275
276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (fixed_pic_rate_within_cvs_flag)
277 get_ue_golomb_long(gb); // elemental_duration_in_tc_minus1
278 else
279 1 low_delay_hrd_flag = get_bits1(gb);
280
281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!low_delay_hrd_flag) {
282 cpb_cnt_minus1 = get_ue_golomb_long(gb);
283 if (cpb_cnt_minus1 > 31)
284 return AVERROR_INVALIDDATA;
285 }
286
287
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (nal_hrd_parameters_present_flag)
288 1 skip_sub_layer_hrd_parameters(gb, cpb_cnt_minus1,
289 sub_pic_hrd_params_present_flag);
290
291
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (vcl_hrd_parameters_present_flag)
292 1 skip_sub_layer_hrd_parameters(gb, cpb_cnt_minus1,
293 sub_pic_hrd_params_present_flag);
294 }
295
296 1 return 0;
297 }
298
299 1 static void skip_timing_info(GetBitContext *gb)
300 {
301 1 skip_bits_long(gb, 32); // num_units_in_tick
302 1 skip_bits_long(gb, 32); // time_scale
303
304
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (get_bits1(gb)) // poc_proportional_to_timing_flag
305 get_ue_golomb_long(gb); // num_ticks_poc_diff_one_minus1
306 1 }
307
308 2 static void hvcc_parse_vui(GetBitContext *gb,
309 HEVCDecoderConfigurationRecord *hvcc,
310 unsigned int max_sub_layers_minus1)
311 {
312 unsigned int min_spatial_segmentation_idc;
313
314
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (get_bits1(gb)) // aspect_ratio_info_present_flag
315
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits(gb, 8) == 255) // aspect_ratio_idc
316 skip_bits_long(gb, 32); // sar_width u(16), sar_height u(16)
317
318
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits1(gb)) // overscan_info_present_flag
319 skip_bits1(gb); // overscan_appropriate_flag
320
321
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits1(gb)) { // video_signal_type_present_flag
322 skip_bits(gb, 4); // video_format u(3), video_full_range_flag u(1)
323
324 if (get_bits1(gb)) // colour_description_present_flag
325 /*
326 * colour_primaries u(8)
327 * transfer_characteristics u(8)
328 * matrix_coeffs u(8)
329 */
330 skip_bits(gb, 24);
331 }
332
333
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits1(gb)) { // chroma_loc_info_present_flag
334 get_ue_golomb_long(gb); // chroma_sample_loc_type_top_field
335 get_ue_golomb_long(gb); // chroma_sample_loc_type_bottom_field
336 }
337
338 /*
339 * neutral_chroma_indication_flag u(1)
340 * field_seq_flag u(1)
341 * frame_field_info_present_flag u(1)
342 */
343 2 skip_bits(gb, 3);
344
345
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (get_bits1(gb)) { // default_display_window_flag
346 2 get_ue_golomb_long(gb); // def_disp_win_left_offset
347 2 get_ue_golomb_long(gb); // def_disp_win_right_offset
348 2 get_ue_golomb_long(gb); // def_disp_win_top_offset
349 2 get_ue_golomb_long(gb); // def_disp_win_bottom_offset
350 }
351
352
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (get_bits1(gb)) { // vui_timing_info_present_flag
353 1 skip_timing_info(gb);
354
355
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (get_bits1(gb)) // vui_hrd_parameters_present_flag
356 1 skip_hrd_parameters(gb, 1, max_sub_layers_minus1);
357 }
358
359
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits1(gb)) { // bitstream_restriction_flag
360 /*
361 * tiles_fixed_structure_flag u(1)
362 * motion_vectors_over_pic_boundaries_flag u(1)
363 * restricted_ref_pic_lists_flag u(1)
364 */
365 skip_bits(gb, 3);
366
367 min_spatial_segmentation_idc = get_ue_golomb_long(gb);
368
369 /*
370 * unsigned int(12) min_spatial_segmentation_idc;
371 *
372 * The min_spatial_segmentation_idc indication must indicate a level of
373 * spatial segmentation equal to or less than the lowest level of
374 * spatial segmentation indicated in all the parameter sets.
375 */
376 hvcc->min_spatial_segmentation_idc = FFMIN(hvcc->min_spatial_segmentation_idc,
377 min_spatial_segmentation_idc);
378
379 get_ue_golomb_long(gb); // max_bytes_per_pic_denom
380 get_ue_golomb_long(gb); // max_bits_per_min_cu_denom
381 get_ue_golomb_long(gb); // log2_max_mv_length_horizontal
382 get_ue_golomb_long(gb); // log2_max_mv_length_vertical
383 }
384 2 }
385
386 2 static void skip_sub_layer_ordering_info(GetBitContext *gb)
387 {
388 2 get_ue_golomb_long(gb); // max_dec_pic_buffering_minus1
389 2 get_ue_golomb_long(gb); // max_num_reorder_pics
390 2 get_ue_golomb_long(gb); // max_latency_increase_plus1
391 2 }
392
393 static int hvcc_parse_vps_extension(GetBitContext *gb, HVCCNALUnit *nal,
394 HEVCDecoderConfigurationRecord *hvcc,
395 uint8_t vps_max_layers_minus1,
396 uint8_t vps_base_layer_internal_flag)
397 {
398 uint8_t num_scalability_types = 0;
399 uint8_t max_layers_minus_1 = FFMIN(62, vps_max_layers_minus1);
400 uint8_t splitting_flag, vps_nuh_layer_id_present_flag;
401 uint8_t scalability_mask_flag[16] = { 0 };
402 uint8_t dimension_id_len[16] = { 0 };
403 uint8_t layer_id_in_nuh[64] = { 0 };
404 int i, j;
405
406 if (vps_max_layers_minus1 > 0 && vps_base_layer_internal_flag)
407 hvcc_parse_ptl(gb, hvcc, 0, nal->vps_max_sub_layers_minus1);
408
409 splitting_flag = get_bits(gb, 1);
410
411 for (i = 0; i < 16; i++)
412 if (get_bits(gb, 1))
413 scalability_mask_flag[num_scalability_types++] = i;
414
415 for (j = 0; j < (num_scalability_types - splitting_flag); j++)
416 dimension_id_len[j] = get_bits(gb, 3) + 1;
417
418 vps_nuh_layer_id_present_flag = get_bits(gb, 1);
419
420 for (i = 1; i <= max_layers_minus_1; i++) {
421 if (vps_nuh_layer_id_present_flag)
422 layer_id_in_nuh[i] = get_bits(gb, 6);
423 else
424 layer_id_in_nuh[i] = i;
425
426 if (!splitting_flag) {
427 for (j = 0; j < num_scalability_types; j++) {
428 int dimension_id = get_bits(gb, dimension_id_len[j]);
429
430 if (dimension_id == 1 /* AUX_ALPHA */ && scalability_mask_flag[j] == 3 /* AuxId */)
431 hvcc->alpha_layer_nuh_id = layer_id_in_nuh[i];
432 }
433 }
434 }
435
436 if (splitting_flag) {
437 uint8_t dim_bit_offset[17] = { 0 };
438
439 dim_bit_offset[0] = 0;
440 for (j = 1; j < num_scalability_types; j++)
441 dim_bit_offset[j] = dim_bit_offset[j-1] + dimension_id_len[j-1];
442 dim_bit_offset[num_scalability_types] = 6;
443
444 if (num_scalability_types > 0 && dim_bit_offset[num_scalability_types - 1] >= 6)
445 return -1; // invalid bitstream
446
447 for (i = 1; i <= max_layers_minus_1; i++) {
448 for (j = 0; j < num_scalability_types; j++) {
449 int dimension_id = (layer_id_in_nuh[i] & ((1 << dim_bit_offset[j+1]) - 1)) >> dim_bit_offset[j];
450
451 if (dimension_id == 1 /* AUX_ALPHA */ && scalability_mask_flag[j] == 3 /* AuxId */)
452 hvcc->alpha_layer_nuh_id = layer_id_in_nuh[i];
453 }
454 }
455 }
456
457 return 0;
458 }
459
460 2 static int hvcc_parse_vps(GetBitContext *gb, HVCCNALUnit *nal,
461 HEVCDecoderConfigurationRecord *hvcc)
462 {
463 uint8_t vps_base_layer_internal_flag, vps_max_layers_minus1;
464 uint8_t vps_sub_layer_ordering_info_present_flag, vps_max_layer_id;
465 int vps_num_layer_sets_minus1;
466 int i;
467
468 2 nal->parameter_set_id = get_bits(gb, 4);
469
470 2 vps_base_layer_internal_flag = get_bits(gb, 1);
471 2 skip_bits(gb, 1); // vps_base_layer_available_flag
472 2 vps_max_layers_minus1 = get_bits(gb, 6);
473
474 2 nal->vps_max_sub_layers_minus1 = get_bits(gb, 3);
475
476 /*
477 * numTemporalLayers greater than 1 indicates that the stream to which this
478 * configuration record applies is temporally scalable and the contained
479 * number of temporal layers (also referred to as temporal sub-layer or
480 * sub-layer in ISO/IEC 23008-2) is equal to numTemporalLayers. Value 1
481 * indicates that the stream is not temporally scalable. Value 0 indicates
482 * that it is unknown whether the stream is temporally scalable.
483 */
484 2 hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers,
485 nal->vps_max_sub_layers_minus1 + 1);
486
487 /*
488 * vps_temporal_id_nesting_flag u(1)
489 * vps_reserved_0xffff_16bits u(16)
490 */
491 2 skip_bits(gb, 17);
492
493 2 hvcc_parse_ptl(gb, hvcc, 1, nal->vps_max_sub_layers_minus1);
494
495 2 vps_sub_layer_ordering_info_present_flag = get_bits(gb, 1);
496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (i = (vps_sub_layer_ordering_info_present_flag ? 0 : nal->vps_max_sub_layers_minus1);
497
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 i <= nal->vps_max_sub_layers_minus1; i++) {
498 2 get_ue_golomb(gb); // vps_max_dec_pic_buffering_minus1
499 2 get_ue_golomb(gb); // vps_max_num_reorder_pics
500 2 get_ue_golomb(gb); // vps_max_latency_increase_plus1
501 }
502
503 2 vps_max_layer_id = get_bits(gb, 6);
504 2 vps_num_layer_sets_minus1 = get_ue_golomb(gb);
505 2 skip_bits_long(gb, (vps_max_layer_id + 1) * vps_num_layer_sets_minus1); // layer_id_included_flag[i][j]
506
507
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits(gb, 1)) { // vps_timing_info_present_flag
508 int vps_num_hrd_parameters;
509
510 skip_bits_long(gb, 64); // vps_num_units_in_tick, vps_time_scale
511
512 if (get_bits(gb, 1)) // vps_poc_proportional_to_timing_flag
513 get_ue_golomb(gb); // vps_num_ticks_poc_diff_one_minus1
514
515 vps_num_hrd_parameters = get_ue_golomb(gb); // vps_num_hrd_parameters
516
517 for (i = 0; i < vps_num_hrd_parameters; i++) {
518 int cprms_present_flag;
519
520 get_ue_golomb(gb); // hrd_layer_set_idx[i]
521 if (i > 0)
522 cprms_present_flag = get_bits(gb, 1);
523 else
524 cprms_present_flag = 1;
525
526 skip_hrd_parameters(gb, cprms_present_flag, nal->vps_max_sub_layers_minus1);
527 }
528 }
529
530
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits(gb, 1)) { // vps_extension_flag
531 align_get_bits(gb);
532 if (hvcc_parse_vps_extension(gb, nal, hvcc,
533 vps_max_layers_minus1,
534 vps_base_layer_internal_flag) < 0)
535 return 0;
536 }
537
538 /* nothing useful for hvcC past this point */
539 2 return 0;
540 }
541
542 static void skip_scaling_list_data(GetBitContext *gb)
543 {
544 int i, j, k, num_coeffs;
545
546 for (i = 0; i < 4; i++)
547 for (j = 0; j < (i == 3 ? 2 : 6); j++)
548 if (!get_bits1(gb)) // scaling_list_pred_mode_flag[i][j]
549 get_ue_golomb_long(gb); // scaling_list_pred_matrix_id_delta[i][j]
550 else {
551 num_coeffs = FFMIN(64, 1 << (4 + (i << 1)));
552
553 if (i > 1)
554 get_se_golomb_long(gb); // scaling_list_dc_coef_minus8[i-2][j]
555
556 for (k = 0; k < num_coeffs; k++)
557 get_se_golomb_long(gb); // scaling_list_delta_coef
558 }
559 }
560
561 24 static int parse_rps(GetBitContext *gb, unsigned int rps_idx,
562 unsigned int num_rps,
563 unsigned int num_delta_pocs[HEVC_MAX_SHORT_TERM_REF_PIC_SETS])
564 {
565 unsigned int i;
566
567
4/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 2 times.
24 if (rps_idx && get_bits1(gb)) { // inter_ref_pic_set_prediction_flag
568 /* this should only happen for slice headers, and this isn't one */
569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (rps_idx >= num_rps)
570 return AVERROR_INVALIDDATA;
571
572 20 skip_bits1 (gb); // delta_rps_sign
573 20 get_ue_golomb_long(gb); // abs_delta_rps_minus1
574
575 20 num_delta_pocs[rps_idx] = 0;
576
577 /*
578 * From libavcodec/hevc_ps.c:
579 *
580 * if (is_slice_header) {
581 * //foo
582 * } else
583 * rps_ridx = &sps->st_rps[rps - sps->st_rps - 1];
584 *
585 * where:
586 * rps: &sps->st_rps[rps_idx]
587 * sps->st_rps: &sps->st_rps[0]
588 * is_slice_header: rps_idx == num_rps
589 *
590 * thus:
591 * if (num_rps != rps_idx)
592 * rps_ridx = &sps->st_rps[rps_idx - 1];
593 *
594 * NumDeltaPocs[RefRpsIdx]: num_delta_pocs[rps_idx - 1]
595 */
596
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 20 times.
108 for (i = 0; i <= num_delta_pocs[rps_idx - 1]; i++) {
597 88 uint8_t use_delta_flag = 0;
598 88 uint8_t used_by_curr_pic_flag = get_bits1(gb);
599
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 73 times.
88 if (!used_by_curr_pic_flag)
600 15 use_delta_flag = get_bits1(gb);
601
602
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
88 if (used_by_curr_pic_flag || use_delta_flag)
603 73 num_delta_pocs[rps_idx]++;
604 }
605 } else {
606 4 unsigned int num_negative_pics = get_ue_golomb_long(gb);
607 4 unsigned int num_positive_pics = get_ue_golomb_long(gb);
608
609
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((num_positive_pics + (uint64_t)num_negative_pics) * 2 > get_bits_left(gb))
610 return AVERROR_INVALIDDATA;
611
612 4 num_delta_pocs[rps_idx] = num_negative_pics + num_positive_pics;
613
614
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
14 for (i = 0; i < num_negative_pics; i++) {
615 10 get_ue_golomb_long(gb); // delta_poc_s0_minus1[rps_idx]
616 10 skip_bits1 (gb); // used_by_curr_pic_s0_flag[rps_idx]
617 }
618
619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for (i = 0; i < num_positive_pics; i++) {
620 get_ue_golomb_long(gb); // delta_poc_s1_minus1[rps_idx]
621 skip_bits1 (gb); // used_by_curr_pic_s1_flag[rps_idx]
622 }
623 }
624
625 24 return 0;
626 }
627
628 2 static int hvcc_parse_sps(GetBitContext *gb, HVCCNALUnit *nal,
629 HEVCDecoderConfigurationRecord *hvcc)
630 {
631 unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4;
632 unsigned int num_short_term_ref_pic_sets, num_delta_pocs[HEVC_MAX_SHORT_TERM_REF_PIC_SETS];
633 unsigned int sps_ext_or_max_sub_layers_minus1, multi_layer_ext_sps_flag;
634
635 2 unsigned int sps_video_parameter_set_id = get_bits(gb, 4);
636
637
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (nal->nuh_layer_id == 0) {
638 2 sps_ext_or_max_sub_layers_minus1 = 0;
639 2 sps_max_sub_layers_minus1 = get_bits(gb, 3);
640 } else {
641 sps_ext_or_max_sub_layers_minus1 = get_bits(gb, 3);
642 if (sps_ext_or_max_sub_layers_minus1 == 7) {
643 const HVCCNALUnitArray *array = &hvcc->arrays[VPS_INDEX];
644 const HVCCNALUnit *vps = NULL;
645
646 for (i = 0; i < array->numNalus; i++)
647 if (sps_video_parameter_set_id == array->nal[i].parameter_set_id) {
648 vps = &array->nal[i];
649 break;
650 }
651 if (!vps)
652 return AVERROR_INVALIDDATA;
653
654 sps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1;
655 } else
656 sps_max_sub_layers_minus1 = sps_ext_or_max_sub_layers_minus1;
657 }
658
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 multi_layer_ext_sps_flag = nal->nuh_layer_id &&
659 sps_ext_or_max_sub_layers_minus1 == 7;
660
661 /*
662 * numTemporalLayers greater than 1 indicates that the stream to which this
663 * configuration record applies is temporally scalable and the contained
664 * number of temporal layers (also referred to as temporal sub-layer or
665 * sub-layer in ISO/IEC 23008-2) is equal to numTemporalLayers. Value 1
666 * indicates that the stream is not temporally scalable. Value 0 indicates
667 * that it is unknown whether the stream is temporally scalable.
668 */
669 2 hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers,
670 sps_max_sub_layers_minus1 + 1);
671
672
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!multi_layer_ext_sps_flag) {
673 2 hvcc->temporalIdNested = get_bits1(gb);
674 2 hvcc_parse_ptl(gb, hvcc, 1, sps_max_sub_layers_minus1);
675 }
676
677 2 nal->parameter_set_id = get_ue_golomb_long(gb);
678
679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (multi_layer_ext_sps_flag) {
680 if (get_bits1(gb)) // update_rep_format_flag
681 skip_bits(gb, 8); // sps_rep_format_idx
682 } else {
683 2 hvcc->chromaFormat = get_ue_golomb_long(gb);
684
685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (hvcc->chromaFormat == 3)
686 skip_bits1(gb); // separate_colour_plane_flag
687
688 2 get_ue_golomb_long(gb); // pic_width_in_luma_samples
689 2 get_ue_golomb_long(gb); // pic_height_in_luma_samples
690
691
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (get_bits1(gb)) { // conformance_window_flag
692 2 get_ue_golomb_long(gb); // conf_win_left_offset
693 2 get_ue_golomb_long(gb); // conf_win_right_offset
694 2 get_ue_golomb_long(gb); // conf_win_top_offset
695 2 get_ue_golomb_long(gb); // conf_win_bottom_offset
696 }
697
698 2 hvcc->bitDepthLumaMinus8 = get_ue_golomb_long(gb);
699 2 hvcc->bitDepthChromaMinus8 = get_ue_golomb_long(gb);
700 }
701 2 log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb_long(gb);
702
703
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!multi_layer_ext_sps_flag) {
704 /* sps_sub_layer_ordering_info_present_flag */
705
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 i = get_bits1(gb) ? 0 : sps_max_sub_layers_minus1;
706
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (; i <= sps_max_sub_layers_minus1; i++)
707 2 skip_sub_layer_ordering_info(gb);
708 }
709
710 2 get_ue_golomb_long(gb); // log2_min_luma_coding_block_size_minus3
711 2 get_ue_golomb_long(gb); // log2_diff_max_min_luma_coding_block_size
712 2 get_ue_golomb_long(gb); // log2_min_transform_block_size_minus2
713 2 get_ue_golomb_long(gb); // log2_diff_max_min_transform_block_size
714 2 get_ue_golomb_long(gb); // max_transform_hierarchy_depth_inter
715 2 get_ue_golomb_long(gb); // max_transform_hierarchy_depth_intra
716
717
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits1(gb)) { // scaling_list_enabled_flag
718 int sps_infer_scaling_list_flag = 0;
719 if (multi_layer_ext_sps_flag)
720 sps_infer_scaling_list_flag = get_bits1(gb);
721 if (sps_infer_scaling_list_flag)
722 skip_bits(gb, 6); // sps_scaling_list_ref_layer_id
723 else if (get_bits1(gb)) // sps_scaling_list_data_present_flag
724 skip_scaling_list_data(gb);
725 }
726
727 2 skip_bits1(gb); // amp_enabled_flag
728 2 skip_bits1(gb); // sample_adaptive_offset_enabled_flag
729
730
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits1(gb)) { // pcm_enabled_flag
731 skip_bits (gb, 4); // pcm_sample_bit_depth_luma_minus1
732 skip_bits (gb, 4); // pcm_sample_bit_depth_chroma_minus1
733 get_ue_golomb_long(gb); // log2_min_pcm_luma_coding_block_size_minus3
734 get_ue_golomb_long(gb); // log2_diff_max_min_pcm_luma_coding_block_size
735 skip_bits1 (gb); // pcm_loop_filter_disabled_flag
736 }
737
738 2 num_short_term_ref_pic_sets = get_ue_golomb_long(gb);
739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (num_short_term_ref_pic_sets > HEVC_MAX_SHORT_TERM_REF_PIC_SETS)
740 return AVERROR_INVALIDDATA;
741
742
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 for (i = 0; i < num_short_term_ref_pic_sets; i++) {
743 24 int ret = parse_rps(gb, i, num_short_term_ref_pic_sets, num_delta_pocs);
744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
745 return ret;
746 }
747
748
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits1(gb)) { // long_term_ref_pics_present_flag
749 unsigned num_long_term_ref_pics_sps = get_ue_golomb_long(gb);
750 if (num_long_term_ref_pics_sps > 31U)
751 return AVERROR_INVALIDDATA;
752 for (i = 0; i < num_long_term_ref_pics_sps; i++) { // num_long_term_ref_pics_sps
753 int len = FFMIN(log2_max_pic_order_cnt_lsb_minus4 + 4, 16);
754 skip_bits (gb, len); // lt_ref_pic_poc_lsb_sps[i]
755 skip_bits1(gb); // used_by_curr_pic_lt_sps_flag[i]
756 }
757 }
758
759 2 skip_bits1(gb); // sps_temporal_mvp_enabled_flag
760 2 skip_bits1(gb); // strong_intra_smoothing_enabled_flag
761
762
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (get_bits1(gb)) // vui_parameters_present_flag
763 2 hvcc_parse_vui(gb, hvcc, sps_max_sub_layers_minus1);
764
765 /* nothing useful for hvcC past this point */
766 2 return 0;
767 }
768
769 2 static int hvcc_parse_pps(GetBitContext *gb, HVCCNALUnit *nal,
770 HEVCDecoderConfigurationRecord *hvcc)
771 {
772 uint8_t tiles_enabled_flag, entropy_coding_sync_enabled_flag;
773
774 2 nal->parameter_set_id = get_ue_golomb_long(gb); // pps_pic_parameter_set_id
775 2 get_ue_golomb_long(gb); // pps_seq_parameter_set_id
776
777 /*
778 * dependent_slice_segments_enabled_flag u(1)
779 * output_flag_present_flag u(1)
780 * num_extra_slice_header_bits u(3)
781 * sign_data_hiding_enabled_flag u(1)
782 * cabac_init_present_flag u(1)
783 */
784 2 skip_bits(gb, 7);
785
786 2 get_ue_golomb_long(gb); // num_ref_idx_l0_default_active_minus1
787 2 get_ue_golomb_long(gb); // num_ref_idx_l1_default_active_minus1
788 2 get_se_golomb_long(gb); // init_qp_minus26
789
790 /*
791 * constrained_intra_pred_flag u(1)
792 * transform_skip_enabled_flag u(1)
793 */
794 2 skip_bits(gb, 2);
795
796
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (get_bits1(gb)) // cu_qp_delta_enabled_flag
797 2 get_ue_golomb_long(gb); // diff_cu_qp_delta_depth
798
799 2 get_se_golomb_long(gb); // pps_cb_qp_offset
800 2 get_se_golomb_long(gb); // pps_cr_qp_offset
801
802 /*
803 * pps_slice_chroma_qp_offsets_present_flag u(1)
804 * weighted_pred_flag u(1)
805 * weighted_bipred_flag u(1)
806 * transquant_bypass_enabled_flag u(1)
807 */
808 2 skip_bits(gb, 4);
809
810 2 tiles_enabled_flag = get_bits1(gb);
811 2 entropy_coding_sync_enabled_flag = get_bits1(gb);
812
813
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
2 if (entropy_coding_sync_enabled_flag && tiles_enabled_flag)
814 hvcc->parallelismType = 0; // mixed-type parallel decoding
815
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 else if (entropy_coding_sync_enabled_flag)
816 1 hvcc->parallelismType = 3; // wavefront-based parallel decoding
817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if (tiles_enabled_flag)
818 hvcc->parallelismType = 2; // tile-based parallel decoding
819 else
820 1 hvcc->parallelismType = 1; // slice-based parallel decoding
821
822 /* nothing useful for hvcC past this point */
823 2 return 0;
824 }
825
826 42 static void nal_unit_parse_header(GetBitContext *gb, uint8_t *nal_type,
827 uint8_t *nuh_layer_id)
828 {
829 42 skip_bits1(gb); // forbidden_zero_bit
830
831 42 *nal_type = get_bits(gb, 6);
832 42 *nuh_layer_id = get_bits(gb, 6);
833
834 /*
835 * nuh_temporal_id_plus1 u(3)
836 */
837 42 skip_bits(gb, 3);
838 42 }
839
840 40 static int hvcc_array_add_nal_unit(const uint8_t *nal_buf, uint32_t nal_size,
841 HVCCNALUnitArray *array)
842 {
843 HVCCNALUnit *nal;
844 int ret;
845 40 uint16_t numNalus = array->numNalus;
846
847 40 ret = av_reallocp_array(&array->nal, numNalus + 1, sizeof(*array->nal));
848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (ret < 0)
849 return ret;
850
851 40 nal = &array->nal[numNalus];
852 40 nal->nalUnit = nal_buf;
853 40 nal->nalUnitLength = nal_size;
854 40 array->numNalus++;
855
856 40 return 0;
857 }
858
859 42 static int hvcc_add_nal_unit(const uint8_t *nal_buf, uint32_t nal_size,
860 HEVCDecoderConfigurationRecord *hvcc,
861 int flags, unsigned array_idx)
862 {
863 42 int ret = 0;
864 42 int is_nalff = !!(flags & FLAG_IS_NALFF);
865 42 int is_lhvc = !!(flags & FLAG_IS_LHVC);
866 42 int ps_array_completeness = !!(flags & FLAG_ARRAY_COMPLETENESS);
867 42 HVCCNALUnitArray *const array = &hvcc->arrays[array_idx];
868 HVCCNALUnit *nal;
869 GetBitContext gbc;
870 uint8_t nal_type, nuh_layer_id;
871 uint8_t *rbsp_buf;
872 uint32_t rbsp_size;
873
874 42 rbsp_buf = ff_nal_unit_extract_rbsp(nal_buf, nal_size, &rbsp_size, 2);
875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!rbsp_buf) {
876 ret = AVERROR(ENOMEM);
877 goto end;
878 }
879
880 42 ret = init_get_bits8(&gbc, rbsp_buf, rbsp_size);
881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
882 goto end;
883
884 42 nal_unit_parse_header(&gbc, &nal_type, &nuh_layer_id);
885
5/6
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
42 if (!is_lhvc && nuh_layer_id > 0 && nuh_layer_id != hvcc->alpha_layer_nuh_id)
886 2 goto end;
887
888 /*
889 * Note: only 'declarative' SEI messages are allowed in
890 * hvcC. Perhaps the SEI playload type should be checked
891 * and non-declarative SEI messages discarded?
892 */
893 40 ret = hvcc_array_add_nal_unit(nal_buf, nal_size, array);
894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (ret < 0)
895 goto end;
896
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 4 times.
40 if (array->numNalus == 1) {
897 36 hvcc->numOfArrays++;
898 36 array->NAL_unit_type = nal_type;
899
900 /*
901 * When the sample entry name is ‘hvc1’, the default and mandatory value of
902 * array_completeness is 1 for arrays of all types of parameter sets, and 0
903 * for all other arrays. When the sample entry name is ‘hev1’, the default
904 * value of array_completeness is 0 for all arrays.
905 */
906
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 10 times.
36 if (nal_type == HEVC_NAL_VPS || nal_type == HEVC_NAL_SPS ||
907
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 nal_type == HEVC_NAL_PPS)
908 30 array->array_completeness = ps_array_completeness;
909 }
910
911 40 nal = &array->nal[array->numNalus-1];
912 40 nal->nuh_layer_id = nuh_layer_id;
913
914 /* Don't parse parameter sets. We already have the needed information*/
915
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 6 times.
40 if (is_nalff)
916 34 goto end;
917
918
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (nal_type == HEVC_NAL_VPS)
919 2 ret = hvcc_parse_vps(&gbc, nal, hvcc);
920
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 else if (nal_type == HEVC_NAL_SPS)
921 2 ret = hvcc_parse_sps(&gbc, nal, hvcc);
922
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (nal_type == HEVC_NAL_PPS)
923 2 ret = hvcc_parse_pps(&gbc, nal, hvcc);
924
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (ret < 0)
925 goto end;
926
927 6 end:
928 42 av_free(rbsp_buf);
929 42 return ret;
930 }
931
932 10 static void hvcc_init(HEVCDecoderConfigurationRecord *hvcc)
933 {
934 10 memset(hvcc, 0, sizeof(HEVCDecoderConfigurationRecord));
935 10 hvcc->configurationVersion = 1;
936 10 hvcc->lengthSizeMinusOne = 3; // 4 bytes
937
938 /*
939 * The following fields have all their valid bits set by default,
940 * the ProfileTierLevel parsing code will unset them when needed.
941 */
942 10 hvcc->general_profile_compatibility_flags = 0xffffffff;
943 10 hvcc->general_constraint_indicator_flags = 0xffffffffffff;
944
945 /*
946 * Initialize this field with an invalid value which can be used to detect
947 * whether we didn't see any VUI (in which case it should be reset to zero).
948 */
949 10 hvcc->min_spatial_segmentation_idc = MAX_SPATIAL_SEGMENTATION + 1;
950 10 }
951
952 10 static void hvcc_close(HEVCDecoderConfigurationRecord *hvcc)
953 {
954
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (unsigned i = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) {
955 50 HVCCNALUnitArray *const array = &hvcc->arrays[i];
956 50 array->numNalus = 0;
957 50 av_freep(&array->nal);
958 }
959 10 }
960
961 10 static int hvcc_write(void *logctx, AVIOContext *pb,
962 HEVCDecoderConfigurationRecord *hvcc, int flags)
963 {
964 10 uint16_t numNalus[NB_ARRAYS] = { 0 };
965 10 int is_lhvc = !!(flags & FLAG_IS_LHVC);
966 10 int numOfArrays = 0;
967
968 /*
969 * We only support writing HEVCDecoderConfigurationRecord version 1.
970 */
971 10 hvcc->configurationVersion = 1;
972
973 /*
974 * If min_spatial_segmentation_idc is invalid, reset to 0 (unspecified).
975 */
976
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (hvcc->min_spatial_segmentation_idc > MAX_SPATIAL_SEGMENTATION)
977 2 hvcc->min_spatial_segmentation_idc = 0;
978
979 /*
980 * parallelismType indicates the type of parallelism that is used to meet
981 * the restrictions imposed by min_spatial_segmentation_idc when the value
982 * of min_spatial_segmentation_idc is greater than 0.
983 */
984
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (!hvcc->min_spatial_segmentation_idc)
985 10 hvcc->parallelismType = 0;
986
987 /*
988 * It's unclear how to properly compute these fields, so
989 * let's always set them to values meaning 'unspecified'.
990 */
991 10 hvcc->avgFrameRate = 0;
992 /*
993 * lhvC doesn't store this field. It instead reserves the bits, setting them
994 * to '11'b.
995 */
996 10 hvcc->constantFrameRate = is_lhvc * 0x3;
997
998 /*
999 * Skip all NALUs with nuh_layer_id == 0 if writing lhvC. We do it here and
1000 * not before parsing them as some parameter sets with nuh_layer_id > 0
1001 * may reference base layer parameters sets.
1002 */
1003
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (unsigned i = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) {
1004 50 const HVCCNALUnitArray *const array = &hvcc->arrays[i];
1005
1006
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 36 times.
50 if (array->numNalus == 0)
1007 14 continue;
1008
1009
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 36 times.
76 for (unsigned j = 0; j < array->numNalus; j++)
1010
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
40 numNalus[i] += !is_lhvc || (array->nal[j].nuh_layer_id != 0);
1011 36 numOfArrays += (numNalus[i] > 0);
1012 }
1013
1014
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 av_log(logctx, AV_LOG_TRACE, "%s\n", is_lhvc ? "lhvC" : "hvcC");
1015 10 av_log(logctx, AV_LOG_TRACE, "configurationVersion: %"PRIu8"\n",
1016 10 hvcc->configurationVersion);
1017
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 if (!is_lhvc) {
1018 9 av_log(logctx, AV_LOG_TRACE, "general_profile_space: %"PRIu8"\n",
1019 9 hvcc->general_profile_space);
1020 9 av_log(logctx, AV_LOG_TRACE, "general_tier_flag: %"PRIu8"\n",
1021 9 hvcc->general_tier_flag);
1022 9 av_log(logctx, AV_LOG_TRACE, "general_profile_idc: %"PRIu8"\n",
1023 9 hvcc->general_profile_idc);
1024 9 av_log(logctx, AV_LOG_TRACE, "general_profile_compatibility_flags: 0x%08"PRIx32"\n",
1025 hvcc->general_profile_compatibility_flags);
1026 9 av_log(logctx, AV_LOG_TRACE, "general_constraint_indicator_flags: 0x%012"PRIx64"\n",
1027 hvcc->general_constraint_indicator_flags);
1028 9 av_log(logctx, AV_LOG_TRACE, "general_level_idc: %"PRIu8"\n",
1029 9 hvcc->general_level_idc);
1030 }
1031 10 av_log(logctx, AV_LOG_TRACE, "min_spatial_segmentation_idc: %"PRIu16"\n",
1032 10 hvcc->min_spatial_segmentation_idc);
1033 10 av_log(logctx, AV_LOG_TRACE, "parallelismType: %"PRIu8"\n",
1034 10 hvcc->parallelismType);
1035
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 if (!is_lhvc) {
1036 9 av_log(logctx, AV_LOG_TRACE, "chromaFormat: %"PRIu8"\n",
1037 9 hvcc->chromaFormat);
1038 9 av_log(logctx, AV_LOG_TRACE, "bitDepthLumaMinus8: %"PRIu8"\n",
1039 9 hvcc->bitDepthLumaMinus8);
1040 9 av_log(logctx, AV_LOG_TRACE, "bitDepthChromaMinus8: %"PRIu8"\n",
1041 9 hvcc->bitDepthChromaMinus8);
1042 9 av_log(logctx, AV_LOG_TRACE, "avgFrameRate: %"PRIu16"\n",
1043 9 hvcc->avgFrameRate);
1044 9 av_log(logctx, AV_LOG_TRACE, "constantFrameRate: %"PRIu8"\n",
1045 9 hvcc->constantFrameRate);
1046 }
1047 10 av_log(logctx, AV_LOG_TRACE, "numTemporalLayers: %"PRIu8"\n",
1048 10 hvcc->numTemporalLayers);
1049 10 av_log(logctx, AV_LOG_TRACE, "temporalIdNested: %"PRIu8"\n",
1050 10 hvcc->temporalIdNested);
1051 10 av_log(logctx, AV_LOG_TRACE, "lengthSizeMinusOne: %"PRIu8"\n",
1052 10 hvcc->lengthSizeMinusOne);
1053 10 av_log(logctx, AV_LOG_TRACE, "numOfArrays: %"PRIu8"\n",
1054 numOfArrays);
1055
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (unsigned i = 0, j = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) {
1056 50 const HVCCNALUnitArray *const array = &hvcc->arrays[i];
1057
1058
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 34 times.
50 if (numNalus[i] == 0)
1059 16 continue;
1060
1061 34 av_log(logctx, AV_LOG_TRACE, "array_completeness[%u]: %"PRIu8"\n",
1062 34 j, array->array_completeness);
1063 34 av_log(logctx, AV_LOG_TRACE, "NAL_unit_type[%u]: %"PRIu8"\n",
1064 34 j, array->NAL_unit_type);
1065 34 av_log(logctx, AV_LOG_TRACE, "numNalus[%u]: %"PRIu16"\n",
1066 34 j, numNalus[i]);
1067
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 34 times.
72 for (unsigned k = 0; k < array->numNalus; k++) {
1068
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
38 if (is_lhvc && array->nal[k].nuh_layer_id == 0)
1069 2 continue;
1070
1071 36 av_log(logctx, AV_LOG_TRACE,
1072 "nuh_layer_id[%u][%u]: %"PRIu8"\n",
1073 36 j, k, array->nal[k].nuh_layer_id);
1074 36 av_log(logctx, AV_LOG_TRACE,
1075 "parameter_set_id[%u][%u]: %"PRIu8"\n",
1076 36 j, k, array->nal[k].parameter_set_id);
1077 36 av_log(logctx, AV_LOG_TRACE,
1078 "nalUnitLength[%u][%u]: %"PRIu16"\n",
1079 36 j, k, array->nal[k].nalUnitLength);
1080 }
1081 34 j++;
1082 }
1083
1084 /*
1085 * We need at least one of each: VPS, SPS and PPS.
1086 */
1087
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if ((flags & FLAG_ARRAY_COMPLETENESS) &&
1088
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
2 (!numNalus[VPS_INDEX] || numNalus[VPS_INDEX] > HEVC_MAX_VPS_COUNT) && !is_lhvc)
1089 return AVERROR_INVALIDDATA;
1090
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if ((flags & FLAG_ARRAY_COMPLETENESS) &&
1091
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 (!numNalus[SPS_INDEX] || numNalus[SPS_INDEX] > HEVC_MAX_SPS_COUNT ||
1092
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 !numNalus[PPS_INDEX] || numNalus[PPS_INDEX] > HEVC_MAX_PPS_COUNT))
1093 return AVERROR_INVALIDDATA;
1094
1095 /* unsigned int(8) configurationVersion = 1; */
1096 10 avio_w8(pb, hvcc->configurationVersion);
1097
1098
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 if (!is_lhvc) {
1099 /*
1100 * unsigned int(2) general_profile_space;
1101 * unsigned int(1) general_tier_flag;
1102 * unsigned int(5) general_profile_idc;
1103 */
1104 9 avio_w8(pb, hvcc->general_profile_space << 6 |
1105 9 hvcc->general_tier_flag << 5 |
1106 9 hvcc->general_profile_idc);
1107
1108 /* unsigned int(32) general_profile_compatibility_flags; */
1109 9 avio_wb32(pb, hvcc->general_profile_compatibility_flags);
1110
1111 /* unsigned int(48) general_constraint_indicator_flags; */
1112 9 avio_wb32(pb, hvcc->general_constraint_indicator_flags >> 16);
1113 9 avio_wb16(pb, hvcc->general_constraint_indicator_flags);
1114
1115 /* unsigned int(8) general_level_idc; */
1116 9 avio_w8(pb, hvcc->general_level_idc);
1117 }
1118
1119 /*
1120 * bit(4) reserved = '1111'b;
1121 * unsigned int(12) min_spatial_segmentation_idc;
1122 */
1123 10 avio_wb16(pb, hvcc->min_spatial_segmentation_idc | 0xf000);
1124
1125 /*
1126 * bit(6) reserved = '111111'b;
1127 * unsigned int(2) parallelismType;
1128 */
1129 10 avio_w8(pb, hvcc->parallelismType | 0xfc);
1130
1131
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 if (!is_lhvc) {
1132 /*
1133 * bit(6) reserved = '111111'b;
1134 * unsigned int(2) chromaFormat;
1135 */
1136 9 avio_w8(pb, hvcc->chromaFormat | 0xfc);
1137
1138 /*
1139 * bit(5) reserved = '11111'b;
1140 * unsigned int(3) bitDepthLumaMinus8;
1141 */
1142 9 avio_w8(pb, hvcc->bitDepthLumaMinus8 | 0xf8);
1143
1144 /*
1145 * bit(5) reserved = '11111'b;
1146 * unsigned int(3) bitDepthChromaMinus8;
1147 */
1148 9 avio_w8(pb, hvcc->bitDepthChromaMinus8 | 0xf8);
1149
1150 /* bit(16) avgFrameRate; */
1151 9 avio_wb16(pb, hvcc->avgFrameRate);
1152 }
1153
1154 /*
1155 * if (!is_lhvc)
1156 * bit(2) constantFrameRate;
1157 * else
1158 * bit(2) reserved = '11'b;
1159 * bit(3) numTemporalLayers;
1160 * bit(1) temporalIdNested;
1161 * unsigned int(2) lengthSizeMinusOne;
1162 */
1163 10 avio_w8(pb, hvcc->constantFrameRate << 6 |
1164 10 hvcc->numTemporalLayers << 3 |
1165 10 hvcc->temporalIdNested << 2 |
1166 10 hvcc->lengthSizeMinusOne);
1167
1168 /* unsigned int(8) numOfArrays; */
1169 10 avio_w8(pb, numOfArrays);
1170
1171
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (unsigned i = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) {
1172 50 const HVCCNALUnitArray *const array = &hvcc->arrays[i];
1173
1174
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 34 times.
50 if (!numNalus[i])
1175 16 continue;
1176 /*
1177 * bit(1) array_completeness;
1178 * unsigned int(1) reserved = 0;
1179 * unsigned int(6) NAL_unit_type;
1180 */
1181 34 avio_w8(pb, array->array_completeness << 7 |
1182 34 array->NAL_unit_type & 0x3f);
1183
1184 /* unsigned int(16) numNalus; */
1185 34 avio_wb16(pb, numNalus[i]);
1186
1187
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 34 times.
72 for (unsigned j = 0; j < array->numNalus; j++) {
1188 38 HVCCNALUnit *nal = &array->nal[j];
1189
1190
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
38 if (is_lhvc && nal->nuh_layer_id == 0)
1191 2 continue;
1192
1193 /* unsigned int(16) nalUnitLength; */
1194 36 avio_wb16(pb, nal->nalUnitLength);
1195
1196 /* bit(8*nalUnitLength) nalUnit; */
1197 36 avio_write(pb, nal->nalUnit, nal->nalUnitLength);
1198 }
1199 }
1200
1201 10 return 0;
1202 }
1203
1204 144 int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in,
1205 int size, int filter_ps, int *ps_count)
1206 {
1207 144 int num_ps = 0, ret = 0;
1208 144 uint8_t *buf, *end, *start = NULL;
1209
1210
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 if (!filter_ps) {
1211 144 ret = ff_nal_parse_units(pb, buf_in, size);
1212 144 goto end;
1213 }
1214
1215 ret = ff_nal_parse_units_buf(buf_in, &start, &size);
1216 if (ret < 0)
1217 goto end;
1218
1219 ret = 0;
1220 buf = start;
1221 end = start + size;
1222
1223 while (end - buf > 4) {
1224 uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4);
1225 uint8_t type = (buf[4] >> 1) & 0x3f;
1226
1227 buf += 4;
1228
1229 switch (type) {
1230 case HEVC_NAL_VPS:
1231 case HEVC_NAL_SPS:
1232 case HEVC_NAL_PPS:
1233 num_ps++;
1234 break;
1235 default:
1236 ret += 4 + len;
1237 avio_wb32(pb, len);
1238 avio_write(pb, buf, len);
1239 break;
1240 }
1241
1242 buf += len;
1243 }
1244
1245 end:
1246 144 av_free(start);
1247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (ps_count)
1248 *ps_count = num_ps;
1249 144 return ret;
1250 }
1251
1252 int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out,
1253 int *size, int filter_ps, int *ps_count)
1254 {
1255 AVIOContext *pb;
1256 int ret;
1257
1258 ret = avio_open_dyn_buf(&pb);
1259 if (ret < 0)
1260 return ret;
1261
1262 ret = ff_hevc_annexb2mp4(pb, buf_in, *size, filter_ps, ps_count);
1263 if (ret < 0) {
1264 ffio_free_dyn_buf(&pb);
1265 return ret;
1266 }
1267
1268 *size = avio_close_dyn_buf(pb, buf_out);
1269
1270 return 0;
1271 }
1272
1273 42 static int hvcc_parse_nal_unit(const uint8_t *buf, uint32_t len, int type,
1274 HEVCDecoderConfigurationRecord *hvcc,
1275 int flags)
1276 {
1277
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 for (unsigned i = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) {
1278 static const uint8_t array_idx_to_type[] =
1279 { HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS,
1280 HEVC_NAL_SEI_PREFIX, HEVC_NAL_SEI_SUFFIX };
1281
1282
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 58 times.
100 if (type == array_idx_to_type[i]) {
1283 42 int ret = hvcc_add_nal_unit(buf, len, hvcc, flags, i);
1284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
1285 return ret;
1286 42 break;
1287 }
1288 }
1289
1290 42 return 0;
1291 }
1292
1293 10 static int write_configuration_record(void *logctx, AVIOContext *pb, const uint8_t *data,
1294 int size, int flags)
1295 {
1296 HEVCDecoderConfigurationRecord hvcc;
1297 10 uint8_t *buf, *end, *start = NULL;
1298 int ret;
1299
1300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (size < 6) {
1301 /* We can't write a valid hvcC from the provided data */
1302 return AVERROR_INVALIDDATA;
1303
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 } else if (*data == 1) {
1304 /* Data is already hvcC-formatted. Parse the arrays to skip any NALU
1305 with nuh_layer_id > 0 */
1306 GetBitContext gbc;
1307 int num_arrays;
1308
1309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (size < 23)
1310 return AVERROR_INVALIDDATA;
1311
1312 8 ret = init_get_bits8(&gbc, data, size);
1313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
1314 return ret;
1315
1316 8 hvcc_init(&hvcc);
1317 8 skip_bits(&gbc, 8); // hvcc.configurationVersion
1318 8 hvcc.general_profile_space = get_bits(&gbc, 2);
1319 8 hvcc.general_tier_flag = get_bits1(&gbc);
1320 8 hvcc.general_profile_idc = get_bits(&gbc, 5);
1321 8 hvcc.general_profile_compatibility_flags = get_bits_long(&gbc, 32);
1322 8 hvcc.general_constraint_indicator_flags = get_bits64(&gbc, 48);
1323 8 hvcc.general_level_idc = get_bits(&gbc, 8);
1324 8 skip_bits(&gbc, 4); // reserved
1325 8 hvcc.min_spatial_segmentation_idc = get_bits(&gbc, 12);
1326 8 skip_bits(&gbc, 6); // reserved
1327 8 hvcc.parallelismType = get_bits(&gbc, 2);
1328 8 skip_bits(&gbc, 6); // reserved
1329 8 hvcc.chromaFormat = get_bits(&gbc, 2);
1330 8 skip_bits(&gbc, 5); // reserved
1331 8 hvcc.bitDepthLumaMinus8 = get_bits(&gbc, 3);
1332 8 skip_bits(&gbc, 5); // reserved
1333 8 hvcc.bitDepthChromaMinus8 = get_bits(&gbc, 3);
1334 8 hvcc.avgFrameRate = get_bits(&gbc, 16);
1335 8 hvcc.constantFrameRate = get_bits(&gbc, 2);
1336 8 hvcc.numTemporalLayers = get_bits(&gbc, 3);
1337 8 hvcc.temporalIdNested = get_bits1(&gbc);
1338 8 hvcc.lengthSizeMinusOne = get_bits(&gbc, 2);
1339
1340 8 flags |= FLAG_IS_NALFF;
1341
1342 8 num_arrays = get_bits(&gbc, 8);
1343
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 8 times.
42 for (int i = 0; i < num_arrays; i++) {
1344 int type, num_nalus;
1345
1346 34 skip_bits(&gbc, 2);
1347 34 type = get_bits(&gbc, 6);
1348 34 num_nalus = get_bits(&gbc, 16);
1349
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 34 times.
70 for (int j = 0; j < num_nalus; j++) {
1350 36 int len = get_bits(&gbc, 16);
1351
1352
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
36 if (len > (get_bits_left(&gbc) / 8))
1353 8 goto end;
1354
1355 36 ret = hvcc_parse_nal_unit(data + get_bits_count(&gbc) / 8,
1356 len, type, &hvcc, flags);
1357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (ret < 0)
1358 goto end;
1359
1360 36 skip_bits_long(&gbc, len * 8);
1361 }
1362 }
1363
1364 8 ret = hvcc_write(logctx, pb, &hvcc, flags);
1365 8 goto end;
1366
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 } else if (!(AV_RB24(data) == 1 || AV_RB32(data) == 1)) {
1367 /* Not a valid Annex B start code prefix */
1368 return AVERROR_INVALIDDATA;
1369 }
1370
1371 2 ret = ff_nal_parse_units_buf(data, &start, &size);
1372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1373 return ret;
1374
1375 2 hvcc_init(&hvcc);
1376
1377 2 buf = start;
1378 2 end = start + size;
1379
1380
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 while (end - buf > 4) {
1381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4);
1382 6 uint8_t type = (buf[4] >> 1) & 0x3f;
1383
1384 6 buf += 4;
1385
1386 6 ret = hvcc_parse_nal_unit(buf, len, type, &hvcc, flags);
1387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
1388 goto end;
1389
1390 6 buf += len;
1391 }
1392
1393 2 ret = hvcc_write(logctx, pb, &hvcc, flags);
1394
1395 10 end:
1396 10 hvcc_close(&hvcc);
1397 10 av_free(start);
1398 10 return ret;
1399 }
1400
1401 9 int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data,
1402 int size, int ps_array_completeness, void *logctx)
1403 {
1404 9 return write_configuration_record(logctx, pb, data, size,
1405 !!ps_array_completeness * FLAG_ARRAY_COMPLETENESS);
1406 }
1407
1408 1 int ff_isom_write_lhvc(AVIOContext *pb, const uint8_t *data,
1409 int size, int ps_array_completeness, void *logctx)
1410 {
1411
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return write_configuration_record(logctx, pb, data, size,
1412 (!!ps_array_completeness * FLAG_ARRAY_COMPLETENESS) | FLAG_IS_LHVC);
1413 }
1414