| @@ -43,12 +43,16 @@ enum { · 42 unmodified lines |
| 43 | | 43 | |
| 44 | #define FLAG_ARRAY_COMPLETENESS (1 << 0) | 44 | #define FLAG_ARRAY_COMPLETENESS (1 << 0) |
| 45 | #define FLAG_IS_NALFF (1 << 1) | 45 | #define FLAG_IS_NALFF (1 << 1) |
| | 46 | #define FLAG_IS_LHVC (1 << 2) |
| 46 | | 47 | |
| 47 | typedef struct HVCCNALUnit { | 48 | typedef struct HVCCNALUnit { |
| 48 | uint8_t nuh_layer_id; | 49 | uint8_t nuh_layer_id; |
| 49 | uint8_t parameter_set_id; | 50 | uint8_t parameter_set_id; |
| 50 | uint16_t nalUnitLength; | 51 | uint16_t nalUnitLength; |
| 51 | const uint8_t *nalUnit; | 52 | const uint8_t *nalUnit; |
| | 53 | |
| | 54 | // VPS |
| | 55 | uint8_t vps_max_sub_layers_minus1; |
| 52 | } HVCCNALUnit; | 56 | } HVCCNALUnit; |
| 53 | | 57 | |
| 54 | typedef struct HVCCNALUnitArray { | 58 | typedef struct HVCCNALUnitArray { |
| @@ -383,8 +387,6 @@ static void skip_sub_layer_ordering_info(GetBitContext *gb) · 328 unmodified lines |
| 383 | static int hvcc_parse_vps(GetBitContext *gb, HVCCNALUnit *nal, | 387 | static int hvcc_parse_vps(GetBitContext *gb, HVCCNALUnit *nal, |
| 384 | HEVCDecoderConfigurationRecord *hvcc) | 388 | HEVCDecoderConfigurationRecord *hvcc) |
| 385 | { | 389 | { |
| 386 | unsigned int vps_max_sub_layers_minus1; | | |
| 387 | | | |
| 388 | nal->parameter_set_id = get_bits(gb, 4); | 390 | nal->parameter_set_id = get_bits(gb, 4); |
| 389 | /* | 391 | /* |
| 390 | * vps_reserved_three_2bits u(2) | 392 | * vps_reserved_three_2bits u(2) |
| @@ -392,7 +394,7 @@ static int hvcc_parse_vps(GetBitContext *gb, HVCCNALUnit *nal, · 1 unmodified line |
| 392 | */ | 394 | */ |
| 393 | skip_bits(gb, 8); | 395 | skip_bits(gb, 8); |
| 394 | | 396 | |
| 395 | vps_max_sub_layers_minus1 = get_bits(gb, 3); | 397 | nal->vps_max_sub_layers_minus1 = get_bits(gb, 3); |
| 396 | | 398 | |
| 397 | /* | 399 | /* |
| 398 | * numTemporalLayers greater than 1 indicates that the stream to which this | 400 | * 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 |
| 403 | * that it is unknown whether the stream is temporally scalable. | 405 | * that it is unknown whether the stream is temporally scalable. |
| 404 | */ | 406 | */ |
| 405 | hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers, | 407 | hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers, |
| 406 | vps_max_sub_layers_minus1 + 1); | 408 | nal->vps_max_sub_layers_minus1 + 1); |
| 407 | | 409 | |
| 408 | /* | 410 | /* |
| 409 | * vps_temporal_id_nesting_flag u(1) | 411 | * vps_temporal_id_nesting_flag u(1) |
| @@ -411,7 +413,7 @@ static int hvcc_parse_vps(GetBitContext *gb, HVCCNALUnit *nal, · 1 unmodified line |
| 411 | */ | 413 | */ |
| 412 | skip_bits(gb, 17); | 414 | skip_bits(gb, 17); |
| 413 | | 415 | |
| 414 | hvcc_parse_ptl(gb, hvcc, vps_max_sub_layers_minus1); | 416 | hvcc_parse_ptl(gb, hvcc, nal->vps_max_sub_layers_minus1); |
| 415 | | 417 | |
| 416 | /* nothing useful for hvcC past this point */ | 418 | /* nothing useful for hvcC past this point */ |
| 417 | return 0; | 419 | return 0; |
| @@ -508,10 +510,33 @@ static int hvcc_parse_sps(GetBitContext *gb, HVCCNALUnit *nal, · 90 unmodified lines |
| 508 | { | 510 | { |
| 509 | unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4; | 511 | unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4; |
| 510 | unsigned int num_short_term_ref_pic_sets, num_delta_pocs[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; | 512 | 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); |
| 511 | | 516 | |
| 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; |
| 513 | | 533 | |
| 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; |
| 515 | | 540 | |
| 516 | /* | 541 | /* |
| 517 | * numTemporalLayers greater than 1 indicates that the stream to which this | 542 | * 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 |
| 524 | hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers, | 549 | hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers, |
| 525 | sps_max_sub_layers_minus1 + 1); | 550 | sps_max_sub_layers_minus1 + 1); |
| 526 | | 551 | |
| 527 | hvcc->temporalIdNested = get_bits1(gb); | 552 | if (!multi_layer_ext_sps_flag) { |
| 528 | | 553 | hvcc->temporalIdNested = get_bits1(gb); |
| 529 | hvcc_parse_ptl(gb, hvcc, sps_max_sub_layers_minus1); | 554 | hvcc_parse_ptl(gb, hvcc, sps_max_sub_layers_minus1); |
| | 555 | } |
| 530 | | 556 | |
| 531 | nal->parameter_set_id = get_ue_golomb_long(gb); | 557 | nal->parameter_set_id = get_ue_golomb_long(gb); |
| 532 | | 558 | |
| | 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 { |
| 533 | hvcc->chromaFormat = get_ue_golomb_long(gb); | 563 | hvcc->chromaFormat = get_ue_golomb_long(gb); |
| 534 | | 564 | |
| 535 | if (hvcc->chromaFormat == 3) | 565 | if (hvcc->chromaFormat == 3) |
| @@ -547,12 +577,15 @@ static int hvcc_parse_sps(GetBitContext *gb, HVCCNALUnit *nal, · 11 unmodified lines |
| 547 | | 577 | |
| 548 | hvcc->bitDepthLumaMinus8 = get_ue_golomb_long(gb); | 578 | hvcc->bitDepthLumaMinus8 = get_ue_golomb_long(gb); |
| 549 | hvcc->bitDepthChromaMinus8 = get_ue_golomb_long(gb); | 579 | hvcc->bitDepthChromaMinus8 = get_ue_golomb_long(gb); |
| | 580 | } |
| 550 | log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb_long(gb); | 581 | log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb_long(gb); |
| 551 | | 582 | |
| | 583 | if (!multi_layer_ext_sps_flag) { |
| 552 | /* sps_sub_layer_ordering_info_present_flag */ | 584 | /* sps_sub_layer_ordering_info_present_flag */ |
| 553 | i = get_bits1(gb) ? 0 : sps_max_sub_layers_minus1; | 585 | i = get_bits1(gb) ? 0 : sps_max_sub_layers_minus1; |
| 554 | for (; i <= sps_max_sub_layers_minus1; i++) | 586 | for (; i <= sps_max_sub_layers_minus1; i++) |
| 555 | skip_sub_layer_ordering_info(gb); | 587 | skip_sub_layer_ordering_info(gb); |
| | 588 | } |
| 556 | | 589 | |
| 557 | get_ue_golomb_long(gb); // log2_min_luma_coding_block_size_minus3 | 590 | get_ue_golomb_long(gb); // log2_min_luma_coding_block_size_minus3 |
| 558 | get_ue_golomb_long(gb); // log2_diff_max_min_luma_coding_block_size | 591 | 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 |
| 561 | get_ue_golomb_long(gb); // max_transform_hierarchy_depth_inter | 594 | get_ue_golomb_long(gb); // max_transform_hierarchy_depth_inter |
| 562 | get_ue_golomb_long(gb); // max_transform_hierarchy_depth_intra | 595 | get_ue_golomb_long(gb); // max_transform_hierarchy_depth_intra |
| 563 | | 596 | |
| 564 | if (get_bits1(gb) && // scaling_list_enabled_flag | 597 | if (get_bits1(gb)) { // scaling_list_enabled_flag |
| 565 | get_bits1(gb)) // sps_scaling_list_data_present_flag | 598 | int sps_infer_scaling_list_flag = 0; |
| 566 | skip_scaling_list_data(gb); | 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 | } |
| 567 | | 606 | |
| 568 | skip_bits1(gb); // amp_enabled_flag | 607 | skip_bits1(gb); // amp_enabled_flag |
| 569 | skip_bits1(gb); // sample_adaptive_offset_enabled_flag | 608 | 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 |
| 703 | { | 742 | { |
| 704 | int ret = 0; | 743 | int ret = 0; |
| 705 | int is_nalff = !!(flags & FLAG_IS_NALFF); | 744 | int is_nalff = !!(flags & FLAG_IS_NALFF); |
| | 745 | int is_lhvc = !!(flags & FLAG_IS_LHVC); |
| 706 | int ps_array_completeness = !!(flags & FLAG_ARRAY_COMPLETENESS); | 746 | int ps_array_completeness = !!(flags & FLAG_ARRAY_COMPLETENESS); |
| 707 | HVCCNALUnitArray *const array = &hvcc->arrays[array_idx]; | 747 | HVCCNALUnitArray *const array = &hvcc->arrays[array_idx]; |
| 708 | HVCCNALUnit *nal; | 748 | HVCCNALUnit *nal; |
| @@ -722,7 +762,7 @@ static int hvcc_add_nal_unit(const uint8_t *nal_buf, uint32_t nal_size, · 13 unmodified lines |
| 722 | goto end; | 762 | goto end; |
| 723 | | 763 | |
| 724 | nal_unit_parse_header(&gbc, &nal_type, &nuh_layer_id); | 764 | nal_unit_parse_header(&gbc, &nal_type, &nuh_layer_id); |
| 725 | if (nuh_layer_id > 0) | 765 | if (!is_lhvc && nuh_layer_id > 0) |
| 726 | goto end; | 766 | goto end; |
| 727 | | 767 | |
| 728 | /* | 768 | /* |
| @@ -798,9 +838,12 @@ static void hvcc_close(HEVCDecoderConfigurationRecord *hvcc) · 69 unmodified lines |
| 798 | } | 838 | } |
| 799 | } | 839 | } |
| 800 | | 840 | |
| 801 | static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) | 841 | static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc, |
| | 842 | int flags) |
| 802 | { | 843 | { |
| 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; |
| 804 | | 847 | |
| 805 | /* | 848 | /* |
| 806 | * We only support writing HEVCDecoderConfigurationRecord version 1. | 849 | * We only support writing HEVCDecoderConfigurationRecord version 1. |
| @@ -826,10 +869,32 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 19 unmodified lines |
| 826 | * let's always set them to values meaning 'unspecified'. | 869 | * let's always set them to values meaning 'unspecified'. |
| 827 | */ | 870 | */ |
| 828 | hvcc->avgFrameRate = 0; | 871 | 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; |
| 830 | | 888 | |
| | 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"); |
| 831 | av_log(NULL, AV_LOG_TRACE, "configurationVersion: %"PRIu8"\n", | 895 | av_log(NULL, AV_LOG_TRACE, "configurationVersion: %"PRIu8"\n", |
| 832 | hvcc->configurationVersion); | 896 | hvcc->configurationVersion); |
| | 897 | if (!is_lhvc) { |
| 833 | av_log(NULL, AV_LOG_TRACE, "general_profile_space: %"PRIu8"\n", | 898 | av_log(NULL, AV_LOG_TRACE, "general_profile_space: %"PRIu8"\n", |
| 834 | hvcc->general_profile_space); | 899 | hvcc->general_profile_space); |
| 835 | av_log(NULL, AV_LOG_TRACE, "general_tier_flag: %"PRIu8"\n", | 900 | 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 |
| 842 | hvcc->general_constraint_indicator_flags); | 907 | hvcc->general_constraint_indicator_flags); |
| 843 | av_log(NULL, AV_LOG_TRACE, "general_level_idc: %"PRIu8"\n", | 908 | av_log(NULL, AV_LOG_TRACE, "general_level_idc: %"PRIu8"\n", |
| 844 | hvcc->general_level_idc); | 909 | hvcc->general_level_idc); |
| | 910 | } |
| 845 | av_log(NULL, AV_LOG_TRACE, "min_spatial_segmentation_idc: %"PRIu16"\n", | 911 | av_log(NULL, AV_LOG_TRACE, "min_spatial_segmentation_idc: %"PRIu16"\n", |
| 846 | hvcc->min_spatial_segmentation_idc); | 912 | hvcc->min_spatial_segmentation_idc); |
| 847 | av_log(NULL, AV_LOG_TRACE, "parallelismType: %"PRIu8"\n", | 913 | av_log(NULL, AV_LOG_TRACE, "parallelismType: %"PRIu8"\n", |
| 848 | hvcc->parallelismType); | 914 | hvcc->parallelismType); |
| | 915 | if (!is_lhvc) { |
| 849 | av_log(NULL, AV_LOG_TRACE, "chromaFormat: %"PRIu8"\n", | 916 | av_log(NULL, AV_LOG_TRACE, "chromaFormat: %"PRIu8"\n", |
| 850 | hvcc->chromaFormat); | 917 | hvcc->chromaFormat); |
| 851 | av_log(NULL, AV_LOG_TRACE, "bitDepthLumaMinus8: %"PRIu8"\n", | 918 | av_log(NULL, AV_LOG_TRACE, "bitDepthLumaMinus8: %"PRIu8"\n", |
| @@ -856,6 +923,7 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 4 unmodified lines |
| 856 | hvcc->avgFrameRate); | 923 | hvcc->avgFrameRate); |
| 857 | av_log(NULL, AV_LOG_TRACE, "constantFrameRate: %"PRIu8"\n", | 924 | av_log(NULL, AV_LOG_TRACE, "constantFrameRate: %"PRIu8"\n", |
| 858 | hvcc->constantFrameRate); | 925 | hvcc->constantFrameRate); |
| | 926 | } |
| 859 | av_log(NULL, AV_LOG_TRACE, "numTemporalLayers: %"PRIu8"\n", | 927 | av_log(NULL, AV_LOG_TRACE, "numTemporalLayers: %"PRIu8"\n", |
| 860 | hvcc->numTemporalLayers); | 928 | hvcc->numTemporalLayers); |
| 861 | av_log(NULL, AV_LOG_TRACE, "temporalIdNested: %"PRIu8"\n", | 929 | av_log(NULL, AV_LOG_TRACE, "temporalIdNested: %"PRIu8"\n", |
| @@ -863,11 +931,11 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 1 unmodified line |
| 863 | av_log(NULL, AV_LOG_TRACE, "lengthSizeMinusOne: %"PRIu8"\n", | 931 | av_log(NULL, AV_LOG_TRACE, "lengthSizeMinusOne: %"PRIu8"\n", |
| 864 | hvcc->lengthSizeMinusOne); | 932 | hvcc->lengthSizeMinusOne); |
| 865 | av_log(NULL, AV_LOG_TRACE, "numOfArrays: %"PRIu8"\n", | 933 | av_log(NULL, AV_LOG_TRACE, "numOfArrays: %"PRIu8"\n", |
| 866 | hvcc->numOfArrays); | 934 | numOfArrays); |
| 867 | for (unsigned i = 0, j = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) { | 935 | for (unsigned i = 0, j = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) { |
| 868 | const HVCCNALUnitArray *const array = &hvcc->arrays[i]; | 936 | const HVCCNALUnitArray *const array = &hvcc->arrays[i]; |
| 869 | | 937 | |
| 870 | if (array->numNalus == 0) | 938 | if (numNalus[i] == 0) |
| 871 | continue; | 939 | continue; |
| 872 | | 940 | |
| 873 | av_log(NULL, AV_LOG_TRACE, "array_completeness[%u]: %"PRIu8"\n", | 941 | 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 |
| 875 | av_log(NULL, AV_LOG_TRACE, "NAL_unit_type[%u]: %"PRIu8"\n", | 943 | av_log(NULL, AV_LOG_TRACE, "NAL_unit_type[%u]: %"PRIu8"\n", |
| 876 | j, array->NAL_unit_type); | 944 | j, array->NAL_unit_type); |
| 877 | av_log(NULL, AV_LOG_TRACE, "numNalus[%u]: %"PRIu16"\n", | 945 | av_log(NULL, AV_LOG_TRACE, "numNalus[%u]: %"PRIu16"\n", |
| 878 | j, array->numNalus); | 946 | j, numNalus[i]); |
| 879 | for (unsigned k = 0; k < array->numNalus; k++) | 947 | for (unsigned k = 0; k < array->numNalus; k++) { |
| | 948 | if (is_lhvc && array->nal[k].nuh_layer_id == 0) |
| | 949 | continue; |
| | 950 | |
| 880 | av_log(NULL, AV_LOG_TRACE, | 951 | av_log(NULL, AV_LOG_TRACE, |
| 881 | "nalUnitLength[%u][%u]: %"PRIu16"\n", | 952 | "nalUnitLength[%u][%u]: %"PRIu16"\n", |
| 882 | j, k, array->nal[k].nalUnitLength); | 953 | j, k, array->nal[k].nalUnitLength); |
| | 954 | } |
| 883 | j++; | 955 | j++; |
| 884 | } | 956 | } |
| 885 | | 957 | |
| 886 | /* | 958 | /* |
| 887 | * We need at least one of each: VPS, SPS and PPS. | 959 | * We need at least one of each: VPS, SPS and PPS. |
| 888 | */ | 960 | */ |
| 889 | vps_count = hvcc->arrays[VPS_INDEX].numNalus; | 961 | if ((!numNalus[VPS_INDEX] || numNalus[VPS_INDEX] > HEVC_MAX_VPS_COUNT) && !is_lhvc) |
| 890 | sps_count = hvcc->arrays[SPS_INDEX].numNalus; | 962 | return AVERROR_INVALIDDATA; |
| 891 | pps_count = hvcc->arrays[PPS_INDEX].numNalus; | 963 | if (!numNalus[SPS_INDEX] || numNalus[SPS_INDEX] > HEVC_MAX_SPS_COUNT || |
| 892 | if (!vps_count || vps_count > HEVC_MAX_VPS_COUNT || | 964 | !numNalus[PPS_INDEX] || numNalus[PPS_INDEX] > HEVC_MAX_PPS_COUNT) |
| 893 | !sps_count || sps_count > HEVC_MAX_SPS_COUNT || | | |
| 894 | !pps_count || pps_count > HEVC_MAX_PPS_COUNT) | | |
| 895 | return AVERROR_INVALIDDATA; | 965 | return AVERROR_INVALIDDATA; |
| 896 | | 966 | |
| 897 | /* unsigned int(8) configurationVersion = 1; */ | 967 | /* unsigned int(8) configurationVersion = 1; */ |
| 898 | avio_w8(pb, hvcc->configurationVersion); | 968 | avio_w8(pb, hvcc->configurationVersion); |
| 899 | | 969 | |
| | 970 | if (!is_lhvc) { |
| 900 | /* | 971 | /* |
| 901 | * unsigned int(2) general_profile_space; | 972 | * unsigned int(2) general_profile_space; |
| 902 | * unsigned int(1) general_tier_flag; | 973 | * unsigned int(1) general_tier_flag; |
| @@ -915,6 +986,7 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 12 unmodified lines |
| 915 | | 986 | |
| 916 | /* unsigned int(8) general_level_idc; */ | 987 | /* unsigned int(8) general_level_idc; */ |
| 917 | avio_w8(pb, hvcc->general_level_idc); | 988 | avio_w8(pb, hvcc->general_level_idc); |
| | 989 | } |
| 918 | | 990 | |
| 919 | /* | 991 | /* |
| 920 | * bit(4) reserved = '1111'b; | 992 | * bit(4) reserved = '1111'b; |
| @@ -928,6 +1000,7 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 7 unmodified lines |
| 928 | */ | 1000 | */ |
| 929 | avio_w8(pb, hvcc->parallelismType | 0xfc); | 1001 | avio_w8(pb, hvcc->parallelismType | 0xfc); |
| 930 | | 1002 | |
| | 1003 | if (!is_lhvc) { |
| 931 | /* | 1004 | /* |
| 932 | * bit(6) reserved = '111111'b; | 1005 | * bit(6) reserved = '111111'b; |
| 933 | * unsigned int(2) chromaFormat; | 1006 | * unsigned int(2) chromaFormat; |
| @@ -948,9 +1021,13 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 14 unmodified lines |
| 948 | | 1021 | |
| 949 | /* bit(16) avgFrameRate; */ | 1022 | /* bit(16) avgFrameRate; */ |
| 950 | avio_wb16(pb, hvcc->avgFrameRate); | 1023 | avio_wb16(pb, hvcc->avgFrameRate); |
| | 1024 | } |
| 951 | | 1025 | |
| 952 | /* | 1026 | /* |
| | 1027 | * if (!is_lhvc) |
| 953 | * bit(2) constantFrameRate; | 1028 | * bit(2) constantFrameRate; |
| | 1029 | * else |
| | 1030 | * bit(2) reserved = '11'b; |
| 954 | * bit(3) numTemporalLayers; | 1031 | * bit(3) numTemporalLayers; |
| 955 | * bit(1) temporalIdNested; | 1032 | * bit(1) temporalIdNested; |
| 956 | * unsigned int(2) lengthSizeMinusOne; | 1033 | * unsigned int(2) lengthSizeMinusOne; |
| @@ -961,12 +1038,12 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 4 unmodified lines |
| 961 | hvcc->lengthSizeMinusOne); | 1038 | hvcc->lengthSizeMinusOne); |
| 962 | | 1039 | |
| 963 | /* unsigned int(8) numOfArrays; */ | 1040 | /* unsigned int(8) numOfArrays; */ |
| 964 | avio_w8(pb, hvcc->numOfArrays); | 1041 | avio_w8(pb, numOfArrays); |
| 965 | | 1042 | |
| 966 | for (unsigned i = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) { | 1043 | for (unsigned i = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) { |
| 967 | const HVCCNALUnitArray *const array = &hvcc->arrays[i]; | 1044 | const HVCCNALUnitArray *const array = &hvcc->arrays[i]; |
| 968 | | 1045 | |
| 969 | if (!array->numNalus) | 1046 | if (!numNalus[i]) |
| 970 | continue; | 1047 | continue; |
| 971 | /* | 1048 | /* |
| 972 | * bit(1) array_completeness; | 1049 | * bit(1) array_completeness; |
| @@ -977,11 +1054,14 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 4 unmodified lines |
| 977 | array->NAL_unit_type & 0x3f); | 1054 | array->NAL_unit_type & 0x3f); |
| 978 | | 1055 | |
| 979 | /* unsigned int(16) numNalus; */ | 1056 | /* unsigned int(16) numNalus; */ |
| 980 | avio_wb16(pb, array->numNalus); | 1057 | avio_wb16(pb, numNalus[i]); |
| 981 | | 1058 | |
| 982 | for (unsigned j = 0; j < array->numNalus; j++) { | 1059 | for (unsigned j = 0; j < array->numNalus; j++) { |
| 983 | HVCCNALUnit *nal = &array->nal[j]; | 1060 | HVCCNALUnit *nal = &array->nal[j]; |
| 984 | | 1061 | |
| | 1062 | if (is_lhvc && nal->nuh_layer_id == 0) |
| | 1063 | continue; |
| | 1064 | |
| 985 | /* unsigned int(16) nalUnitLength; */ | 1065 | /* unsigned int(16) nalUnitLength; */ |
| 986 | avio_wb16(pb, nal->nalUnitLength); | 1066 | avio_wb16(pb, nal->nalUnitLength); |
| 987 | | 1067 | |
| @@ -1082,12 +1162,11 @@ static int hvcc_parse_nal_unit(const uint8_t *buf, uint32_t len, int type, · 94 unmodified lines |
| 1082 | return 0; | 1162 | return 0; |
| 1083 | } | 1163 | } |
| 1084 | | 1164 | |
| 1085 | int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, | 1165 | static int write_configuration_record(AVIOContext *pb, const uint8_t *data, |
| 1086 | int size, int ps_array_completeness) | 1166 | int size, int flags) |
| 1087 | { | 1167 | { |
| 1088 | HEVCDecoderConfigurationRecord hvcc; | 1168 | HEVCDecoderConfigurationRecord hvcc; |
| 1089 | uint8_t *buf, *end, *start = NULL; | 1169 | uint8_t *buf, *end, *start = NULL; |
| 1090 | int flags = !!ps_array_completeness * FLAG_ARRAY_COMPLETENESS; | | |
| 1091 | int ret; | 1170 | int ret; |
| 1092 | | 1171 | |
| 1093 | if (size < 6) { | 1172 | if (size < 6) { |
| @@ -1154,7 +1233,7 @@ int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, · 60 unmodified lines |
| 1154 | } | 1233 | } |
| 1155 | } | 1234 | } |
| 1156 | | 1235 | |
| 1157 | ret = hvcc_write(pb, &hvcc); | 1236 | ret = hvcc_write(pb, &hvcc, flags); |
| 1158 | goto end; | 1237 | goto end; |
| 1159 | } else if (!(AV_RB24(data) == 1 || AV_RB32(data) == 1)) { | 1238 | } else if (!(AV_RB24(data) == 1 || AV_RB32(data) == 1)) { |
| 1160 | /* Not a valid Annex B start code prefix */ | 1239 | /* 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 |
| 1183 | buf += len; | 1262 | buf += len; |
| 1184 | } | 1263 | } |
| 1185 | | 1264 | |
| 1186 | ret = hvcc_write(pb, &hvcc); | 1265 | ret = hvcc_write(pb, &hvcc, flags); |
| 1187 | | 1266 | |
| 1188 | end: | 1267 | end: |
| 1189 | hvcc_close(&hvcc); | 1268 | hvcc_close(&hvcc); |
| 1190 | av_free(start); | 1269 | av_free(start); |
| 1191 | return ret; | 1270 | return ret; |
| 1192 | } | 1271 | } |
| | 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 | } |