| #include <stdlib.h> |
| #include "gtest/gtest.h" |
| |
| #include "au_set.h" |
| #include "param_svc.h" |
| #include "parameter_sets.h" |
| #include "wels_const.h" |
| #include "paraset_strategy.h" |
| |
| using namespace WelsEnc; |
| |
| class ParameterSetStrategyTest : public ::testing::Test { |
| public: |
| virtual void SetUp() { |
| pMa = NULL; |
| m_pSpsArray = NULL; |
| m_pSubsetArray = NULL; |
| |
| pMa = new CMemoryAlign (0); |
| m_pSpsArray = (SWelsSPS*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SWelsSPS), "m_pSpsArray"); |
| ASSERT_TRUE (NULL != m_pSpsArray); |
| m_pSubsetArray = (SSubsetSps*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SSubsetSps), "m_pSubsetArray"); |
| ASSERT_TRUE (NULL != m_pSubsetArray); |
| |
| m_pSpsArrayPointer = &m_pSpsArray[0]; |
| m_pSubsetArrayPointer = &m_pSubsetArray[0]; |
| |
| } |
| virtual void TearDown() { |
| pMa->WelsFree (m_pSpsArray, "m_pSpsArray"); |
| pMa->WelsFree (m_pSubsetArray, "m_pSubsetArray"); |
| delete pMa; |
| } |
| void GenerateParam (SWelsSvcCodingParam* pParam); |
| public: |
| CMemoryAlign* pMa; |
| SWelsSPS* m_pSpsArray; |
| SSubsetSps* m_pSubsetArray; |
| |
| SWelsSPS* m_pSpsArrayPointer; |
| SSubsetSps* m_pSubsetArrayPointer; |
| |
| }; |
| |
| void ParameterSetStrategyTest::GenerateParam (SWelsSvcCodingParam* pParam) { |
| SEncParamBase sEncParamBase; |
| //TODO: consider randomize it |
| sEncParamBase.iUsageType = CAMERA_VIDEO_REAL_TIME; |
| sEncParamBase.iPicWidth = 1280; |
| sEncParamBase.iPicHeight = 720; |
| sEncParamBase.iTargetBitrate = 1000000; |
| sEncParamBase.iRCMode = RC_BITRATE_MODE; |
| sEncParamBase.fMaxFrameRate = 30.0f; |
| pParam->ParamBaseTranscode (sEncParamBase); |
| } |
| |
| TEST_F (ParameterSetStrategyTest, FindExistingSps) { |
| int iDlayerIndex = 0; |
| int iDlayerCount = 0; |
| bool bUseSubsetSps = false; |
| int iFoundId = -1; |
| int iRet = 0; |
| SSpatialLayerConfig* pDlayerParam; |
| |
| //init parameter |
| SWelsSvcCodingParam sParam1; |
| GenerateParam (&sParam1); |
| |
| //prepare first SPS |
| int iCurSpsId = 0; |
| int iCurSpsInUse = 1; |
| m_pSpsArrayPointer = &m_pSpsArray[iCurSpsId]; |
| |
| pDlayerParam = & (sParam1.sSpatialLayers[iDlayerIndex]); |
| iRet = WelsInitSps (m_pSpsArrayPointer, pDlayerParam, &sParam1.sDependencyLayers[iDlayerIndex], sParam1.uiIntraPeriod, |
| sParam1.iMaxNumRefFrame, |
| iCurSpsId, sParam1.bEnableFrameCroppingFlag, sParam1.iRCMode != RC_OFF_MODE, iDlayerCount, false); |
| |
| // try finding #0 |
| iFoundId = FindExistingSps (&sParam1, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse, |
| m_pSpsArray, m_pSubsetArray, false); |
| EXPECT_EQ (iFoundId, iCurSpsId); |
| |
| // try not finding |
| SWelsSvcCodingParam sParam2 = sParam1; |
| sParam2.iMaxNumRefFrame ++; |
| iFoundId = FindExistingSps (&sParam2, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse, |
| m_pSpsArray, m_pSubsetArray, false); |
| EXPECT_EQ (iFoundId, INVALID_ID); |
| |
| // add new sps |
| iCurSpsId = 1; |
| m_pSpsArrayPointer = &m_pSpsArray[iCurSpsId]; |
| pDlayerParam = & (sParam2.sSpatialLayers[iDlayerIndex]); |
| iRet = WelsInitSps (m_pSpsArrayPointer, pDlayerParam, &sParam2.sDependencyLayers[iDlayerIndex], sParam2.uiIntraPeriod, |
| sParam2.iMaxNumRefFrame, |
| iCurSpsId, sParam2.bEnableFrameCroppingFlag, sParam2.iRCMode != RC_OFF_MODE, iDlayerCount, false); |
| iCurSpsInUse = 2; |
| |
| // try finding #1 |
| iFoundId = FindExistingSps (&sParam2, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse, |
| m_pSpsArray, m_pSubsetArray, false); |
| EXPECT_EQ (iFoundId, iCurSpsId); |
| |
| // try finding #0 |
| iFoundId = FindExistingSps (&sParam1, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse, |
| m_pSpsArray, m_pSubsetArray, false); |
| EXPECT_EQ (iFoundId, 0); |
| |
| // try not finding |
| if (sParam2.sDependencyLayers[0].iActualWidth > 1) { |
| |
| sParam2.sDependencyLayers[0].iActualWidth--; |
| } else { |
| sParam2.sDependencyLayers[0].iActualWidth++; |
| } |
| |
| iFoundId = FindExistingSps (&sParam2, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse, |
| m_pSpsArray, m_pSubsetArray, false); |
| EXPECT_EQ (iFoundId, INVALID_ID); |
| (void) iRet; // Not using iRet at the moment |
| } |
| |
| TEST_F (ParameterSetStrategyTest, TestVSTPParameters) { |
| int32_t iRet = 0; |
| bool FalseLocal = false; // EXPECT_EQ does not like "true" or "false" as its first arg |
| |
| // this test verifies that the client's "video signal type present" parameter values end up in SWelsSPS |
| |
| //init client parameters |
| SEncParamExt sParamExt; |
| SWelsSvcCodingParam::FillDefault(sParamExt); |
| sParamExt.iUsageType = CAMERA_VIDEO_REAL_TIME; |
| sParamExt.iPicWidth = 1280; |
| sParamExt.iPicHeight = 720; |
| sParamExt.iTargetBitrate = 1000000; |
| sParamExt.iRCMode = RC_BITRATE_MODE; |
| sParamExt.fMaxFrameRate = 30.0f; |
| |
| // VSTP parameters should be their default values (see SWelsSvcCodingParam::FillDefault()) |
| for ( int i = 0; i < MAX_SPATIAL_LAYER_NUM; i++ ) |
| { |
| // expected actual |
| EXPECT_EQ( FalseLocal, sParamExt.sSpatialLayers[i].bVideoSignalTypePresent); |
| EXPECT_EQ( VF_UNDEF, sParamExt.sSpatialLayers[i].uiVideoFormat);//5 |
| EXPECT_EQ( FalseLocal, sParamExt.sSpatialLayers[i].bFullRange); |
| EXPECT_EQ( FalseLocal, sParamExt.sSpatialLayers[i].bColorDescriptionPresent); |
| EXPECT_EQ( CP_UNDEF, sParamExt.sSpatialLayers[i].uiColorPrimaries);//2 |
| EXPECT_EQ( TRC_UNDEF, sParamExt.sSpatialLayers[i].uiTransferCharacteristics);//2 |
| EXPECT_EQ( CM_UNDEF, sParamExt.sSpatialLayers[i].uiColorMatrix);//2 |
| } |
| |
| // set non-default VSTP values |
| sParamExt.iSpatialLayerNum = 2; |
| |
| sParamExt.sSpatialLayers[0].bVideoSignalTypePresent = true; |
| sParamExt.sSpatialLayers[0].uiVideoFormat = VF_NTSC;//2 |
| sParamExt.sSpatialLayers[0].bFullRange = true; |
| sParamExt.sSpatialLayers[0].bColorDescriptionPresent = true; |
| sParamExt.sSpatialLayers[0].uiColorPrimaries = CP_BT709;//1 |
| sParamExt.sSpatialLayers[0].uiTransferCharacteristics = TRC_BT709;//1 |
| sParamExt.sSpatialLayers[0].uiColorMatrix = CM_BT709;//1 |
| |
| sParamExt.sSpatialLayers[1].bVideoSignalTypePresent = true; |
| sParamExt.sSpatialLayers[1].uiVideoFormat = VF_PAL;//1 |
| sParamExt.sSpatialLayers[1].bFullRange = true; |
| sParamExt.sSpatialLayers[1].bColorDescriptionPresent = true; |
| sParamExt.sSpatialLayers[1].uiColorPrimaries = CP_SMPTE170M;//6 |
| sParamExt.sSpatialLayers[1].uiTransferCharacteristics = TRC_SMPTE170M;//6 |
| sParamExt.sSpatialLayers[1].uiColorMatrix = CM_SMPTE170M;//6 |
| |
| // transcode parameters from client |
| SWelsSvcCodingParam sSvcCodingParam; |
| iRet = sSvcCodingParam.ParamTranscode(sParamExt); |
| EXPECT_EQ (iRet, 0); |
| |
| // transcoded VSTP parameters should match the client values |
| for ( int i = 0; i < sParamExt.iSpatialLayerNum; i++ ) |
| { |
| EXPECT_EQ( sParamExt.sSpatialLayers[i].bVideoSignalTypePresent, sSvcCodingParam.sSpatialLayers[i].bVideoSignalTypePresent); |
| EXPECT_EQ( sParamExt.sSpatialLayers[i].uiVideoFormat, sSvcCodingParam.sSpatialLayers[i].uiVideoFormat); |
| EXPECT_EQ( sParamExt.sSpatialLayers[i].bFullRange, sSvcCodingParam.sSpatialLayers[i].bFullRange); |
| EXPECT_EQ( sParamExt.sSpatialLayers[i].bColorDescriptionPresent, sSvcCodingParam.sSpatialLayers[i].bColorDescriptionPresent); |
| EXPECT_EQ( sParamExt.sSpatialLayers[i].uiColorPrimaries, sSvcCodingParam.sSpatialLayers[i].uiColorPrimaries); |
| EXPECT_EQ( sParamExt.sSpatialLayers[i].uiTransferCharacteristics, sSvcCodingParam.sSpatialLayers[i].uiTransferCharacteristics); |
| EXPECT_EQ( sParamExt.sSpatialLayers[i].uiColorMatrix, sSvcCodingParam.sSpatialLayers[i].uiColorMatrix); |
| } |
| |
| // use transcoded parameters to initialize an SWelsSPS |
| m_pSpsArrayPointer = &m_pSpsArray[0]; |
| SSpatialLayerConfig* pDlayerParam = &(sSvcCodingParam.sSpatialLayers[0]); |
| iRet = WelsInitSps ( |
| m_pSpsArrayPointer, |
| pDlayerParam, |
| &sSvcCodingParam.sDependencyLayers[0], |
| sSvcCodingParam.uiIntraPeriod, |
| sSvcCodingParam.iMaxNumRefFrame, |
| 0, //SpsId |
| sSvcCodingParam.bEnableFrameCroppingFlag, |
| sSvcCodingParam.iRCMode != RC_OFF_MODE, |
| 0, //DlayerCount |
| false |
| ); |
| EXPECT_EQ (iRet, 0); |
| |
| // SPS VSTP parameters should match the transcoded values |
| EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].bVideoSignalTypePresent, m_pSpsArrayPointer->bVideoSignalTypePresent); |
| EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].uiVideoFormat, m_pSpsArrayPointer->uiVideoFormat); |
| EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].bFullRange, m_pSpsArrayPointer->bFullRange); |
| EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].bColorDescriptionPresent, m_pSpsArrayPointer->bColorDescriptionPresent); |
| EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].uiColorPrimaries, m_pSpsArrayPointer->uiColorPrimaries); |
| EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].uiTransferCharacteristics, m_pSpsArrayPointer->uiTransferCharacteristics); |
| EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].uiColorMatrix, m_pSpsArrayPointer->uiColorMatrix); |
| |
| // TODO: verify that WriteVUI (au_set.cpp) writes the SPS VSTP values to the output file (verified using FFmpeg) |
| |
| (void) iRet; // Not using iRet at the moment |
| } |
| |
| |