Merge "added encode/decode matching validation to tests"
This commit is contained in:
commit
488ba1ab9c
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user