void RcCalculateGomQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iSliceId) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[iSliceId]; double dBitsRatio = 1.0; int32_t iLeftBits = pSOverRc->iTargetBitsSlice - pSOverRc->iFrameBitsSlice; int32_t iTargetLeftBits = iLeftBits + pSOverRc->iGomBitsSlice - pSOverRc->iGomTargetBits; if (iLeftBits <= 0) { pSOverRc->iCalculatedQpSlice += 2; } else { //globe decision dBitsRatio = iLeftBits / (iTargetLeftBits + 0.1); if (dBitsRatio < 0.8409) //2^(-1.5/6) pSOverRc->iCalculatedQpSlice += 2; else if (dBitsRatio < 0.9439) //2^(-0.5/6) pSOverRc->iCalculatedQpSlice += 1; else if (dBitsRatio > 1.06) //2^(0.5/6) pSOverRc->iCalculatedQpSlice -= 1; else if (dBitsRatio > 1.19) //2^(1.5/6) pSOverRc->iCalculatedQpSlice -= 2; } pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pEncCtx->iGlobalQp - pWelsSvcRc->iQpRangeLowerInFrame, pEncCtx->iGlobalQp + pWelsSvcRc->iQpRangeUpperInFrame); if (! (pEncCtx->pSvcParam->iRCMode == RC_LOW_BW_MODE)) pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); pSOverRc->iGomBitsSlice = 0; }
void RcCalculateGomQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iSliceId) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[iSliceId]; int64_t iBitsRatio = 1; int64_t iLeftBits = pSOverRc->iTargetBitsSlice - pSOverRc->iFrameBitsSlice; int64_t iTargetLeftBits = iLeftBits + pSOverRc->iGomBitsSlice - pSOverRc->iGomTargetBits; if (iLeftBits <= 0) { pSOverRc->iCalculatedQpSlice += 2; } else { //globe decision iBitsRatio = 10000 * iLeftBits / (iTargetLeftBits + 1); if (iBitsRatio < 8409) //2^(-1.5/6)*10000 pSOverRc->iCalculatedQpSlice += 2; else if (iBitsRatio < 9439) //2^(-0.5/6)*10000 pSOverRc->iCalculatedQpSlice += 1; else if (iBitsRatio > 10600) //2^(0.5/6)*10000 pSOverRc->iCalculatedQpSlice -= 1; else if (iBitsRatio > 11900) //2^(1.5/6)*10000 pSOverRc->iCalculatedQpSlice -= 2; } pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pEncCtx->iGlobalQp - pWelsSvcRc->iQpRangeLowerInFrame, pEncCtx->iGlobalQp + pWelsSvcRc->iQpRangeUpperInFrame); if (!((pEncCtx->pSvcParam->iRCMode == RC_BITRATE_MODE) && (pEncCtx->pSvcParam->bEnableFrameSkip == false))) pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); pSOverRc->iGomBitsSlice = 0; }
void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; int32_t iTl = pEncCtx->uiTemporalId; SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[iTl]; int32_t iLumaQp = 0; if (0 == pTOverRc->iPFrameNum) { iLumaQp = pWelsSvcRc->iInitialQp; } else { double dCmplxRatio = (double)pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity / pTOverRc->iFrameCmplxMean; dCmplxRatio = WELS_CLIP3 (dCmplxRatio, 1.0 - FRAME_CMPLX_RATIO_RANGE, 1.0 + FRAME_CMPLX_RATIO_RANGE); pWelsSvcRc->dQStep = pTOverRc->dLinearCmplx * dCmplxRatio / pWelsSvcRc->iTargetBits; iLumaQp = (int32_t) (RcConvertQStep2Qp (pWelsSvcRc->dQStep) + 0.5); //limit QP int32_t iLastIdxCodecInVGop = pWelsSvcRc->iFrameCodedInVGop - 1; if (iLastIdxCodecInVGop < 0) iLastIdxCodecInVGop += VGOP_SIZE; int32_t iTlLast = pWelsSvcRc->iTlOfFrames[iLastIdxCodecInVGop]; int32_t iDeltaQpTemporal = iTl - iTlLast; if (0 == iTlLast && iTl > 0) iDeltaQpTemporal += 3; else if (0 == iTl && iTlLast > 0) iDeltaQpTemporal -= 3; iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower + iDeltaQpTemporal, pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal); } iLumaQp = WELS_CLIP3 (iLumaQp, GOM_MIN_QP_MODE, GOM_MAX_QP_MODE); pWelsSvcRc->dQStep = RcConvertQp2QStep (iLumaQp); pWelsSvcRc->iLastCalculatedQScale = iLumaQp; #ifndef _NOT_USE_AQ_FOR_TEST_ if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { iLumaQp = (int32_t)WELS_CLIP3 (iLumaQp - pEncCtx->pVaa->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); } #endif pEncCtx->iGlobalQp = iLumaQp; }
void RcCalculateIdrQp (sWelsEncCtx* pEncCtx) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; //obtain the idr qp using previous idr complexity if (pWelsSvcRc->iNumberMbFrame != pWelsSvcRc->iIntraMbCount) { pWelsSvcRc->iIntraComplexity = WELS_ROUND((double)pWelsSvcRc->iIntraComplexity * pWelsSvcRc->iNumberMbFrame / pWelsSvcRc->iIntraMbCount); } pWelsSvcRc->iInitialQp = WELS_ROUND(RcConvertQStep2Qp ((double)pWelsSvcRc->iIntraComplexity / pWelsSvcRc->iTargetBits)); pWelsSvcRc->iInitialQp = WELS_ROUND(WELS_CLIP3 (pWelsSvcRc->iInitialQp, MIN_IDR_QP, MAX_IDR_QP)); pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp; pWelsSvcRc->dQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp); pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp; }
void RcDecideTargetBits (sWelsEncCtx* pEncCtx) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[pEncCtx->uiTemporalId]; //allocate bits if (pEncCtx->eSliceType == I_SLICE) { pWelsSvcRc->iTargetBits = (int32_t) (pWelsSvcRc->dBitsPerFrame * IDR_BITRATE_RATIO); } else { pWelsSvcRc->iTargetBits = (int32_t) (pWelsSvcRc->iRemainingBits * pTOverRc->dTlayerWeight / pWelsSvcRc->dRemainingWeights); pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, pTOverRc->iMinBitsTl, pTOverRc->iMaxBitsTl); } pWelsSvcRc->dRemainingWeights -= pTOverRc->dTlayerWeight; }
void RcCalculateMbQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, const int32_t kiSliceId) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[kiSliceId]; int32_t iLumaQp = pSOverRc->iCalculatedQpSlice; #ifndef _NOT_USE_AQ_FOR_TEST_ if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { iLumaQp = (int8_t)WELS_CLIP3 (iLumaQp + pEncCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[pCurMb->iMbXY], pWelsSvcRc->iMinQp, 51); } #endif pCurMb->uiChromaQp = g_kuiChromaQpTable[iLumaQp]; pCurMb->uiLumaQp = iLumaQp; }
void RcInitIdrQp (sWelsEncCtx* pEncCtx) { double dBpp = 0; int32_t i; //64k@6fps for 90p: bpp 0.74 QP:24 //192k@12fps for 180p: bpp 0.28 QP:26 //512k@24fps for 360p: bpp 0.09 QP:30 //1500k@30fps for 720p: bpp 0.05 QP:32 double dBppArray[4][3] = {{0.5, 0.75, 1.0}, {0.2, 0.3, 0.4}, {0.05, 0.09, 0.13}, {0.03, 0.06, 0.1}}; int32_t dInitialQPArray[4][4] = {{28, 26, 24, 22}, {30, 28, 26, 24}, {32, 30, 28, 26}, {34, 32, 30, 28}}; int32_t iBppIndex = 0; SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SDLayerParam* pDLayerParam = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; if (pDLayerParam->fOutputFrameRate > EPSN && pDLayerParam->iFrameWidth && pDLayerParam->iFrameHeight) dBpp = (double) (pDLayerParam->iSpatialBitrate) / (double) (pDLayerParam->fOutputFrameRate * pDLayerParam->iFrameWidth * pDLayerParam->iFrameHeight); else dBpp = 0.1; //Area*2 if (pDLayerParam->iFrameWidth * pDLayerParam->iFrameHeight <= 28800) // 90p video:160*90 iBppIndex = 0; else if (pDLayerParam->iFrameWidth * pDLayerParam->iFrameHeight <= 115200) // 180p video:320*180 iBppIndex = 1; else if (pDLayerParam->iFrameWidth * pDLayerParam->iFrameHeight <= 460800) // 360p video:640*360 iBppIndex = 2; else iBppIndex = 3; //Search for (i = 0; i < 3; i++) { if (dBpp <= dBppArray[iBppIndex][i]) break; } pWelsSvcRc->iInitialQp = dInitialQPArray[iBppIndex][i]; pWelsSvcRc->iInitialQp = WELS_CLIP3 (pWelsSvcRc->iInitialQp, MIN_IDR_QP, MAX_IDR_QP); pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp; pWelsSvcRc->dQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp); pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp; }
void RcDecideTargetBits (sWelsEncCtx* pEncCtx) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[pEncCtx->uiTemporalId]; pWelsSvcRc->iCurrentBitsLevel = BITS_NORMAL; //allocate bits if (pEncCtx->eSliceType == I_SLICE) { pWelsSvcRc->iTargetBits = WELS_ROUND(pWelsSvcRc->dBitsPerFrame * IDR_BITRATE_RATIO); } else { pWelsSvcRc->iTargetBits = WELS_ROUND(pWelsSvcRc->iRemainingBits * pTOverRc->dTlayerWeight / pWelsSvcRc->dRemainingWeights); if ((pWelsSvcRc->iTargetBits <= 0) && (pEncCtx->pSvcParam->iRCMode == RC_LOW_BW_MODE)) { pWelsSvcRc->iCurrentBitsLevel = BITS_EXCEEDED; } else if ((pWelsSvcRc->iTargetBits <= pTOverRc->iMinBitsTl) && (pEncCtx->pSvcParam->iRCMode == RC_LOW_BW_MODE)) { pWelsSvcRc->iCurrentBitsLevel = BITS_LIMITED; } pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, pTOverRc->iMinBitsTl, pTOverRc->iMaxBitsTl); } pWelsSvcRc->dRemainingWeights -= pTOverRc->dTlayerWeight; }
void RcDecideTargetBits (sWelsEncCtx* pEncCtx) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[pEncCtx->uiTemporalId]; pWelsSvcRc->iCurrentBitsLevel = BITS_NORMAL; //allocate bits if (pEncCtx->eSliceType == I_SLICE) { pWelsSvcRc->iTargetBits = WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame * IDR_BITRATE_RATIO, INT_MULTIPLY); } else { if (pWelsSvcRc->iRemainingWeights > pTOverRc->iTlayerWeight) pWelsSvcRc->iTargetBits = (int32_t) ((int64_t)pWelsSvcRc->iRemainingBits * pTOverRc->iTlayerWeight / pWelsSvcRc->iRemainingWeights); else //this case should be not hit. needs to more test case to verify this pWelsSvcRc->iTargetBits = pWelsSvcRc->iRemainingBits; if ((pWelsSvcRc->iTargetBits <= 0) && ((pEncCtx->pSvcParam->iRCMode == RC_BITRATE_MODE) && (pEncCtx->pSvcParam->bEnableFrameSkip == false))) { pWelsSvcRc->iCurrentBitsLevel = BITS_EXCEEDED; } pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, pTOverRc->iMinBitsTl, pTOverRc->iMaxBitsTl); } pWelsSvcRc->iRemainingWeights -= pTOverRc->iTlayerWeight; }
//start the encoder bool edk::codecs::EncoderH264::startEncoder(edk::size2ui32 size, edk::uint32 fps){ if(edk::codecs::EncoderVideo::startEncoder(size, fps)){ //start the encoder #ifdef EDK_USE_OPENH264 if(!WelsCreateSVCEncoder(&this->encoder)){ if(this->encoder){ // //start the parameters this->param.iUsageType = CAMERA_VIDEO_REAL_TIME; this->param.iPicWidth = size.width; this->param.iPicHeight = size.height; this->param.iTargetBitrate = rand() + 1; // !=0 // Force a bitrate of at least w*h/50, otherwise we will only get skipped frames this->param.iTargetBitrate = WELS_CLIP3 (this->param.iTargetBitrate, this->param.iPicWidth * this->param.iPicHeight / 50, 100000000); int32_t iLevelMaxBitrate = WelsCommon::g_ksLevelLimits[LEVEL_5_0 - 1].uiMaxBR * CpbBrNalFactor; if (this->param.iTargetBitrate > iLevelMaxBitrate) this->param.iTargetBitrate = iLevelMaxBitrate; this->param.iRCMode = RC_BITRATE_MODE; //use the FPS this->param.fMaxFrameRate = fps; //!=0 //start the encoder if(!encoder->Initialize(¶m)){ this->setNextkeyframe(); return true; } } } #else edk_printDebug("You must define EDK_USE_OPENH264 before use"); #endif //finish encoder edk::codecs::EncoderVideo::finishEncoder(); } return false; }
void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; int32_t iTl = pEncCtx->uiTemporalId; SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[iTl]; int32_t iLumaQp = 0; if (0 == pTOverRc->iPFrameNum) { iLumaQp = pWelsSvcRc->iInitialQp; } else if (pWelsSvcRc->iCurrentBitsLevel == BITS_EXCEEDED) { iLumaQp = MAX_LOW_BR_QP; //limit QP int32_t iLastIdxCodecInVGop = pWelsSvcRc->iFrameCodedInVGop - 1; if (iLastIdxCodecInVGop < 0) iLastIdxCodecInVGop += VGOP_SIZE; int32_t iTlLast = pWelsSvcRc->iTlOfFrames[iLastIdxCodecInVGop]; int32_t iDeltaQpTemporal = iTl - iTlLast; if (0 == iTlLast && iTl > 0) iDeltaQpTemporal += 3; else if (0 == iTl && iTlLast > 0) iDeltaQpTemporal -= 3; iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower + iDeltaQpTemporal, pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal); iLumaQp = WELS_CLIP3 (iLumaQp, GOM_MIN_QP_MODE, MAX_LOW_BR_QP); pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp); pWelsSvcRc->iLastCalculatedQScale = iLumaQp; if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { iLumaQp = WELS_CLIP3 ((iLumaQp * INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp) / INT_MULTIPLY, GOM_MIN_QP_MODE, MAX_LOW_BR_QP); } pEncCtx->iGlobalQp = iLumaQp; return; } else { int64_t iCmplxRatio = WELS_DIV_ROUND64 (pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity * INT_MULTIPLY, pTOverRc->iFrameCmplxMean); iCmplxRatio = WELS_CLIP3 (iCmplxRatio, INT_MULTIPLY - FRAME_CMPLX_RATIO_RANGE, INT_MULTIPLY + FRAME_CMPLX_RATIO_RANGE); pWelsSvcRc->iQStep = WELS_DIV_ROUND ((pTOverRc->iLinearCmplx * iCmplxRatio), (pWelsSvcRc->iTargetBits * INT_MULTIPLY)); iLumaQp = RcConvertQStep2Qp (pWelsSvcRc->iQStep); //limit QP int32_t iLastIdxCodecInVGop = pWelsSvcRc->iFrameCodedInVGop - 1; if (iLastIdxCodecInVGop < 0) iLastIdxCodecInVGop += VGOP_SIZE; int32_t iTlLast = pWelsSvcRc->iTlOfFrames[iLastIdxCodecInVGop]; int32_t iDeltaQpTemporal = iTl - iTlLast; if (0 == iTlLast && iTl > 0) iDeltaQpTemporal += 3; else if (0 == iTl && iTlLast > 0) iDeltaQpTemporal -= 3; iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower + iDeltaQpTemporal, pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal); } iLumaQp = WELS_CLIP3 (iLumaQp, GOM_MIN_QP_MODE, GOM_MAX_QP_MODE); pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp); pWelsSvcRc->iLastCalculatedQScale = iLumaQp; #ifndef _NOT_USE_AQ_FOR_TEST_ if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { iLumaQp = WELS_DIV_ROUND (iLumaQp * INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp, INT_MULTIPLY); if (pEncCtx->pSvcParam->iRCMode != RC_LOW_BW_MODE) iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); } #endif pEncCtx->iGlobalQp = iLumaQp; }
/* * Set Option */ long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) { int iVal = 0; if (m_pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL && eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT) return dsInitialOptExpected; if (eOptID == DECODER_OPTION_DATAFORMAT) { // Set color space of decoding output frame if (m_pDecContext->pParam->bParseOnly) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "CWelsDecoder::SetOption for data format meaningless for parseonly."); return cmResultSuccess; } if (pOption == NULL) return cmInitParaError; iVal = * ((int*)pOption); // is_rgb return DecoderSetCsp (m_pDecContext, iVal); } else if (eOptID == DECODER_OPTION_END_OF_STREAM) { // Indicate bit-stream of the final frame to be decoded if (pOption == NULL) return cmInitParaError; iVal = * ((int*)pOption); // boolean value for whether enabled End Of Stream flag m_pDecContext->bEndOfStreamFlag = iVal ? true : false; return cmResultSuccess; } else if (eOptID == DECODER_OPTION_ERROR_CON_IDC) { // Indicate error concealment status if (pOption == NULL) return cmInitParaError; iVal = * ((int*)pOption); // int value for error concealment idc iVal = WELS_CLIP3 (iVal, (int32_t) ERROR_CON_DISABLE, (int32_t) ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE); m_pDecContext->pParam->eEcActiveIdc = m_pDecContext->eErrorConMethod = (ERROR_CON_IDC) iVal; if ((m_pDecContext->pParam->bParseOnly) && (m_pDecContext->eErrorConMethod != ERROR_CON_DISABLE)) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal); return cmInitParaError; } InitErrorCon (m_pDecContext); WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::SetOption for ERROR_CON_IDC = %d.", iVal); return cmResultSuccess; } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) { if (m_pWelsTrace) { uint32_t level = * ((uint32_t*)pOption); m_pWelsTrace->SetTraceLevel (level); } return cmResultSuccess; } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) { if (m_pWelsTrace) { WelsTraceCallback callback = * ((WelsTraceCallback*)pOption); m_pWelsTrace->SetTraceCallback (callback); WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::SetOption(), openh264 codec version = %s.", VERSION_NUMBER); } return cmResultSuccess; } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) { if (m_pWelsTrace) { void* ctx = * ((void**)pOption); m_pWelsTrace->SetTraceCallbackContext (ctx); } return cmResultSuccess; } else if (eOptID == DECODER_OPTION_GET_STATISTICS) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!"); return cmInitParaError; } return cmInitParaError; }
/* * Set Option */ long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) { int iVal = 0; if (m_pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL && eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT) return dsInitialOptExpected; if (eOptID == DECODER_OPTION_END_OF_STREAM) { // Indicate bit-stream of the final frame to be decoded if (pOption == NULL) return cmInitParaError; iVal = * ((int*)pOption); // boolean value for whether enabled End Of Stream flag m_pDecContext->bEndOfStreamFlag = iVal ? true : false; return cmResultSuccess; } else if (eOptID == DECODER_OPTION_ERROR_CON_IDC) { // Indicate error concealment status if (pOption == NULL) return cmInitParaError; iVal = * ((int*)pOption); // int value for error concealment idc iVal = WELS_CLIP3 (iVal, (int32_t) ERROR_CON_DISABLE, (int32_t) ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE); if ((m_pDecContext->pParam->bParseOnly) && (iVal != (int32_t) ERROR_CON_DISABLE)) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal); return cmInitParaError; } m_pDecContext->pParam->eEcActiveIdc = (ERROR_CON_IDC) iVal; InitErrorCon (m_pDecContext); WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::SetOption for ERROR_CON_IDC = %d.", iVal); return cmResultSuccess; } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) { if (m_pWelsTrace) { uint32_t level = * ((uint32_t*)pOption); m_pWelsTrace->SetTraceLevel (level); } return cmResultSuccess; } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) { if (m_pWelsTrace) { WelsTraceCallback callback = * ((WelsTraceCallback*)pOption); m_pWelsTrace->SetTraceCallback (callback); WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::SetOption():DECODER_OPTION_TRACE_CALLBACK callback = %p.", callback); } return cmResultSuccess; } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) { if (m_pWelsTrace) { void* ctx = * ((void**)pOption); m_pWelsTrace->SetTraceCallbackContext (ctx); } return cmResultSuccess; } else if (eOptID == DECODER_OPTION_GET_STATISTICS) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!"); return cmInitParaError; } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) { if (pOption) { m_pDecContext->sDecoderStatistics.iStatisticsLogInterval = (* ((unsigned int*)pOption)); return cmResultSuccess; } } else if (eOptID == DECODER_OPTION_GET_SAR_INFO) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "CWelsDecoder::SetOption():DECODER_OPTION_GET_SAR_INFO: this option is get-only!"); return cmInitParaError; } return cmInitParaError; }
int CWelsH264SVCEncoder::InitializeInternal(SWelsSvcCodingParam* pCfg) { if (NULL == pCfg) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p.\n", pCfg); return cmInitParaError; } if (m_bInitialFlag) { WelsLog (m_pEncContext, WELS_LOG_WARNING, "CWelsH264SVCEncoder::Initialize(), reinitialize, m_bInitialFlag= %d.\n", m_bInitialFlag); Uninitialize(); } #ifdef REC_FRAME_COUNT SWelsSvcCodingParam &sEncodingParam = *pCfg; WelsLog (m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Initialize, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal); WelsLog (m_pEncContext, WELS_LOG_INFO, "coding_param->iPicWidth= %d;coding_param->iPicHeight= %d;coding_param->iTargetBitrate= %d;coding_param->iRCMode= %d;coding_param->iTemporalLayerNum= %d;coding_param->iSpatialLayerNum= %d;coding_param->fFrameRate= %.6ff;coding_param->iInputCsp= %d;coding_param->uiIntraPeriod= %d;coding_param->bEnableSpsPpsIdAddition = %d;coding_param->bPrefixNalAddingCtrl = %d;coding_param->bEnableDenoise= %d;coding_param->bEnableBackgroundDetection= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableFrameSkip= %d;coding_param->bEnableCropPic= %d;coding_param->bEnableLongTermReference= %d;coding_param->iLtrMarkPeriod= %d;\n", sEncodingParam.iPicWidth, sEncodingParam.iPicHeight, sEncodingParam.iTargetBitrate, sEncodingParam.iRCMode, sEncodingParam.iTemporalLayerNum, sEncodingParam.iSpatialLayerNum, sEncodingParam.fMaxFrameRate, sEncodingParam.iInputCsp, sEncodingParam.uiIntraPeriod, sEncodingParam.bEnableSpsPpsIdAddition, sEncodingParam.bPrefixNalAddingCtrl, sEncodingParam.bEnableDenoise, sEncodingParam.bEnableBackgroundDetection, sEncodingParam.bEnableAdaptiveQuant, sEncodingParam.bEnableFrameSkip, sEncodingParam.bEnableCropPic, sEncodingParam.bEnableLongTermReference, sEncodingParam.iLtrMarkPeriod); int32_t i = 0; while (i < sEncodingParam.iSpatialLayerNum) { SSpatialLayerConfig* spatial_cfg = &sEncodingParam.sSpatialLayers[i]; WelsLog (m_pEncContext, WELS_LOG_INFO, "coding_param->sSpatialLayers[%d]: .iVideoWidth= %d; .iVideoHeight= %d; .fFrameRate= %.6ff; .iSpatialBitrate= %d; .sSliceCfg.uiSliceMode= %d; .sSliceCfg.sSliceArgument.uiSliceNum= %d; .sSliceCfg.sSliceArgument.uiSliceSizeConstraint= %d;\n", i, spatial_cfg->iVideoWidth, spatial_cfg->iVideoHeight, spatial_cfg->fFrameRate, spatial_cfg->iSpatialBitrate, spatial_cfg->sSliceCfg.uiSliceMode, spatial_cfg->sSliceCfg.sSliceArgument.uiSliceNum, spatial_cfg->sSliceCfg.sSliceArgument.uiSliceSizeConstraint ); ++ i; } #endif//REC_FRAME_COUNT const int32_t iColorspace = pCfg->iInputCsp; if (videoFormatI420 != iColorspace) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInputCsp= %d.\n", iColorspace); Uninitialize(); return cmInitParaError; } // Check valid parameters const int32_t iNumOfLayers = pCfg->iSpatialLayerNum; if (iNumOfLayers < 1 || iNumOfLayers > MAX_DEPENDENCY_LAYER) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iSpatialLayerNum= %d, valid at range of [1, %d].\n", iNumOfLayers, MAX_DEPENDENCY_LAYER); Uninitialize(); return cmInitParaError; } if (pCfg->iTemporalLayerNum < 1) pCfg->iTemporalLayerNum = 1; if (pCfg->iTemporalLayerNum > MAX_TEMPORAL_LEVEL) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iTemporalLayerNum= %d, valid at range of [1, %d].\n", pCfg->iTemporalLayerNum, MAX_TEMPORAL_LEVEL); Uninitialize(); return cmInitParaError; } // assert( cfg.uiGopSize >= 1 && ( cfg.uiIntraPeriod && (cfg.uiIntraPeriod % cfg.uiGopSize) == 0) ); if (pCfg->uiGopSize < 1 || pCfg->uiGopSize > MAX_GOP_SIZE) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid uiGopSize= %d, valid at range of [1, %d].\n", pCfg->uiGopSize, MAX_GOP_SIZE); Uninitialize(); return cmInitParaError; } if (!WELS_POWER2_IF (pCfg->uiGopSize)) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid uiGopSize= %d, valid at range of [1, %d] and yield to power of 2.\n", pCfg->uiGopSize, MAX_GOP_SIZE); Uninitialize(); return cmInitParaError; } if (pCfg->uiIntraPeriod && pCfg->uiIntraPeriod < pCfg->uiGopSize) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid uiIntraPeriod= %d, valid in case it equals to 0 for unlimited intra period or exceeds specified uiGopSize= %d.\n", pCfg->uiIntraPeriod, pCfg->uiGopSize); Uninitialize(); return cmInitParaError; } if ((pCfg->uiIntraPeriod && (pCfg->uiIntraPeriod & (pCfg->uiGopSize - 1)) != 0)) { WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid uiIntraPeriod= %d, valid in case it equals to 0 for unlimited intra period or exceeds specified uiGopSize= %d also multiple of it.\n", pCfg->uiIntraPeriod, pCfg->uiGopSize); Uninitialize(); return cmInitParaError; } if (pCfg->iUsageType == SCREEN_CONTENT_REAL_TIME) { if (pCfg->bEnableLongTermReference) { pCfg->iLTRRefNum = WELS_CLIP3(pCfg->iLTRRefNum,1,LONG_TERM_REF_NUM_SCREEN); pCfg->iNumRefFrame = WELS_MAX(1,WELS_LOG2 (pCfg->uiGopSize)) + pCfg->iLTRRefNum; } else { pCfg->iLTRRefNum = 0; pCfg->iNumRefFrame = WELS_MAX(1, pCfg->uiGopSize>>1); } } else {
WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid uiIntraPeriod= %d, valid in case it equals to 0 for unlimited intra period or exceeds specified uiGopSize= %d also multiple of it.\n", pCfg->uiIntraPeriod, pCfg->uiGopSize); Uninitialize(); return cmInitParaError; } if (pCfg->iUsageType == SCREEN_CONTENT_REAL_TIME) { if (pCfg->bEnableLongTermReference) { pCfg->iLTRRefNum = WELS_CLIP3(pCfg->iLTRRefNum,1,LONG_TERM_REF_NUM_SCREEN); pCfg->iNumRefFrame = WELS_MAX(1,WELS_LOG2 (pCfg->uiGopSize)) + pCfg->iLTRRefNum; } else { pCfg->iLTRRefNum = 0; pCfg->iNumRefFrame = WELS_MAX(1, pCfg->uiGopSize>>1); } } else { pCfg->iLTRRefNum = pCfg->bEnableLongTermReference ? WELS_CLIP3(pCfg->iLTRRefNum,1,LONG_TERM_REF_NUM) : 0; pCfg->iNumRefFrame = ((pCfg->uiGopSize >> 1) > 1) ? ((pCfg->uiGopSize >> 1) + pCfg->iLTRRefNum) : (MIN_REF_PIC_COUNT + pCfg->iLTRRefNum); pCfg->iNumRefFrame = WELS_CLIP3 (pCfg->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM); } if (pCfg->iLtrMarkPeriod == 0) { pCfg->iLtrMarkPeriod = 30; } const int32_t kiDecStages = WELS_LOG2 (pCfg->uiGopSize); pCfg->iInputCsp = iColorspace; pCfg->iTemporalLayerNum = (int8_t) (1 + kiDecStages); pCfg->iLoopFilterAlphaC0Offset = WELS_CLIP3 (pCfg->iLoopFilterAlphaC0Offset, -6, 6); pCfg->iLoopFilterBetaOffset = WELS_CLIP3 (pCfg->iLoopFilterBetaOffset, -6, 6);
pCfg->uiIntraPeriod, pCfg->uiGopSize); Uninitialize(); return cmInitParaError; } if (pCfg->iUsageType == SCREEN_CONTENT_REAL_TIME) { if (pCfg->bEnableLongTermReference) { pCfg->iLTRRefNum = WELS_CLIP3 (pCfg->iLTRRefNum, 1, LONG_TERM_REF_NUM_SCREEN); if(pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT) pCfg->iNumRefFrame = WELS_MAX (1, WELS_LOG2 (pCfg->uiGopSize)) + pCfg->iLTRRefNum; } else { pCfg->iLTRRefNum = 0; if(pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT) pCfg->iNumRefFrame = WELS_MAX (1, pCfg->uiGopSize >> 1); } } else { pCfg->iLTRRefNum = pCfg->bEnableLongTermReference ? WELS_CLIP3 (pCfg->iLTRRefNum, 1, LONG_TERM_REF_NUM) : 0; if(pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT){ pCfg->iNumRefFrame = ((pCfg->uiGopSize >> 1) > 1) ? ((pCfg->uiGopSize >> 1) + pCfg->iLTRRefNum) : (MIN_REF_PIC_COUNT + pCfg->iLTRRefNum); pCfg->iNumRefFrame = WELS_CLIP3 (pCfg->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM); } } if (pCfg->iLtrMarkPeriod == 0) { pCfg->iLtrMarkPeriod = 30; } const int32_t kiDecStages = WELS_LOG2 (pCfg->uiGopSize); pCfg->iInputCsp = iColorspace; pCfg->iTemporalLayerNum = (int8_t) (1 + kiDecStages); pCfg->iLoopFilterAlphaC0Offset = WELS_CLIP3 (pCfg->iLoopFilterAlphaC0Offset, -6, 6);