[Encoder] Implementation of bSimulcastAVC and UT
Showing the changes to test/api/encode_decode_api_test.cpp (1 of 3 files). Show all
Unified · Split
| @@ -3020,3 +3020,225 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING3) { · 3019 unmodified lines | |||
| 3020 | #endif | 3020 | #endif |
| 3021 | } | 3021 | } |
| 3022 | 3022 | ||
| 3023 | |||
| 3024 | TEST_F (EncodeDecodeTestAPI, SimulcastSVC) { | ||
| 3025 | #define LAYER_NUM (4) | ||
| 3026 | int iSpatialLayerNum = WelsClip3 ((rand() % LAYER_NUM), 2, LAYER_NUM);; | ||
| 3027 | int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 1 << iSpatialLayerNum, MAX_WIDTH); | ||
| 3028 | int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 1 << iSpatialLayerNum, MAX_HEIGHT); | ||
| 3029 | float fFrameRate = rand() + 0.5f; | ||
| 3030 | int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM); | ||
| 3031 | int iSliceNum = 1; | ||
| 3032 | encoder_->GetDefaultParams (¶m_); | ||
| 3033 | prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_); | ||
| 3034 | |||
| 3035 | int rv = encoder_->InitializeExt (¶m_); | ||
| 3036 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 3037 | |||
| 3038 | unsigned char* pBsBuf[LAYER_NUM]; | ||
| 3039 | int aLen[LAYER_NUM] = {0}; | ||
| 3040 | ISVCDecoder* decoder[LAYER_NUM]; | ||
| 3041 | |||
| 3042 | #ifdef DEBUG_FILE_SAVE2 | ||
| 3043 | FILE* fEnc[LAYER_NUM] = { NULL }; | ||
| 3044 | fEnc[0] = fopen ("enc0.264", "wb"); | ||
| 3045 | fEnc[1] = fopen ("enc1.264", "wb"); | ||
| 3046 | fEnc[2] = fopen ("enc2.264", "wb"); | ||
| 3047 | fEnc[3] = fopen ("enc3.264", "wb"); | ||
| 3048 | #endif | ||
| 3049 | |||
| 3050 | // init decoders | ||
| 3051 | int iIdx = 0; | ||
| 3052 | for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) { | ||
| 3053 | pBsBuf[iIdx] = static_cast<unsigned char*> (malloc (iWidth * iHeight * 3 * sizeof (unsigned char) / 2)); | ||
| 3054 | aLen[iIdx] = 0; | ||
| 3055 | |||
| 3056 | long rv = WelsCreateDecoder (&decoder[iIdx]); | ||
| 3057 | ASSERT_EQ (0, rv); | ||
| 3058 | ASSERT_TRUE (decoder[iIdx] != NULL); | ||
| 3059 | |||
| 3060 | SDecodingParam decParam; | ||
| 3061 | memset (&decParam, 0, sizeof (SDecodingParam)); | ||
| 3062 | decParam.eOutputColorFormat = videoFormatI420; | ||
| 3063 | decParam.uiTargetDqLayer = UCHAR_MAX; | ||
| 3064 | decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY; | ||
| 3065 | decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; | ||
| 3066 | |||
| 3067 | rv = decoder[iIdx]->Initialize (&decParam); | ||
| 3068 | ASSERT_EQ (0, rv); | ||
| 3069 | } | ||
| 3070 | |||
| 3071 | for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) { | ||
| 3072 | int iResult; | ||
| 3073 | int iLayerLen = 0; | ||
| 3074 | unsigned char* pData[3] = { NULL }; | ||
| 3075 | |||
| 3076 | InitialEncDec (param_.iPicWidth, param_.iPicHeight); | ||
| 3077 | EncodeOneFrame (0); | ||
| 3078 | |||
| 3079 | iLayerLen = 0; | ||
| 3080 | for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) { | ||
| 3081 | aLen[iIdx] = 0; | ||
| 3082 | } | ||
| 3083 | for (int iLayer = 0; iLayer < info.iLayerNum; ++iLayer) { | ||
| 3084 | iLayerLen = 0; | ||
| 3085 | const SLayerBSInfo& layerInfo = info.sLayerInfo[iLayer]; | ||
| 3086 | for (int iNal = 0; iNal < layerInfo.iNalCount; ++iNal) { | ||
| 3087 | iLayerLen += layerInfo.pNalLengthInByte[iNal]; | ||
| 3088 | } | ||
| 3089 | |||
| 3090 | if (layerInfo.uiLayerType == NON_VIDEO_CODING_LAYER) { | ||
| 3091 | // under SimulcastSVC, need to copy non-VCL to all layers | ||
| 3092 | for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) { | ||
| 3093 | memcpy ((pBsBuf[iIdx] + aLen[iIdx]), layerInfo.pBsBuf, iLayerLen * sizeof (unsigned char)); | ||
| 3094 | aLen[iIdx] += iLayerLen; | ||
| 3095 | } | ||
| 3096 | } else { | ||
| 3097 | iIdx = layerInfo.uiSpatialId; | ||
| 3098 | EXPECT_TRUE (iIdx < iSpatialLayerNum); | ||
| 3099 | memcpy ((pBsBuf[iIdx] + aLen[iIdx]), layerInfo.pBsBuf, iLayerLen * sizeof (unsigned char)); | ||
| 3100 | aLen[iIdx] += iLayerLen; | ||
| 3101 | } | ||
| 3102 | } | ||
| 3103 | |||
| 3104 | for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) { | ||
| 3105 | pData[0] = pData[1] = pData[2] = 0; | ||
| 3106 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 3107 | |||
| 3108 | #ifdef DEBUG_FILE_SAVE2 | ||
| 3109 | fwrite (pBsBuf[iIdx], aLen[iIdx], 1, fEnc[iIdx]); | ||
| 3110 | #endif | ||
| 3111 | iResult = decoder[iIdx]->DecodeFrame2 (pBsBuf[iIdx], aLen[iIdx], pData, &dstBufInfo_); | ||
| 3112 | EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << "LayerIdx=" << iIdx; | ||
| 3113 | iResult = decoder[iIdx]->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); | ||
| 3114 | EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << "LayerIdx=" << iIdx; | ||
| 3115 | EXPECT_EQ (dstBufInfo_.iBufferStatus, 1) << "LayerIdx=" << iIdx; | ||
| 3116 | } | ||
| 3117 | } | ||
| 3118 | |||
| 3119 | // free all | ||
| 3120 | for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) { | ||
| 3121 | if (pBsBuf[iIdx]) { | ||
| 3122 | free (pBsBuf[iIdx]); | ||
| 3123 | } | ||
| 3124 | |||
| 3125 | if (decoder[iIdx] != NULL) { | ||
| 3126 | decoder[iIdx]->Uninitialize(); | ||
| 3127 | WelsDestroyDecoder (decoder[iIdx]); | ||
| 3128 | } | ||
| 3129 | |||
| 3130 | #ifdef DEBUG_FILE_SAVE2 | ||
| 3131 | fclose (fEnc[iIdx]); | ||
| 3132 | #endif | ||
| 3133 | } | ||
| 3134 | |||
| 3135 | } | ||
| 3136 | |||
| 3137 | TEST_F (EncodeDecodeTestAPI, SimulcastAVC) { | ||
| 3138 | //#define DEBUG_FILE_SAVE3 | ||
| 3139 | #define LAYER_NUM (4) | ||
| 3140 | int iSpatialLayerNum = WelsClip3 ((rand() % LAYER_NUM), 2, LAYER_NUM);; | ||
| 3141 | int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 1 << iSpatialLayerNum, MAX_WIDTH); | ||
| 3142 | int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 1 << iSpatialLayerNum, MAX_HEIGHT); | ||
| 3143 | float fFrameRate = rand() + 0.5f; | ||
| 3144 | int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM); | ||
| 3145 | int iSliceNum = 1; | ||
| 3146 | encoder_->GetDefaultParams (¶m_); | ||
| 3147 | prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_); | ||
| 3148 | |||
| 3149 | //set flag of bSimulcastAVC | ||
| 3150 | param_.bSimulcastAVC = true; | ||
| 3151 | |||
| 3152 | int rv = encoder_->InitializeExt (¶m_); | ||
| 3153 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 3154 | |||
| 3155 | unsigned char* pBsBuf[LAYER_NUM]; | ||
| 3156 | int aLen[LAYER_NUM] = {0}; | ||
| 3157 | ISVCDecoder* decoder[LAYER_NUM]; | ||
| 3158 | |||
| 3159 | #ifdef DEBUG_FILE_SAVE3 | ||
| 3160 | FILE* fEnc[LAYER_NUM]; | ||
| 3161 | fEnc[0] = fopen ("enc0.264", "wb"); | ||
| 3162 | fEnc[1] = fopen ("enc1.264", "wb"); | ||
| 3163 | fEnc[2] = fopen ("enc2.264", "wb"); | ||
| 3164 | fEnc[3] = fopen ("enc3.264", "wb"); | ||
| 3165 | #endif | ||
| 3166 | |||
| 3167 | int iIdx = 0; | ||
| 3168 | |||
| 3169 | //create decoder | ||
| 3170 | for (int iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) { | ||
| 3171 | pBsBuf[iIdx] = static_cast<unsigned char*> (malloc (iWidth * iHeight * 3 * sizeof (unsigned char) / 2)); | ||
| 3172 | aLen[iIdx] = 0; | ||
| 3173 | |||
| 3174 | long rv = WelsCreateDecoder (&decoder[iIdx]); | ||
| 3175 | ASSERT_EQ (0, rv); | ||
| 3176 | ASSERT_TRUE (decoder[iIdx] != NULL); | ||
| 3177 | |||
| 3178 | SDecodingParam decParam; | ||
| 3179 | memset (&decParam, 0, sizeof (SDecodingParam)); | ||
| 3180 | decParam.eOutputColorFormat = videoFormatI420; | ||
| 3181 | decParam.uiTargetDqLayer = UCHAR_MAX; | ||
| 3182 | decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY; | ||
| 3183 | decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; | ||
| 3184 | |||
| 3185 | rv = decoder[iIdx]->Initialize (&decParam); | ||
| 3186 | ASSERT_EQ (0, rv); | ||
| 3187 | } | ||
| 3188 | |||
| 3189 | iEncFrameNum = 1; | ||
| 3190 | for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) { | ||
| 3191 | int iResult; | ||
| 3192 | int iLayerLen = 0; | ||
| 3193 | unsigned char* pData[3] = { NULL }; | ||
| 3194 | |||
| 3195 | InitialEncDec (param_.iPicWidth, param_.iPicHeight); | ||
| 3196 | EncodeOneFrame (0); | ||
| 3197 | |||
| 3198 | // init | ||
| 3199 | for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) { | ||
| 3200 | aLen[iIdx] = 0; | ||
| 3201 | } | ||
| 3202 | for (int iLayer = 0; iLayer < info.iLayerNum; ++iLayer) { | ||
| 3203 | iLayerLen = 0; | ||
| 3204 | const SLayerBSInfo& layerInfo = info.sLayerInfo[iLayer]; | ||
| 3205 | for (int iNal = 0; iNal < layerInfo.iNalCount; ++iNal) { | ||
| 3206 | iLayerLen += layerInfo.pNalLengthInByte[iNal]; | ||
| 3207 | } | ||
| 3208 | |||
| 3209 | iIdx = layerInfo.uiSpatialId; | ||
| 3210 | EXPECT_TRUE (iIdx < iSpatialLayerNum); | ||
| 3211 | memcpy ((pBsBuf[iIdx] + aLen[iIdx]), layerInfo.pBsBuf, iLayerLen * sizeof (unsigned char)); | ||
| 3212 | aLen[iIdx] += iLayerLen; | ||
| 3213 | } | ||
| 3214 | |||
| 3215 | for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) { | ||
| 3216 | pData[0] = pData[1] = pData[2] = 0; | ||
| 3217 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 3218 | |||
| 3219 | #ifdef DEBUG_FILE_SAVE3 | ||
| 3220 | fwrite (pBsBuf[iIdx], aLen[iIdx], 1, fEnc[iIdx]); | ||
| 3221 | #endif | ||
| 3222 | iResult = decoder[iIdx]->DecodeFrame2 (pBsBuf[iIdx], aLen[iIdx], pData, &dstBufInfo_); | ||
| 3223 | EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << "LayerIdx=" << iIdx; | ||
| 3224 | |||
| 3225 | iResult = decoder[iIdx]->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); | ||
| 3226 | EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << "LayerIdx=" << iIdx; | ||
| 3227 | EXPECT_EQ (dstBufInfo_.iBufferStatus, 1) << "LayerIdx=" << iIdx; | ||
| 3228 | } | ||
| 3229 | |||
| 3230 | } | ||
| 3231 | |||
| 3232 | for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) { | ||
| 3233 | free (pBsBuf[iIdx]); | ||
| 3234 | |||
| 3235 | if (decoder[iIdx] != NULL) { | ||
| 3236 | decoder[iIdx]->Uninitialize(); | ||
| 3237 | WelsDestroyDecoder (decoder[iIdx]); | ||
| 3238 | } | ||
| 3239 | #ifdef DEBUG_FILE_SAVE3 | ||
| 3240 | fclose (fEnc[iIdx]); | ||
| 3241 | #endif | ||
| 3242 | } | ||
| 3243 | } | ||
| 3244 | |||