Skip H246 scaling lists in SPS packets

This code is originally written by marc@frankensteinmotorworks.com

Bug: webrtc:8275
Change-Id: I35e6d21b12e71199e0209ff91740d95c9df3bd10
Reviewed-on: https://webrtc-review.googlesource.com/36520
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21528}
This commit is contained in:
Todd Wong
2018-01-09 16:03:49 +08:00
committed by Commit Bot
parent 81ca3bfb18
commit 6728003bcf
3 changed files with 38 additions and 16 deletions

View File

@ -58,6 +58,7 @@ Xiaolei Yu <dreifachstein@gmail.com>
Yura Yaroshevich <yura.yaroshevich@gmail.com>
Hans Knoechel <hans@hans-knoechel.de>
Korniltsev Anatoly <korniltsev.anatoly@gmail.com>
Todd Wong <todd.wong.ndq@gmail.com>
&yet LLC <*@andyet.com>
Agora IO <*@agora.io>

View File

@ -94,23 +94,31 @@ rtc::Optional<SpsParser::SpsState> SpsParser::ParseSpsUpToVui(
uint32_t seq_scaling_matrix_present_flag;
RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&seq_scaling_matrix_present_flag, 1));
if (seq_scaling_matrix_present_flag) {
// seq_scaling_list_present_flags. Either 8 or 12, depending on
// chroma_format_idc.
// Process the scaling lists just enough to be able to properly
// skip over them, so we can still read the resolution on streams
// where this is included.
int scaling_list_count = (chroma_format_idc == 3 ? 12 : 8);
for (int i = 0; i < scaling_list_count; ++i) {
// seq_scaling_list_present_flag[i] : u(1)
uint32_t seq_scaling_list_present_flags;
if (chroma_format_idc != 3) {
RETURN_EMPTY_ON_FAIL(
buffer->ReadBits(&seq_scaling_list_present_flags, 8));
} else {
buffer->ReadBits(&seq_scaling_list_present_flags, 1));
if (seq_scaling_list_present_flags != 0) {
int last_scale = 8;
int next_scale = 8;
int size_of_scaling_list = i < 6 ? 16 : 64;
for (int j = 0; j < size_of_scaling_list; j++) {
if (next_scale != 0) {
int32_t delta_scale;
// delta_scale: se(v)
RETURN_EMPTY_ON_FAIL(
buffer->ReadBits(&seq_scaling_list_present_flags, 12));
buffer->ReadSignedExponentialGolomb(&delta_scale));
next_scale = (last_scale + delta_scale + 256) % 256;
}
if (next_scale != 0)
last_scale = next_scale;
}
}
// We don't support reading the sequence scaling list, and we don't really
// see/use them in practice, so we'll just reject the full sps if we see
// any provided.
if (seq_scaling_list_present_flags > 0) {
RTC_LOG(LS_WARNING)
<< "SPS contains scaling lists, which are unsupported.";
return OptionalSps();
}
}
}

View File

@ -171,4 +171,17 @@ TEST_F(H264SpsParserTest, TestSyntheticSPSWeirdResolution) {
EXPECT_EQ(2u, sps_->id);
}
TEST_F(H264SpsParserTest, TestSampleSPSWithScalingLists) {
// SPS from a 1920x1080 video. Contains scaling lists (and veritcal cropping).
const uint8_t buffer[] = {0x64, 0x00, 0x2a, 0xad, 0x84, 0x01, 0x0c, 0x20,
0x08, 0x61, 0x00, 0x43, 0x08, 0x02, 0x18, 0x40,
0x10, 0xc2, 0x00, 0x84, 0x3b, 0x50, 0x3c, 0x01,
0x13, 0xf2, 0xcd, 0xc0, 0x40, 0x40, 0x50, 0x00,
0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0xe8, 0x40};
EXPECT_TRUE(
static_cast<bool>(sps_ = SpsParser::ParseSps(buffer, arraysize(buffer))));
EXPECT_EQ(1920u, sps_->width);
EXPECT_EQ(1080u, sps_->height);
}
} // namespace webrtc