h265_bitstream_parser_unittest.cc (9262B)
1 /* 2 * Copyright (c) 2023 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "common_video/h265/h265_bitstream_parser.h" 12 13 #include <cstdint> 14 #include <optional> 15 16 #include "api/array_view.h" 17 #include "common_video/h265/h265_common.h" 18 #include "test/gmock.h" 19 #include "test/gtest.h" 20 21 using ::testing::Eq; 22 using ::testing::Optional; 23 24 namespace webrtc { 25 26 // VPS/SPS/PPS part of below chunk. 27 constexpr uint8_t kH265VpsSpsPps[] = { 28 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x04, 0x08, 29 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 30 0x95, 0x98, 0x09, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x04, 0x08, 31 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 32 0xb0, 0x03, 0xc0, 0x80, 0x10, 0xe5, 0x96, 0x56, 0x69, 0x24, 0xca, 0xe0, 33 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, 0xe0, 0x80, 34 0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x72, 0xb4, 0x62, 0x40}; 35 36 // Contains enough of the image slice to contain slice QP. 37 constexpr uint8_t kH265BitstreamChunk[] = { 38 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x04, 0x08, 39 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 40 0x95, 0x98, 0x09, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x04, 0x08, 41 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 42 0xb0, 0x03, 0xc0, 0x80, 0x10, 0xe5, 0x96, 0x56, 0x69, 0x24, 0xca, 0xe0, 43 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, 0xe0, 0x80, 44 0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x72, 0xb4, 0x62, 0x40, 0x00, 45 0x00, 0x01, 0x26, 0x01, 0xaf, 0x08, 0x42, 0x23, 0x10, 0x5d, 0x2b, 0x51, 46 0xf9, 0x7a, 0x55, 0x15, 0x0d, 0x10, 0x40, 0xe8, 0x10, 0x05, 0x30, 0x95, 47 0x09, 0x9a, 0xa5, 0xb6, 0x6a, 0x66, 0x6d, 0xde, 0xe0, 0xf9, 48 }; 49 50 // Contains enough of the image slice to contain slice QP. 51 constexpr uint8_t kH265BitstreamNextImageSliceChunk[] = { 52 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xe0, 0x24, 0xbf, 0x82, 0x05, 53 0x21, 0x12, 0x22, 0xa3, 0x29, 0xb4, 0x21, 0x91, 0xa1, 0xaa, 0x40, 54 }; 55 56 // Contains enough of the image slice to contain slice QP. 57 constexpr uint8_t kH265SliceChunk[] = { 58 0xa4, 0x04, 0x55, 0xa2, 0x6d, 0xce, 0xc0, 0xc3, 0xed, 0x0b, 0xac, 0xbc, 59 0x00, 0xc4, 0x44, 0x2e, 0xf7, 0x55, 0xfd, 0x05, 0x86, 0x92, 0x19, 0xdf, 60 0x58, 0xec, 0x38, 0x36, 0xb7, 0x7c, 0x00, 0x15, 0x33, 0x78, 0x03, 0x67, 61 0x26, 0x0f, 0x7b, 0x30, 0x1c, 0xd7, 0xd4, 0x3a, 0xec, 0xad, 0xef, 0x73, 62 }; 63 64 // Contains enough of data for the second slice of a frame. 65 constexpr uint8_t kH265SecondSliceChunkInAFrame[] = { 66 0x02, 0x01, 0x23, 0xfc, 0x20, 0x22, 0xad, 0x13, 0x68, 0xce, 0xc3, 0x5a, 67 0x00, 0xdc, 0xeb, 0x86, 0x4b, 0x0b, 0xa7, 0x6a, 0xe1, 0x9c, 0x5c, 0xea, 68 }; 69 70 // Contains short term ref pic set slice to verify Log2Ceiling path. 71 constexpr uint8_t kH265SliceStrChunk[] = { 72 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x00, 73 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 74 0x00, 0x99, 0x94, 0x90, 0x24, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 75 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 76 0x03, 0x00, 0x00, 0x99, 0xa0, 0x01, 0x40, 0x20, 0x06, 0x41, 0xfe, 0x59, 77 0x49, 0x26, 0x4d, 0x86, 0x16, 0x22, 0xaa, 0x4c, 0x4c, 0x32, 0xfb, 0x3e, 78 0xbc, 0xdf, 0x96, 0x7d, 0x78, 0x51, 0x18, 0x9c, 0xbb, 0x20, 0x00, 0x00, 79 0x00, 0x01, 0x44, 0x01, 0xc1, 0xa5, 0x58, 0x11, 0x20, 0x00, 0x00, 0x01, 80 0x02, 0x01, 0xe1, 0x18, 0xfe, 0x47, 0x60, 0xd2, 0x74, 0xd6, 0x9f, 0xfc, 81 0xbe, 0x6b, 0x15, 0x48, 0x59, 0x1f, 0xf7, 0xc1, 0x7c, 0xe2, 0xe8, 0x10, 82 }; 83 84 // Contains enough of the image slice to contain invalid slice QP -52. 85 constexpr uint8_t kH265BitstreamInvalidQPChunk[] = { 86 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x04, 0x08, 87 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 88 0x95, 0x98, 0x09, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x04, 0x08, 89 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 90 0xb0, 0x03, 0xc0, 0x80, 0x10, 0xe5, 0x96, 0x56, 0x69, 0x24, 0xca, 0xe0, 91 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, 0xe0, 0x80, 92 0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x72, 0xb4, 0x62, 0x40, 0x00, 93 0x00, 0x01, 0x26, 0x01, 0xaf, 0x03, 0x4c, 94 }; 95 96 // Contains enough of the image slice to contain invalid slice QP 52. 97 constexpr uint8_t kH265BitstreamInvalidQPChunk52[] = { 98 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x04, 0x08, 99 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 100 0x95, 0x98, 0x09, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x04, 0x08, 101 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 102 0xb0, 0x03, 0xc0, 0x80, 0x10, 0xe5, 0x96, 0x56, 0x69, 0x24, 0xca, 0xe0, 103 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, 0xe0, 0x80, 104 0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x72, 0xb4, 0x62, 0x40, 0x00, 105 0x00, 0x01, 0x26, 0x01, 0xaf, 0x03, 0x44, 106 }; 107 108 // Bitstream that contains pred_weight_table. Contains enough data to parse 109 // over pred_weight_table for slice QP. This is bear.hevc from Chromium source, 110 // used for H265 hardware decoder's parser test, with some slices truncated. 111 constexpr uint8_t kH265BitstreamWithPredWeightTable[] = { 112 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60, 113 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 114 0x3c, 0x95, 0xc0, 0x90, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01, 115 0x60, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 116 0x00, 0x3c, 0xa0, 0x0a, 0x08, 0x0b, 0x9f, 0x79, 0x65, 0x79, 0x24, 0xca, 117 0xe0, 0x10, 0x00, 0x00, 0x06, 0x40, 0x00, 0x00, 0xbb, 0x50, 0x80, 0x00, 118 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x73, 0xd1, 0x89, 0x00, 0x00, 0x00, 119 0x01, 0x02, 0x01, 0xd0, 0x21, 0x49, 0xe8, 0xee, 0x50, 0x9c, 0x27, 0x20, 120 0x42, 0xc4, 0xcd, 0x33, 0xf0, 0xb1, 0x23, 0x7b, 0xfe, 0x4d, 0xcf, 0x40, 121 0xeb, 0x17, 0x37, 0x91, 0x1c, 0xb6, 0xba, 0x21, 0x42, 0xf7, 0xef, 0x01, 122 0x08, 0x90, 0x49, 0xdc, 0xfc, 0x10, 0x1f, 0x5e, 0x02, 0xd9, 0xaa, 0xe8, 123 0x32, 0xeb, 0x74, 0xbc, 0xdb, 0x2c, 0xa3, 0xec, 124 }; 125 126 TEST(H265BitstreamParserTest, ReportsNoQpWithoutParsedSlices) { 127 H265BitstreamParser h265_parser; 128 EXPECT_FALSE(h265_parser.GetLastSliceQp().has_value()); 129 } 130 131 TEST(H265BitstreamParserTest, ReportsNoQpWithOnlyParsedPpsAndSpsSlices) { 132 H265BitstreamParser h265_parser; 133 h265_parser.ParseBitstream(kH265VpsSpsPps); 134 EXPECT_FALSE(h265_parser.GetLastSliceQp().has_value()); 135 } 136 137 TEST(H265BitstreamParserTest, ReportQpWithPredWeightTable) { 138 H265BitstreamParser h265_parser; 139 h265_parser.ParseBitstream(kH265BitstreamWithPredWeightTable); 140 std::optional<int> qp = h265_parser.GetLastSliceQp(); 141 ASSERT_TRUE(qp.has_value()); 142 EXPECT_EQ(34, *qp); 143 } 144 145 TEST(H265BitstreamParserTest, ReportsLastSliceQpForImageSlices) { 146 H265BitstreamParser h265_parser; 147 h265_parser.ParseBitstream(kH265BitstreamChunk); 148 std::optional<int> qp = h265_parser.GetLastSliceQp(); 149 ASSERT_TRUE(qp.has_value()); 150 EXPECT_EQ(34, *qp); 151 152 // Parse an additional image slice. 153 h265_parser.ParseBitstream(kH265BitstreamNextImageSliceChunk); 154 qp = h265_parser.GetLastSliceQp(); 155 ASSERT_TRUE(qp.has_value()); 156 EXPECT_EQ(36, *qp); 157 } 158 159 TEST(H265BitstreamParserTest, ReportsLastSliceQpFromShortTermReferenceSlices) { 160 H265BitstreamParser h265_parser; 161 h265_parser.ParseBitstream(kH265SliceStrChunk); 162 std::optional<int> qp = h265_parser.GetLastSliceQp(); 163 ASSERT_TRUE(qp.has_value()); 164 EXPECT_EQ(33, *qp); 165 } 166 167 TEST(H265BitstreamParserTest, PpsIdFromSlice) { 168 std::optional<uint32_t> pps_id = 169 H265BitstreamParser::ParsePpsIdFromSliceSegmentLayerRbsp( 170 kH265SliceChunk, H265::NaluType::kTrailR); 171 ASSERT_TRUE(pps_id); 172 EXPECT_EQ(1u, *pps_id); 173 } 174 175 TEST(H265BitstreamParserTest, ReportsLastSliceQpInvalidQPSlices) { 176 H265BitstreamParser h265_parser; 177 h265_parser.ParseBitstream(kH265BitstreamInvalidQPChunk); 178 std::optional<int> qp = h265_parser.GetLastSliceQp(); 179 ASSERT_FALSE(qp.has_value()); 180 181 h265_parser.ParseBitstream(kH265BitstreamInvalidQPChunk52); 182 qp = h265_parser.GetLastSliceQp(); 183 ASSERT_FALSE(qp.has_value()); 184 } 185 186 TEST(H265BitstreamParserTest, ReportsFirstSliceSegmentInPic) { 187 EXPECT_THAT(H265BitstreamParser::IsFirstSliceSegmentInPic(kH265SliceChunk), 188 Optional(Eq(true))); 189 } 190 191 TEST(H265BitstreamParserTest, ReportsFirstSliceSegmentInPicFalse) { 192 EXPECT_THAT(H265BitstreamParser::IsFirstSliceSegmentInPic( 193 kH265SecondSliceChunkInAFrame), 194 Optional(Eq(false))); 195 } 196 197 TEST(H265BitstreamParserTest, ReportsFirstSliceSegmentInPicParseInvalidSlice) { 198 ArrayView<const uint8_t> slice_data(kH265SliceChunk); 199 EXPECT_THAT( 200 H265BitstreamParser::IsFirstSliceSegmentInPic(slice_data.subview(50)), 201 Eq(std::nullopt)); 202 } 203 204 } // namespace webrtc