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