shithub: libvpx

Download patch

ref: 488ba1ab9ca875e48e6ea8f0f30a6bca6b730664
parent: c6fd0a5dd65f0723dbabed2f17f12c87b37aab7a
parent: c953aeacd4ff1418a81f809e11e1d9bca4e9aac5
author: Yaowu Xu <yaowu@google.com>
date: Thu Sep 6 05:28:17 EDT 2012

Merge "added encode/decode matching validation to tests"

--- /dev/null
+++ b/test/decode_test_driver.cc
@@ -1,0 +1,28 @@
+/*
+ *  Copyright (c) 2012 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/decode_test_driver.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+namespace libvpx_test {
+#if CONFIG_VP8_DECODER
+void Decoder::DecodeFrame(const uint8_t *cxdata, int size) {
+  if(!decoder_.priv) {
+    const vpx_codec_err_t res_init = vpx_codec_dec_init(&decoder_,
+                                                        &vpx_codec_vp8_dx_algo,
+                                                        &cfg_, 0);
+    ASSERT_EQ(VPX_CODEC_OK, res_init) << DecodeError();
+  }
+
+  const vpx_codec_err_t res_dec = vpx_codec_decode(&decoder_,
+                                                   cxdata, size, NULL, 0);
+  ASSERT_EQ(VPX_CODEC_OK, res_dec) << DecodeError();
+}
+#endif
+}  // namespace libvpx_test
--- /dev/null
+++ b/test/decode_test_driver.h
@@ -1,0 +1,79 @@
+/*
+ *  Copyright (c) 2012 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.
+ */
+
+#ifndef TEST_DECODE_TEST_DRIVER_H_
+#define TEST_DECODE_TEST_DRIVER_H_
+#include <string>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "vpx_config.h"
+#include "vpx/vpx_decoder.h"
+#include "vpx/vp8dx.h"
+namespace libvpx_test {
+
+
+// Provides an object to handle decoding output
+class DxDataIterator {
+ public:
+  explicit DxDataIterator(vpx_codec_ctx_t *decoder)
+    : decoder_(decoder), iter_(NULL) {}
+
+  const vpx_image_t *Next() {
+    return vpx_codec_get_frame(decoder_, &iter_);
+  }
+
+ private:
+  vpx_codec_ctx_t  *decoder_;
+  vpx_codec_iter_t  iter_;
+};
+
+// Provides a simplified interface to manage one video decoding.
+//
+// TODO: similar to Encoder class, the exact services should be
+// added as more tests are added.
+class Decoder {
+ public:
+  Decoder (vpx_codec_dec_cfg_t cfg, unsigned long deadline = 0)
+    : cfg_(cfg), deadline_(deadline) {
+    memset(&decoder_, 0, sizeof(decoder_));
+  }
+
+  ~Decoder () {
+    vpx_codec_destroy(&decoder_);
+  }
+
+  void DecodeFrame(const uint8_t *cxdata, int size);
+
+  DxDataIterator GetDxData() {
+    return DxDataIterator(&decoder_);
+  }
+
+  void set_deadline(unsigned long deadline) {
+    deadline_ = deadline;
+  }
+
+  void Control(int ctrl_id, int arg) {
+    const vpx_codec_err_t res = vpx_codec_control_(&decoder_, ctrl_id, arg);
+    ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
+  }
+
+ protected:
+  const char *DecodeError() {
+    const char *detail = vpx_codec_error_detail(&decoder_);
+    return detail ? detail : vpx_codec_error(&decoder_);
+  }
+
+  vpx_codec_ctx_t     decoder_;
+  vpx_codec_dec_cfg_t cfg_;
+  unsigned int        deadline_;
+};
+
+}  // namespace libvpx_test
+#endif /* TEST_DECODE_TEST_DRIVER_H_ */
--- a/test/encode_test_driver.cc
+++ b/test/encode_test_driver.cc
@@ -7,12 +7,15 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
+#include "vpx_config.h"
 #include "test/encode_test_driver.h"
+#if CONFIG_VP8_DECODER
+#include "test/decode_test_driver.h"
+#endif
 #include "test/video_source.h"
 #include "third_party/googletest/src/include/gtest/gtest.h"
 
 namespace libvpx_test {
-
 void Encoder::EncodeFrame(VideoSource *video, unsigned long flags) {
   if (video->img())
     EncodeFrameInternal(*video, flags);
@@ -91,8 +94,38 @@
   else
     passes_ = 1;
 }
+// The function should return "true" most of the time, therefore no early
+// break-out is implemented within the match checking process.
+static bool compare_img(const vpx_image_t *img1,
+                        const vpx_image_t *img2) {
+  bool match = (img1->fmt == img2->fmt) &&
+               (img1->d_w == img2->d_w) &&
+               (img1->d_h == img2->d_h);
 
+  const unsigned int width_y  = img1->d_w;
+  const unsigned int height_y = img1->d_h;
+  unsigned int i;
+  for (i = 0; i < height_y; ++i)
+    match = ( memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y],
+                     img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y],
+                     width_y) == 0) && match;
+  const unsigned int width_uv  = (img1->d_w + 1) >> 1;
+  const unsigned int height_uv = (img1->d_h + 1) >> 1;
+  for (i = 0; i <  height_uv; ++i)
+    match = ( memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U],
+                     img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U],
+                     width_uv) == 0) && match;
+  for (i = 0; i < height_uv; ++i)
+    match = ( memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V],
+                     img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V],
+                     width_uv) == 0) && match;
+  return match;
+}
+
 void EncoderTest::RunLoop(VideoSource *video) {
+#if CONFIG_VP8_DECODER
+  vpx_codec_dec_cfg_t dec_cfg = {0};
+#endif
   for (unsigned int pass = 0; pass < passes_; pass++) {
     last_pts_ = 0;
 
@@ -105,7 +138,10 @@
 
     BeginPassHook(pass);
     Encoder encoder(cfg_, deadline_, &stats_);
-
+#if CONFIG_VP8_DECODER
+    Decoder decoder(dec_cfg);
+    bool has_cxdata = false;
+#endif
     bool again;
     for (again = true, video->Begin(); again; video->Next()) {
       again = video->img() != NULL;
@@ -121,12 +157,27 @@
 
         if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
           continue;
-
+#if CONFIG_VP8_DECODER
+        has_cxdata = true;
+        decoder.DecodeFrame((const uint8_t*)pkt->data.frame.buf,
+                            pkt->data.frame.sz);
+#endif
         ASSERT_GE(pkt->data.frame.pts, last_pts_);
         last_pts_ = pkt->data.frame.pts;
         FramePktHook(pkt);
       }
 
+#if CONFIG_VP8_DECODER
+      if (has_cxdata) {
+        const vpx_image_t *img_enc = encoder.GetPreviewFrame();
+        DxDataIterator dec_iter = decoder.GetDxData();
+        const vpx_image_t *img_dec = dec_iter.Next();
+        if(img_enc && img_dec) {
+          const bool res = compare_img(img_enc, img_dec);
+          ASSERT_TRUE(res)<< "Encoder/Decoder mismatch found.";
+        }
+      }
+#endif
       if (!Continue())
         break;
     }
@@ -137,5 +188,4 @@
       break;
   }
 }
-
 }  // namespace libvpx_test
--- a/test/encode_test_driver.h
+++ b/test/encode_test_driver.h
@@ -52,7 +52,6 @@
   vpx_codec_iter_t  iter_;
 };
 
-
 // Implements an in-memory store for libvpx twopass statistics
 class TwopassStatsStore {
  public:
@@ -92,6 +91,9 @@
     return CxDataIterator(&encoder_);
   }
 
+  const vpx_image_t *GetPreviewFrame() {
+    return vpx_codec_get_preview_frame(&encoder_);
+  }
   // This is a thin wrapper around vpx_codec_encode(), so refer to
   // vpx_encoder.h for its semantics.
   void EncodeFrame(VideoSource *video, unsigned long flags);
@@ -127,7 +129,6 @@
   unsigned long        deadline_;
   TwopassStatsStore   *stats_;
 };
-
 
 // Common test functionality for all Encoder tests.
 //
--- a/test/test.mk
+++ b/test/test.mk
@@ -16,6 +16,8 @@
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += keyframe_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += resize_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += video_source.h
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += decode_test_driver.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += decode_test_driver.h
 
 ##
 ## WHITE BOX TESTS