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}
diff --git a/AUTHORS b/AUTHORS
index abf8b5b..799e1cc 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -58,6 +58,7 @@
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>
diff --git a/common_video/h264/sps_parser.cc b/common_video/h264/sps_parser.cc
index 946c685..1b9f0cd 100644
--- a/common_video/h264/sps_parser.cc
+++ b/common_video/h264/sps_parser.cc
@@ -94,23 +94,31 @@
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.
- uint32_t seq_scaling_list_present_flags;
- if (chroma_format_idc != 3) {
+ // 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;
RETURN_EMPTY_ON_FAIL(
- buffer->ReadBits(&seq_scaling_list_present_flags, 8));
- } else {
- RETURN_EMPTY_ON_FAIL(
- buffer->ReadBits(&seq_scaling_list_present_flags, 12));
- }
- // 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();
+ 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->ReadSignedExponentialGolomb(&delta_scale));
+ next_scale = (last_scale + delta_scale + 256) % 256;
+ }
+ if (next_scale != 0)
+ last_scale = next_scale;
+ }
+ }
}
}
}
diff --git a/common_video/h264/sps_parser_unittest.cc b/common_video/h264/sps_parser_unittest.cc
index e982449..39e6f2e 100644
--- a/common_video/h264/sps_parser_unittest.cc
+++ b/common_video/h264/sps_parser_unittest.cc
@@ -171,4 +171,17 @@
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