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
 | 
					 *  in the file PATENTS.  All contributing project authors may
 | 
				
			||||||
 *  be found in the AUTHORS file in the root of the source tree.
 | 
					 *  be found in the AUTHORS file in the root of the source tree.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					#include "vpx_config.h"
 | 
				
			||||||
#include "test/encode_test_driver.h"
 | 
					#include "test/encode_test_driver.h"
 | 
				
			||||||
 | 
					#if CONFIG_VP8_DECODER
 | 
				
			||||||
 | 
					#include "test/decode_test_driver.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#include "test/video_source.h"
 | 
					#include "test/video_source.h"
 | 
				
			||||||
#include "third_party/googletest/src/include/gtest/gtest.h"
 | 
					#include "third_party/googletest/src/include/gtest/gtest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace libvpx_test {
 | 
					namespace libvpx_test {
 | 
				
			||||||
 | 
					 | 
				
			||||||
void Encoder::EncodeFrame(VideoSource *video, unsigned long flags) {
 | 
					void Encoder::EncodeFrame(VideoSource *video, unsigned long flags) {
 | 
				
			||||||
  if (video->img())
 | 
					  if (video->img())
 | 
				
			||||||
    EncodeFrameInternal(*video, flags);
 | 
					    EncodeFrameInternal(*video, flags);
 | 
				
			||||||
@@ -91,8 +94,38 @@ void EncoderTest::SetMode(TestMode mode) {
 | 
				
			|||||||
  else
 | 
					  else
 | 
				
			||||||
    passes_ = 1;
 | 
					    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) {
 | 
					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++) {
 | 
					  for (unsigned int pass = 0; pass < passes_; pass++) {
 | 
				
			||||||
    last_pts_ = 0;
 | 
					    last_pts_ = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -105,7 +138,10 @@ void EncoderTest::RunLoop(VideoSource *video) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    BeginPassHook(pass);
 | 
					    BeginPassHook(pass);
 | 
				
			||||||
    Encoder encoder(cfg_, deadline_, &stats_);
 | 
					    Encoder encoder(cfg_, deadline_, &stats_);
 | 
				
			||||||
 | 
					#if CONFIG_VP8_DECODER
 | 
				
			||||||
 | 
					    Decoder decoder(dec_cfg);
 | 
				
			||||||
 | 
					    bool has_cxdata = false;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    bool again;
 | 
					    bool again;
 | 
				
			||||||
    for (again = true, video->Begin(); again; video->Next()) {
 | 
					    for (again = true, video->Begin(); again; video->Next()) {
 | 
				
			||||||
      again = video->img() != NULL;
 | 
					      again = video->img() != NULL;
 | 
				
			||||||
@@ -121,12 +157,27 @@ void EncoderTest::RunLoop(VideoSource *video) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
 | 
					        if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
 | 
				
			||||||
          continue;
 | 
					          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_);
 | 
					        ASSERT_GE(pkt->data.frame.pts, last_pts_);
 | 
				
			||||||
        last_pts_ = pkt->data.frame.pts;
 | 
					        last_pts_ = pkt->data.frame.pts;
 | 
				
			||||||
        FramePktHook(pkt);
 | 
					        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())
 | 
					      if (!Continue())
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -137,5 +188,4 @@ void EncoderTest::RunLoop(VideoSource *video) {
 | 
				
			|||||||
      break;
 | 
					      break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace libvpx_test
 | 
					}  // namespace libvpx_test
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,7 +52,6 @@ class CxDataIterator {
 | 
				
			|||||||
  vpx_codec_iter_t  iter_;
 | 
					  vpx_codec_iter_t  iter_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Implements an in-memory store for libvpx twopass statistics
 | 
					// Implements an in-memory store for libvpx twopass statistics
 | 
				
			||||||
class TwopassStatsStore {
 | 
					class TwopassStatsStore {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
@@ -92,6 +91,9 @@ class Encoder {
 | 
				
			|||||||
    return CxDataIterator(&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
 | 
					  // This is a thin wrapper around vpx_codec_encode(), so refer to
 | 
				
			||||||
  // vpx_encoder.h for its semantics.
 | 
					  // vpx_encoder.h for its semantics.
 | 
				
			||||||
  void EncodeFrame(VideoSource *video, unsigned long flags);
 | 
					  void EncodeFrame(VideoSource *video, unsigned long flags);
 | 
				
			||||||
@@ -128,7 +130,6 @@ class Encoder {
 | 
				
			|||||||
  TwopassStatsStore   *stats_;
 | 
					  TwopassStatsStore   *stats_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Common test functionality for all Encoder tests.
 | 
					// Common test functionality for all Encoder tests.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// This class is a mixin which provides the main loop common to all
 | 
					// 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) += keyframe_test.cc
 | 
				
			||||||
LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += resize_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_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
 | 
					## WHITE BOX TESTS
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user