Merge pull request #495 from sijchen/add_me_test11
[Encoder UnitTest] add basic me test
This commit is contained in:
commit
c8f2f08403
5
Makefile
5
Makefile
@ -78,7 +78,10 @@ GTEST_INCLUDES += \
|
||||
-Igtest/include
|
||||
|
||||
CODEC_UNITTEST_INCLUDES += \
|
||||
-Igtest/include
|
||||
-Igtest/include \
|
||||
-Icodec/processing/interface \
|
||||
-Icodec/common \
|
||||
-Icodec/encoder/core/inc
|
||||
|
||||
H264DEC_INCLUDES = $(DECODER_INCLUDES) -Icodec/console/dec/inc
|
||||
H264DEC_LDFLAGS = -L. $(call LINK_LIB,decoder) $(call LINK_LIB,common)
|
||||
|
65
test/DataGenerator.cpp
Normal file
65
test/DataGenerator.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include <string.h>//memset/memcpy
|
||||
#include "utils/DataGenerator.h"
|
||||
#include "utils/BufferedData.h"
|
||||
#include "utils/FileInputStream.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
bool YUVPixelDataGenerator( uint8_t* pPointer, int32_t iWidth, int32_t iHeight, int32_t iStride )
|
||||
{
|
||||
#define SRC_FRAME_WIDTH (160)
|
||||
#define SRC_FRAME_HEIGHT (96)
|
||||
|
||||
if ( SRC_FRAME_WIDTH-iWidth <= 0 || SRC_FRAME_HEIGHT-iHeight <= 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int32_t kiFrameSize = SRC_FRAME_WIDTH*SRC_FRAME_HEIGHT;
|
||||
BufferedData sBuf;
|
||||
sBuf.SetLength(kiFrameSize);
|
||||
if (sBuf.Length() != kiFrameSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FileInputStream fileStream;
|
||||
if (!fileStream.Open("res/CiscoVT2people_160x96_6fps.yuv")) {
|
||||
return false;
|
||||
}
|
||||
if (fileStream.read(sBuf.data(), kiFrameSize) == kiFrameSize) {
|
||||
srand((uint32_t)time(NULL));
|
||||
int32_t iStartPosX = rand()%(SRC_FRAME_WIDTH-iWidth);
|
||||
int32_t iStartPosY = rand()%(SRC_FRAME_HEIGHT-iHeight);
|
||||
uint8_t* pSrcPointer = sBuf.data() + iStartPosX + iStartPosY*SRC_FRAME_WIDTH;
|
||||
uint8_t* pLocalPointer = pPointer;
|
||||
|
||||
for (int j=0;j<iHeight;j++) {
|
||||
memcpy(pLocalPointer, pSrcPointer, iWidth*sizeof(uint8_t));
|
||||
pLocalPointer += iStride;
|
||||
pSrcPointer += SRC_FRAME_WIDTH;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RandomPixelDataGenerator( uint8_t* pPointer, int32_t iWidth, int32_t iHeight, int32_t iStride )
|
||||
{
|
||||
uint8_t* pLocalPointer = pPointer;
|
||||
for (int32_t j=0;j<iHeight;j++) {
|
||||
for (int32_t i=0;i<iWidth;i++) {
|
||||
pLocalPointer[i] = rand()%256;
|
||||
}
|
||||
pLocalPointer += iStride;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RandomResidueDataGenerator( uint16_t* pPointer, int32_t iWidth, int32_t iHeight, int32_t iStride )
|
||||
{
|
||||
}
|
||||
|
||||
void RandomCoeffDataGenerator( uint16_t* pPointer, int32_t iWidth, int32_t iHeight, int32_t iStride )
|
||||
{
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
#include "../gtest/include/gtest/gtest.h"
|
||||
#include <string.h> // use memset/memcmp
|
||||
#include <time.h>
|
||||
#include "../codec/encoder/core/inc/memory_align.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "memory_align.h"
|
||||
|
||||
using namespace WelsSVCEnc;
|
||||
|
||||
@ -46,7 +44,7 @@ TEST(MemoryAlignTest, WelsMallocAndFreeOnceFunctionVerify)
|
||||
const uint32_t kuiExpectedSize = sizeof( void ** ) + sizeof( int32_t ) + kuiExtraAlignSize + uiSize;
|
||||
uint8_t *pUnitTestData = static_cast<uint8_t *>(cTestMa.WelsMalloc(uiSize, strUnitTestTag));
|
||||
if ( pUnitTestData != NULL ) {
|
||||
ASSERT_TRUE( (((int64_t)(static_cast<void *>(pUnitTestData))) & kuiExtraAlignSize) == 0 );
|
||||
ASSERT_TRUE( (((uintptr_t)(pUnitTestData)) & kuiExtraAlignSize) == 0 );
|
||||
EXPECT_EQ( kuiExpectedSize, cTestMa.WelsGetMemoryUsage() );
|
||||
cTestMa.WelsFree( pUnitTestData, strUnitTestTag );
|
||||
EXPECT_EQ( 0, cTestMa.WelsGetMemoryUsage() );
|
||||
|
125
test/EncUT_MotionEstimate.cpp
Normal file
125
test/EncUT_MotionEstimate.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
#include <stdlib.h>
|
||||
#include "gtest/gtest.h"
|
||||
#include "utils/DataGenerator.h"
|
||||
#include "md.h"
|
||||
#include "sample.h"
|
||||
#include "svc_motion_estimate.h"
|
||||
#include "wels_func_ptr_def.h"
|
||||
|
||||
|
||||
using namespace WelsSVCEnc;
|
||||
|
||||
void CopyTargetBlock( uint8_t* pSrcBlock, const int32_t kiBlockSize, SMVUnitXY sTargetMv, const int32_t kiRefPicStride,
|
||||
uint8_t* pRefPic)
|
||||
{
|
||||
uint8_t* pTargetPos = pRefPic+sTargetMv.iMvY*kiRefPicStride+sTargetMv.iMvX;
|
||||
uint8_t* pSourcePos = pSrcBlock;
|
||||
|
||||
for (int i = 0; i<kiBlockSize; i++) {
|
||||
memcpy( pSourcePos, pTargetPos, kiBlockSize*sizeof(uint8_t) );
|
||||
pTargetPos += kiRefPicStride;
|
||||
pSourcePos += kiBlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InitMe( const uint8_t kuiQp, const uint32_t kuiMvdTableMiddle, const uint32_t kuiMvdTableStride,
|
||||
uint16_t* pMvdCostTable, SWelsME* pMe)
|
||||
{
|
||||
MvdCostInit( pMvdCostTable, kuiMvdTableStride );
|
||||
pMe->pMvdCost = &pMvdCostTable[kuiQp*kuiMvdTableStride + kuiMvdTableMiddle];
|
||||
pMe->sMvp.iMvX = pMe->sMvp.iMvY = 0;
|
||||
pMe->sMvBase.iMvX = pMe->sMvBase.iMvY = 0;
|
||||
pMe->sMv.iMvX = pMe->sMv.iMvY = 0;
|
||||
}
|
||||
|
||||
class MotionEstimateTest : public ::testing::Test {
|
||||
public:
|
||||
virtual void SetUp() {
|
||||
m_pRefPic = NULL;
|
||||
m_pSrcBlock = NULL;
|
||||
m_pMvdCostTable = NULL;
|
||||
|
||||
m_iWidth = 64;//size of search window
|
||||
m_iHeight = 64;//size of search window
|
||||
m_iMaxSearchBlock = 16;
|
||||
m_uiMvdTableSize = (1 + (648 << 1));
|
||||
|
||||
m_pRefPic = static_cast<uint8_t *>
|
||||
(malloc(m_iWidth*m_iHeight));
|
||||
ASSERT_TRUE( NULL != m_pRefPic );
|
||||
m_pSrcBlock = static_cast<uint8_t *>
|
||||
(malloc(m_iMaxSearchBlock*m_iMaxSearchBlock));
|
||||
ASSERT_TRUE( NULL != m_pSrcBlock );
|
||||
m_pMvdCostTable=new uint16_t[52*m_uiMvdTableSize];
|
||||
ASSERT_TRUE( NULL != m_pMvdCostTable );
|
||||
}
|
||||
virtual void TearDown() {
|
||||
delete [] m_pMvdCostTable;
|
||||
free( m_pRefPic );
|
||||
free( m_pSrcBlock );
|
||||
}
|
||||
public:
|
||||
uint8_t *m_pRefPic;
|
||||
uint8_t *m_pSrcBlock;
|
||||
uint32_t m_uiMvdTableSize;
|
||||
uint16_t *m_pMvdCostTable;
|
||||
|
||||
int32_t m_iWidth;
|
||||
int32_t m_iHeight;
|
||||
int32_t m_iMaxSearchBlock;
|
||||
};
|
||||
|
||||
|
||||
TEST_F(MotionEstimateTest, TestDiamondSearch)
|
||||
{
|
||||
#define TEST_POS (5)
|
||||
const int32_t kiPositionToCheck[TEST_POS][2] = {{0,0}, {0,1}, {1,0}, {0,-1}, {-1,0}};
|
||||
const int32_t kiMaxBlock16Sad = 72000;//a rough number
|
||||
SWelsFuncPtrList sFuncList;
|
||||
SWelsME sMe;
|
||||
|
||||
srand((uint32_t)time(NULL));
|
||||
const uint8_t kuiQp = rand()%52;
|
||||
InitMe(kuiQp, 648, m_uiMvdTableSize, m_pMvdCostTable, &sMe);
|
||||
|
||||
SMVUnitXY sTargetMv;
|
||||
WelsInitSampleSadFunc( &sFuncList, 0 );//test c functions
|
||||
|
||||
uint8_t *pRefPicCenter = m_pRefPic+(m_iHeight/2)*m_iWidth+(m_iWidth/2);
|
||||
bool bDataGeneratorSucceed = false;
|
||||
bool bFoundMatch = false;
|
||||
int32_t i,j,iTryTimes;
|
||||
for (i=0;i<TEST_POS;i++) {
|
||||
sTargetMv.iMvX = kiPositionToCheck[i][0];
|
||||
sTargetMv.iMvY = kiPositionToCheck[i][1];
|
||||
iTryTimes = 100;
|
||||
bDataGeneratorSucceed = false;
|
||||
bFoundMatch = false;
|
||||
while (!bFoundMatch && (iTryTimes--)>0) {
|
||||
if (!YUVPixelDataGenerator( m_pRefPic, m_iWidth, m_iHeight, m_iWidth ))
|
||||
continue;
|
||||
|
||||
bDataGeneratorSucceed = true;
|
||||
CopyTargetBlock( m_pSrcBlock, 16, sTargetMv, m_iWidth, pRefPicCenter);
|
||||
|
||||
//clean the sMe status
|
||||
sMe.uiPixel = rand()%5;
|
||||
sMe.pEncMb = m_pSrcBlock;
|
||||
sMe.pRefMb = pRefPicCenter;
|
||||
sMe.sMv.iMvX = sMe.sMv.iMvY = 0;
|
||||
sMe.uiSadCost = sMe.uiSatdCost = kiMaxBlock16Sad;
|
||||
WelsMotionEstimateIterativeSearch (&sFuncList, &sMe, m_iMaxSearchBlock,
|
||||
m_iWidth, pRefPicCenter);
|
||||
|
||||
//the last selection may be affected by MVDcost, that is when (0,0) will be better
|
||||
//when comparing (1,1) and (1,0), due to the difference between MVD cost, it is possible that (1,0) is selected while the best match is (1,1)
|
||||
bFoundMatch = ((sMe.sMv.iMvX==(sTargetMv.iMvX*4))||(sMe.sMv.iMvX==0)) && ((sMe.sMv.iMvY==(sTargetMv.iMvY*4))||(sMe.sMv.iMvY==0));
|
||||
}
|
||||
if (bDataGeneratorSucceed) {
|
||||
//if DataGenerator never succeed, there is no meaning to check iTryTimes
|
||||
ASSERT_TRUE(iTryTimes > 0);
|
||||
//it is possible that ref at differnt position is identical, but that should be under a low probability
|
||||
}
|
||||
}
|
||||
}
|
@ -3,11 +3,13 @@ CODEC_UNITTEST_CPP_SRCS=\
|
||||
$(CODEC_UNITTEST_SRCDIR)/BaseDecoderTest.cpp\
|
||||
$(CODEC_UNITTEST_SRCDIR)/BaseEncoderTest.cpp\
|
||||
$(CODEC_UNITTEST_SRCDIR)/cpp_interface_test.cpp\
|
||||
$(CODEC_UNITTEST_SRCDIR)/DataGenerator.cpp\
|
||||
$(CODEC_UNITTEST_SRCDIR)/decode_encode_test.cpp\
|
||||
$(CODEC_UNITTEST_SRCDIR)/decoder_test.cpp\
|
||||
$(CODEC_UNITTEST_SRCDIR)/encoder_test.cpp\
|
||||
$(CODEC_UNITTEST_SRCDIR)/simple_test.cpp\
|
||||
$(CODEC_UNITTEST_SRCDIR)/EncUT_MemoryAlloc.cpp\
|
||||
$(CODEC_UNITTEST_SRCDIR)/EncUT_MotionEstimate.cpp\
|
||||
$(CODEC_UNITTEST_SRCDIR)/simple_test.cpp\
|
||||
|
||||
CODEC_UNITTEST_OBJS += $(CODEC_UNITTEST_CPP_SRCS:.cpp=.o)
|
||||
|
||||
|
15
test/utils/DataGenerator.h
Normal file
15
test/utils/DataGenerator.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef DATA_GENERATOR_H__
|
||||
#define DATA_GENERATOR_H__
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
bool YUVPixelDataGenerator( uint8_t* pPointer, int32_t iWidth, int32_t iHeight, int32_t iStride );
|
||||
|
||||
void RandomPixelDataGenerator( uint8_t* pPointer, int32_t iWidth, int32_t iHeight, int32_t iStride );
|
||||
|
||||
void RandomResidueDataGenerator( uint16_t* pPointer, int32_t iWidth, int32_t iHeight, int32_t iStride );
|
||||
|
||||
void RandomCoeffDataGenerator( uint16_t* pPointer, int32_t iWidth, int32_t iHeight, int32_t iStride );
|
||||
|
||||
|
||||
#endif//DATA_GENERATOR_H__
|
Loading…
Reference in New Issue
Block a user