From 858fcd869853c5cdd80ea15ba730f1ac8fdf27c4 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Fri, 5 Jan 2018 20:57:51 -0800 Subject: [PATCH] Fix incorrect HEVC decoder configuration data When transmuxing from TS to MP4 if there is emulation prevention bytes in general_profile_tier_level_data. Fixes #312 Change-Id: I48857046c1ea4bed4f455d03d060551e3ef4bec8 --- .../h265_byte_to_unit_stream_converter.cc | 5 ++-- ..._byte_to_unit_stream_converter_unittest.cc | 2 +- packager/media/codecs/h265_parser.cc | 30 +++++++++++-------- packager/media/codecs/h265_parser.h | 11 +++++-- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/packager/media/codecs/h265_byte_to_unit_stream_converter.cc b/packager/media/codecs/h265_byte_to_unit_stream_converter.cc index 7abd45b458..f6b46860f4 100644 --- a/packager/media/codecs/h265_byte_to_unit_stream_converter.cc +++ b/packager/media/codecs/h265_byte_to_unit_stream_converter.cc @@ -51,9 +51,8 @@ bool H265ByteToUnitStreamConverter::GetDecoderConfigurationRecord( // (4) general_profile_compatibility_flags // (6) general_constraint_indicator_flags // (1) general_level_idc - // Skip Nalu header (2) and the first byte of the SPS to get the - // profile_tier_level. - buffer.AppendArray(&last_sps_[2+1], 12); + for (int byte : sps->general_profile_tier_level_data) + buffer.AppendInt(static_cast(byte)); // The default value for this field is 0, which is Unknown. int min_spatial_segmentation_idc = diff --git a/packager/media/codecs/h265_byte_to_unit_stream_converter_unittest.cc b/packager/media/codecs/h265_byte_to_unit_stream_converter_unittest.cc index c37240eab1..dfe00cc0c9 100644 --- a/packager/media/codecs/h265_byte_to_unit_stream_converter_unittest.cc +++ b/packager/media/codecs/h265_byte_to_unit_stream_converter_unittest.cc @@ -14,7 +14,7 @@ namespace { const char kExpectedConfigRecord[] = - "01016000000300900000030000f000fcfdf8f800000303a00001001840010c01ffff01" + "0101600000009000000000005df000fcfdf8f800000303a00001001840010c01ffff01" "600000030090000003000003005d999809a10001002e42010101600000030090000003" "000003005da0028080241f265999a4932bffc0d5c0d64040000003004000000602a200" "0100074401c172b46240"; diff --git a/packager/media/codecs/h265_parser.cc b/packager/media/codecs/h265_parser.cc index 7292c55a24..7fc344267f 100644 --- a/packager/media/codecs/h265_parser.cc +++ b/packager/media/codecs/h265_parser.cc @@ -518,7 +518,8 @@ H265Parser::Result H265Parser::ParseSps(const Nalu& nalu, int* sps_id) { TRUE_OR_RETURN(br->ReadBits(3, &sps->max_sub_layers_minus1)); TRUE_OR_RETURN(br->ReadBool(&sps->temporal_id_nesting_flag)); - OK_OR_RETURN(SkipProfileTierLevel(true, sps->max_sub_layers_minus1, br)); + OK_OR_RETURN( + ReadProfileTierLevel(true, sps->max_sub_layers_minus1, br, sps.get())); TRUE_OR_RETURN(br->ReadUE(&sps->seq_parameter_set_id)); TRUE_OR_RETURN(br->ReadUE(&sps->chroma_format_idc)); @@ -947,24 +948,27 @@ H265Parser::Result H265Parser::SkipPredictionWeightTable( return kOk; } -H265Parser::Result H265Parser::SkipProfileTierLevel( +H265Parser::Result H265Parser::ReadProfileTierLevel( bool profile_present, int max_num_sub_layers_minus1, - H26xBitReader* br) { + H26xBitReader* br, + H265Sps* sps) { // Reads whole element, ignores it. if (profile_present) { - // general_profile_space, general_tier_flag, general_profile_idc - // general_profile_compativility_flag - // general_progressive_source_flag - // general_interlaced_source_flag - // general_non_packed_constraint_flag - // general_frame_only_constraint_flag - // 44-bits of other flags - TRUE_OR_RETURN(br->SkipBits(2 + 1 + 5 + 32 + 4 + 44)); + // 11 bytes of general_profile_tier flags: + // general_profile_space, general_tier_flag, general_profile_idc + // general_profile_compativility_flag + // general_progressive_source_flag + // general_interlaced_source_flag + // general_non_packed_constraint_flag + // general_frame_only_constraint_flag + // 44-bits of other flags + for (int i = 0; i < 11; i++) + TRUE_OR_RETURN(br->ReadBits(8, &sps->general_profile_tier_level_data[i])); } - - TRUE_OR_RETURN(br->SkipBits(8)); // general_level_idc + // general_level_idc + TRUE_OR_RETURN(br->ReadBits(8, &sps->general_profile_tier_level_data[11])); std::vector sub_layer_profile_present(max_num_sub_layers_minus1); std::vector sub_layer_level_present(max_num_sub_layers_minus1); diff --git a/packager/media/codecs/h265_parser.h b/packager/media/codecs/h265_parser.h index 9b6215def5..5b0253a33f 100644 --- a/packager/media/codecs/h265_parser.h +++ b/packager/media/codecs/h265_parser.h @@ -131,7 +131,11 @@ struct H265Sps { int video_parameter_set_id = 0; int max_sub_layers_minus1 = 0; bool temporal_id_nesting_flag = false; - // Ignored: profile_tier_level(...) + + // general_profile_space (2), general_tier_flag (1), general_profile_idc (5), + // general_profile_compatibility_flags (32), + // general_constraint_indicator_flags (48), general_level_idc (8). + int general_profile_tier_level_data[12] = {}; int seq_parameter_set_id = 0; @@ -334,9 +338,10 @@ class H265Parser { const H265SliceHeader& slice_header, H26xBitReader* br); - Result SkipProfileTierLevel(bool profile_present, + Result ReadProfileTierLevel(bool profile_present, int max_num_sub_layers_minus1, - H26xBitReader* br); + H26xBitReader* br, + H265Sps* sps); Result SkipScalingListData(H26xBitReader* br);