shithub: libvpx

Download patch

ref: a0d9a9dd5179d0c6816c871f073b18a8aff67b1a
parent: be7a2858201ab7585d1e4f5528b98c95a147b075
author: Jim Bankoski <jimbankoski@google.com>
date: Thu Dec 11 12:34:32 EST 2014

Adds a test to make sure encoder parms get to decoder.

This is meant as a framework for testing that encode parms make it
through to the decoder.

Change-Id: Idb86ee3668b45b4e73c23c6e4daef94b0650b786

--- a/test/decode_test_driver.h
+++ b/test/decode_test_driver.h
@@ -97,6 +97,10 @@
 
   bool IsVP8() const;
 
+  vpx_codec_ctx_t * GetDecoder() {
+    return &decoder_;
+  }
+
  protected:
   virtual vpx_codec_iface_t* CodecInterface() const = 0;
 
--- a/test/test-data.mk
+++ b/test/test-data.mk
@@ -17,6 +17,7 @@
 LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_444.y4m
 LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_440.yuv
 
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv
 LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m
 LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += screendata.y4m
 
--- a/test/test.mk
+++ b/test/test.mk
@@ -124,6 +124,12 @@
 LIBVPX_TEST_SRCS-yes                   += tile_independence_test.cc
 LIBVPX_TEST_SRCS-yes                   += vp9_boolcoder_test.cc
 
+# TODO(jbb): Remove this when the TODO(minghai): in vpx_encoder.h gets resolved.
+# This test fails because of a mismatch in the size of the vpx_codec_alg_priv
+# between encoder and decoder when this is enabled.
+ifneq ($(CONFIG_SPATIAL_SVC),yes)
+LIBVPX_TEST_SRCS-yes                   += vp9_encoder_parms_get_to_decoder.cc
+endif
 endif
 
 LIBVPX_TEST_SRCS-$(CONFIG_VP9)         += convolve_test.cc
--- /dev/null
+++ b/test/vp9_encoder_parms_get_to_decoder.cc
@@ -1,0 +1,189 @@
+/*
+ *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/y4m_video_source.h"
+#include "test/yuv_video_source.h"
+#include "test/util.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "vp9/decoder/vp9_decoder.h"
+
+typedef vpx_codec_stream_info_t vp9_stream_info_t;
+struct vpx_codec_alg_priv {
+  vpx_codec_priv_t        base;
+  vpx_codec_dec_cfg_t     cfg;
+  vp9_stream_info_t       si;
+  struct VP9Decoder      *pbi;
+  int                     postproc_cfg_set;
+  vp8_postproc_cfg_t      postproc_cfg;
+  vpx_decrypt_cb          decrypt_cb;
+  void                   *decrypt_state;
+  vpx_image_t             img;
+  int                     img_avail;
+  int                     flushed;
+  int                     invert_tile_order;
+  int                     frame_parallel_decode;
+
+  // External frame buffer info to save for VP9 common.
+  void *ext_priv;  // Private data associated with the external frame buffers.
+  vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb;
+  vpx_release_frame_buffer_cb_fn_t release_ext_fb_cb;
+};
+
+static vpx_codec_alg_priv_t *get_alg_priv(vpx_codec_ctx_t *ctx) {
+  return (vpx_codec_alg_priv_t *)ctx->priv;
+}
+
+namespace {
+
+const unsigned int kFramerate = 50;
+const int kCpuUsed = 2;
+
+struct EncodePerfTestVideo {
+  const char *name;
+  uint32_t width;
+  uint32_t height;
+  uint32_t bitrate;
+  int frames;
+};
+
+const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
+    {"niklas_1280_720_30.yuv", 1280, 720, 600, 10},
+};
+
+struct EncodeParameters {
+  int32_t tile_rows;
+  int32_t tile_cols;
+  int32_t lossless;
+  int32_t error_resilient;
+  int32_t frame_parallel;
+  // TODO(JBB): quantizers / bitrate
+};
+
+const EncodeParameters kVP9EncodeParameterSet[] = {
+    {0, 0, 0, 1, 0},
+    {0, 0, 0, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 2, 0, 0, 1},
+    // TODO(JBB): Test profiles (requires more work).
+};
+
+int is_extension_y4m(const char *filename) {
+  const char *dot = strrchr(filename, '.');
+  if (!dot || dot == filename)
+    return 0;
+  else
+    return !strcmp(dot, ".y4m");
+}
+
+class Vp9EncoderParmsGetToDecoder
+    : public ::libvpx_test::EncoderTest,
+      public ::libvpx_test::CodecTestWith2Params<EncodeParameters, \
+                                                 EncodePerfTestVideo> {
+ protected:
+  Vp9EncoderParmsGetToDecoder()
+      : EncoderTest(GET_PARAM(0)),
+        encode_parms(GET_PARAM(1)) {
+  }
+
+  virtual ~Vp9EncoderParmsGetToDecoder() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(::libvpx_test::kTwoPassGood);
+    cfg_.g_lag_in_frames = 25;
+    cfg_.g_error_resilient = encode_parms.error_resilient;
+    dec_cfg_.threads = 4;
+    test_video_ = GET_PARAM(2);
+    cfg_.rc_target_bitrate = test_video_.bitrate;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      encoder->Control(VP9E_SET_LOSSLESS, encode_parms.lossless);
+      encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING,
+                       encode_parms.frame_parallel);
+      encoder->Control(VP9E_SET_TILE_ROWS, encode_parms.tile_rows);
+      encoder->Control(VP9E_SET_TILE_COLUMNS, encode_parms.tile_cols);
+      encoder->Control(VP8E_SET_CPUUSED, kCpuUsed);
+      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+      encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+      encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+      encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+    }
+  }
+
+  virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
+                                  const libvpx_test::VideoSource& video,
+                                  libvpx_test::Decoder *decoder) {
+    vpx_codec_ctx_t* vp9_decoder = decoder->GetDecoder();
+    vpx_codec_alg_priv_t* priv =
+        (vpx_codec_alg_priv_t*) get_alg_priv(vp9_decoder);
+
+    VP9Decoder* pbi = priv->pbi;
+    VP9_COMMON* common = &pbi->common;
+
+    if (encode_parms.lossless) {
+      EXPECT_EQ(common->base_qindex, 0);
+      EXPECT_EQ(common->y_dc_delta_q, 0);
+      EXPECT_EQ(common->uv_dc_delta_q, 0);
+      EXPECT_EQ(common->uv_ac_delta_q, 0);
+      EXPECT_EQ(common->tx_mode, ONLY_4X4);
+    }
+    EXPECT_EQ(common->error_resilient_mode, encode_parms.error_resilient);
+    if (encode_parms.error_resilient) {
+      EXPECT_EQ(common->frame_parallel_decoding_mode, 1);
+      EXPECT_EQ(common->use_prev_frame_mvs, 0);
+    } else {
+      EXPECT_EQ(common->frame_parallel_decoding_mode,
+                encode_parms.frame_parallel);
+    }
+
+    EXPECT_EQ(common->log2_tile_cols, encode_parms.tile_cols);
+    EXPECT_EQ(common->log2_tile_rows, encode_parms.tile_rows);
+
+    EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
+    return VPX_CODEC_OK == res_dec;
+  }
+
+  EncodePerfTestVideo test_video_;
+
+ private:
+  EncodeParameters encode_parms;
+};
+
+TEST_P(Vp9EncoderParmsGetToDecoder, BitstreamParms) {
+  init_flags_ = VPX_CODEC_USE_PSNR;
+
+  libvpx_test::VideoSource *video;
+  if (is_extension_y4m(test_video_.name)) {
+    video = new libvpx_test::Y4mVideoSource(test_video_.name,
+                                            0, test_video_.frames);
+  } else {
+    video = new libvpx_test::YUVVideoSource(test_video_.name,
+                                            VPX_IMG_FMT_I420,
+                                            test_video_.width,
+                                            test_video_.height,
+                                            kFramerate, 1, 0,
+                                            test_video_.frames);
+  }
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
+  delete(video);
+}
+
+VP9_INSTANTIATE_TEST_CASE(
+    Vp9EncoderParmsGetToDecoder,
+    ::testing::ValuesIn(kVP9EncodeParameterSet),
+    ::testing::ValuesIn(kVP9EncodePerfTestVectors));
+
+}  // namespace