added encode/decode matching validation to tests
This commit adds the ability of validating matched encoder and decoder to unit tests. Change-Id: Ie00d69a42477b6a69b324a6bd134939684f7300b
This commit is contained in:
		
							
								
								
									
										28
									
								
								test/decode_test_driver.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								test/decode_test_driver.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,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
 | 
			
		||||
							
								
								
									
										79
									
								
								test/decode_test_driver.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								test/decode_test_driver.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,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_ */
 | 
			
		||||
@@ -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 @@ void EncoderTest::SetMode(TestMode mode) {
 | 
			
		||||
  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 @@ void EncoderTest::RunLoop(VideoSource *video) {
 | 
			
		||||
 | 
			
		||||
    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 @@ void EncoderTest::RunLoop(VideoSource *video) {
 | 
			
		||||
 | 
			
		||||
        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 @@ void EncoderTest::RunLoop(VideoSource *video) {
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace libvpx_test
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,6 @@ class CxDataIterator {
 | 
			
		||||
  vpx_codec_iter_t  iter_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Implements an in-memory store for libvpx twopass statistics
 | 
			
		||||
class TwopassStatsStore {
 | 
			
		||||
 public:
 | 
			
		||||
@@ -92,6 +91,9 @@ class Encoder {
 | 
			
		||||
    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);
 | 
			
		||||
@@ -128,7 +130,6 @@ class Encoder {
 | 
			
		||||
  TwopassStatsStore   *stats_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Common test functionality for all Encoder tests.
 | 
			
		||||
//
 | 
			
		||||
// This class is a mixin which provides the main loop common to all
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,8 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += i420_video_source.h
 | 
			
		||||
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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user