Skip to content

Commit

Permalink
REGRESSION (275173@main): [ MacOS wk2 Debug] webrtc/h265.html is a co…
Browse files Browse the repository at this point in the history
…nstant timeout

rdar://123637394
https://bugs.webkit.org/show_bug.cgi?id=270096

Reviewed by Eric Carlson.

We were using the SPS sps_max_num_reorder_pics to compute the reorder window size.
But it appears from testing and from Chrome source code that we should instead use the VPS vps_max_num_reorder_pics.
We should probably get the VPS from PPS -> SPS -> VPS chain but for now, we use the first VPS available.

We add VPS parsing up to vps_max_num_reorder_pics.
We make use of it for computing the reorder window size for both HVCC and AnnexB cases.

Covered by LayoutTests/webrtc/h265.html and LayoutTests/http/tests/webcodecs/ HEVC tests.

* LayoutTests/platform/mac-wk2/TestExpectations:
* Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_vps_parser.cc:
* Source/ThirdParty/libwebrtc/Source/webrtc/common_video/h265/h265_vps_parser.h:
* Source/ThirdParty/libwebrtc/Source/webrtc/sdk/objc/components/video_codec/RTCVideoDecoderH265.mm:
(vpsDataFromHvcc):
(ComputeH265ReorderSizeFromVPS):
(ComputeH265ReorderSizeFromHVCC):
(ComputeH265ReorderSizeFromAnnexB):
(spsDataFromHvcc): Deleted.
(ComputeH265ReorderSizeFromSPS): Deleted.

Canonical link: https://commits.webkit.org/275434@main
  • Loading branch information
youennf committed Feb 28, 2024
1 parent d4af38d commit cd09e2f
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 23 deletions.
2 changes: 0 additions & 2 deletions LayoutTests/platform/mac-wk2/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -2009,5 +2009,3 @@ webkit.org/b/269996 [ Monterey+ Debug ] imported/w3c/web-platform-tests/css/css-
[ Sonoma+ ] compositing/plugins/pdf/pdf-in-styled-embed.html [ Failure ]
[ Sonoma+ ] compositing/plugins/pdf/pdf-scrolling-tree-dynamic.html [ Failure ]
[ Sonoma+ ] compositing/plugins/pdf/pdf-scrolling-tree.html [ Failure ]

webkit.org/b/270096 [ Monterey+ Debug ] webrtc/h265.html [ Timeout ]
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#include "rtc_base/bitstream_reader.h"
#include "rtc_base/logging.h"

#if WEBRTC_WEBKIT_BUILD
#include "common_video/h265/h265_sps_parser.h"
#endif

namespace webrtc {

H265VpsParser::VpsState::VpsState() = default;
Expand Down Expand Up @@ -47,6 +51,53 @@ absl::optional<H265VpsParser::VpsState> H265VpsParser::ParseInternal(
return absl::nullopt;
}

#if WEBRTC_WEBKIT_BUILD
// vps_base_layer_internal_flag u(1)
reader.ConsumeBits(1);
// vps_base_layer_available_flag u(1)
reader.ConsumeBits(1);
// vps_max_layers_minus1 u(6)
vps.vps_max_sub_layers_minus1 = reader.ReadBits(6);

if (!reader.Ok() || (vps.vps_max_sub_layers_minus1 >= kMaxSubLayers)) {
return absl::nullopt;
}

// vps_max_sub_layers_minus1 u(3)
reader.ConsumeBits(3);
// vps_temporal_id_nesting_flag u(1)
reader.ConsumeBits(1);
// vps_reserved_0xffff_16bits u(16)
reader.ConsumeBits(16);

auto profile_tier_level = H265SpsParser::ParseProfileTierLevel(true, vps.vps_max_sub_layers_minus1, reader);
if (!reader.Ok() || !profile_tier_level) {
return absl::nullopt;
}

bool vps_sub_layer_ordering_info_present_flag = reader.Read<bool>();
for (uint32_t i = (vps_sub_layer_ordering_info_present_flag != 0) ? 0 : vps.vps_max_sub_layers_minus1; i <= vps.vps_max_sub_layers_minus1; i++) {
// vps_max_dec_pic_buffering_minus1[ i ]: ue(v)
reader.ReadExponentialGolomb();
// vps_max_num_reorder_pics[ i ]: ue(v)
vps.vps_max_num_reorder_pics[i] = reader.ReadExponentialGolomb();
if (!reader.Ok() || (i > 0 && vps.vps_max_num_reorder_pics[i] < vps.vps_max_num_reorder_pics[i - 1])) {
return absl::nullopt;
}

// vps_max_latency_increase_plus1: ue(v)
reader.ReadExponentialGolomb();
}
if (!vps_sub_layer_ordering_info_present_flag) {
for (int i = 0; i < vps.vps_max_sub_layers_minus1; ++i) {
vps.vps_max_num_reorder_pics[i] = vps.vps_max_num_reorder_pics[vps.vps_max_sub_layers_minus1];
}
}
if (!reader.Ok() || !profile_tier_level) {
return absl::nullopt;
}
#endif

return vps;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,20 @@ namespace webrtc {
// A class for parsing out video parameter set (VPS) data from an H265 NALU.
class H265VpsParser {
public:
#if WEBRTC_WEBKIT_BUILD
static constexpr uint32_t kMaxSubLayers = 7;
#endif

// The parsed state of the VPS. Only some select values are stored.
// Add more as they are actually needed.
struct VpsState {
VpsState();

uint32_t id = 0;
#if WEBRTC_WEBKIT_BUILD
uint32_t vps_max_sub_layers_minus1 = 0;
uint32_t vps_max_num_reorder_pics[kMaxSubLayers] = {};
#endif
};

// Unpack RBSP and parse VPS state from the supplied buffer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#import "RTCVideoFrameReorderQueue.h"
#import "base/RTCVideoFrame.h"
#import "base/RTCVideoFrameBuffer.h"
#import "common_video/h265/h265_sps_parser.h"
#import "common_video/h265/h265_vps_parser.h"
#import "components/video_frame_buffer/RTCCVPixelBuffer.h"
#import "helpers.h"
#import "helpers/scoped_cftyperef.h"
Expand Down Expand Up @@ -49,7 +49,7 @@ static void overrideColorSpaceAttachments(CVImageBufferRef imageBuffer) {
CVBufferSetAttachment(imageBuffer, (CFStringRef)@"ColorInfoGuessedBy", (CFStringRef)@"RTCVideoDecoderH265", kCVAttachmentMode_ShouldPropagate);
}

std::span<const uint8_t> spsDataFromHvcc(const uint8_t* hvccData, size_t hvccDataSize) {
std::span<const uint8_t> vpsDataFromHvcc(const uint8_t* hvccData, size_t hvccDataSize) {
std::vector<uint8_t> unpacked_buffer { hvccData, hvccData + hvccDataSize };
webrtc::BitstreamReader reader(unpacked_buffer);

Expand Down Expand Up @@ -110,7 +110,7 @@ static void overrideColorSpaceAttachments(CVImageBufferRef imageBuffer) {
return { };
}

if (nalUnitType != webrtc::H265::NaluType::kSps) {
if (nalUnitType != webrtc::H265::NaluType::kVps) {
position += size;
continue;
}
Expand All @@ -122,38 +122,41 @@ static void overrideColorSpaceAttachments(CVImageBufferRef imageBuffer) {
return { };
}

uint8_t ComputeH265ReorderSizeFromSPS(const uint8_t* spsData, size_t spsDataSize)
uint8_t ComputeH265ReorderSizeFromVPS(const uint8_t* spsData, size_t spsDataSize)
{
auto parsedSps = webrtc::H265SpsParser::ParseSps(spsData, spsDataSize);
if (!parsedSps)
return 0;
auto reorderSize = *std::max_element(parsedSps->sps_max_num_reorder_pics, parsedSps->sps_max_num_reorder_pics + parsedSps->sps_max_sub_layers_minus1 + 1);
auto parsedVps = webrtc::H265VpsParser::ParseVps(spsData, spsDataSize);
if (!parsedVps)
return 0;

auto reorderSize = *std::max_element(parsedVps->vps_max_num_reorder_pics, parsedVps->vps_max_num_reorder_pics + parsedVps->vps_max_sub_layers_minus1 + 1);
// We use a max value of 16
return std::max(reorderSize, 16u);
return std::min(reorderSize, 16u);
}

uint8_t ComputeH265ReorderSizeFromHVCC(const uint8_t* hvccData, size_t hvccDataSize)
{
auto spsData = spsDataFromHvcc(hvccData, hvccDataSize);
if (!spsData.size()) {
return 0;
}
return ComputeH265ReorderSizeFromSPS(spsData.data(), spsData.size());
// FIXME: we should probably get the VPS from the SPS sps_video_parameter_set_id.
auto vpsData = vpsDataFromHvcc(hvccData, hvccDataSize);
if (!vpsData.size())
return 0;

return ComputeH265ReorderSizeFromVPS(vpsData.data(), vpsData.size());
}

uint8_t ComputeH265ReorderSizeFromAnnexB(const uint8_t* annexb_buffer, size_t annexb_buffer_size)
{
// FIXME: we should probably get the VPS from the SPS sps_video_parameter_set_id.
webrtc::AnnexBBufferReader bufferReader(annexb_buffer, annexb_buffer_size);
if (!bufferReader.SeekToNextNaluOfType(webrtc::H265::kSps)) {
return 0;
}
if (!bufferReader.SeekToNextNaluOfType(webrtc::H265::kVps))
return 0;

static const size_t hevcNalHeaderSize = 2;
const uint8_t* data;
size_t data_len;
if (!bufferReader.ReadNalu(&data, &data_len) || data_len <= hevcNalHeaderSize) {
return 0;
}
return ComputeH265ReorderSizeFromSPS(data + hevcNalHeaderSize, data_len - hevcNalHeaderSize);
if (!bufferReader.ReadNalu(&data, &data_len) || data_len <= hevcNalHeaderSize)
return 0;

return ComputeH265ReorderSizeFromVPS(data + hevcNalHeaderSize, data_len - hevcNalHeaderSize);
}

// This is the callback function that VideoToolbox calls when decode is
Expand Down

0 comments on commit cd09e2f

Please sign in to comment.