Bug 1952339 - Vendor libwebrtc from a152ada304

Upstream commit: https://webrtc.googlesource.com/src/+/a152ada304a19769bfbd1e6e19c626dc5c66dc67
    Support h265 streams with weighted prediction tables.

    Some H265 encoders may encode with weighted prediction turned on. Allow
    such streams to be parsed.

    Bug: chromium:41480904
    Change-Id: I25e7ca7b8151f264eeb9a4eae3cd49719dfeef9c
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/378703
    Reviewed-by: Henrik Boström <hbos@webrtc.org>
    Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
    Commit-Queue: Jianlin Qiu <jianlin.qiu@intel.com>
    Cr-Commit-Position: refs/heads/main@{#43991}

Differential Revision: https://phabricator.services.mozilla.com/D243999
This commit is contained in:
Michael Froman
2025-03-07 16:42:33 -06:00
parent ee8568c1cf
commit 3255f8207f
3 changed files with 130 additions and 8 deletions

View File

@@ -1,4 +1,4 @@
# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-03-07T22:41:33.244180+00:00.
libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-03-07T22:42:22.082859+00:00.
# base of lastest vendoring
4b67f8d3f7
a152ada304

View File

@@ -364,13 +364,109 @@ H265BitstreamParser::Result H265BitstreamParser::ParseNonParameterSetNalu(
}
}
}
if (!slice_reader.Ok() ||
((pps->weighted_pred_flag && slice_type == H265::SliceType::kP) ||
(pps->weighted_bipred_flag && slice_type == H265::SliceType::kB))) {
// pred_weight_table()
RTC_LOG(LS_ERROR) << "Streams with pred_weight_table unsupported.";
return kUnsupportedStream;
// pred_weight_table()
if ((pps->weighted_pred_flag && slice_type == H265::SliceType::kP) ||
(pps->weighted_bipred_flag && slice_type == H265::SliceType::kB)) {
uint32_t luma_log2_weight_denom = slice_reader.ReadExponentialGolomb();
IN_RANGE_OR_RETURN(luma_log2_weight_denom, 0, 7);
uint32_t chroma_array_type =
sps->separate_colour_plane_flag == 0 ? sps->chroma_format_idc : 0;
int32_t chroma_log2_weight_denom = luma_log2_weight_denom;
// wp_offset_half_range_c and wp_offset_half_range_y depends on
// sps.high_precision_offsets_enable_flag. Since range extension is not
// supported, so for now below two are fixed to 128 instead of 1 <<
// (sps.bit_depth_luma|chroma_minus8 + 7).
int32_t wp_offset_half_range_c = (1 << 7);
int32_t wp_offset_half_range_y = (1 << 7);
if (chroma_array_type != 0) {
// delta_chroma_log2_weight_denom: se(v)
chroma_log2_weight_denom +=
slice_reader.ReadSignedExponentialGolomb();
}
IN_RANGE_OR_RETURN(chroma_log2_weight_denom, 0, 7);
bool luma_weight_flag_l0[kMaxRefIdxActive] = {};
bool chroma_weight_flag_l0[kMaxRefIdxActive] = {};
int32_t delta_chroma_weight_l0[kMaxRefIdxActive][2] = {};
int32_t luma_offset_l0[kMaxRefIdxActive] = {};
int32_t delta_chroma_offset_l0[kMaxRefIdxActive][2] = {};
for (uint32_t i = 0; i <= num_ref_idx_l0_active_minus1; i++) {
// luma_weight_l0_flag: u(1). By syntax this should conditionally
// check if the POC or layer ID of the reference picture is different,
// but we don't support encoding referencing different layers in the
// same AU. Skip the check for now.
luma_weight_flag_l0[i] = slice_reader.Read<bool>();
}
if (chroma_array_type != 0) {
for (uint32_t i = 0; i <= num_ref_idx_l0_active_minus1; i++) {
// chroma_weight_l0_flag: u(1)
chroma_weight_flag_l0[i] = slice_reader.Read<bool>();
}
}
for (uint32_t i = 0; i <= num_ref_idx_l0_active_minus1; i++) {
if (luma_weight_flag_l0[i]) {
int32_t delta_luma_weight_l0[kMaxRefIdxActive] = {};
delta_luma_weight_l0[i] =
slice_reader.ReadSignedExponentialGolomb();
IN_RANGE_OR_RETURN(delta_luma_weight_l0[i], -128, 127);
luma_offset_l0[i] = slice_reader.ReadSignedExponentialGolomb();
IN_RANGE_OR_RETURN(luma_offset_l0[i], -wp_offset_half_range_y,
wp_offset_half_range_y - 1);
}
if (chroma_weight_flag_l0[i]) {
for (uint32_t j = 0; j < 2; j++) {
delta_chroma_weight_l0[i][j] =
slice_reader.ReadSignedExponentialGolomb();
IN_RANGE_OR_RETURN(delta_chroma_weight_l0[i][j], -128, 127);
delta_chroma_offset_l0[i][j] =
slice_reader.ReadSignedExponentialGolomb();
IN_RANGE_OR_RETURN(delta_chroma_offset_l0[i][j],
-4 * wp_offset_half_range_c,
4 * wp_offset_half_range_c - 1);
}
}
}
if (slice_type == H265::SliceType::kB) {
bool luma_weight_flag_l1[kMaxRefIdxActive] = {};
bool chroma_weight_flag_l1[kMaxRefIdxActive] = {};
int32_t delta_chroma_weight_l1[kMaxRefIdxActive][2] = {};
int32_t luma_offset_l1[kMaxRefIdxActive] = {};
int32_t delta_chroma_offset_l1[kMaxRefIdxActive][2] = {};
for (uint32_t i = 0; i < num_ref_idx_l1_active_minus1; i++) {
luma_weight_flag_l1[i] = slice_reader.Read<bool>();
}
if (chroma_array_type != 0) {
for (uint32_t i = 0; i <= num_ref_idx_l1_active_minus1; i++) {
chroma_weight_flag_l1[i] = slice_reader.Read<bool>();
}
}
for (uint32_t i = 0; i <= num_ref_idx_l1_active_minus1; i++) {
if (luma_weight_flag_l1[i]) {
int32_t delta_luma_weight_l1[kMaxRefIdxActive] = {};
delta_luma_weight_l1[i] =
slice_reader.ReadSignedExponentialGolomb();
IN_RANGE_OR_RETURN(delta_luma_weight_l1[i], -128, 127);
luma_offset_l1[i] = slice_reader.ReadSignedExponentialGolomb();
IN_RANGE_OR_RETURN(luma_offset_l1[i], -wp_offset_half_range_y,
wp_offset_half_range_y - 1);
}
if (chroma_weight_flag_l1[i]) {
for (uint32_t j = 0; j < 2; j++) {
delta_chroma_weight_l1[i][j] =
slice_reader.ReadSignedExponentialGolomb();
IN_RANGE_OR_RETURN(delta_chroma_weight_l1[i][j], -128, 127);
delta_chroma_offset_l1[i][j] =
slice_reader.ReadSignedExponentialGolomb();
IN_RANGE_OR_RETURN(delta_chroma_offset_l1[i][j],
-4 * wp_offset_half_range_c,
4 * wp_offset_half_range_c - 1);
}
}
}
}
}
// five_minus_max_num_merge_cand: ue(v)
uint32_t five_minus_max_num_merge_cand =
slice_reader.ReadExponentialGolomb();

View File

@@ -101,6 +101,24 @@ const uint8_t kH265BitstreamInvalidQPChunk52[] = {
0x00, 0x01, 0x26, 0x01, 0xaf, 0x03, 0x44,
};
// Bitstream that contains pred_weight_table. Contains enough data to parse
// over pred_weight_table for slice QP. This is bear.hevc from Chromium source,
// used for H265 hardware decoder's parser test, with some slices truncated.
const uint8_t kH265BitstreamWithPredWeightTable[] = {
0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60,
0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
0x3c, 0x95, 0xc0, 0x90, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01,
0x60, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03,
0x00, 0x3c, 0xa0, 0x0a, 0x08, 0x0b, 0x9f, 0x79, 0x65, 0x79, 0x24, 0xca,
0xe0, 0x10, 0x00, 0x00, 0x06, 0x40, 0x00, 0x00, 0xbb, 0x50, 0x80, 0x00,
0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x73, 0xd1, 0x89, 0x00, 0x00, 0x00,
0x01, 0x02, 0x01, 0xd0, 0x21, 0x49, 0xe8, 0xee, 0x50, 0x9c, 0x27, 0x20,
0x42, 0xc4, 0xcd, 0x33, 0xf0, 0xb1, 0x23, 0x7b, 0xfe, 0x4d, 0xcf, 0x40,
0xeb, 0x17, 0x37, 0x91, 0x1c, 0xb6, 0xba, 0x21, 0x42, 0xf7, 0xef, 0x01,
0x08, 0x90, 0x49, 0xdc, 0xfc, 0x10, 0x1f, 0x5e, 0x02, 0xd9, 0xaa, 0xe8,
0x32, 0xeb, 0x74, 0xbc, 0xdb, 0x2c, 0xa3, 0xec,
};
TEST(H265BitstreamParserTest, ReportsNoQpWithoutParsedSlices) {
H265BitstreamParser h265_parser;
EXPECT_FALSE(h265_parser.GetLastSliceQp().has_value());
@@ -112,6 +130,14 @@ TEST(H265BitstreamParserTest, ReportsNoQpWithOnlyParsedPpsAndSpsSlices) {
EXPECT_FALSE(h265_parser.GetLastSliceQp().has_value());
}
TEST(H265BitstreamParserTest, ReportQpWithPredWeightTable) {
H265BitstreamParser h265_parser;
h265_parser.ParseBitstream(kH265BitstreamWithPredWeightTable);
std::optional<int> qp = h265_parser.GetLastSliceQp();
ASSERT_TRUE(qp.has_value());
EXPECT_EQ(34, *qp);
}
TEST(H265BitstreamParserTest, ReportsLastSliceQpForImageSlices) {
H265BitstreamParser h265_parser;
h265_parser.ParseBitstream(kH265BitstreamChunk);