📄 h263_enc_frame.cpp
字号:
Ipp32s ippVideoEncoderH263::TransMacroBlockInter_H263(Ipp8u *pYc, Ipp8u *pUc, Ipp8u *pVc, Ipp16s *coeffMB,
Ipp32s *nzCount, Ipp32s quant, Ipp8u *mcPred, Ipp32s lumaErr)
{
Ipp32s pattern, sU, sV, sL0, sL1, sL2, sL3, lim;
lim = quant * 16;
if (lumaErr < quant * 20) {
nzCount[0] = nzCount[1] = nzCount[2] = nzCount[3] = 0;
coeffMB[0*64] = coeffMB[1*64] = coeffMB[2*64] = coeffMB[3*64] = 0;
} else {
ippiSubSAD8x8_8u16s_C1R(pYc, mStepLuma, mcPred, 16, coeffMB+0*64, 16, &sL0);
ippiSubSAD8x8_8u16s_C1R(pYc+8, mStepLuma, mcPred+8, 16, coeffMB+1*64, 16, &sL1);
ippiSubSAD8x8_8u16s_C1R(pYc+8*mStepLuma, mStepLuma, mcPred+128, 16, coeffMB+2*64, 16, &sL2);
ippiSubSAD8x8_8u16s_C1R(pYc+8*mStepLuma+8, mStepLuma, mcPred+136, 16, coeffMB+3*64, 16, &sL3);
if (sL0 < lim) {
nzCount[0] = 0;
coeffMB[0*64] = 0;
} else {
ippiDCT8x8Fwd_16s_C1I(coeffMB+0*64);
ippiQuantInter_H263_16s_C1I(coeffMB+0*64, quant, &nzCount[0], mVideoPicture.modQuant);
}
if (sL1 < lim) {
nzCount[1] = 0;
coeffMB[1*64] = 0;
} else {
ippiDCT8x8Fwd_16s_C1I(coeffMB+1*64);
ippiQuantInter_H263_16s_C1I(coeffMB+1*64, quant, &nzCount[1], mVideoPicture.modQuant);
}
if (sL2 < lim) {
nzCount[2] = 0;
coeffMB[2*64] = 0;
} else {
ippiDCT8x8Fwd_16s_C1I(coeffMB+2*64);
ippiQuantInter_H263_16s_C1I(coeffMB+2*64, quant, &nzCount[2], mVideoPicture.modQuant);
}
if (sL3 < lim) {
nzCount[3] = 0;
coeffMB[3*64] = 0;
} else {
ippiDCT8x8Fwd_16s_C1I(coeffMB+3*64);
ippiQuantInter_H263_16s_C1I(coeffMB+3*64, quant, &nzCount[3], mVideoPicture.modQuant);
}
}
ippiSubSAD8x8_8u16s_C1R(pUc, mStepChroma, mcPred+64*4, 8, coeffMB+4*64, 16, &sU);
ippiSubSAD8x8_8u16s_C1R(pVc, mStepChroma, mcPred+64*5, 8, coeffMB+5*64, 16, &sV);
if (sU < lim) {
nzCount[4] = 0;
coeffMB[4*64] = 0;
} else {
ippiDCT8x8Fwd_16s_C1I(coeffMB+4*64);
ippiQuantInter_H263_16s_C1I(coeffMB+4*64, quant, &nzCount[4], mVideoPicture.modQuant);
}
if (sV < lim) {
nzCount[5] = 0;
coeffMB[5*64] = 0;
} else {
ippiDCT8x8Fwd_16s_C1I(coeffMB+5*64);
ippiQuantInter_H263_16s_C1I(coeffMB+5*64, quant, &nzCount[5], mVideoPicture.modQuant);
}
h263e_SetPatternInter(pattern, nzCount);
return pattern;
}
inline void ippVideoEncoderH263::EncodeMacroBlockIntra_H263(Ipp16s *coeffMB, Ipp32s pattern, Ipp32s *nzCount, Ipp32s scan)
{
Ipp32s i, pm = 32;
if (mVideoPicture.advIntra) {
for (i = 0; i < 6; i ++) {
if (pattern & pm)
ippiEncodeCoeffsIntra_H263_16s1u(coeffMB+i*64, &cBS.mPtr, &cBS.mBitOff, nzCount[i], 1, mVideoPicture.modQuant, scan);
pm >>= 1;
}
} else {
for (i = 0; i < 6; i ++) {
ippiEncodeDCIntra_H263_16s1u(coeffMB[i*64], &cBS.mPtr, &cBS.mBitOff);
if (pattern & pm)
ippiEncodeCoeffsIntra_H263_16s1u(coeffMB+i*64, &cBS.mPtr, &cBS.mBitOff, nzCount[i] - 1, 0, mVideoPicture.modQuant, IPPVC_SCAN_ZIGZAG);
pm >>= 1;
}
}
}
inline void ippVideoEncoderH263::EncodeMacroBlockInter_H263(Ipp16s *coeffMB, Ipp32s pattern, Ipp32s *nzCount)
{
Ipp32s i, pm = 32;
for (i = 0; i < 6; i ++) {
if (pattern & pm)
ippiEncodeCoeffsInter_H263_16s1u(coeffMB+i*64, &cBS.mPtr, &cBS.mBitOff, nzCount[i], mVideoPicture.modQuant, IPPVC_SCAN_ZIGZAG);
pm >>= 1;
}
}
inline void ippVideoEncoderH263::ReconMacroBlockNotCoded(Ipp8u *pYc, Ipp8u *pUc, Ipp8u *pVc, Ipp8u *mcPred)
{
if (mCalcPSNR) {
mPSNR_Y += h263e_CalcMSE_16x16(mcPred, 16, pYc, mStepLuma);
mPSNR_U += h263e_CalcMSE_8x8(mcPred+64*4, 8, pUc, mStepChroma);
mPSNR_V += h263e_CalcMSE_8x8(mcPred+64*5, 8, pVc, mStepChroma);
}
ippiCopy16x16_8u_C1R(mcPred, 16, pYc, mStepLuma);
ippiCopy8x8_8u_C1R(mcPred+64*4, 8, pUc, mStepChroma);
ippiCopy8x8_8u_C1R(mcPred+64*5, 8, pVc, mStepChroma);
}
// called only if (!mVideoPicture.advIntra)
void ippVideoEncoderH263::ReconMacroBlockIntra_H263(Ipp8u *pY, Ipp8u *pU, Ipp8u *pV, Ipp16s *coeffMB, Ipp32s quant, Ipp32s pattern)
{
__ALIGN16(Ipp8u, pDec, 64*6);
if (mCalcPSNR) {
ippiCopy16x16_8u_C1R(pY, mStepLuma, pDec, 16);
ippiCopy8x8_8u_C1R(pU, mStepChroma, pDec+256, 8);
ippiCopy8x8_8u_C1R(pV, mStepChroma, pDec+320, 8);
}
if (pattern & 32) {
ippiQuantInvIntra_H263_16s_C1I(coeffMB+0*64, 63, quant, 0, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s8u_C1R(coeffMB+0*64, pY, mStepLuma);
} else {
h263e_Set8x8_8u(pY, mStepLuma, (Ipp8u)coeffMB[0*64]);
}
if (pattern & 16) {
ippiQuantInvIntra_H263_16s_C1I(coeffMB+1*64, 63, quant, 0, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s8u_C1R(coeffMB+1*64, pY+8, mStepLuma);
} else {
h263e_Set8x8_8u(pY+8, mStepLuma, (Ipp8u)coeffMB[1*64]);
}
if (pattern & 8) {
ippiQuantInvIntra_H263_16s_C1I(coeffMB+2*64, 63, quant, 0, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s8u_C1R(coeffMB+2*64, pY+8*mStepLuma, mStepLuma);
} else {
h263e_Set8x8_8u(pY+8*mStepLuma, mStepLuma, (Ipp8u)coeffMB[2*64]);
}
if (pattern & 4) {
ippiQuantInvIntra_H263_16s_C1I(coeffMB+3*64, 63, quant, 0, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s8u_C1R(coeffMB+3*64, pY+8*mStepLuma+8, mStepLuma);
} else {
h263e_Set8x8_8u(pY+8*mStepLuma+8, mStepLuma, (Ipp8u)coeffMB[3*64]);
}
if (pattern & 2) {
ippiQuantInvIntra_H263_16s_C1I(coeffMB+4*64, 63, quant, 0, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s8u_C1R(coeffMB+4*64, pU, mStepChroma);
} else {
h263e_Set8x8_8u(pU, mStepChroma, (Ipp8u)coeffMB[4*64]);
}
if (pattern & 1) {
ippiQuantInvIntra_H263_16s_C1I(coeffMB+5*64, 63, quant, 0, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s8u_C1R(coeffMB+5*64, pV, mStepChroma);
} else {
h263e_Set8x8_8u(pV, mStepChroma, (Ipp8u)coeffMB[5*64]);
}
if (mCalcPSNR) {
mPSNR_Y += h263e_CalcMSE_16x16(pY, mStepLuma, pDec, 16);
mPSNR_U += h263e_CalcMSE_8x8(pU, mStepChroma, pDec+256, 8);
mPSNR_V += h263e_CalcMSE_8x8(pV, mStepChroma, pDec+320, 8);
}
}
void ippVideoEncoderH263::ReconBlockIntra_AdvI_H263(Ipp8u *p, Ipp32s step, Ipp16s *coef, h263e_Block *bCurr,
Ipp32s quant, Ipp32s pattern, Ipp32s scan)
{
Ipp32s v;
Ipp16s *predAcA, *predAcC, pred;
Ipp32s lnz;
predAcA = bCurr->predA ? (bCurr->predA->validPredIntra ? bCurr->predA->dct_acA : NULL) : NULL;
predAcC = bCurr->predC ? (bCurr->predC->validPredIntra ? bCurr->predC->dct_acC : NULL) : NULL;
if (pattern) {
ippiQuantInvIntra_H263_16s_C1I(coef, 63, quant, 1, mVideoPicture.modQuant);
lnz = 63;
} else {
if (scan != IPPVC_SCAN_ZIGZAG) {
h263e_Zero64_16s(coef);
} else
coef[0] = 0;
lnz = 0;
}
if (scan == IPPVC_SCAN_ZIGZAG) {
if (predAcA)
if (predAcC)
pred = (predAcA[0] + predAcC[0] + 1) >> 1;
else
pred = predAcA[0];
else
pred = predAcC ? predAcC[0] : 1024;
pred += coef[0];
pred |= 1;
h263e_Clip(pred, 0, 2047);
coef[0] = pred;
} else if (scan == IPPVC_SCAN_VERTICAL) {
if (predAcA) {
pred = coef[0] + predAcA[0];
pred |= 1;
h263e_Clip(pred, 0, 2047);
coef[0] = pred;
for (v = 1; v < 8; v++) {
pred = coef[v*8] + predAcA[v];
h263e_Clip(pred, -2048, 2047);
coef[v*8] = pred;
lnz |= pred;
}
} else {
pred = coef[0] + 1024;
pred |= 1;
h263e_Clip(pred, 0, 2047);
coef[0] = pred;
}
} else {
if (predAcC) {
pred = coef[0] + predAcC[0];
pred |= 1;
h263e_Clip(pred, 0, 2047);
coef[0] = pred;
for (v = 1; v < 8; v++) {
pred = coef[v] + predAcC[v];
h263e_Clip(pred, -2048, 2047);
coef[v] = pred;
lnz |= pred;
}
} else {
pred = coef[0] + 1024;
pred |= 1;
h263e_Clip(pred, 0, 2047);
coef[0] = pred;
}
}
if (lnz) {
ippiDCT8x8Inv_16s8u_C1R(coef, p, step);
/* copy predicted coeffs for future Prediction */
for (v = 0; v < 8; v ++) {
bCurr->dct_acC[v] = coef[v];
bCurr->dct_acA[v] = coef[v*8];
}
} else {
h263e_Zero8_16s(bCurr->dct_acA);
h263e_Zero8_16s(bCurr->dct_acC);
bCurr->dct_acA[0] = bCurr->dct_acC[0] = coef[0];
pred = (coef[0] + 4) >> 3;
h263e_ClipR(pred, 255);
h263e_Set8x8_8u(p, step, (Ipp8u)pred);
}
}
void ippVideoEncoderH263::ReconMacroBlockInter_H263(Ipp8u *pYc, Ipp8u *pUc, Ipp8u *pVc, Ipp8u *mcPred,
Ipp16s *coeffMB, Ipp32s quant, Ipp32s pattern)
{
if (pattern & 32) {
ippiQuantInvInter_H263_16s_C1I(coeffMB+0*64, 63, quant, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s_C1I(coeffMB+0*64);
h263e_Add8x8_16s8u(mcPred, coeffMB+0*64, 16);
}
if (pattern & 16) {
ippiQuantInvInter_H263_16s_C1I(coeffMB+1*64, 63, quant, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s_C1I(coeffMB+1*64);
h263e_Add8x8_16s8u(mcPred+8, coeffMB+1*64, 16);
}
if (pattern & 8) {
ippiQuantInvInter_H263_16s_C1I(coeffMB+2*64, 63, quant, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s_C1I(coeffMB+2*64);
h263e_Add8x8_16s8u(mcPred+16*8, coeffMB+2*64, 16);
}
if (pattern & 4) {
ippiQuantInvInter_H263_16s_C1I(coeffMB+3*64, 63, quant, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s_C1I(coeffMB+3*64);
h263e_Add8x8_16s8u(mcPred+16*8+8, coeffMB+3*64, 16);
}
if (pattern & 2) {
ippiQuantInvInter_H263_16s_C1I(coeffMB+4*64, 63, quant, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s_C1I(coeffMB+4*64);
h263e_Add8x8_16s8u(mcPred+64*4, coeffMB+4*64, 8);
}
if (pattern & 1) {
ippiQuantInvInter_H263_16s_C1I(coeffMB+5*64, 63, quant, mVideoPicture.modQuant);
ippiDCT8x8Inv_16s_C1I(coeffMB+5*64);
h263e_Add8x8_16s8u(mcPred+64*5, coeffMB+5*64, 8);
}
if (mCalcPSNR) {
mPSNR_Y += h263e_CalcMSE_16x16(pYc, mStepLuma, mcPred, 16);
mPSNR_U += h263e_CalcMSE_8x8(pUc, mStepChroma, mcPred+64*4, 8);
mPSNR_V += h263e_CalcMSE_8x8(pVc, mStepChroma, mcPred+64*5, 8);
}
ippiCopy16x16_8u_C1R(mcPred, 16, pYc, mStepLuma);
ippiCopy8x8_8u_C1R(mcPred+64*4, 8, pUc, mStepChroma);
ippiCopy8x8_8u_C1R(mcPred+64*5, 8, pVc, mStepChroma);
}
void ippVideoEncoderH263::EncodeIPic()
{
__ALIGN16(Ipp16s, coeffMB, 64*6);
Ipp8u *pY, *pU, *pV, *pF[6];
Ipp32s i, j, quant, pattern;
Ipp32s nzCount[6];
h263e_MacroBlock *MBcurr = mMBinfo;
Ipp32s scan;
Ipp32s nmbf = 0;
Ipp32s gn, gRow, frGOB = 0;
mVideoPicture.gob_number = 1;
quant = mVideoPicture.pic_quant;
for (gn = 0; gn < mVideoPicture.num_gobs_in_pic; gn++) {
mRTPdata.GOBstartPos[gn] = 8 * (cBS.mPtr - cBS.mBuffer) + cBS.mBitOff;
if (mGOBheaders && gn) {
EncodeGOB_Header(gn);
frGOB = gn*mVideoPicture.num_MBrows_in_gob;
}
for (gRow = 0; gRow < mVideoPicture.num_MBrows_in_gob; gRow++) {
Ipp32s boundOnTop;
i = gn*mVideoPicture.num_MBrows_in_gob + gRow;
boundOnTop = (i == frGOB && i);
pY = mFrameC->pY + i * 16 * mStepLuma;
pU = mFrameC->pU + i * 8 * mStepChroma;
pV = mFrameC->pV + i * 8 * mStepChroma;
for (j = 0; j < mNumMacroBlockPerRow; j++) {
MBcurr->mv[0].dx = MBcurr->mv[0].dy = 0;
MBcurr->block[0].validPredIntra = MBcurr->block[1].validPredIntra = MBcurr->block[2].validPredIntra = MBcurr->block[3].validPredIntra = MBcurr->block[4].validPredIntra = MBcurr->block[5].validPredIntra = 1;
// for RTP support
mRTPdata.MBpos[nmbf] = 8 * (cBS.mPtr - cBS.mBuffer) + cBS.mBitOff;
mRTPdata.MBquant[nmbf] = (Ipp8u)quant;
DCT8x8MacroBlock_H263(pY, pU, pV, coeffMB);
if (mVideoPicture.advIntra) {
pF[0] = pY; pF[1] = pY + 8; pF[2] = pY + 8*mStepLuma; pF[3] = pY + 8*mStepLuma + 8;
pF[4] = pU; pF[5] = pV;
if (boundOnTop) { // mark top row blocks as invalid
MBcurr->block[0].predC->validPredIntra = 0;
MBcurr->block[1].predC->validPredIntra = 0;
MBcurr->block[4].predC->validPredIntra = 0;
MBcurr->block[5].predC->validPredIntra = 0;
}
ChooseAdvIntraPred(MBcurr, coeffMB, &scan);
pattern = PredictReconstructAdvIntra(pF, MBcurr, coeffMB, nzCount, quant, scan);
} else {
scan = IPPVC_SCAN_ZIGZAG;
pattern = QuantMacroBlockIntra_H263(coeffMB, nzCount, quant);
}
EncodeMCBPC_I(IPPVC_MBTYPE_INTRA, pattern & 3);
if (mVideoPicture.advIntra)
EncodeAdvIntraPredMode(scan);
EncodeCBPY_I(pattern >> 2);
EncodeMacroBlockIntra_H263(coeffMB, pattern, nzCount, scan);
if (!mVideoPicture.advIntra && (mIPicdist != 1 || mCalcPSNR))
ReconMacroBlockIntra_H263(pY, pU, pV, coeffMB, quant, pattern);
pY += 16; pU += 8; pV += 8;
MBcurr ++;
nmbf ++;
}
}
}
EncodeZeroBitsAlign();
}
inline Ipp32s h263e_MC_type(IppMotionVector *mv)
{
return (((mv->dy & 1) << 2) + ((mv->dx & 1) << 3));
}
inline Ipp32s h263e_MC_offs(IppMotionVector *mv, Ipp32s step)
{
return ((mv->dy >> 1) * step + (mv->dx >> 1));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -