| @@ -43,12 +43,16 @@ enum { · 42 unmodified lines |
| 43 | 43 | |
| 44 | 44 | #define FLAG_ARRAY_COMPLETENESS (1 << 0) |
| 45 | 45 | #define FLAG_IS_NALFF (1 << 1) |
| 46 | +#define FLAG_IS_LHVC (1 << 2) |
| 46 | 47 | |
| 47 | 48 | typedef struct HVCCNALUnit { |
| 48 | 49 | uint8_t nuh_layer_id; |
| 49 | 50 | uint8_t parameter_set_id; |
| 50 | 51 | uint16_t nalUnitLength; |
| 51 | 52 | const uint8_t *nalUnit; |
| 53 | + |
| 54 | + // VPS |
| 55 | + uint8_t vps_max_sub_layers_minus1; |
| 52 | 56 | } HVCCNALUnit; |
| 53 | 57 | |
| 54 | 58 | typedef struct HVCCNALUnitArray { |
| @@ -383,8 +387,6 @@ static void skip_sub_layer_ordering_info(GetBitContext *gb) · 328 unmodified lines |
| 383 | 387 | static int hvcc_parse_vps(GetBitContext *gb, HVCCNALUnit *nal, |
| 384 | 388 | HEVCDecoderConfigurationRecord *hvcc) |
| 385 | 389 | { |
| 386 | | − unsigned int vps_max_sub_layers_minus1; |
| 387 | | − |
| 388 | 390 | nal->parameter_set_id = get_bits(gb, 4); |
| 389 | 391 | /* |
| 390 | 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 | 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 | 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 | 405 | * that it is unknown whether the stream is temporally scalable. |
| 404 | 406 | */ |
| 405 | 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 | 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 | 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 | 418 | /* nothing useful for hvcC past this point */ |
| 417 | 419 | return 0; |
| @@ -508,10 +510,33 @@ static int hvcc_parse_sps(GetBitContext *gb, HVCCNALUnit *nal, · 90 unmodified lines |
| 508 | 510 | { |
| 509 | 511 | unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4; |
| 510 | 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 | 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 | 549 | hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers, |
| 525 | 550 | sps_max_sub_layers_minus1 + 1); |
| 526 | 551 | |
| 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 | + } |
| 530 | 556 | |
| 531 | 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 | 563 | hvcc->chromaFormat = get_ue_golomb_long(gb); |
| 534 | 564 | |
| 535 | 565 | if (hvcc->chromaFormat == 3) |
| @@ -547,12 +577,15 @@ static int hvcc_parse_sps(GetBitContext *gb, HVCCNALUnit *nal, · 11 unmodified lines |
| 547 | 577 | |
| 548 | 578 | hvcc->bitDepthLumaMinus8 = get_ue_golomb_long(gb); |
| 549 | 579 | hvcc->bitDepthChromaMinus8 = get_ue_golomb_long(gb); |
| 580 | + } |
| 550 | 581 | log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb_long(gb); |
| 551 | 582 | |
| 583 | + if (!multi_layer_ext_sps_flag) { |
| 552 | 584 | /* sps_sub_layer_ordering_info_present_flag */ |
| 553 | 585 | i = get_bits1(gb) ? 0 : sps_max_sub_layers_minus1; |
| 554 | 586 | for (; i <= sps_max_sub_layers_minus1; i++) |
| 555 | 587 | skip_sub_layer_ordering_info(gb); |
| 588 | + } |
| 556 | 589 | |
| 557 | 590 | get_ue_golomb_long(gb); // log2_min_luma_coding_block_size_minus3 |
| 558 | 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 | 594 | get_ue_golomb_long(gb); // max_transform_hierarchy_depth_inter |
| 562 | 595 | get_ue_golomb_long(gb); // max_transform_hierarchy_depth_intra |
| 563 | 596 | |
| 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 | + } |
| 567 | 606 | |
| 568 | 607 | skip_bits1(gb); // amp_enabled_flag |
| 569 | 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 | 743 | int ret = 0; |
| 705 | 744 | int is_nalff = !!(flags & FLAG_IS_NALFF); |
| 745 | + int is_lhvc = !!(flags & FLAG_IS_LHVC); |
| 706 | 746 | int ps_array_completeness = !!(flags & FLAG_ARRAY_COMPLETENESS); |
| 707 | 747 | HVCCNALUnitArray *const array = &hvcc->arrays[array_idx]; |
| 708 | 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 | 762 | goto end; |
| 723 | 763 | |
| 724 | 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 | 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 | 849 | * We only support writing HEVCDecoderConfigurationRecord version 1. |
| @@ -826,10 +869,32 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 19 unmodified lines |
| 826 | 869 | * let's always set them to values meaning 'unspecified'. |
| 827 | 870 | */ |
| 828 | 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 | 895 | av_log(NULL, AV_LOG_TRACE, "configurationVersion: %"PRIu8"\n", |
| 832 | 896 | hvcc->configurationVersion); |
| 897 | + if (!is_lhvc) { |
| 833 | 898 | av_log(NULL, AV_LOG_TRACE, "general_profile_space: %"PRIu8"\n", |
| 834 | 899 | hvcc->general_profile_space); |
| 835 | 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 | 907 | hvcc->general_constraint_indicator_flags); |
| 843 | 908 | av_log(NULL, AV_LOG_TRACE, "general_level_idc: %"PRIu8"\n", |
| 844 | 909 | hvcc->general_level_idc); |
| 910 | + } |
| 845 | 911 | av_log(NULL, AV_LOG_TRACE, "min_spatial_segmentation_idc: %"PRIu16"\n", |
| 846 | 912 | hvcc->min_spatial_segmentation_idc); |
| 847 | 913 | av_log(NULL, AV_LOG_TRACE, "parallelismType: %"PRIu8"\n", |
| 848 | 914 | hvcc->parallelismType); |
| 915 | + if (!is_lhvc) { |
| 849 | 916 | av_log(NULL, AV_LOG_TRACE, "chromaFormat: %"PRIu8"\n", |
| 850 | 917 | hvcc->chromaFormat); |
| 851 | 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 | 923 | hvcc->avgFrameRate); |
| 857 | 924 | av_log(NULL, AV_LOG_TRACE, "constantFrameRate: %"PRIu8"\n", |
| 858 | 925 | hvcc->constantFrameRate); |
| 926 | + } |
| 859 | 927 | av_log(NULL, AV_LOG_TRACE, "numTemporalLayers: %"PRIu8"\n", |
| 860 | 928 | hvcc->numTemporalLayers); |
| 861 | 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 | 931 | av_log(NULL, AV_LOG_TRACE, "lengthSizeMinusOne: %"PRIu8"\n", |
| 864 | 932 | hvcc->lengthSizeMinusOne); |
| 865 | 933 | av_log(NULL, AV_LOG_TRACE, "numOfArrays: %"PRIu8"\n", |
| 866 | | − hvcc->numOfArrays); |
| 934 | + numOfArrays); |
| 867 | 935 | for (unsigned i = 0, j = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) { |
| 868 | 936 | const HVCCNALUnitArray *const array = &hvcc->arrays[i]; |
| 869 | 937 | |
| 870 | | − if (array->numNalus == 0) |
| 938 | + if (numNalus[i] == 0) |
| 871 | 939 | continue; |
| 872 | 940 | |
| 873 | 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 | 943 | av_log(NULL, AV_LOG_TRACE, "NAL_unit_type[%u]: %"PRIu8"\n", |
| 876 | 944 | j, array->NAL_unit_type); |
| 877 | 945 | 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 | + |
| 880 | 951 | av_log(NULL, AV_LOG_TRACE, |
| 881 | 952 | "nalUnitLength[%u][%u]: %"PRIu16"\n", |
| 882 | 953 | j, k, array->nal[k].nalUnitLength); |
| 954 | + } |
| 883 | 955 | j++; |
| 884 | 956 | } |
| 885 | 957 | |
| 886 | 958 | /* |
| 887 | 959 | * We need at least one of each: VPS, SPS and PPS. |
| 888 | 960 | */ |
| 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) |
| 895 | 965 | return AVERROR_INVALIDDATA; |
| 896 | 966 | |
| 897 | 967 | /* unsigned int(8) configurationVersion = 1; */ |
| 898 | 968 | avio_w8(pb, hvcc->configurationVersion); |
| 899 | 969 | |
| 970 | + if (!is_lhvc) { |
| 900 | 971 | /* |
| 901 | 972 | * unsigned int(2) general_profile_space; |
| 902 | 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 | 987 | /* unsigned int(8) general_level_idc; */ |
| 917 | 988 | avio_w8(pb, hvcc->general_level_idc); |
| 989 | + } |
| 918 | 990 | |
| 919 | 991 | /* |
| 920 | 992 | * bit(4) reserved = '1111'b; |
| @@ -928,6 +1000,7 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 7 unmodified lines |
| 928 | 1000 | */ |
| 929 | 1001 | avio_w8(pb, hvcc->parallelismType | 0xfc); |
| 930 | 1002 | |
| 1003 | + if (!is_lhvc) { |
| 931 | 1004 | /* |
| 932 | 1005 | * bit(6) reserved = '111111'b; |
| 933 | 1006 | * unsigned int(2) chromaFormat; |
| @@ -948,9 +1021,13 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 14 unmodified lines |
| 948 | 1021 | |
| 949 | 1022 | /* bit(16) avgFrameRate; */ |
| 950 | 1023 | avio_wb16(pb, hvcc->avgFrameRate); |
| 1024 | + } |
| 951 | 1025 | |
| 952 | 1026 | /* |
| 1027 | + * if (!is_lhvc) |
| 953 | 1028 | * bit(2) constantFrameRate; |
| 1029 | + * else |
| 1030 | + * bit(2) reserved = '11'b; |
| 954 | 1031 | * bit(3) numTemporalLayers; |
| 955 | 1032 | * bit(1) temporalIdNested; |
| 956 | 1033 | * unsigned int(2) lengthSizeMinusOne; |
| @@ -961,12 +1038,12 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 4 unmodified lines |
| 961 | 1038 | hvcc->lengthSizeMinusOne); |
| 962 | 1039 | |
| 963 | 1040 | /* unsigned int(8) numOfArrays; */ |
| 964 | | − avio_w8(pb, hvcc->numOfArrays); |
| 1041 | + avio_w8(pb, numOfArrays); |
| 965 | 1042 | |
| 966 | 1043 | for (unsigned i = 0; i < FF_ARRAY_ELEMS(hvcc->arrays); i++) { |
| 967 | 1044 | const HVCCNALUnitArray *const array = &hvcc->arrays[i]; |
| 968 | 1045 | |
| 969 | | − if (!array->numNalus) |
| 1046 | + if (!numNalus[i]) |
| 970 | 1047 | continue; |
| 971 | 1048 | /* |
| 972 | 1049 | * bit(1) array_completeness; |
| @@ -977,11 +1054,14 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) · 4 unmodified lines |
| 977 | 1054 | array->NAL_unit_type & 0x3f); |
| 978 | 1055 | |
| 979 | 1056 | /* unsigned int(16) numNalus; */ |
| 980 | | − avio_wb16(pb, array->numNalus); |
| 1057 | + avio_wb16(pb, numNalus[i]); |
| 981 | 1058 | |
| 982 | 1059 | for (unsigned j = 0; j < array->numNalus; j++) { |
| 983 | 1060 | HVCCNALUnit *nal = &array->nal[j]; |
| 984 | 1061 | |
| 1062 | + if (is_lhvc && nal->nuh_layer_id == 0) |
| 1063 | + continue; |
| 1064 | + |
| 985 | 1065 | /* unsigned int(16) nalUnitLength; */ |
| 986 | 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 | 1162 | return 0; |
| 1083 | 1163 | } |
| 1084 | 1164 | |
| 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) |
| 1087 | 1167 | { |
| 1088 | 1168 | HEVCDecoderConfigurationRecord hvcc; |
| 1089 | 1169 | uint8_t *buf, *end, *start = NULL; |
| 1090 | | − int flags = !!ps_array_completeness * FLAG_ARRAY_COMPLETENESS; |
| 1091 | 1170 | int ret; |
| 1092 | 1171 | |
| 1093 | 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 | 1237 | goto end; |
| 1159 | 1238 | } else if (!(AV_RB24(data) == 1 || AV_RB32(data) == 1)) { |
| 1160 | 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 | 1262 | buf += len; |
| 1184 | 1263 | } |
| 1185 | 1264 | |
| 1186 | | − ret = hvcc_write(pb, &hvcc); |
| 1265 | + ret = hvcc_write(pb, &hvcc, flags); |
| 1187 | 1266 | |
| 1188 | 1267 | end: |
| 1189 | 1268 | hvcc_close(&hvcc); |
| 1190 | 1269 | av_free(start); |
| 1191 | 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 | +} |