diff --git a/codec/console/enc/src/welsenc.cpp b/codec/console/enc/src/welsenc.cpp index ee803440..7501d2c4 100644 --- a/codec/console/enc/src/welsenc.cpp +++ b/codec/console/enc/src/welsenc.cpp @@ -294,6 +294,8 @@ int ParseConfig (CReadConfig& cRdCfg, SSourcePicture* pSrcPic, SEncParamExt& pSv pSvcParam.iLTRRefNum = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("LtrMarkPeriod") == 0) { pSvcParam.iLtrMarkPeriod = (uint32_t)atoi (strTag[1].c_str()); + } else if (strTag[0].compare ("LosslessLink") == 0) { + pSvcParam.bIsLosslessLink = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("NumLayers") == 0) { pSvcParam.iSpatialLayerNum = (int8_t)atoi (strTag[1].c_str()); if (pSvcParam.iSpatialLayerNum > MAX_DEPENDENCY_LAYER || pSvcParam.iSpatialLayerNum <= 0) { diff --git a/codec/encoder/core/inc/param_svc.h b/codec/encoder/core/inc/param_svc.h index 253e363d..a6d04998 100644 --- a/codec/encoder/core/inc/param_svc.h +++ b/codec/encoder/core/inc/param_svc.h @@ -64,32 +64,32 @@ extern const uint8_t g_kuiTemporalIdListTable[MAX_TEMPORAL_LEVEL][MAX_GOP_SIZE * \return 2 based scaling factor */ static inline uint32_t GetLogFactor (float base, float upper) { -const double dLog2factor = log10 (1.0 * upper / base) / log10 (2.0); -const double dEpsilon = 0.0001; -const double dRound = floor (dLog2factor + 0.5); + const double dLog2factor = log10 (1.0 * upper / base) / log10 (2.0); + const double dEpsilon = 0.0001; + const double dRound = floor (dLog2factor + 0.5); -if (dLog2factor < dRound + dEpsilon && dRound < dLog2factor + dEpsilon) { - return (uint32_t) (dRound); -} -return UINT_MAX; + if (dLog2factor < dRound + dEpsilon && dRound < dLog2factor + dEpsilon) { + return (uint32_t) (dRound); + } + return UINT_MAX; } /* * Dependency Layer Parameter */ typedef struct TagDLayerParam { -int32_t iActualWidth; // input source picture actual width -int32_t iActualHeight; // input source picture actual height -int32_t iTemporalResolution; -int32_t iDecompositionStages; -uint8_t uiCodingIdx2TemporalId[ (1 << MAX_TEMPORAL_LEVEL) + 1]; + int32_t iActualWidth; // input source picture actual width + int32_t iActualHeight; // input source picture actual height + int32_t iTemporalResolution; + int32_t iDecompositionStages; + uint8_t uiCodingIdx2TemporalId[ (1 << MAX_TEMPORAL_LEVEL) + 1]; -int8_t iHighestTemporalId; -float fInputFrameRate; // input frame rate -float fOutputFrameRate; // output frame rate + int8_t iHighestTemporalId; + float fInputFrameRate; // input frame rate + float fOutputFrameRate; // output frame rate #ifdef ENABLE_FRAME_DUMP -char sRecFileName[MAX_FNAME_LEN]; // file to be constructed + char sRecFileName[MAX_FNAME_LEN]; // file to be constructed #endif//ENABLE_FRAME_DUMP } SSpatialLayerInternal; @@ -97,422 +97,426 @@ char sRecFileName[MAX_FNAME_LEN]; // file to be constructed * Cisco OpenH264 Encoder Parameter Configuration */ typedef struct TagWelsSvcCodingParam: SEncParamExt { -SSpatialLayerInternal sDependencyLayers[MAX_DEPENDENCY_LAYER]; + SSpatialLayerInternal sDependencyLayers[MAX_DEPENDENCY_LAYER]; -/* General */ -uint32_t uiGopSize; // GOP size (at maximal frame rate: 16) -struct { - int32_t iLeft; - int32_t iTop; - int32_t iWidth; - int32_t iHeight; -} SUsedPicRect; // the rect in input picture that encoder actually used + /* General */ + uint32_t uiGopSize; // GOP size (at maximal frame rate: 16) + struct { + int32_t iLeft; + int32_t iTop; + int32_t iWidth; + int32_t iHeight; + } SUsedPicRect; // the rect in input picture that encoder actually used -char* pCurPath; // record current lib path such as:/pData/pData/com.wels.enc/lib/ + char* pCurPath; // record current lib path such as:/pData/pData/com.wels.enc/lib/ -bool bDeblockingParallelFlag; // deblocking filter parallelization control flag + bool bDeblockingParallelFlag; // deblocking filter parallelization control flag -short -iCountThreadsNum; // # derived from disable_multiple_slice_idc (=0 or >1) means; + short + iCountThreadsNum; // # derived from disable_multiple_slice_idc (=0 or >1) means; -int8_t iDecompStages; // GOP size dependency -int32_t iMaxNumRefFrame; + int8_t iDecompStages; // GOP size dependency + int32_t iMaxNumRefFrame; //setting this according to link type in use MAY invoke some algorithms targeting higher coding efficiency -bool bIsLossLessLink; + bool bIsLosslessLink; public: -TagWelsSvcCodingParam() { - FillDefault(); -} -~TagWelsSvcCodingParam() {} + TagWelsSvcCodingParam() { + FillDefault(); + } + ~TagWelsSvcCodingParam() {} -static void FillDefault (SEncParamExt& param) { - memset (¶m, 0, sizeof (param)); - param.uiIntraPeriod = 0; // intra period (multiple of GOP size as desired) - param.iNumRefFrame = AUTO_REF_PIC_COUNT;// number of reference frame used + static void FillDefault (SEncParamExt& param) { + memset (¶m, 0, sizeof (param)); + param.uiIntraPeriod = 0; // intra period (multiple of GOP size as desired) + param.iNumRefFrame = AUTO_REF_PIC_COUNT;// number of reference frame used - param.iPicWidth = 0; // actual input picture width - param.iPicHeight = 0; // actual input picture height + param.iPicWidth = 0; // actual input picture width + param.iPicHeight = 0; // actual input picture height - param.fMaxFrameRate = MAX_FRAME_RATE; // maximal frame rate [Hz / fps] + param.fMaxFrameRate = MAX_FRAME_RATE; // maximal frame rate [Hz / fps] - param.iComplexityMode = MEDIUM_COMPLEXITY; - param.iTargetBitrate = 0; // overall target bitrate introduced in RC module - param.iMaxBitrate = MAX_BIT_RATE; - param.iMultipleThreadIdc = 1; + param.iComplexityMode = MEDIUM_COMPLEXITY; + param.iTargetBitrate = 0; // overall target bitrate introduced in RC module + param.iMaxBitrate = MAX_BIT_RATE; + param.iMultipleThreadIdc = 1; - param.iLTRRefNum = 0; - param.iLtrMarkPeriod = 30; //the min distance of two int32_t references + param.iLTRRefNum = 0; + param.iLtrMarkPeriod = 30; //the min distance of two int32_t references - param.bEnableSSEI = true; - param.bEnableFrameCroppingFlag = true; // enable frame cropping flag: true alwayse in application - // false: Streaming Video Sharing; true: Video Conferencing Meeting; + param.bEnableSSEI = true; + param.bEnableFrameCroppingFlag = true; // enable frame cropping flag: true alwayse in application + // false: Streaming Video Sharing; true: Video Conferencing Meeting; - /* Deblocking loop filter */ - param.iLoopFilterDisableIdc = 0; // 0: on, 1: off, 2: on except for slice boundaries - param.iLoopFilterAlphaC0Offset = 0; // AlphaOffset: valid range [-6, 6], default 0 - param.iLoopFilterBetaOffset = 0; // BetaOffset: valid range [-6, 6], default 0 + /* Deblocking loop filter */ + param.iLoopFilterDisableIdc = 0; // 0: on, 1: off, 2: on except for slice boundaries + param.iLoopFilterAlphaC0Offset = 0; // AlphaOffset: valid range [-6, 6], default 0 + param.iLoopFilterBetaOffset = 0; // BetaOffset: valid range [-6, 6], default 0 - /* Rate Control */ - param.iRCMode = RC_QUALITY_MODE; - param.iPaddingFlag = 0; + /* Rate Control */ + param.iRCMode = RC_QUALITY_MODE; + param.iPaddingFlag = 0; - param.bEnableDenoise = false; // denoise control - param.bEnableSceneChangeDetect = true; // scene change detection control - param.bEnableBackgroundDetection = true; // background detection control - param.bEnableAdaptiveQuant = true; // adaptive quantization control - param.bEnableFrameSkip = true; // frame skipping - param.bEnableLongTermReference = false; // long term reference control - param.bEnableSpsPpsIdAddition = true; // pSps pPps id addition control - param.bPrefixNalAddingCtrl = false; // prefix NAL adding control - param.iSpatialLayerNum = 1; // number of dependency(Spatial/CGS) layers used to be encoded - param.iTemporalLayerNum = 1; // number of temporal layer specified + param.bEnableDenoise = false; // denoise control + param.bEnableSceneChangeDetect = true; // scene change detection control + param.bEnableBackgroundDetection = true; // background detection control + param.bEnableAdaptiveQuant = true; // adaptive quantization control + param.bEnableFrameSkip = true; // frame skipping + param.bEnableLongTermReference = false; // long term reference control + param.bEnableSpsPpsIdAddition = true; // pSps pPps id addition control + param.bPrefixNalAddingCtrl = false; // prefix NAL adding control + param.iSpatialLayerNum = 1; // number of dependency(Spatial/CGS) layers used to be encoded + param.iTemporalLayerNum = 1; // number of temporal layer specified - param.iMaxQp = 51; - param.iMinQp = 0; - param.iUsageType = CAMERA_VIDEO_REAL_TIME; - param.uiMaxNalSize = 0; + param.iMaxQp = 51; + param.iMinQp = 0; + param.iUsageType = CAMERA_VIDEO_REAL_TIME; + param.uiMaxNalSize = 0; - for (int32_t iLayer = 0; iLayer < MAX_SPATIAL_LAYER_NUM; iLayer++) { - param.sSpatialLayers[iLayer].uiProfileIdc = PRO_BASELINE; - param.sSpatialLayers[iLayer].uiLevelIdc = LEVEL_5_0; - param.sSpatialLayers[iLayer].iDLayerQp = SVC_QUALITY_BASE_QP; - param.sSpatialLayers[iLayer].fFrameRate = param.fMaxFrameRate; - param.sSpatialLayers[iLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE; - param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 1500; - param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceNum = 1; + for (int32_t iLayer = 0; iLayer < MAX_SPATIAL_LAYER_NUM; iLayer++) { + param.sSpatialLayers[iLayer].uiProfileIdc = PRO_BASELINE; + param.sSpatialLayers[iLayer].uiLevelIdc = LEVEL_5_0; + param.sSpatialLayers[iLayer].iDLayerQp = SVC_QUALITY_BASE_QP; + param.sSpatialLayers[iLayer].fFrameRate = param.fMaxFrameRate; + param.sSpatialLayers[iLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE; + param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 1500; + param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceNum = 1; + + const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP); + for (int32_t idx = 0; idx < kiLesserSliceNum; idx++) + param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceMbNum[idx] = 960; + } + } + + void FillDefault() { + FillDefault (*this); + uiGopSize = 1; // GOP size (at maximal frame rate: 16) + iMaxNumRefFrame = 1; + SUsedPicRect.iLeft = + SUsedPicRect.iTop = + SUsedPicRect.iWidth = + SUsedPicRect.iHeight = 0; // the rect in input picture that encoder actually used + + pCurPath = NULL; // record current lib path such as:/pData/pData/com.wels.enc/lib/ + + bDeblockingParallelFlag = false; // deblocking filter parallelization control flag + + iCountThreadsNum = 1; // # derived from disable_multiple_slice_idc (=0 or >1) means; + + iDecompStages = 0; // GOP size dependency, unknown here and be revised later + iComplexityMode = MEDIUM_COMPLEXITY; + memset (sDependencyLayers, 0, sizeof (SSpatialLayerInternal)*MAX_DEPENDENCY_LAYER); + memset (sSpatialLayers, 0 , sizeof (SSpatialLayerConfig)*MAX_SPATIAL_LAYER_NUM); + + + //init multi-slice + sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE; + sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 1500; + sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = 1; const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP); for (int32_t idx = 0; idx < kiLesserSliceNum; idx++) - param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceMbNum[idx] = 960; - } -} + sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceMbNum[idx] = 960; + sSpatialLayers[0].iDLayerQp = SVC_QUALITY_BASE_QP; -void FillDefault() { - FillDefault (*this); - uiGopSize = 1; // GOP size (at maximal frame rate: 16) - iMaxNumRefFrame = 1; - SUsedPicRect.iLeft = - SUsedPicRect.iTop = - SUsedPicRect.iWidth = - SUsedPicRect.iHeight = 0; // the rect in input picture that encoder actually used - - pCurPath = NULL; // record current lib path such as:/pData/pData/com.wels.enc/lib/ - - bDeblockingParallelFlag = false; // deblocking filter parallelization control flag - - iCountThreadsNum = 1; // # derived from disable_multiple_slice_idc (=0 or >1) means; - - iDecompStages = 0; // GOP size dependency, unknown here and be revised later - iComplexityMode = MEDIUM_COMPLEXITY; - memset (sDependencyLayers, 0, sizeof (SSpatialLayerInternal)*MAX_DEPENDENCY_LAYER); - memset (sSpatialLayers, 0 , sizeof (SSpatialLayerConfig)*MAX_SPATIAL_LAYER_NUM); - - - //init multi-slice - sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE; - sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 1500; - sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = 1; - - const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP); - for (int32_t idx = 0; idx < kiLesserSliceNum; idx++) - sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceMbNum[idx] = 960; - sSpatialLayers[0].iDLayerQp = SVC_QUALITY_BASE_QP; - - bIsLossLessLink = false; -} - -int32_t ParamBaseTranscode (const SEncParamBase& pCodingParam) { - - fMaxFrameRate = WELS_CLIP3 (pCodingParam.fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE); - iTargetBitrate = pCodingParam.iTargetBitrate; - iUsageType = pCodingParam.iUsageType; - iPicWidth = pCodingParam.iPicWidth; - iPicHeight = pCodingParam.iPicHeight; - - SUsedPicRect.iLeft = 0; - SUsedPicRect.iTop = 0; - SUsedPicRect.iWidth = ((iPicWidth >> 1) << 1); - SUsedPicRect.iHeight = ((iPicHeight >> 1) << 1); - - iRCMode = pCodingParam.iRCMode; // rc mode - - int8_t iIdxSpatial = 0; - EProfileIdc uiProfileIdc = PRO_BASELINE; - - SSpatialLayerInternal* pDlp = &sDependencyLayers[0]; - - while (iIdxSpatial < iSpatialLayerNum) { - - sSpatialLayers->uiProfileIdc = uiProfileIdc; - sSpatialLayers[iIdxSpatial].fFrameRate = WELS_CLIP3 (pCodingParam.fMaxFrameRate, - MIN_FRAME_RATE, MAX_FRAME_RATE); - pDlp->fInputFrameRate = - pDlp->fOutputFrameRate = WELS_CLIP3 (sSpatialLayers[iIdxSpatial].fFrameRate, MIN_FRAME_RATE, - MAX_FRAME_RATE); -#ifdef ENABLE_FRAME_DUMP - pDlp->sRecFileName[0] = '\0'; // file to be constructed -#endif//ENABLE_FRAME_DUMP - pDlp->iActualWidth = sSpatialLayers[iIdxSpatial].iVideoWidth = iPicWidth; - pDlp->iActualHeight = sSpatialLayers[iIdxSpatial].iVideoHeight = iPicHeight; - - sSpatialLayers->iSpatialBitrate = - sSpatialLayers[iIdxSpatial].iSpatialBitrate = pCodingParam.iTargetBitrate; // target bitrate for current spatial layer - - sSpatialLayers->iDLayerQp = SVC_QUALITY_BASE_QP; - - uiProfileIdc = PRO_SCALABLE_BASELINE; - ++ pDlp; - ++ iIdxSpatial; - } - SetActualPicResolution(); - - return 0; -} -void GetBaseParams (SEncParamBase* pCodingParam) { - pCodingParam->iUsageType = iUsageType; - pCodingParam->iPicWidth = iPicWidth; - pCodingParam->iPicHeight = iPicHeight; - pCodingParam->iTargetBitrate = iTargetBitrate; - pCodingParam->iRCMode = iRCMode; - pCodingParam->fMaxFrameRate = fMaxFrameRate; -} -int32_t ParamTranscode (const SEncParamExt& pCodingParam) { - float fParamMaxFrameRate = WELS_CLIP3 (pCodingParam.fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE); - - iUsageType = pCodingParam.iUsageType; - iPicWidth = pCodingParam.iPicWidth; - iPicHeight = pCodingParam.iPicHeight; - iComplexityMode = pCodingParam.iComplexityMode; - - SUsedPicRect.iLeft = 0; - SUsedPicRect.iTop = 0; - SUsedPicRect.iWidth = ((iPicWidth >> 1) << 1); - SUsedPicRect.iHeight = ((iPicHeight >> 1) << 1); - - iMultipleThreadIdc = pCodingParam.iMultipleThreadIdc; - - /* Deblocking loop filter */ - iLoopFilterDisableIdc = pCodingParam.iLoopFilterDisableIdc; // 0: on, 1: off, 2: on except for slice boundaries, - iLoopFilterAlphaC0Offset = pCodingParam.iLoopFilterAlphaC0Offset; // AlphaOffset: valid range [-6, 6], default 0 - iLoopFilterBetaOffset = pCodingParam.iLoopFilterBetaOffset; // BetaOffset: valid range [-6, 6], default 0 - - bEnableFrameCroppingFlag = pCodingParam.bEnableFrameCroppingFlag; - - /* Rate Control */ - iRCMode = pCodingParam.iRCMode; // rc mode - iPaddingFlag = pCodingParam.iPaddingFlag; - - iTargetBitrate = pCodingParam.iTargetBitrate; // target bitrate - iMaxBitrate = pCodingParam.iMaxBitrate; - if (iMaxBitrate < iTargetBitrate) { - iMaxBitrate = iTargetBitrate; + bIsLosslessLink = false; } - uiMaxNalSize = pCodingParam.uiMaxNalSize; - /* Denoise Control */ - bEnableDenoise = pCodingParam.bEnableDenoise ? true : false; // Denoise Control // only support 0 or 1 now + int32_t ParamBaseTranscode (const SEncParamBase& pCodingParam) { - /* Scene change detection control */ - bEnableSceneChangeDetect = pCodingParam.bEnableSceneChangeDetect; + fMaxFrameRate = WELS_CLIP3 (pCodingParam.fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE); + iTargetBitrate = pCodingParam.iTargetBitrate; + iUsageType = pCodingParam.iUsageType; + iPicWidth = pCodingParam.iPicWidth; + iPicHeight = pCodingParam.iPicHeight; - /* Background detection Control */ - bEnableBackgroundDetection = pCodingParam.bEnableBackgroundDetection ? true : false; + SUsedPicRect.iLeft = 0; + SUsedPicRect.iTop = 0; + SUsedPicRect.iWidth = ((iPicWidth >> 1) << 1); + SUsedPicRect.iHeight = ((iPicHeight >> 1) << 1); - /* Adaptive quantization control */ - bEnableAdaptiveQuant = pCodingParam.bEnableAdaptiveQuant ? true : false; + iRCMode = pCodingParam.iRCMode; // rc mode - /* Frame skipping */ - bEnableFrameSkip = pCodingParam.bEnableFrameSkip ? true : false; + int8_t iIdxSpatial = 0; + EProfileIdc uiProfileIdc = PRO_BASELINE; - /* Enable int32_t term reference */ - bEnableLongTermReference = pCodingParam.bEnableLongTermReference ? true : false; - iLtrMarkPeriod = pCodingParam.iLtrMarkPeriod; + SSpatialLayerInternal* pDlp = &sDependencyLayers[0]; - /* For ssei information */ - bEnableSSEI = pCodingParam.bEnableSSEI; + while (iIdxSpatial < iSpatialLayerNum) { - /* Layer definition */ - iSpatialLayerNum = (int8_t)WELS_CLIP3 (pCodingParam.iSpatialLayerNum, 1, - MAX_DEPENDENCY_LAYER); // number of dependency(Spatial/CGS) layers used to be encoded - iTemporalLayerNum = (int8_t)WELS_CLIP3 (pCodingParam.iTemporalLayerNum, 1, - MAX_TEMPORAL_LEVEL); // number of temporal layer specified - - uiGopSize = 1 << (iTemporalLayerNum - 1); // Override GOP size based temporal layer - iDecompStages = iTemporalLayerNum - 1; // WELS_LOG2( uiGopSize );// GOP size dependency - uiIntraPeriod = pCodingParam.uiIntraPeriod;// intra period (multiple of GOP size as desired) - if (uiIntraPeriod == (uint32_t) (-1)) - uiIntraPeriod = 0; - else if (uiIntraPeriod & (uiGopSize - 1)) // none multiple of GOP size - uiIntraPeriod = ((uiIntraPeriod + uiGopSize - 1) / uiGopSize) * uiGopSize; - - if (iUsageType == SCREEN_CONTENT_REAL_TIME) { - if (bEnableLongTermReference) { - iLTRRefNum = LONG_TERM_REF_NUM_SCREEN; - if (iNumRefFrame == AUTO_REF_PIC_COUNT) - iNumRefFrame = WELS_MAX (1, WELS_LOG2 (uiGopSize)) + iLTRRefNum; - } else { - iLTRRefNum = 0; - - if (iNumRefFrame == AUTO_REF_PIC_COUNT) - iNumRefFrame = WELS_MAX (1, uiGopSize >> 1); - } - } else { - iLTRRefNum = bEnableLongTermReference ? LONG_TERM_REF_NUM : 0; - if (iNumRefFrame == AUTO_REF_PIC_COUNT) { - iNumRefFrame = ((uiGopSize >> 1) > 1) ? ((uiGopSize >> 1) + iLTRRefNum) : (MIN_REF_PIC_COUNT + iLTRRefNum); - iNumRefFrame = WELS_CLIP3 (iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA); - } - } - if (iNumRefFrame > iMaxNumRefFrame) - iMaxNumRefFrame = iNumRefFrame; - iLtrMarkPeriod = pCodingParam.iLtrMarkPeriod; - - bPrefixNalAddingCtrl = pCodingParam.bPrefixNalAddingCtrl; - - bEnableSpsPpsIdAddition = - pCodingParam.bEnableSpsPpsIdAddition;//For SVC meeting application, to avoid mosaic issue caused by cross-IDR reference. - //SHOULD enable this feature. - - SSpatialLayerInternal* pDlp = &sDependencyLayers[0]; - SSpatialLayerConfig* pSpatialLayer = &sSpatialLayers[0]; - float fMaxFr = .0f; - EProfileIdc uiProfileIdc = PRO_BASELINE; - int8_t iIdxSpatial = 0; - while (iIdxSpatial < iSpatialLayerNum) { - pSpatialLayer->uiProfileIdc = (pCodingParam.sSpatialLayers[iIdxSpatial].uiProfileIdc == PRO_UNKNOWN) ? uiProfileIdc : - pCodingParam.sSpatialLayers[iIdxSpatial].uiProfileIdc; - pSpatialLayer->uiLevelIdc = (pCodingParam.sSpatialLayers[iIdxSpatial].uiLevelIdc == LEVEL_UNKNOWN) ? LEVEL_5_0 : - pCodingParam.sSpatialLayers[iIdxSpatial].uiLevelIdc; - - float fLayerFrameRate = WELS_CLIP3 (pCodingParam.sSpatialLayers[iIdxSpatial].fFrameRate, - MIN_FRAME_RATE, fParamMaxFrameRate); - pSpatialLayer->fFrameRate = + sSpatialLayers->uiProfileIdc = uiProfileIdc; + sSpatialLayers[iIdxSpatial].fFrameRate = WELS_CLIP3 (pCodingParam.fMaxFrameRate, + MIN_FRAME_RATE, MAX_FRAME_RATE); pDlp->fInputFrameRate = - pDlp->fOutputFrameRate = WELS_CLIP3 (fLayerFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE); - if (pDlp->fInputFrameRate > fMaxFr + EPSN) - fMaxFr = pDlp->fInputFrameRate; + pDlp->fOutputFrameRate = WELS_CLIP3 (sSpatialLayers[iIdxSpatial].fFrameRate, MIN_FRAME_RATE, + MAX_FRAME_RATE); +#ifdef ENABLE_FRAME_DUMP + pDlp->sRecFileName[0] = '\0'; // file to be constructed +#endif//ENABLE_FRAME_DUMP + pDlp->iActualWidth = sSpatialLayers[iIdxSpatial].iVideoWidth = iPicWidth; + pDlp->iActualHeight = sSpatialLayers[iIdxSpatial].iVideoHeight = iPicHeight; + + sSpatialLayers->iSpatialBitrate = + sSpatialLayers[iIdxSpatial].iSpatialBitrate = pCodingParam.iTargetBitrate; // target bitrate for current spatial layer + + sSpatialLayers->iDLayerQp = SVC_QUALITY_BASE_QP; + + uiProfileIdc = PRO_SCALABLE_BASELINE; + ++ pDlp; + ++ iIdxSpatial; + } + SetActualPicResolution(); + + return 0; + } + void GetBaseParams (SEncParamBase* pCodingParam) { + pCodingParam->iUsageType = iUsageType; + pCodingParam->iPicWidth = iPicWidth; + pCodingParam->iPicHeight = iPicHeight; + pCodingParam->iTargetBitrate = iTargetBitrate; + pCodingParam->iRCMode = iRCMode; + pCodingParam->fMaxFrameRate = fMaxFrameRate; + } + int32_t ParamTranscode (const SEncParamExt& pCodingParam) { + float fParamMaxFrameRate = WELS_CLIP3 (pCodingParam.fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE); + + iUsageType = pCodingParam.iUsageType; + iPicWidth = pCodingParam.iPicWidth; + iPicHeight = pCodingParam.iPicHeight; + iComplexityMode = pCodingParam.iComplexityMode; + + SUsedPicRect.iLeft = 0; + SUsedPicRect.iTop = 0; + SUsedPicRect.iWidth = ((iPicWidth >> 1) << 1); + SUsedPicRect.iHeight = ((iPicHeight >> 1) << 1); + + iMultipleThreadIdc = pCodingParam.iMultipleThreadIdc; + + /* Deblocking loop filter */ + iLoopFilterDisableIdc = pCodingParam.iLoopFilterDisableIdc; // 0: on, 1: off, 2: on except for slice boundaries, + iLoopFilterAlphaC0Offset = pCodingParam.iLoopFilterAlphaC0Offset; // AlphaOffset: valid range [-6, 6], default 0 + iLoopFilterBetaOffset = pCodingParam.iLoopFilterBetaOffset; // BetaOffset: valid range [-6, 6], default 0 + + bEnableFrameCroppingFlag = pCodingParam.bEnableFrameCroppingFlag; + + /* Rate Control */ + iRCMode = pCodingParam.iRCMode; // rc mode + iPaddingFlag = pCodingParam.iPaddingFlag; + + iTargetBitrate = pCodingParam.iTargetBitrate; // target bitrate + iMaxBitrate = pCodingParam.iMaxBitrate; + if (iMaxBitrate < iTargetBitrate) { + iMaxBitrate = iTargetBitrate; + } + + uiMaxNalSize = pCodingParam.uiMaxNalSize; + /* Denoise Control */ + bEnableDenoise = pCodingParam.bEnableDenoise ? true : false; // Denoise Control // only support 0 or 1 now + + /* Scene change detection control */ + bEnableSceneChangeDetect = pCodingParam.bEnableSceneChangeDetect; + + /* Background detection Control */ + bEnableBackgroundDetection = pCodingParam.bEnableBackgroundDetection ? true : false; + + /* Adaptive quantization control */ + bEnableAdaptiveQuant = pCodingParam.bEnableAdaptiveQuant ? true : false; + + /* Frame skipping */ + bEnableFrameSkip = pCodingParam.bEnableFrameSkip ? true : false; + + /* Enable int32_t term reference */ + bEnableLongTermReference = pCodingParam.bEnableLongTermReference ? true : false; + iLtrMarkPeriod = pCodingParam.iLtrMarkPeriod; + bIsLosslessLink = pCodingParam.bIsLosslessLink; + if (iUsageType == SCREEN_CONTENT_REAL_TIME && !bIsLosslessLink && bEnableLongTermReference) { + bEnableLongTermReference = false; + } + + /* For ssei information */ + bEnableSSEI = pCodingParam.bEnableSSEI; + + /* Layer definition */ + iSpatialLayerNum = (int8_t)WELS_CLIP3 (pCodingParam.iSpatialLayerNum, 1, + MAX_DEPENDENCY_LAYER); // number of dependency(Spatial/CGS) layers used to be encoded + iTemporalLayerNum = (int8_t)WELS_CLIP3 (pCodingParam.iTemporalLayerNum, 1, + MAX_TEMPORAL_LEVEL); // number of temporal layer specified + + uiGopSize = 1 << (iTemporalLayerNum - 1); // Override GOP size based temporal layer + iDecompStages = iTemporalLayerNum - 1; // WELS_LOG2( uiGopSize );// GOP size dependency + uiIntraPeriod = pCodingParam.uiIntraPeriod;// intra period (multiple of GOP size as desired) + if (uiIntraPeriod == (uint32_t) (-1)) + uiIntraPeriod = 0; + else if (uiIntraPeriod & (uiGopSize - 1)) // none multiple of GOP size + uiIntraPeriod = ((uiIntraPeriod + uiGopSize - 1) / uiGopSize) * uiGopSize; + + if (iUsageType == SCREEN_CONTENT_REAL_TIME) { + if (bEnableLongTermReference) { + iLTRRefNum = LONG_TERM_REF_NUM_SCREEN; + if (iNumRefFrame == AUTO_REF_PIC_COUNT) + iNumRefFrame = WELS_MAX (1, WELS_LOG2 (uiGopSize)) + iLTRRefNum; + } else { + iLTRRefNum = 0; + + if (iNumRefFrame == AUTO_REF_PIC_COUNT) + iNumRefFrame = WELS_MAX (1, uiGopSize >> 1); + } + } else { + iLTRRefNum = bEnableLongTermReference ? LONG_TERM_REF_NUM : 0; + if (iNumRefFrame == AUTO_REF_PIC_COUNT) { + iNumRefFrame = ((uiGopSize >> 1) > 1) ? ((uiGopSize >> 1) + iLTRRefNum) : (MIN_REF_PIC_COUNT + iLTRRefNum); + iNumRefFrame = WELS_CLIP3 (iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA); + } + } + if (iNumRefFrame > iMaxNumRefFrame) + iMaxNumRefFrame = iNumRefFrame; + iLtrMarkPeriod = pCodingParam.iLtrMarkPeriod; + + bPrefixNalAddingCtrl = pCodingParam.bPrefixNalAddingCtrl; + + bEnableSpsPpsIdAddition = + pCodingParam.bEnableSpsPpsIdAddition;//For SVC meeting application, to avoid mosaic issue caused by cross-IDR reference. + //SHOULD enable this feature. + + SSpatialLayerInternal* pDlp = &sDependencyLayers[0]; + SSpatialLayerConfig* pSpatialLayer = &sSpatialLayers[0]; + float fMaxFr = .0f; + EProfileIdc uiProfileIdc = PRO_BASELINE; + int8_t iIdxSpatial = 0; + while (iIdxSpatial < iSpatialLayerNum) { + pSpatialLayer->uiProfileIdc = (pCodingParam.sSpatialLayers[iIdxSpatial].uiProfileIdc == PRO_UNKNOWN) ? uiProfileIdc : + pCodingParam.sSpatialLayers[iIdxSpatial].uiProfileIdc; + pSpatialLayer->uiLevelIdc = (pCodingParam.sSpatialLayers[iIdxSpatial].uiLevelIdc == LEVEL_UNKNOWN) ? LEVEL_5_0 : + pCodingParam.sSpatialLayers[iIdxSpatial].uiLevelIdc; + + float fLayerFrameRate = WELS_CLIP3 (pCodingParam.sSpatialLayers[iIdxSpatial].fFrameRate, + MIN_FRAME_RATE, fParamMaxFrameRate); + pSpatialLayer->fFrameRate = + pDlp->fInputFrameRate = + pDlp->fOutputFrameRate = WELS_CLIP3 (fLayerFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE); + if (pDlp->fInputFrameRate > fMaxFr + EPSN) + fMaxFr = pDlp->fInputFrameRate; #ifdef ENABLE_FRAME_DUMP - pDlp->sRecFileName[0] = '\0'; // file to be constructed + pDlp->sRecFileName[0] = '\0'; // file to be constructed #endif//ENABLE_FRAME_DUMP - pSpatialLayer->iVideoWidth = pCodingParam.sSpatialLayers[iIdxSpatial].iVideoWidth; // frame width - pSpatialLayer->iVideoHeight = pCodingParam.sSpatialLayers[iIdxSpatial].iVideoHeight;// frame height - pSpatialLayer->iSpatialBitrate = - pCodingParam.sSpatialLayers[iIdxSpatial].iSpatialBitrate; // target bitrate for current spatial layer - pSpatialLayer->iMaxSpatialBitrate = - pCodingParam.sSpatialLayers[iIdxSpatial].iMaxSpatialBitrate; + pSpatialLayer->iVideoWidth = pCodingParam.sSpatialLayers[iIdxSpatial].iVideoWidth; // frame width + pSpatialLayer->iVideoHeight = pCodingParam.sSpatialLayers[iIdxSpatial].iVideoHeight;// frame height + pSpatialLayer->iSpatialBitrate = + pCodingParam.sSpatialLayers[iIdxSpatial].iSpatialBitrate; // target bitrate for current spatial layer + pSpatialLayer->iMaxSpatialBitrate = + pCodingParam.sSpatialLayers[iIdxSpatial].iMaxSpatialBitrate; - //multi slice - pSpatialLayer->sSliceCfg.uiSliceMode = pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.uiSliceMode; - pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceSizeConstraint - = (uint32_t) (pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceSizeConstraint); - pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceNum - = pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceNum; - const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP); - memcpy (pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceMbNum, - pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceMbNum, // confirmed_safe_unsafe_usage - kiLesserSliceNum * sizeof (uint32_t)) ; + //multi slice + pSpatialLayer->sSliceCfg.uiSliceMode = pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.uiSliceMode; + pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceSizeConstraint + = (uint32_t) (pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceSizeConstraint); + pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceNum + = pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceNum; + const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP); + memcpy (pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceMbNum, + pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceMbNum, // confirmed_safe_unsafe_usage + kiLesserSliceNum * sizeof (uint32_t)) ; - pSpatialLayer->iDLayerQp = pCodingParam.sSpatialLayers[iIdxSpatial].iDLayerQp; + pSpatialLayer->iDLayerQp = pCodingParam.sSpatialLayers[iIdxSpatial].iDLayerQp; - uiProfileIdc = PRO_SCALABLE_BASELINE; - ++ pDlp; - ++ pSpatialLayer; - ++ iIdxSpatial; + uiProfileIdc = PRO_SCALABLE_BASELINE; + ++ pDlp; + ++ pSpatialLayer; + ++ iIdxSpatial; + } + + fMaxFrameRate = fMaxFr; + + SetActualPicResolution(); + + return 0; } - fMaxFrameRate = fMaxFr; - - SetActualPicResolution(); - - return 0; -} - // assuming that the width/height ratio of all spatial layers are the same -void SetActualPicResolution() { - int32_t iSpatialIdx = iSpatialLayerNum - 1; - for (; iSpatialIdx >= 0; iSpatialIdx --) { - SSpatialLayerInternal* pDlayerInternal = &sDependencyLayers[iSpatialIdx]; - SSpatialLayerConfig* pDlayer = &sSpatialLayers[iSpatialIdx]; + void SetActualPicResolution() { + int32_t iSpatialIdx = iSpatialLayerNum - 1; + for (; iSpatialIdx >= 0; iSpatialIdx --) { + SSpatialLayerInternal* pDlayerInternal = &sDependencyLayers[iSpatialIdx]; + SSpatialLayerConfig* pDlayer = &sSpatialLayers[iSpatialIdx]; - pDlayerInternal->iActualWidth = pDlayer->iVideoWidth; - pDlayerInternal->iActualHeight = pDlayer->iVideoHeight; - pDlayer->iVideoWidth = WELS_ALIGN (pDlayerInternal->iActualWidth, MB_WIDTH_LUMA); - pDlayer->iVideoHeight = WELS_ALIGN (pDlayerInternal->iActualHeight, MB_HEIGHT_LUMA); + pDlayerInternal->iActualWidth = pDlayer->iVideoWidth; + pDlayerInternal->iActualHeight = pDlayer->iVideoHeight; + pDlayer->iVideoWidth = WELS_ALIGN (pDlayerInternal->iActualWidth, MB_WIDTH_LUMA); + pDlayer->iVideoHeight = WELS_ALIGN (pDlayerInternal->iActualHeight, MB_HEIGHT_LUMA); + } } -} -/*! -* \brief determined key coding tables for temporal scalability, uiProfileIdc etc for each spatial layer settings -* \param SWelsSvcCodingParam, and carried with known GOP size, max, input and output frame rate of each spatial -* \return NONE (should ensure valid parameter before this procedure) -*/ -void DetermineTemporalSettings() { - const int32_t iDecStages = WELS_LOG2 ( - uiGopSize); // (int8_t)GetLogFactor(1.0f, 1.0f * pcfg->uiGopSize); //log2(uiGopSize) - const uint8_t* pTemporalIdList = &g_kuiTemporalIdListTable[iDecStages][0]; - SSpatialLayerInternal* pDlp = &sDependencyLayers[0]; - SSpatialLayerConfig* pSpatialLayer = &sSpatialLayers[0]; - EProfileIdc uiProfileIdc = PRO_BASELINE; - int8_t i = 0; + /*! + * \brief determined key coding tables for temporal scalability, uiProfileIdc etc for each spatial layer settings + * \param SWelsSvcCodingParam, and carried with known GOP size, max, input and output frame rate of each spatial + * \return NONE (should ensure valid parameter before this procedure) + */ + void DetermineTemporalSettings() { + const int32_t iDecStages = WELS_LOG2 ( + uiGopSize); // (int8_t)GetLogFactor(1.0f, 1.0f * pcfg->uiGopSize); //log2(uiGopSize) + const uint8_t* pTemporalIdList = &g_kuiTemporalIdListTable[iDecStages][0]; + SSpatialLayerInternal* pDlp = &sDependencyLayers[0]; + SSpatialLayerConfig* pSpatialLayer = &sSpatialLayers[0]; + EProfileIdc uiProfileIdc = PRO_BASELINE; + int8_t i = 0; - while (i < iSpatialLayerNum) { - const uint32_t kuiLogFactorInOutRate = GetLogFactor (pDlp->fOutputFrameRate, pDlp->fInputFrameRate); - const uint32_t kuiLogFactorMaxInRate = GetLogFactor (pDlp->fInputFrameRate, fMaxFrameRate); - int32_t iNotCodedMask = 0; - int8_t iMaxTemporalId = 0; + while (i < iSpatialLayerNum) { + const uint32_t kuiLogFactorInOutRate = GetLogFactor (pDlp->fOutputFrameRate, pDlp->fInputFrameRate); + const uint32_t kuiLogFactorMaxInRate = GetLogFactor (pDlp->fInputFrameRate, fMaxFrameRate); + int32_t iNotCodedMask = 0; + int8_t iMaxTemporalId = 0; - memset (pDlp->uiCodingIdx2TemporalId, INVALID_TEMPORAL_ID, sizeof (pDlp->uiCodingIdx2TemporalId)); - pSpatialLayer->uiProfileIdc = uiProfileIdc; // PRO_BASELINE, PRO_SCALABLE_BASELINE; + memset (pDlp->uiCodingIdx2TemporalId, INVALID_TEMPORAL_ID, sizeof (pDlp->uiCodingIdx2TemporalId)); + pSpatialLayer->uiProfileIdc = uiProfileIdc; // PRO_BASELINE, PRO_SCALABLE_BASELINE; - iNotCodedMask = (1 << (kuiLogFactorInOutRate + kuiLogFactorMaxInRate)) - 1; - for (uint32_t uiFrameIdx = 0; uiFrameIdx <= uiGopSize; ++ uiFrameIdx) { - if (0 == (uiFrameIdx & iNotCodedMask)) { - const int8_t kiTemporalId = pTemporalIdList[uiFrameIdx]; - pDlp->uiCodingIdx2TemporalId[uiFrameIdx] = kiTemporalId; - if (kiTemporalId > iMaxTemporalId) { - iMaxTemporalId = kiTemporalId; + iNotCodedMask = (1 << (kuiLogFactorInOutRate + kuiLogFactorMaxInRate)) - 1; + for (uint32_t uiFrameIdx = 0; uiFrameIdx <= uiGopSize; ++ uiFrameIdx) { + if (0 == (uiFrameIdx & iNotCodedMask)) { + const int8_t kiTemporalId = pTemporalIdList[uiFrameIdx]; + pDlp->uiCodingIdx2TemporalId[uiFrameIdx] = kiTemporalId; + if (kiTemporalId > iMaxTemporalId) { + iMaxTemporalId = kiTemporalId; + } } } + + pDlp->iHighestTemporalId = iMaxTemporalId; + pDlp->iTemporalResolution = kuiLogFactorMaxInRate + kuiLogFactorInOutRate; + pDlp->iDecompositionStages = iDecStages - kuiLogFactorMaxInRate - kuiLogFactorInOutRate; + + uiProfileIdc = PRO_SCALABLE_BASELINE; + ++ pDlp; + ++ pSpatialLayer; + ++ i; } - - pDlp->iHighestTemporalId = iMaxTemporalId; - pDlp->iTemporalResolution = kuiLogFactorMaxInRate + kuiLogFactorInOutRate; - pDlp->iDecompositionStages = iDecStages - kuiLogFactorMaxInRate - kuiLogFactorInOutRate; - - uiProfileIdc = PRO_SCALABLE_BASELINE; - ++ pDlp; - ++ pSpatialLayer; - ++ i; + iDecompStages = (int8_t)iDecStages; } - iDecompStages = (int8_t)iDecStages; -} } SWelsSvcCodingParam; static inline int32_t FreeCodingParam (SWelsSvcCodingParam** pParam, CMemoryAlign* pMa) { -if (pParam == NULL || *pParam == NULL || pMa == NULL) - return 1; -pMa->WelsFree (*pParam, "SWelsSvcCodingParam"); -*pParam = NULL; -return 0; + if (pParam == NULL || *pParam == NULL || pMa == NULL) + return 1; + pMa->WelsFree (*pParam, "SWelsSvcCodingParam"); + *pParam = NULL; + return 0; } static inline int32_t AllocCodingParam (SWelsSvcCodingParam** pParam, CMemoryAlign* pMa) { -if (pParam == NULL || pMa == NULL) - return 1; -if (*pParam != NULL) { - FreeCodingParam (pParam, pMa); -} -SWelsSvcCodingParam* pCodingParam = (SWelsSvcCodingParam*)pMa->WelsMalloc (sizeof (SWelsSvcCodingParam), - "SWelsSvcCodingParam"); -if (NULL == pCodingParam) - return 1; -*pParam = pCodingParam; -return 0; + if (pParam == NULL || pMa == NULL) + return 1; + if (*pParam != NULL) { + FreeCodingParam (pParam, pMa); + } + SWelsSvcCodingParam* pCodingParam = (SWelsSvcCodingParam*)pMa->WelsMalloc (sizeof (SWelsSvcCodingParam), + "SWelsSvcCodingParam"); + if (NULL == pCodingParam) + return 1; + *pParam = pCodingParam; + return 0; } }//end of namespace WelsEnc diff --git a/codec/encoder/plus/src/welsEncoderExt.cpp b/codec/encoder/plus/src/welsEncoderExt.cpp index f2f8cc6e..8f5758c8 100644 --- a/codec/encoder/plus/src/welsEncoderExt.cpp +++ b/codec/encoder/plus/src/welsEncoderExt.cpp @@ -912,7 +912,7 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) { break; case ENCODER_OPTION_IS_LOSSLESS_LINK: { bool bValue = * (static_cast(pOption)); - m_pEncContext->pSvcParam->bIsLossLessLink = bValue; + m_pEncContext->pSvcParam->bIsLosslessLink = bValue; } break; default: