History

avformat/hevc: add a function to write a lhvC box

James Almer committed 2 years ago

Commit cbfbacf1 parent cee43e52 files · +145 −35Browse files

Unified · Split

2 files
  1. libavformat/hevc.c +128 −35
  2. libavformat/hevc.h +17 −0
libavformat/hevc.c+128−35
@@ -43,12 +43,16 @@ enum { · 42 unmodified lines
4343
4444 #define FLAG_ARRAY_COMPLETENESS (1 << 0)
4545 #define FLAG_IS_NALFF (1 << 1)
46+#define FLAG_IS_LHVC (1 << 2)
4647
4748 typedef struct HVCCNALUnit {
4849 uint8_t nuh_layer_id;
4950 uint8_t parameter_set_id;
5051 uint16_t nalUnitLength;
5152 const uint8_t *nalUnit;
53+
54+ // VPS
55+ uint8_t vps_max_sub_layers_minus1;
5256 } HVCCNALUnit;
5357
5458 typedef struct HVCCNALUnitArray {
@@ -383,8 +387,6 @@ static void skip_sub_layer_ordering_info(GetBitContext *gb) · 328 unmodified lines
383387 static int hvcc_parse_vps(GetBitContext *gb, HVCCNALUnit *nal,
384388 HEVCDecoderConfigurationRecord *hvcc)
385389 {
386− unsigned int vps_max_sub_layers_minus1;
387−
388390 nal->parameter_set_id = get_bits(gb, 4);
389391 /*
390392 * vps_reserved_three_2bits u(2)
@@ -392,7 +394,7 @@ static int hvcc_parse_vps(GetBitContext *gb, HVCCNALUnit *nal, · 1 unmodified line
392394 */
393395 skip_bits(gb, 8);
394396
395− vps_max_sub_layers_minus1 = get_bits(gb, 3);
397+ nal->vps_max_sub_layers_minus1 = get_bits(gb, 3);
396398
397399 /*
398400 * numTemporalLayers greater than 1 indicates that the stream to which this
@@ -403,7 +405,7 @@ static int hvcc_parse_vps(GetBitContext *gb, HVCCNALUnit *nal, · 4 unmodified lines
403405 * that it is unknown whether the stream is temporally scalable.
404406 */
405407 hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers,
406− vps_max_sub_layers_minus1 + 1);
408+ nal->vps_max_sub_layers_minus1 + 1);
407409
408410 /*
409411 * vps_temporal_id_nesting_flag u(1)
@@ -411,7 +413,7 @@ static int hvcc_parse_vps(GetBitContext *gb, HVCCNALUnit *nal, · 1 unmodified line
411413 */
412414 skip_bits(gb, 17);
413415
414− hvcc_parse_ptl(gb, hvcc, vps_max_sub_layers_minus1);
416+ hvcc_parse_ptl(gb, hvcc, nal->vps_max_sub_layers_minus1);
415417
416418 /* nothing useful for hvcC past this point */
417419 return 0;
@@ -508,10 +510,33 @@ static int hvcc_parse_sps(GetBitContext *gb, HVCCNALUnit *nal, · 90 unmodified lines
508510 {
509511 unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4;
510512 unsigned int num_short_term_ref_pic_sets, num_delta_pocs[HEVC_MAX_SHORT_TERM_REF_PIC_SETS];
513+ unsigned int sps_ext_or_max_sub_layers_minus1, multi_layer_ext_sps_flag;
514+
515+ unsigned int sps_video_parameter_set_id = get_bits(gb, 4);
511516
512− skip_bits(gb, 4); // sps_video_parameter_set_id
517+ if (nal->nuh_layer_id == 0) {
518+ sps_ext_or_max_sub_layers_minus1 = 0;
519+ sps_max_sub_layers_minus1 = get_bits(gb, 3);
520+ } else {
521+ sps_ext_or_max_sub_layers_minus1 = get_bits(gb, 3);
522+ if (sps_ext_or_max_sub_layers_minus1 == 7) {
523+ const HVCCNALUnitArray *array = &hvcc->arrays[VPS_INDEX];
524+ const HVCCNALUnit *vps = NULL;
525+
526+ for (i = 0; i < array->numNalus; i++)
527+ if (sps_video_parameter_set_id == array->nal[i].parameter_set_id) {
528+ vps = &array->nal[i];
529+ break;
530+ }
531+ if (!vps)
532+ return AVERROR_INVALIDDATA;
513533
514− sps_max_sub_layers_minus1 = get_bits (gb, 3);
534+ sps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1;
535+ } else
536+ sps_max_sub_layers_minus1 = sps_ext_or_max_sub_layers_minus1;
537+ }
538+ multi_layer_ext_sps_flag = nal->nuh_layer_id &&
539+ sps_ext_or_max_sub_layers_minus1 == 7;
515540
516541 /*
517542 * numTemporalLayers greater than 1 indicates that the stream to which this
@@ -524,12 +549,17 @@ static int hvcc_parse_sps(GetBitContext *gb, HVCCNALUnit *nal, · 6 unmodified lines
524549 hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers,
525550 sps_max_sub_layers_minus1 + 1);
526551
527− hvcc->temporalIdNested = get_bits1(gb);
528−
529− hvcc_parse_ptl(gb, hvcc, sps_max_sub_layers_minus1);
552+ if (!multi_layer_ext_sps_flag) {
553+ hvcc->temporalIdNested = get_bits1(gb);
554+ hvcc_parse_ptl(gb, hvcc, sps_max_sub_layers_minus1);
555+ }
530556
531557 nal->parameter_set_id = get_ue_golomb_long(gb);
532558
559+ if (multi_layer_ext_sps_flag) {
560+ if (get_bits1(gb)) // update_rep_format_flag
561+ skip_bits(gb, 8); // sps_rep_format_idx
562+ } else {
533563 hvcc->chromaFormat = get_ue_golomb_long(gb);
534564
535565 if (hvcc->chromaFormat == 3)
@@ -547,12 +577,15 @@ static int hvcc_parse_sps(GetBitContext *gb, HVCCNALUnit *nal, · 11 unmodified lines
547577
548578 hvcc->bitDepthLumaMinus8 = get_ue_golomb_long(gb);
549579 hvcc->bitDepthChromaMinus8 = get_ue_golomb_long(gb);
580+ }
550581 log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb_long(gb);
551582
583+ if (!multi_layer_ext_sps_flag) {
552584 /* sps_sub_layer_ordering_info_present_flag */
553585 i = get_bits1(gb) ? 0 : sps_max_sub_layers_minus1;
554586 for (; i <= sps_max_sub_layers_minus1; i++)
555587 skip_sub_layer_ordering_info(gb);
588+ }
556589
557590 get_ue_golomb_long(gb); // log2_min_luma_coding_block_size_minus3
558591 get_ue_golomb_long(gb); // log2_diff_max_min_luma_coding_block_size
@@ -561,9 +594,15 @@ static int hvcc_parse_sps(GetBitContext *gb, HVCCNALUnit *nal, · 2 unmodified lines
561594 get_ue_golomb_long(gb); // max_transform_hierarchy_depth_inter
562595 get_ue_golomb_long(gb); // max_transform_hierarchy_depth_intra
563596
564− if (get_bits1(gb) && // scaling_list_enabled_flag
565− get_bits1(gb)) // sps_scaling_list_data_present_flag
566− skip_scaling_list_data(gb);
597+ if (get_bits1(gb)) { // scaling_list_enabled_flag
598+ int sps_infer_scaling_list_flag = 0;
599+ if (multi_layer_ext_sps_flag)
600+ sps_infer_scaling_list_flag = get_bits1(gb);
601+ if (sps_infer_scaling_list_flag)
602+ skip_bits(gb, 6); // sps_scaling_list_ref_layer_id
603+ else if (get_bits1(gb)) // sps_scaling_list_data_present_flag
604+ skip_scaling_list_data(gb);
605+ }
567606
568607 skip_bits1(gb); // amp_enabled_flag
569608 skip_bits1(gb); // sample_adaptive_offset_enabled_flag
@@ -703,6 +742,7 @@ static int hvcc_add_nal_unit(const uint8_t *nal_buf, uint32_t nal_size, · 133 unmodified lines
703742 {
704743 int ret = 0;
705744 int is_nalff = !!(flags & FLAG_IS_NALFF);
745+ int is_lhvc = !!(flags & FLAG_IS_LHVC);
706746 int ps_array_completeness = !!(flags & FLAG_ARRAY_COMPLETENESS);
707747 HVCCNALUnitArray *const array = &hvcc->arrays[array_idx];
708748 HVCCNALUnit *nal;
@@ -722,7 +762,7 @@ static int hvcc_add_nal_unit(const uint8_t *nal_buf, uint32_t nal_size, · 13 unmodified lines
722762 goto end;
723763
724764 nal_unit_parse_header(&gbc, &nal_type, &nuh_layer_id);
725− if (nuh_layer_id > 0)
765+ if (!is_lhvc && nuh_layer_id > 0)
726766 goto end;
727767
728768 /*
@@ -798,9 +838,12 @@ static void hvcc_close(HEVCDecoderConfigurationRecord *hvcc) · 69 unmodified lines
798838 }
799839 }
800840
801−static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc)
841+static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc,
842+ int flags)
802843 {
803− uint16_t vps_count, sps_count, pps_count;
844+ uint16_t numNalus[NB_ARRAYS] = { 0 };
845+ int is_lhvc = !!(flags & FLAG_IS_LHVC);
846+ int numOfArrays = 0;
804847
805848 /*
806849 * We only support writing HEVCDecoderConfigurationRecord version 1.
@@ -826,10 +869,32 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 19 unmodified lines
826869 * let's always set them to values meaning 'unspecified'.
827870 */
828871 hvcc->avgFrameRate = 0;
829− hvcc->constantFrameRate = 0;
872+ /*
873+ * lhvC doesn't store this field. It instead reserves the bits, setting them
874+ * to '11'b.
875+ */
876+ hvcc->constantFrameRate = is_lhvc * 0x3;
877+
878+ /*
879+ * Skip all NALUs with nuh_layer_id == 0 if writing lhvC. We do it here and
880+ * not before parsing them as some parameter sets with nuh_layer_id > 0
881+ * may reference base layer parameters sets.
882+ */
883+ for (unsigned i = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) {
884+ const HVCCNALUnitArray *const array = &hvcc->arrays[i];
885+
886+ if (array->numNalus == 0)
887+ continue;
830888
889+ for (unsigned j = 0; j < array->numNalus; j++)
890+ numNalus[i] += !is_lhvc || (array->nal[j].nuh_layer_id != 0);
891+ numOfArrays += (numNalus[i] > 0);
892+ }
893+
894+ av_log(NULL, AV_LOG_TRACE, "%s\n", is_lhvc ? "lhvC" : "hvcC");
831895 av_log(NULL, AV_LOG_TRACE, "configurationVersion: %"PRIu8"\n",
832896 hvcc->configurationVersion);
897+ if (!is_lhvc) {
833898 av_log(NULL, AV_LOG_TRACE, "general_profile_space: %"PRIu8"\n",
834899 hvcc->general_profile_space);
835900 av_log(NULL, AV_LOG_TRACE, "general_tier_flag: %"PRIu8"\n",
@@ -842,10 +907,12 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 6 unmodified lines
842907 hvcc->general_constraint_indicator_flags);
843908 av_log(NULL, AV_LOG_TRACE, "general_level_idc: %"PRIu8"\n",
844909 hvcc->general_level_idc);
910+ }
845911 av_log(NULL, AV_LOG_TRACE, "min_spatial_segmentation_idc: %"PRIu16"\n",
846912 hvcc->min_spatial_segmentation_idc);
847913 av_log(NULL, AV_LOG_TRACE, "parallelismType: %"PRIu8"\n",
848914 hvcc->parallelismType);
915+ if (!is_lhvc) {
849916 av_log(NULL, AV_LOG_TRACE, "chromaFormat: %"PRIu8"\n",
850917 hvcc->chromaFormat);
851918 av_log(NULL, AV_LOG_TRACE, "bitDepthLumaMinus8: %"PRIu8"\n",
@@ -856,6 +923,7 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 4 unmodified lines
856923 hvcc->avgFrameRate);
857924 av_log(NULL, AV_LOG_TRACE, "constantFrameRate: %"PRIu8"\n",
858925 hvcc->constantFrameRate);
926+ }
859927 av_log(NULL, AV_LOG_TRACE, "numTemporalLayers: %"PRIu8"\n",
860928 hvcc->numTemporalLayers);
861929 av_log(NULL, AV_LOG_TRACE, "temporalIdNested: %"PRIu8"\n",
@@ -863,11 +931,11 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 1 unmodified line
863931 av_log(NULL, AV_LOG_TRACE, "lengthSizeMinusOne: %"PRIu8"\n",
864932 hvcc->lengthSizeMinusOne);
865933 av_log(NULL, AV_LOG_TRACE, "numOfArrays: %"PRIu8"\n",
866− hvcc->numOfArrays);
934+ numOfArrays);
867935 for (unsigned i = 0, j = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) {
868936 const HVCCNALUnitArray *const array = &hvcc->arrays[i];
869937
870− if (array->numNalus == 0)
938+ if (numNalus[i] == 0)
871939 continue;
872940
873941 av_log(NULL, AV_LOG_TRACE, "array_completeness[%u]: %"PRIu8"\n",
@@ -875,28 +943,31 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 1 unmodified line
875943 av_log(NULL, AV_LOG_TRACE, "NAL_unit_type[%u]: %"PRIu8"\n",
876944 j, array->NAL_unit_type);
877945 av_log(NULL, AV_LOG_TRACE, "numNalus[%u]: %"PRIu16"\n",
878− j, array->numNalus);
879− for (unsigned k = 0; k < array->numNalus; k++)
946+ j, numNalus[i]);
947+ for (unsigned k = 0; k < array->numNalus; k++) {
948+ if (is_lhvc && array->nal[k].nuh_layer_id == 0)
949+ continue;
950+
880951 av_log(NULL, AV_LOG_TRACE,
881952 "nalUnitLength[%u][%u]: %"PRIu16"\n",
882953 j, k, array->nal[k].nalUnitLength);
954+ }
883955 j++;
884956 }
885957
886958 /*
887959 * We need at least one of each: VPS, SPS and PPS.
888960 */
889− vps_count = hvcc->arrays[VPS_INDEX].numNalus;
890− sps_count = hvcc->arrays[SPS_INDEX].numNalus;
891− pps_count = hvcc->arrays[PPS_INDEX].numNalus;
892− if (!vps_count || vps_count > HEVC_MAX_VPS_COUNT ||
893− !sps_count || sps_count > HEVC_MAX_SPS_COUNT ||
894− !pps_count || pps_count > HEVC_MAX_PPS_COUNT)
961+ if ((!numNalus[VPS_INDEX] || numNalus[VPS_INDEX] > HEVC_MAX_VPS_COUNT) && !is_lhvc)
962+ return AVERROR_INVALIDDATA;
963+ if (!numNalus[SPS_INDEX] || numNalus[SPS_INDEX] > HEVC_MAX_SPS_COUNT ||
964+ !numNalus[PPS_INDEX] || numNalus[PPS_INDEX] > HEVC_MAX_PPS_COUNT)
895965 return AVERROR_INVALIDDATA;
896966
897967 /* unsigned int(8) configurationVersion = 1; */
898968 avio_w8(pb, hvcc->configurationVersion);
899969
970+ if (!is_lhvc) {
900971 /*
901972 * unsigned int(2) general_profile_space;
902973 * unsigned int(1) general_tier_flag;
@@ -915,6 +986,7 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 12 unmodified lines
915986
916987 /* unsigned int(8) general_level_idc; */
917988 avio_w8(pb, hvcc->general_level_idc);
989+ }
918990
919991 /*
920992 * bit(4) reserved = '1111'b;
@@ -928,6 +1000,7 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 7 unmodified lines
9281000 */
9291001 avio_w8(pb, hvcc->parallelismType | 0xfc);
9301002
1003+ if (!is_lhvc) {
9311004 /*
9321005 * bit(6) reserved = '111111'b;
9331006 * unsigned int(2) chromaFormat;
@@ -948,9 +1021,13 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 14 unmodified lines
9481021
9491022 /* bit(16) avgFrameRate; */
9501023 avio_wb16(pb, hvcc->avgFrameRate);
1024+ }
9511025
9521026 /*
1027+ * if (!is_lhvc)
9531028 * bit(2) constantFrameRate;
1029+ * else
1030+ * bit(2) reserved = '11'b;
9541031 * bit(3) numTemporalLayers;
9551032 * bit(1) temporalIdNested;
9561033 * unsigned int(2) lengthSizeMinusOne;
@@ -961,12 +1038,12 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 4 unmodified lines
9611038 hvcc->lengthSizeMinusOne);
9621039
9631040 /* unsigned int(8) numOfArrays; */
964− avio_w8(pb, hvcc->numOfArrays);
1041+ avio_w8(pb, numOfArrays);
9651042
9661043 for (unsigned i = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) {
9671044 const HVCCNALUnitArray *const array = &hvcc->arrays[i];
9681045
969− if (!array->numNalus)
1046+ if (!numNalus[i])
9701047 continue;
9711048 /*
9721049 * bit(1) array_completeness;
@@ -977,11 +1054,14 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 4 unmodified lines
9771054 array->NAL_unit_type & 0x3f);
9781055
9791056 /* unsigned int(16) numNalus; */
980− avio_wb16(pb, array->numNalus);
1057+ avio_wb16(pb, numNalus[i]);
9811058
9821059 for (unsigned j = 0; j < array->numNalus; j++) {
9831060 HVCCNALUnit *nal = &array->nal[j];
9841061
1062+ if (is_lhvc && nal->nuh_layer_id == 0)
1063+ continue;
1064+
9851065 /* unsigned int(16) nalUnitLength; */
9861066 avio_wb16(pb, nal->nalUnitLength);
9871067
@@ -1082,12 +1162,11 @@ static int hvcc_parse_nal_unit(const uint8_t *buf, uint32_t len, int type, · 94 unmodified lines
10821162 return 0;
10831163 }
10841164
1085−int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data,
1086− int size, int ps_array_completeness)
1165+static int write_configuration_record(AVIOContext *pb, const uint8_t *data,
1166+ int size, int flags)
10871167 {
10881168 HEVCDecoderConfigurationRecord hvcc;
10891169 uint8_t *buf, *end, *start = NULL;
1090− int flags = !!ps_array_completeness * FLAG_ARRAY_COMPLETENESS;
10911170 int ret;
10921171
10931172 if (size < 6) {
@@ -1154,7 +1233,7 @@ int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, · 60 unmodified lines
11541233 }
11551234 }
11561235
1157− ret = hvcc_write(pb, &hvcc);
1236+ ret = hvcc_write(pb, &hvcc, flags);
11581237 goto end;
11591238 } else if (!(AV_RB24(data) == 1 || AV_RB32(data) == 1)) {
11601239 /* Not a valid Annex B start code prefix */
@@ -1183,10 +1262,24 @@ int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, · 22 unmodified lines
11831262 buf += len;
11841263 }
11851264
1186− ret = hvcc_write(pb, &hvcc);
1265+ ret = hvcc_write(pb, &hvcc, flags);
11871266
11881267 end:
11891268 hvcc_close(&hvcc);
11901269 av_free(start);
11911270 return ret;
11921271 }
1272+
1273+int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data,
1274+ int size, int ps_array_completeness)
1275+{
1276+ return write_configuration_record(pb, data, size,
1277+ !!ps_array_completeness * FLAG_ARRAY_COMPLETENESS);
1278+}
1279+
1280+int ff_isom_write_lhvc(AVIOContext *pb, const uint8_t *data,
1281+ int size, int ps_array_completeness)
1282+{
1283+ return write_configuration_record(pb, data, size,
1284+ (!!ps_array_completeness * FLAG_ARRAY_COMPLETENESS) | FLAG_IS_LHVC);
1285+}
libavformat/hevc.h+17−0
@@ -97,4 +97,21 @@ int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out, · 96 unmodified lines
9797 int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data,
9898 int size, int ps_array_completeness);
9999
100+/**
101+ * Writes L-HEVC extradata (parameter sets with nuh_layer_id > 0, as a
102+ * LHEVCDecoderConfigurationRecord) to the provided AVIOContext.
103+ *
104+ * If the extradata is Annex B format, it gets converted to lhvC format before
105+ * writing. Otherwise, hvcC formated extradata is expected, not lhvC.
106+ *
107+ * @param pb address of the AVIOContext where the lhvC shall be written
108+ * @param data address of the buffer holding the data needed to write the lhvC
109+ * @param size size (in bytes) of the data buffer
110+ * @param ps_array_completeness whether all parameter sets are in the lhvC (1)
111+ * or there may be additional parameter sets in the bitstream (0)
112+ * @return >=0 in case of success, a negative value corresponding to an AVERROR
113+ * code in case of failure
114+ */
115+int ff_isom_write_lhvc(AVIOContext *pb, const uint8_t *data,
116+ int size, int ps_array_completeness);
100117 #endif /* AVFORMAT_HEVC_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t