add reading of the new option

This commit is contained in:
Sijia Chen 2014-09-23 18:04:24 +08:00
parent cfbf32b3fb
commit 147c9052b8
3 changed files with 378 additions and 372 deletions

View File

@ -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) {

View File

@ -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 (&param, 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 (&param, 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

View File

@ -912,7 +912,7 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
break;
case ENCODER_OPTION_IS_LOSSLESS_LINK: {
bool bValue = * (static_cast<bool*>(pOption));
m_pEncContext->pSvcParam->bIsLossLessLink = bValue;
m_pEncContext->pSvcParam->bIsLosslessLink = bValue;
}
break;
default: