diff --git a/packager/media/codecs/h264_parser.cc b/packager/media/codecs/h264_parser.cc index f57361d8a9..59f5ca10e2 100644 --- a/packager/media/codecs/h264_parser.cc +++ b/packager/media/codecs/h264_parser.cc @@ -858,8 +858,8 @@ H264Parser::Result H264Parser::ParseWeightingFactors( int def_chroma_weight = 1 << chroma_log2_weight_denom; for (int i = 0; i < num_ref_idx_active_minus1 + 1; ++i) { - READ_BOOL_OR_RETURN(&w_facts->luma_weight_flag); - if (w_facts->luma_weight_flag) { + READ_BOOL_OR_RETURN(&w_facts->luma_weight_flag[i]); + if (w_facts->luma_weight_flag[i]) { READ_SE_OR_RETURN(&w_facts->luma_weight[i]); IN_RANGE_OR_RETURN(w_facts->luma_weight[i], -128, 127); @@ -871,8 +871,8 @@ H264Parser::Result H264Parser::ParseWeightingFactors( } if (chroma_array_type != 0) { - READ_BOOL_OR_RETURN(&w_facts->chroma_weight_flag); - if (w_facts->chroma_weight_flag) { + READ_BOOL_OR_RETURN(&w_facts->chroma_weight_flag[i]); + if (w_facts->chroma_weight_flag[i]) { for (int j = 0; j < 2; ++j) { READ_SE_OR_RETURN(&w_facts->chroma_weight[i][j]); IN_RANGE_OR_RETURN(w_facts->chroma_weight[i][j], -128, 127); diff --git a/packager/media/codecs/h264_parser.h b/packager/media/codecs/h264_parser.h index 11b1555675..76e75a5c72 100644 --- a/packager/media/codecs/h264_parser.h +++ b/packager/media/codecs/h264_parser.h @@ -125,8 +125,8 @@ struct H264ModificationOfPicNum { }; struct H264WeightingFactors { - bool luma_weight_flag; - bool chroma_weight_flag; + bool luma_weight_flag[32]; + bool chroma_weight_flag[32]; int luma_weight[32]; int luma_offset[32]; int chroma_weight[32][2]; diff --git a/packager/media/codecs/h264_parser_unittest.cc b/packager/media/codecs/h264_parser_unittest.cc index 842ad38504..5211109c8b 100644 --- a/packager/media/codecs/h264_parser_unittest.cc +++ b/packager/media/codecs/h264_parser_unittest.cc @@ -20,11 +20,35 @@ const uint8_t kSps[] = { const uint8_t kPps[] = { 0x28, 0xDE, 0x9, 0x88, }; -// This is the prefix of a video slice that only has the header. -// The actual slice header size is 30 bits (not including the nalu header). +// This is the prefix of a video slice (including the nalu header) that only has +// the slice header. The actual slice header size is 30 bits (not including the +// nalu header). const uint8_t kVideoSliceTrimmed[] = { 0x25, 0xB8, 0x20, 0x20, 0x63, }; + +// This is another prefix of a video slice (including the nalu header). +// The slice header is 67 bits. So the first 10 bytes is the data before +// slice_data(). +// Note also that this is from a real video slice and +// PPS's entropy_coding_mode_flag is true. So slice_data() starts from the 11th +// byte. +const uint8_t kVideoSliceTrimmedMultipleLumaWeights[] = { + 0x41, 0x9A, 0x72, 0x78, 0x43, 0xC9, 0x94, 0xC0, + 0x8C, 0xFF, 0xC1, 0x54, +}; + +// SPS for KVideoSliceTrimmedMultipleLumaWeights. +const uint8_t kSps2[] = { + 0x67, 0x64, 0x00, 0x28, 0xAC, 0xB2, 0x00, 0xF0, 0x04, 0x4F, + 0xCB, 0x80, 0xB5, 0x01, 0x01, 0x01, 0x40, 0x00, 0x00, 0x03, + 0x00, 0x40, 0x00, 0x00, 0x0F, 0x03, 0xC6, 0x0C, 0x92, +}; + +// PPS for KVideoSliceTrimmedMultipleLumaWeights. +const uint8_t kPps2[] = { + 0x68, 0xEB, 0xCC, 0xB2, 0x2C, +}; } // namespace TEST(H264ParserTest, StreamFileParsing) { @@ -100,6 +124,69 @@ TEST(H264ParserTest, SliceHeaderSize) { EXPECT_EQ(30u, slice_header.header_bit_size); } +TEST(H264ParserTest, PredWeightTable) { + H264Parser parser; + int unused_id; + Nalu nalu; + ASSERT_TRUE(nalu.Initialize(Nalu::kH264, kSps2, arraysize(kSps2))); + ASSERT_EQ(H264Parser::kOk, parser.ParseSps(nalu, &unused_id)); + ASSERT_TRUE(nalu.Initialize(Nalu::kH264, kPps2, arraysize(kPps2))); + ASSERT_EQ(H264Parser::kOk, parser.ParsePps(nalu, &unused_id)); + ASSERT_TRUE( + nalu.Initialize(Nalu::kH264, kVideoSliceTrimmedMultipleLumaWeights, + arraysize(kVideoSliceTrimmedMultipleLumaWeights))); + + H264SliceHeader slice_header; + ASSERT_EQ(H264Parser::kOk, parser.ParseSliceHeader(nalu, &slice_header)); + + EXPECT_TRUE(slice_header.num_ref_idx_active_override_flag); + ASSERT_EQ(3, slice_header.num_ref_idx_l0_active_minus1); + + const H264WeightingFactors& pred_weight_table = + slice_header.pred_weight_table_l0; + + EXPECT_FALSE(pred_weight_table.luma_weight_flag[0]); + EXPECT_TRUE(pred_weight_table.luma_weight_flag[1]); + EXPECT_FALSE(pred_weight_table.luma_weight_flag[2]); + EXPECT_FALSE(pred_weight_table.luma_weight_flag[3]); + + // Luma checks. + EXPECT_EQ(1, pred_weight_table.luma_weight[0]); + EXPECT_EQ(1, pred_weight_table.luma_weight[1]); + EXPECT_EQ(1, pred_weight_table.luma_weight[2]); + EXPECT_EQ(1, pred_weight_table.luma_weight[3]); + EXPECT_EQ(0, pred_weight_table.luma_offset[0]); + EXPECT_EQ(-1, pred_weight_table.luma_offset[1]); + EXPECT_EQ(0, pred_weight_table.luma_offset[2]); + EXPECT_EQ(0, pred_weight_table.luma_offset[3]); + + EXPECT_FALSE(pred_weight_table.chroma_weight_flag[0]); + EXPECT_FALSE(pred_weight_table.chroma_weight_flag[1]); + EXPECT_FALSE(pred_weight_table.chroma_weight_flag[2]); + EXPECT_FALSE(pred_weight_table.chroma_weight_flag[3]); + + // Chroma checks. + // U plane. + EXPECT_EQ(1, pred_weight_table.chroma_weight[0][0]); + EXPECT_EQ(1, pred_weight_table.chroma_weight[1][0]); + EXPECT_EQ(1, pred_weight_table.chroma_weight[2][0]); + EXPECT_EQ(1, pred_weight_table.chroma_weight[3][0]); + EXPECT_EQ(0, pred_weight_table.chroma_offset[0][0]); + EXPECT_EQ(0, pred_weight_table.chroma_offset[1][0]); + EXPECT_EQ(0, pred_weight_table.chroma_offset[2][0]); + EXPECT_EQ(0, pred_weight_table.chroma_offset[3][0]); + + // V plane. + EXPECT_EQ(1, pred_weight_table.chroma_weight[0][1]); + EXPECT_EQ(1, pred_weight_table.chroma_weight[1][1]); + EXPECT_EQ(1, pred_weight_table.chroma_weight[2][1]); + EXPECT_EQ(1, pred_weight_table.chroma_weight[3][1]); + EXPECT_EQ(0, pred_weight_table.chroma_offset[0][1]); + EXPECT_EQ(0, pred_weight_table.chroma_offset[1][1]); + EXPECT_EQ(0, pred_weight_table.chroma_offset[2][1]); + EXPECT_EQ(0, pred_weight_table.chroma_offset[3][1]); +} + TEST(H264ParserTest, ExtractResolutionFromSpsData) { const uint8_t kSps[] = {0x67, 0x64, 0x00, 0x1E, 0xAC, 0xD9, 0x40, 0xB4, 0x2F, 0xF9, 0x7F, 0xF0, 0x00, 0x80, 0x00, 0x91,