shithub: libvpx

Download patch

ref: c447a50aea7afe54bb7f7f71650bbd71a96bf66a
parent: f349b071c6d5e806552c261ba13bd99bb5f7c6ce
author: Deb Mukherjee <debargha@google.com>
date: Mon Jul 14 21:54:29 EDT 2014

Separates profile 2 into 2 profiles 2 and 3

Separates HBD profile int two profiles (2 and 3) consistent with the
highbitdepth branch. This patch is ported from the original highbitdepth
branch patch: https://gerrit.chromium.org/gerrit/#/c/70460/

Two of the invalid file tests needed to be updated.

Change-Id: I6a4acd2f7a60b1fb4cbcc8e0dad4eab4248431e3

--- a/test/decode_test_driver.cc
+++ b/test/decode_test_driver.cc
@@ -39,12 +39,34 @@
   return res_dec;
 }
 
+bool Decoder::IsVP8() const {
+  const char *codec_name = GetDecoderName();
+  return strncmp(kVP8Name, codec_name, sizeof(kVP8Name) - 1) == 0;
+}
+
+void DecoderTest::HandlePeekResult(Decoder *const decoder,
+                                   CompressedVideoSource *video,
+                                   const vpx_codec_err_t res_peek) {
+  const bool is_vp8 = decoder->IsVP8();
+  if (is_vp8) {
+    /* Vp8's implementation of PeekStream returns an error if the frame you
+     * pass it is not a keyframe, so we only expect VPX_CODEC_OK on the first
+     * frame, which must be a keyframe. */
+    if (video->frame_number() == 0)
+      ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: "
+                                        << vpx_codec_err_to_string(res_peek);
+  } else {
+    /* The Vp9 implementation of PeekStream returns an error only if the
+     * data passed to it isn't a valid Vp9 chunk. */
+    ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: "
+                                      << vpx_codec_err_to_string(res_peek);
+  }
+}
+
 void DecoderTest::RunLoop(CompressedVideoSource *video,
                           const vpx_codec_dec_cfg_t &dec_cfg) {
   Decoder* const decoder = codec_->CreateDecoder(dec_cfg, 0);
   ASSERT_TRUE(decoder != NULL);
-  const char *codec_name = decoder->GetDecoderName();
-  const bool is_vp8 = strncmp(kVP8Name, codec_name, sizeof(kVP8Name) - 1) == 0;
 
   // Decode frames.
   for (video->Begin(); !::testing::Test::HasFailure() && video->cxdata();
@@ -56,19 +78,8 @@
     const vpx_codec_err_t res_peek = decoder->PeekStream(video->cxdata(),
                                                          video->frame_size(),
                                                          &stream_info);
-    if (is_vp8) {
-      /* Vp8's implementation of PeekStream returns an error if the frame you
-       * pass it is not a keyframe, so we only expect VPX_CODEC_OK on the first
-       * frame, which must be a keyframe. */
-      if (video->frame_number() == 0)
-        ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: "
-            << vpx_codec_err_to_string(res_peek);
-    } else {
-      /* The Vp9 implementation of PeekStream returns an error only if the
-       * data passed to it isn't a valid Vp9 chunk. */
-      ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: "
-          << vpx_codec_err_to_string(res_peek);
-    }
+    HandlePeekResult(decoder, video, res_peek);
+    ASSERT_FALSE(::testing::Test::HasFailure());
 
     vpx_codec_err_t res_dec = decoder->DecodeFrame(video->cxdata(),
                                                    video->frame_size());
--- a/test/decode_test_driver.h
+++ b/test/decode_test_driver.h
@@ -91,10 +91,12 @@
         &decoder_, cb_get, cb_release, user_priv);
   }
 
-  const char* GetDecoderName() {
+  const char* GetDecoderName() const {
     return vpx_codec_iface_name(CodecInterface());
   }
 
+  bool IsVP8() const;
+
  protected:
   virtual vpx_codec_iface_t* CodecInterface() const = 0;
 
@@ -137,6 +139,11 @@
   // Hook to be called on every decompressed frame.
   virtual void DecompressedFrameHook(const vpx_image_t& img,
                                      const unsigned int frame_number) {}
+
+  // Hook to be called on peek result
+  virtual void HandlePeekResult(Decoder* const decoder,
+                                CompressedVideoSource *video,
+                                const vpx_codec_err_t res_peek);
 
  protected:
   explicit DecoderTest(const CodecFactory *codec) : codec_(codec) {}
--- a/test/invalid_file_test.cc
+++ b/test/invalid_file_test.cc
@@ -66,46 +66,49 @@
     return !HasFailure();
   }
 
- private:
-  FILE *res_file_;
-};
+  void RunTest() {
+    const DecodeParam input = GET_PARAM(1);
+    libvpx_test::CompressedVideoSource *video = NULL;
+    vpx_codec_dec_cfg_t cfg = {0};
+    cfg.threads = input.threads;
+    const std::string filename = input.filename;
 
-TEST_P(InvalidFileTest, ReturnCode) {
-  libvpx_test::CompressedVideoSource *video = NULL;
-  const DecodeParam input = GET_PARAM(1);
-  vpx_codec_dec_cfg_t cfg = {0};
-  cfg.threads = input.threads;
-  const std::string filename = input.filename;
-
-  // Open compressed video file.
-  if (filename.substr(filename.length() - 3, 3) == "ivf") {
-    video = new libvpx_test::IVFVideoSource(filename);
-  } else if (filename.substr(filename.length() - 4, 4) == "webm") {
+    // Open compressed video file.
+    if (filename.substr(filename.length() - 3, 3) == "ivf") {
+      video = new libvpx_test::IVFVideoSource(filename);
+    } else if (filename.substr(filename.length() - 4, 4) == "webm") {
 #if CONFIG_WEBM_IO
-    video = new libvpx_test::WebMVideoSource(filename);
+      video = new libvpx_test::WebMVideoSource(filename);
 #else
-    fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
-            filename.c_str());
-    return;
+      fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
+              filename.c_str());
+      return;
 #endif
+    }
+    video->Init();
+
+    // Construct result file name. The file holds a list of expected integer
+    // results, one for each decoded frame.  Any result that doesn't match
+    // the files list will cause a test failure.
+    const std::string res_filename = filename + ".res";
+    OpenResFile(res_filename);
+
+    // Decode frame, and check the md5 matching.
+    ASSERT_NO_FATAL_FAILURE(RunLoop(video, cfg));
+    delete video;
   }
-  video->Init();
 
-  // Construct result file name. The file holds a list of expected integer
-  // results, one for each decoded frame.  Any result that doesn't match
-  // the files list will cause a test failure.
-  const std::string res_filename = filename + ".res";
-  OpenResFile(res_filename);
+ private:
+  FILE *res_file_;
+};
 
-  // Decode frame, and check the md5 matching.
-  ASSERT_NO_FATAL_FAILURE(RunLoop(video, cfg));
-  delete video;
+TEST_P(InvalidFileTest, ReturnCode) {
+  RunTest();
 }
 
 const DecodeParam kVP9InvalidFileTests[] = {
-  {1, "invalid-vp90-01-v2.webm"},
   {1, "invalid-vp90-02-v2.webm"},
-  {1, "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf"},
+  {1, "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf"},
   {1, "invalid-vp90-03-v2.webm"},
   {1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf"},
   {1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf"},
@@ -113,6 +116,27 @@
 
 VP9_INSTANTIATE_TEST_CASE(InvalidFileTest,
                           ::testing::ValuesIn(kVP9InvalidFileTests));
+
+// This class will include test vectors that are expected to fail
+// peek. However they are still expected to have no fatal failures.
+class InvalidFileInvalidPeekTest : public InvalidFileTest {
+ protected:
+  InvalidFileInvalidPeekTest() : InvalidFileTest() {}
+  virtual void HandlePeekResult(libvpx_test::Decoder *const decoder,
+                                libvpx_test::CompressedVideoSource *video,
+                                const vpx_codec_err_t res_peek) {}
+};
+
+TEST_P(InvalidFileInvalidPeekTest, ReturnCode) {
+  RunTest();
+}
+
+const DecodeParam kVP9InvalidFileInvalidPeekTests[] = {
+  {1, "invalid-vp90-01-v2.webm"},
+};
+
+VP9_INSTANTIATE_TEST_CASE(InvalidFileInvalidPeekTest,
+                          ::testing::ValuesIn(kVP9InvalidFileInvalidPeekTests));
 
 const DecodeParam kMultiThreadedVP9InvalidFileTests[] = {
   {4, "invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm"},
--- a/test/test-data.sha1
+++ b/test/test-data.sha1
@@ -1,11 +1,19 @@
 d5dfb0151c9051f8c85999255645d7a23916d3c0  hantro_collage_w352h288.yuv
 b87815bf86020c592ccc7a846ba2e28ec8043902  hantro_odd.yuv
-fe346136b9b8c1e6f6084cc106485706915795e4  invalid-vp90-01.webm
-25751f5d3b05ff03f0719ad42cd625348eb8961e  invalid-vp90-01.webm.res
-d78e2fceba5ac942246503ec8366f879c4775ca5  invalid-vp90-02.webm
-2dadee5306245fa5eeb0f99652d0e17afbcba96d  invalid-vp90-02.webm.res
-df1a1453feb3c00d7d89746c7003b4163523bff3  invalid-vp90-03.webm
-8fe6fd82bf537340f586f97a7ae31fb37ccda302  invalid-vp90-03.webm.res
+76024eb753cdac6a5e5703aaea189d35c3c30ac7  invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf
+7448d8798a4380162d4b56f9b452e2f6f9e24e7a  invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf.res
+83f50908c8dc0ef8760595447a2ff7727489542e  invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf
+456d1493e52d32a5c30edf44a27debc1fa6b253a  invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res
+c123d1f9f02fb4143abb5e271916e3a3080de8f6  invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf
+456d1493e52d32a5c30edf44a27debc1fa6b253a  invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf.res
+fe346136b9b8c1e6f6084cc106485706915795e4  invalid-vp90-01-v2.webm
+25751f5d3b05ff03f0719ad42cd625348eb8961e  invalid-vp90-01-v2.webm.res
+d78e2fceba5ac942246503ec8366f879c4775ca5  invalid-vp90-02-v2.webm
+8e2eff4af87d2b561cce2365713269e301457ef3  invalid-vp90-02-v2.webm.res
+df1a1453feb3c00d7d89746c7003b4163523bff3  invalid-vp90-03-v2.webm
+25dd58c22d23f75304d7ce7f69f4e5b02ef9119a  invalid-vp90-03-v2.webm.res
+d637297561dd904eb2c97a9015deeb31c4a1e8d2  invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm
+3a204bdbeaa3c6458b77bcebb8366d107267f55d  invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm.res
 a432f96ff0a787268e2f94a8092ab161a18d1b06  park_joy_90p_10_420.y4m
 0b194cc312c3a2e84d156a221b0a5eb615dfddc5  park_joy_90p_10_422.y4m
 ff0e0a21dc2adc95b8c1b37902713700655ced17  park_joy_90p_10_444.y4m
@@ -657,17 +665,3 @@
 5661b0168752969f055eec37b05fa9fa947dc7eb  vp90-2-16-intra-only.webm.md5
 0321d507ce62dedc8a51b4e9011f7a19aed9c3dc  vp91-2-04-yuv444.webm
 367e423dd41fdb49aa028574a2cfec5c2f325c5c  vp91-2-04-yuv444.webm.md5
-76024eb753cdac6a5e5703aaea189d35c3c30ac7  invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf
-d3964f9dad9f60363c81b688324d95b4ec7c8038  invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf.res
-83f50908c8dc0ef8760595447a2ff7727489542e  invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf
-456d1493e52d32a5c30edf44a27debc1fa6b253a  invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res
-c123d1f9f02fb4143abb5e271916e3a3080de8f6  invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf
-456d1493e52d32a5c30edf44a27debc1fa6b253a  invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf.res
-fe346136b9b8c1e6f6084cc106485706915795e4  invalid-vp90-01-v2.webm
-25751f5d3b05ff03f0719ad42cd625348eb8961e  invalid-vp90-01-v2.webm.res
-d78e2fceba5ac942246503ec8366f879c4775ca5  invalid-vp90-02-v2.webm
-8e2eff4af87d2b561cce2365713269e301457ef3  invalid-vp90-02-v2.webm.res
-df1a1453feb3c00d7d89746c7003b4163523bff3  invalid-vp90-03-v2.webm
-25dd58c22d23f75304d7ce7f69f4e5b02ef9119a  invalid-vp90-03-v2.webm.res
-d637297561dd904eb2c97a9015deeb31c4a1e8d2  invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm
-3a204bdbeaa3c6458b77bcebb8366d107267f55d  invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm.res
--- a/test/test.mk
+++ b/test/test.mk
@@ -783,8 +783,8 @@
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02-v2.webm.res
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-03-v2.webm
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-03-v2.webm.res
-LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf
-LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf.res
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res
 LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf
--- a/vp9/common/vp9_enums.h
+++ b/vp9/common/vp9_enums.h
@@ -25,15 +25,18 @@
 
 #define MI_MASK (MI_BLOCK_SIZE - 1)
 
-// Bitstream profiles indicated by 2 bits in the uncompressed header.
-// 00: Profile 0. 4:2:0 only.
-// 10: Profile 1. adds 4:4:4, 4:2:2, alpha.
-// 01: Profile 2. Supports 10-bit and 12-bit color only.
-// 11: Undefined profile.
+// Bitstream profiles indicated by 2-3 bits in the uncompressed header.
+// 00: Profile 0.  8-bit 4:2:0 only.
+// 10: Profile 1.  Adds 4:4:4, 4:2:2, alpha to Profile 0.
+// 01: Profile 2.  Supports 10-bit and 12-bit color only, with 4:2:0 sampling.
+// 110: Profile 3. Supports 10-bit and 12-bit color only, with 4:2:2/4:4:4
+//                 sampling and alpha.
+// 111: Undefined profile.
 typedef enum BITSTREAM_PROFILE {
   PROFILE_0,
   PROFILE_1,
   PROFILE_2,
+  PROFILE_3,
   MAX_PROFILES
 } BITSTREAM_PROFILE;
 
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -1065,9 +1065,11 @@
          vp9_rb_read_literal(rb, 8) == VP9_SYNC_CODE_2;
 }
 
-static BITSTREAM_PROFILE read_profile(struct vp9_read_bit_buffer *rb) {
+BITSTREAM_PROFILE vp9_read_profile(struct vp9_read_bit_buffer *rb) {
   int profile = vp9_rb_read_bit(rb);
   profile |= vp9_rb_read_bit(rb) << 1;
+  if (profile > 2)
+    profile += vp9_rb_read_bit(rb);
   return (BITSTREAM_PROFILE) profile;
 }
 
@@ -1083,7 +1085,7 @@
       vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
                          "Invalid frame marker");
 
-  cm->profile = read_profile(rb);
+  cm->profile = vp9_read_profile(rb);
   if (cm->profile >= MAX_PROFILES)
     vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
                        "Unsupported bitstream profile");
@@ -1118,7 +1120,7 @@
     cm->color_space = (COLOR_SPACE)vp9_rb_read_literal(rb, 3);
     if (cm->color_space != SRGB) {
       vp9_rb_read_bit(rb);  // [16,235] (including xvycc) vs [0,255] range
-      if (cm->profile >= PROFILE_1) {
+      if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
         cm->subsampling_x = vp9_rb_read_bit(rb);
         cm->subsampling_y = vp9_rb_read_bit(rb);
         vp9_rb_read_bit(rb);  // has extra plane
@@ -1126,12 +1128,12 @@
         cm->subsampling_y = cm->subsampling_x = 1;
       }
     } else {
-      if (cm->profile >= PROFILE_1) {
+      if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
         cm->subsampling_y = cm->subsampling_x = 0;
         vp9_rb_read_bit(rb);  // has extra plane
       } else {
         vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
-                           "RGB not supported in profile 0");
+                           "4:4:4 color not supported in profile 0");
       }
     }
 
--- a/vp9/decoder/vp9_decodeframe.h
+++ b/vp9/decoder/vp9_decodeframe.h
@@ -29,6 +29,7 @@
 int vp9_read_sync_code(struct vp9_read_bit_buffer *const rb);
 void vp9_read_frame_size(struct vp9_read_bit_buffer *rb,
                          int *width, int *height);
+BITSTREAM_PROFILE vp9_read_profile(struct vp9_read_bit_buffer *rb);
 
 #ifdef __cplusplus
 }  // extern "C"
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -1024,9 +1024,22 @@
 
 static void write_profile(BITSTREAM_PROFILE profile,
                           struct vp9_write_bit_buffer *wb) {
-  assert(profile < MAX_PROFILES);
-  vp9_wb_write_bit(wb, profile & 1);
-  vp9_wb_write_bit(wb, profile >> 1);
+  switch (profile) {
+    case PROFILE_0:
+      vp9_wb_write_literal(wb, 0, 2);
+      break;
+    case PROFILE_1:
+      vp9_wb_write_literal(wb, 2, 2);
+      break;
+    case PROFILE_2:
+      vp9_wb_write_literal(wb, 1, 2);
+      break;
+    case PROFILE_3:
+      vp9_wb_write_literal(wb, 6, 3);
+      break;
+    default:
+      assert(0);
+  }
 }
 
 static void write_uncompressed_header(VP9_COMP *cpi,
@@ -1052,13 +1065,13 @@
     vp9_wb_write_literal(wb, cs, 3);
     if (cs != SRGB) {
       vp9_wb_write_bit(wb, 0);  // 0: [16, 235] (i.e. xvYCC), 1: [0, 255]
-      if (cm->profile >= PROFILE_1) {
+      if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
         vp9_wb_write_bit(wb, cm->subsampling_x);
         vp9_wb_write_bit(wb, cm->subsampling_y);
         vp9_wb_write_bit(wb, 0);  // has extra plane
       }
     } else {
-      assert(cm->profile == PROFILE_1);
+      assert(cm->profile == PROFILE_1 || cm->profile == PROFILE_3);
       vp9_wb_write_bit(wb, 0);  // has extra plane
     }
 
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -122,13 +122,12 @@
     int error_resilient;
     struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
     const int frame_marker = vp9_rb_read_literal(&rb, 2);
-    const int version = vp9_rb_read_bit(&rb);
-    (void) vp9_rb_read_bit(&rb);  // unused version bit
+    const BITSTREAM_PROFILE profile = vp9_read_profile(&rb);
 
     if (frame_marker != VP9_FRAME_MARKER)
       return VPX_CODEC_UNSUP_BITSTREAM;
 
-    if (version > 1) return VPX_CODEC_UNSUP_BITSTREAM;
+    if (profile >= MAX_PROFILES) return VPX_CODEC_UNSUP_BITSTREAM;
 
     if (vp9_rb_read_bit(&rb)) {  // show an existing frame
       vp9_rb_read_literal(&rb, 3);  // Frame buffer to show.
@@ -149,15 +148,17 @@
       if (!vp9_read_sync_code(&rb))
         return VPX_CODEC_UNSUP_BITSTREAM;
 
+      if (profile > PROFILE_1)
+        rb.bit_offset += 1;  // Bit-depth 10 or 12
       colorspace = vp9_rb_read_literal(&rb, 3);
       if (colorspace != sRGB) {
         rb.bit_offset += 1;  // [16,235] (including xvycc) vs [0,255] range
-        if (version == 1) {
+        if (profile == PROFILE_1 || profile == PROFILE_3) {
           rb.bit_offset += 2;  // subsampling x/y
           rb.bit_offset += 1;  // has extra plane
         }
       } else {
-        if (version == 1) {
+        if (profile == PROFILE_1 || profile == PROFILE_3) {
           rb.bit_offset += 1;  // has extra plane
         } else {
           // RGB is only available in version 1