Showing the changes to libavformat (2 of 2 files). Show all
Unified · Split
| @@ -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 | } | ||
| @@ -97,4 +97,21 @@ int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out, · 96 unmodified lines | |||
| 97 | int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, | 97 | int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, |
| 98 | int size, int ps_array_completeness); | 98 | int size, int ps_array_completeness); |
| 99 | 99 | ||
| 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); | ||
| 100 | #endif /* AVFORMAT_HEVC_H */ | 117 | #endif /* AVFORMAT_HEVC_H */ |