📄 h263_enc_misc.cpp
字号:
mBPicsearchHorBack = par->BPicsearchWidthBack;
mBPicsearchVerBack = par->BPicsearchHeightBack;
// calc pic_fcode_forward for BPics
i = IPP_MAX(mBPicsearchHorForw, mBPicsearchVerForw);
j = i << 1;
mBPicfcodeForw = 1;
while (j > ((16 << mBPicfcodeForw) - 1))
mBPicfcodeForw ++;
// calc pic_fcode_backward for BPics
i = IPP_MAX(mBPicsearchHorBack, mBPicsearchHorBack);
j = i << 1;
mBPicfcodeBack = 1;
while (j > ((16 << mBPicfcodeBack) - 1))
mBPicfcodeBack ++;
}
#endif
mPlanes = (mIPicdist == 1) ? 1 : (mBPicdist == 0) ? 2 : 2 + mBPicdist + 1;
mSourceWidth = par->Width;
mSourceHeight = par->Height;
mSourceFormat = YUV_CHROMA_420;
mExpandSize = 16;
mExpandSizeA = (mExpandSize + 15) & (~15);
mNumMacroBlockPerRow = (mSourceWidth + 15) / 16;
mNumMacroBlockPerCol = (mSourceHeight + 15) / 16;
mNumMacroBlockPerPic = mNumMacroBlockPerRow * mNumMacroBlockPerCol;
mStepLuma = mExpandSizeA * 2 + mNumMacroBlockPerRow * 16;
mLumaPlaneSize = mStepLuma * (mExpandSizeA * 2 + mNumMacroBlockPerCol * 16);
mStepChroma = (mExpandSizeA / 2) * 2 + mNumMacroBlockPerRow * 8;
mChromaPlaneSize = mStepChroma * ((mExpandSizeA / 2) * 2 + mNumMacroBlockPerCol * 8);
mSceneChangeThreshold = (mNumMacroBlockPerPic * par->SceneChangeThreshold + 50) / 100;
mIsInit = true;
// buffers allocation
mFrame = new h263e_Frame[mPlanes];
if (!mFrame)
stsAlloc = ippStsMemAllocErr;
mRTPdata.MBpos = ippsMalloc_32u(mNumMacroBlockPerPic);
mRTPdata.MBquant = ippsMalloc_8u(mNumMacroBlockPerPic);
mRTPdata.MBpredMV = (IppMotionVector*)ippsMalloc_8u(mNumMacroBlockPerPic * sizeof(IppMotionVector));
if (mVideoPicture.advPred) {
mRTPdata.MBpredMV1 = (IppMotionVector*)ippsMalloc_8u(mNumMacroBlockPerPic * sizeof(IppMotionVector));
if (!mRTPdata.MBpredMV1)
stsAlloc = ippStsMemAllocErr;
} else
mRTPdata.MBpredMV1 = NULL;
mRTPdata.GOBstartPos = ippsMalloc_32u(mVideoPicture.num_gobs_in_pic);
if (!mRTPdata.MBpos || !mRTPdata.MBquant || !mRTPdata.MBpredMV || !mRTPdata.GOBstartPos)
stsAlloc = ippStsMemAllocErr;
mRTPdata.codingModes = 0; // forbidden src format 000 to be returned if plusptype is present
// init bitstream buffer
if (par->bsBuffer && (par->bsBuffSize > 0)) {
cBS.mBuffer = par->bsBuffer;
cBS.mBuffSize = par->bsBuffSize;
mbsAlloc = false;
} else {
cBS.mBuffSize = mSourceWidth * mSourceHeight;
cBS.mBuffer = ippsMalloc_8u(cBS.mBuffSize);
if (!cBS.mBuffer)
stsAlloc = ippStsMemAllocErr;
mbsAlloc = true;
}
cBS.mPtr = cBS.mBuffer;
if (mVideoSequence.data_partitioned) {
mBuffer_1 = ippsMalloc_8u(mSourceWidth * mSourceHeight >> 1);
mBuffer_2 = ippsMalloc_8u(mSourceWidth * mSourceHeight >> 1);
if (!mBuffer_1 || !mBuffer_2)
stsAlloc = ippStsMemAllocErr;
} else {
mBuffer_1 = mBuffer_2 = NULL;
}
mMBinfo = new h263e_MacroBlock[mNumMacroBlockPerPic];
// mMEfastSADsize = (IPP_MAX(IPP_MAX(mPPicsearchHor, mBPicsearchHorForw), mBPicsearchHorBack) * 2 + 1) * (IPP_MAX(IPP_MAX(mPPicsearchVer, mBPicsearchVerForw), mBPicsearchVerBack) * 2 + 1);
mMEfastSADsize = (mPPicsearchHor * 2 + 1) * (mPPicsearchVer * 2 + 1);
mMEfastSAD = ippsMalloc_32s(mMEfastSADsize);
if (!mMBinfo || !mMEfastSAD)
stsAlloc = ippStsMemAllocErr;
if (stsAlloc != ippStsNoErr) {
Close();
ErrorMessage(VM_STRING("Not enough memory"));
return H263_STS_ERR_NOMEM;
}
{
h263e_MacroBlock *mbCurr = mMBinfo;
for (i = 0; i < mNumMacroBlockPerCol; i ++) {
for (j = 0; j < mNumMacroBlockPerRow; j ++) {
h263e_MacroBlock *mbA = mbCurr - 1;
h263e_MacroBlock *mbC = mbCurr - mNumMacroBlockPerRow;
mbCurr->block[0].predA = &mbA->block[1];
mbCurr->block[0].predC = &mbC->block[2];
mbCurr->block[1].predA = &mbCurr->block[0];
mbCurr->block[1].predC = &mbC->block[3];
mbCurr->block[2].predA = &mbA->block[3];
mbCurr->block[2].predC = &mbCurr->block[0];
mbCurr->block[3].predA = &mbCurr->block[2];
mbCurr->block[3].predC = &mbCurr->block[1];
mbCurr->block[4].predA = &mbA->block[4];
mbCurr->block[4].predC = &mbC->block[4];
mbCurr->block[5].predA = &mbA->block[5];
mbCurr->block[5].predC = &mbC->block[5];
mbCurr++;
}
}
for (j = 0; j < mNumMacroBlockPerRow; j ++) {
h263e_MacroBlock *mbCurr = &mMBinfo[j];
mbCurr->block[0].predC = NULL;
mbCurr->block[1].predC = NULL;
mbCurr->block[4].predC = NULL;
mbCurr->block[5].predC = NULL;
}
for (i = 0; i < mNumMacroBlockPerCol; i ++) {
h263e_MacroBlock *mbCurr = &mMBinfo[i*mNumMacroBlockPerRow];
mbCurr->block[0].predA = NULL;
mbCurr->block[2].predA = NULL;
mbCurr->block[4].predA = NULL;
mbCurr->block[5].predA = NULL;
}
}
// setup frames
if (mBPicdist == 0) {
mFrameC = &mFrame[0];
if (mIPicdist > 1)
mFrameF = &mFrame[1];
} else {
mFrameC = &mFrame[0];
mFrameF = &mFrame[1];
mFrameB = &mFrame[0];
mIndxBPic = 2;
mNumBPic = 0;
}
mPictime = mSyncTime = mSyncTimeB = 0;
return H263_STS_NOERR;
}
//-----------------------------------------------------------------------------
void ippVideoEncoderH263::PostFrameRC()
{
Ipp64f bo, qs, dq;
int quant, coding_type;
mSkipFrame = 0;
mBitsDesiredTotal += mBitsDesiredFrame;
coding_type = mVideoPicture.picture_coding_type;
quant = (coding_type == H263e_PIC_TYPE_I) ? mQuantIPic : (coding_type == H263e_PIC_TYPE_B) ? mQuantBPic : mQuantPPic;
#ifdef PRINT_INFO
printf("%d %d %d %d %f \n", mFrameCount, coding_type, quant, mBitsEncodedFrame, mBitsEncodedTotal / (Ipp64f)mBitsDesiredTotal);
#endif
if (!mFrameSkipped) {
mRCqa += (1. / quant - mRCqa) / mRCqap;
h263e_Clip(mRCqa, 1./31. , 1./1.);
if (coding_type != H263e_PIC_TYPE_I || mIPicdist < 5) // ???
mRCfa += (mBitsEncodedFrame - mRCfa) / mRCfap;
if (coding_type == H263e_PIC_TYPE_B) {
quant = (mQuantPPic * 5 >> 2) + 1;
h263e_Clip(quant, 2, 31);
mQuantBPic = quant;
return;
}
}
qs = pow(mBitsDesiredFrame / mRCfa, 1.5);
dq = mRCqa * qs;
bo = (Ipp64f)((Ipp64s)mBitsEncodedTotal - (Ipp64s)mBitsDesiredTotal) / mRCbap / mBitsDesiredFrame;
if (mFrameSkipEnabled && bo > 1.05 && quant == 31) {
mSkipFrame = 1;
return;
}
h263e_Clip(bo, -1.0, 1.0);
//dq = dq * (1.0 - bo);
dq = dq + (1./31 - dq) * bo;
h263e_ClipL(dq, 1./31.);
if (bo > -0.05) {
h263e_ClipR(dq, 1./2.);
} else {
h263e_ClipR(dq, 1./1.);
}
quant = (int) (1. / dq + 0.5);
//h263e_Clip(quant, 2, 31);
if (quant >= mRCq + 3)
quant = mRCq + 2;
else if (quant > mRCq + 1)
quant = mRCq + 1;
else if (quant <= mRCq - 3)
quant = mRCq - 2;
else if (quant < mRCq - 1)
quant = mRCq - 1;
mRCq = mQuantIPic = mQuantPPic = quant;
}
void ippVideoEncoderH263::ErrorMessage(const vm_char *msg)
{
vm_debug_trace(VM_DEBUG_INFO, __VM_STRING("H.263 encoder error: "));
vm_debug_trace(VM_DEBUG_INFO, msg);
vm_debug_trace(VM_DEBUG_INFO, __VM_STRING("\n"));
}
static void h263e_ExpandFrameReplicate(Ipp8u *pSrcDstPlane, Ipp32s frameWidth, Ipp32s frameHeight, Ipp32s expandPels, Ipp32s step)
{
Ipp8u *pDst1, *pDst2, *pSrc1, *pSrc2;
Ipp32s i, j;
Ipp32u t1, t2;
pDst1 = pSrcDstPlane + step * expandPels;
pDst2 = pDst1 + frameWidth + expandPels;
if (expandPels == 8) {
for (i = 0; i < frameHeight; i ++) {
t1 = pDst1[8] + (pDst1[8] << 8);
t2 = pDst2[-1] + (pDst2[-1] << 8);
t1 = (t1 << 16) + t1;
t2 = (t2 << 16) + t2;
((Ipp32u*)pDst1)[0] = t1;
((Ipp32u*)pDst1)[1] = t1;
((Ipp32u*)pDst2)[0] = t2;
((Ipp32u*)pDst2)[1] = t2;
pDst1 += step;
pDst2 += step;
}
} else if (expandPels == 16) {
for (i = 0; i < frameHeight; i ++) {
t1 = pDst1[16] + (pDst1[16] << 8);
t2 = pDst2[-1] + (pDst2[-1] << 8);
t1 = (t1 << 16) + t1;
t2 = (t2 << 16) + t2;
((Ipp32u*)pDst1)[0] = t1;
((Ipp32u*)pDst1)[1] = t1;
((Ipp32u*)pDst1)[2] = t1;
((Ipp32u*)pDst1)[3] = t1;
((Ipp32u*)pDst2)[0] = t2;
((Ipp32u*)pDst2)[1] = t2;
((Ipp32u*)pDst2)[2] = t2;
((Ipp32u*)pDst2)[3] = t2;
pDst1 += step;
pDst2 += step;
}
} else {
for (i = 0; i < frameHeight; i ++) {
ippsSet_8u(pDst1[expandPels], pDst1, expandPels);
ippsSet_8u(pDst2[-1], pDst2, expandPels);
pDst1 += step;
pDst2 += step;
}
}
pDst1 = pSrcDstPlane;
pSrc1 = pSrcDstPlane + expandPels * step;
pDst2 = pSrc1 + frameHeight * step;
pSrc2 = pDst2 - step;
j = frameWidth + 2 * expandPels;
for (i = 0; i < expandPels; i ++) {
ippsCopy_8u(pSrc1, pDst1, j);
ippsCopy_8u(pSrc2, pDst2, j);
pDst1 += step;
pDst2 += step;
}
}
/*
// padding frame: replication
*/
void ippVideoEncoderH263::ExpandFrame(Ipp8u *pY, Ipp8u *pU, Ipp8u *pV)
{
if (mExpandSize) {
Ipp32s wL, hL, wC, hC, es = (mExpandSize + 1) >> 1;
wL = mNumMacroBlockPerRow * 16;
hL = mNumMacroBlockPerCol * 16;
wC = mSourceWidth >> 1;
hC = mSourceHeight >> 1;
h263e_ExpandFrameReplicate(pY-mExpandSize*mStepLuma-mExpandSize, wL, hL, mExpandSize, mStepLuma);
h263e_ExpandFrameReplicate(pU-es*mStepChroma-es, wC, hC, es, mStepChroma);
h263e_ExpandFrameReplicate(pV-es*mStepChroma-es, wC, hC, es, mStepChroma);
}
}
Ipp32s ippVideoEncoderH263::GetCurrentFrameInfo(Ipp8u **pY, Ipp8u **pU, Ipp8u **pV, Ipp32s *stepLuma, Ipp32s *stepChroma)
{
if (!mIsInit)
return H263_STS_ERR_NOTINIT;
*pY = mFrameC->pY;
*pU = mFrameC->pU;
*pV = mFrameC->pV;
*stepLuma = mStepLuma;
*stepChroma = mStepChroma;
return H263_STS_NOERR;
}
void ippVideoEncoderH263::OBMC_Macroblock(h263e_MacroBlock *pMBinfo, IppMotionVector *mvCur,
Ipp32s colNum, Ipp32s rowNum, IppiRect limitRectL,
Ipp8u *pYr, Ipp32s stepYr, Ipp8u *pYc, Ipp32s stepYc)
{
IppMotionVector mvOBMCL, mvOBMCU, mvOBMCR, mvOBMCB, *mvLeft, *mvUpper, *mvRight;
Ipp32s mbPerRow = mNumMacroBlockPerRow, dx, dy, rt;
/* get Right MV */
if (colNum == mNumMacroBlockPerRow - 1)
mvRight = &mvCur[1];
// else if ((pMBinfo[1].type & 0xC0) == 0x80) /* INTRA(_Q), no vector for B-part */
else if (pMBinfo[1].type == IPPVC_MBTYPE_INTRA || pMBinfo[1].type == IPPVC_MBTYPE_INTRA_Q)
mvRight = &mvCur[1];
else
mvRight = pMBinfo[1].mv;
/* get Left MV */
if (colNum == 0)
mvLeft = mvCur - 1;
// else if ((pMBinfo[-1].type & 0xC0) == 0x80)
else if (pMBinfo[-1].type == IPPVC_MBTYPE_INTRA || pMBinfo[1].type == IPPVC_MBTYPE_INTRA_Q)
mvLeft = mvCur - 1;
else
mvLeft = pMBinfo[-1].mv;
/* get Upper MV */
if (rowNum == 0)
mvUpper = mvCur - 2;
// else if ((pMBinfo[-mNumMacroBlockPerRow].type & 0xC0) == 0x80)
else if (pMBinfo[-mNumMacroBlockPerRow].type == IPPVC_MBTYPE_INTRA || pMBinfo[-mNumMacroBlockPerRow].type == IPPVC_MBTYPE_INTRA_Q)
mvUpper = mvCur - 2;
else
mvUpper = pMBinfo[-mNumMacroBlockPerRow].mv;
dx = colNum * 16;
dy = rowNum * 16;
rt = mVideoPicture.pic_rounding_type;
h263e_LimitMV(&mvLeft[1], &mvOBMCL, &limitRectL, dx, dy, 8);
h263e_LimitMV(&mvUpper[2], &mvOBMCU, &limitRectL, dx, dy, 8);
h263e_LimitMV(&mvCur[1], &mvOBMCR, &limitRectL, dx, dy, 8);
h263e_LimitMV(&mvCur[2], &mvOBMCB, &limitRectL, dx, dy, 8);
ippiOBMC8x8HP_MPEG4_8u_C1R(pYr, stepYr, pYc, stepYc, &mvCur[0], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvOBMCB, rt);
h263e_LimitMV(&mvCur[0], &mvOBMCL, &limitRectL, dx+8, dy, 8);
h263e_LimitMV(&mvUpper[3], &mvOBMCU, &limitRectL, dx+8, dy, 8);
h263e_LimitMV(&mvRight[0], &mvOBMCR, &limitRectL, dx+8, dy, 8);
h263e_LimitMV(&mvCur[3], &mvOBMCB, &limitRectL, dx+8, dy, 8);
ippiOBMC8x8HP_MPEG4_8u_C1R(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvOBMCB, rt);
h263e_LimitMV(&mvLeft[3], &mvOBMCL, &limitRectL, dx, dy+8, 8);
h263e_LimitMV(&mvCur[0], &mvOBMCU, &limitRectL, dx, dy+8, 8);
h263e_LimitMV(&mvCur[3], &mvOBMCR, &limitRectL, dx, dy+8, 8);
ippiOBMC8x8HP_MPEG4_8u_C1R(pYr+stepYr*8, stepYr, pYc+stepYc*8, stepYc, &mvCur[2], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvCur[2], rt);
h263e_LimitMV(&mvCur[2], &mvOBMCL, &limitRectL, dx+8, dy+8, 8);
h263e_LimitMV(&mvCur[1], &mvOBMCU, &limitRectL, dx+8, dy+8, 8);
h263e_LimitMV(&mvRight[2], &mvOBMCR, &limitRectL, dx+8, dy+8, 8);
ippiOBMC8x8HP_MPEG4_8u_C1R(pYr+8+stepYr*8, stepYr, pYc+8+stepYc*8, stepYc, &mvCur[3], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvCur[3], rt);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -