📄 h263_enc_frame.cpp
字号:
/* /////////////////////////////////////////////////////////////////////////// INTEL CORPORATION PROPRIETARY INFORMATION// This software is supplied under the terms of a license agreement or// nondisclosure agreement with Intel Corporation and may not be copied// or disclosed except in accordance with the terms of that agreement.// Copyright (c) 2005 Intel Corporation. All Rights Reserved.//// Description: class ippVideoEncoderH263 (encode VOPs)// Contents:// EncodeFrame//// References:// Fast ME algorithm// IEEE Transactions on image processing, vol. 9, N. 2, Feb 2000// "A new Diamond Search Algorithm for Fast Block-Matching Motion Estimation"// Shan Zhu and Kai-Kuang Ma// Fast half-pel algorithm// V. Bhaskaran, K. Konstantinides// "Image And Video Compression Standarts"*/#include <stdlib.h>#include <math.h>#include "h263_enc.hpp"#pragma warning(disable : 981) // operands are evaluated in unspecified order#pragma warning(disable : 279) // controlling expression is constant//--------------------- defines to control ME process -------------------------//#define ME_FULLSEARCH_RECT // using rectangle instead of involute search//#define ME_USE_THRESHOLD // using threshold in ME (faster)const int SAD_FAVOR_ZERO = 129 /4;const int SAD_FAVOR_DIRECT = 129 /2;const int SAD_FAVOR_INTER = 512 /2; // 500 H.263 App IIIconst int SAD_FAVOR_16x16 = 200; //129; // 200 H.263 App IIIconst int SAD_FAVOR_PRED = - SAD_FAVOR_ZERO / 2;const int rangeME_8x8 = 1; // radius for search 8x8 MVs from 16x16 approximationconst int SAD_NOTCODED_THR_LUMA = 10;const int SAD_NOTCODED_THR_CHROMA = 20;const int DEV_FAVOR_INTRA = 100;const int MAX_SAD = 16 * 16 * 256;//---------------------- aux defines and functions ----------------------------#define H263_MV_OFF_HP(dx, dy, step) \ (((dx) >> 1) + (step) * ((dy) >> 1))#define H263_MV_ACC_HP(dx, dy) \ ((((dy) & 1) << 1) + ((dx) & 1))#define H263_MV_OFF_QP(dx, dy, step) \ (((dx) >> 2) + (step) * ((dy) >> 2))#define H263_MV_ACC_QP(dx, dy) \ ((((dy) & 3) << 2) + ((dx) & 3))#define h263_Copy8x4HP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \ ippiCopy8x4HP_8u_C1R(pSrc + H263_MV_OFF_HP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, H263_MV_ACC_HP((mv)->dx, (mv)->dy), rc)#define h263_Copy8x8HP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \ ippiCopy8x8HP_8u_C1R(pSrc + H263_MV_OFF_HP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, H263_MV_ACC_HP((mv)->dx, (mv)->dy), rc)#define h263_Copy16x8HP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \ ippiCopy16x8HP_8u_C1R(pSrc + H263_MV_OFF_HP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, H263_MV_ACC_HP((mv)->dx, (mv)->dy), rc)#define h263_Copy16x16HP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \ ippiCopy16x16HP_8u_C1R(pSrc + H263_MV_OFF_HP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, H263_MV_ACC_HP((mv)->dx, (mv)->dy), rc)#define h263_Copy8x8QP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \ ippiCopy8x8QP_H263_8u_C1R(pSrc + H263_MV_OFF_QP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, H263_MV_ACC_QP((mv)->dx, (mv)->dy), rc)#define h263_Copy16x8QP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \ ippiCopy16x8QP_H263_8u_C1R(pSrc + H263_MV_OFF_QP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, H263_MV_ACC_QP((mv)->dx, (mv)->dy), rc)#define h263_Copy16x16QP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \ ippiCopy16x16QP_H263_8u_C1R(pSrc + H263_MV_OFF_QP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, H263_MV_ACC_QP((mv)->dx, (mv)->dy), rc)#define h263_Add8x8_16s8u(pSrcDst, pResid, srcDstStep) \ ippiAdd8x8_16s8u_C1IRS(pResid, 16, pSrcDst, srcDstStep)inline void h263_ComputeChromaMV(const IppMotionVector *mvLuma, IppMotionVector *mvChroma){ mvChroma->dx = (Ipp16s)h263_Div2Round(mvLuma->dx); mvChroma->dy = (Ipp16s)h263_Div2Round(mvLuma->dy);}static void h263_ComputeChroma4MV(const IppMotionVector mvLuma[4], IppMotionVector *mvChroma){ int dx, dy, cdx, cdy, adx, ady; dx = mvLuma[0].dx + mvLuma[1].dx + mvLuma[2].dx + mvLuma[3].dx; dy = mvLuma[0].dy + mvLuma[1].dy + mvLuma[2].dy + mvLuma[3].dy; adx = abs(dx); ady = abs(dy); cdx = h263_cCbCrMvRound16_[adx & 15] + (adx >> 4) * 2; cdy = h263_cCbCrMvRound16_[ady & 15] + (ady >> 4) * 2; mvChroma->dx = (Ipp16s)((dx >= 0) ? cdx : -cdx); mvChroma->dy = (Ipp16s)((dy >= 0) ? cdy : -cdy);}static void h263_Set8x8_8u(Ipp8u *p, int step, Ipp8u level){ Ipp32u val; val = level + (level << 8); val += val << 16; ((Ipp32u*)p)[0] = val; ((Ipp32u*)p)[1] = val; p += step; ((Ipp32u*)p)[0] = val; ((Ipp32u*)p)[1] = val; p += step; ((Ipp32u*)p)[0] = val; ((Ipp32u*)p)[1] = val; p += step; ((Ipp32u*)p)[0] = val; ((Ipp32u*)p)[1] = val; p += step; ((Ipp32u*)p)[0] = val; ((Ipp32u*)p)[1] = val; p += step; ((Ipp32u*)p)[0] = val; ((Ipp32u*)p)[1] = val; p += step; ((Ipp32u*)p)[0] = val; ((Ipp32u*)p)[1] = val; p += step; ((Ipp32u*)p)[0] = val; ((Ipp32u*)p)[1] = val;}inline int h263_CalcMSE_16x16(Ipp8u *pSrc1, int stepSrc1, Ipp8u *pSrc2, int stepSrc2){ int e; ippiSqrDiff16x16_8u32s(pSrc1, stepSrc1, pSrc2, stepSrc2, IPPVC_MC_APX_FF, &e); return e;}inline int h263_CalcMSE_8x8(Ipp8u *pSrc1, int stepSrc1, Ipp8u *pSrc2, int stepSrc2){ int e; ippiSSD8x8_8u32s_C1R(pSrc1, stepSrc1, pSrc2, stepSrc2, &e, IPPVC_MC_APX_FF); return e;}inline Ipp16s h263_Median(Ipp16s a, Ipp16s b, Ipp16s c){ if (a > b) { Ipp16s t = a; a = b; b = t; } return (b <= c) ? b : (c >= a) ? c : a;}inline void h263_MV_CheckRange(IppMotionVector *mvD, int umv){ int fMin, fMax; if (!umv) { fMin = -32; fMax = 31; } else { fMin = -63; fMax = 63; } if (mvD->dx < fMin) mvD->dx = (Ipp16s)(mvD->dx + 64); else if (mvD->dx > fMax) mvD->dx = (Ipp16s)(mvD->dx - 64); if (mvD->dy < fMin) mvD->dy = (Ipp16s)(mvD->dy + 64); else if (mvD->dy > fMax) mvD->dy = (Ipp16s)(mvD->dy - 64);}#define h263_SetPatternInter(pattern, nzCount) \ pattern = 0; \ pattern |= (nzCount[0] > 0) ? 32 : 0; \ pattern |= (nzCount[1] > 0) ? 16 : 0; \ pattern |= (nzCount[2] > 0) ? 8 : 0; \ pattern |= (nzCount[3] > 0) ? 4 : 0; \ pattern |= (nzCount[4] > 0) ? 2 : 0; \ pattern |= (nzCount[5] > 0) ? 1 : 0#define h263_SetPatternIntra(pattern, nzCount, thresh) \{ \ pattern = 0; \ pattern |= (nzCount[0] > thresh) ? 32 : 0; \ pattern |= (nzCount[1] > thresh) ? 16 : 0; \ pattern |= (nzCount[2] > thresh) ? 8 : 0; \ pattern |= (nzCount[3] > thresh) ? 4 : 0; \ pattern |= (nzCount[4] > thresh) ? 2 : 0; \ pattern |= (nzCount[5] > thresh) ? 1 : 0; \}inline void h263_NonZeroCount(Ipp16s *coeff, int *nzCount){ int i; Ipp32u c; for (i = 0; i < 6; i ++) { ippiCountZeros8x8_16s_C1(coeff+i*64, &c); nzCount[i] = 64 - c; }}//-----------------------------------------------------------------------------void ippVideoEncoderH263::PostFrameRC(Ipp32s bpfEncoded){ int bpfExpected = 0, delay, quant, coding_type; coding_type = VOP.picture_coding_type; delay = (int)(mBitsDesiredRC - mBitsEncoded); if (coding_type == H263_VOP_TYPE_I) { bpfExpected = (mBitsPerFrameRC << 1) + (delay >> 1); h263_ClipL(bpfExpected, mBitsPerFrameRC * 7 >> 3);// } else if (coding_type == H263_VOP_TYPE_B) {// bpfExpected = (mBitsPerFrameRC >> 1) + (delay >> 3);// h263_Clip(bpfExpected, mBitsPerFrameRC >> 2, mBitsPerFrameRC * 3 >> 2); } else { // P- and S(GMC)-VOP bpfExpected = mBitsPerFrameRC + (delay >> 2); h263_Clip(bpfExpected, mBitsPerFrameRC >> 1, mBitsPerFrameRC * 3 >> 1); } quant = (coding_type == H263_VOP_TYPE_I) ? mQuantIVOP : (coding_type == H263_VOP_TYPE_B) ? mQuantBVOP : mQuantPVOP; if (abs(bpfEncoded - bpfExpected) > (bpfExpected >> 4)) { if (bpfEncoded > bpfExpected) { quant ++; if (bpfEncoded > 2 * bpfExpected) quant ++; h263_ClipR(quant, 31); } else if (bpfEncoded < bpfExpected) { quant --; if (bpfEncoded * 2 < bpfExpected) quant --; h263_ClipL(quant, 1); } } if (quant < 3) quant = 3; if (coding_type == H263_VOP_TYPE_I) mQuantIVOP = quant;// else if (coding_type == H263_VOP_TYPE_B)// mQuantBVOP = quant; else mQuantPVOP = quant; mBitsDesiredRC += mBitsPerFrameRC;}int ippVideoEncoderH263::EncodeVOP(int vopType, int nt){ int bpfEncoded; mQuantAvg = 0; mPSNR_Y = mPSNR_U = mPSNR_V = 0; mNumIntraMB = 0; VOP.picture_coding_type = vopType; if (VOP.picture_coding_type == H263_VOP_TYPE_I) { VOP.vop_quant = mQuantIVOP;// } else if (VOP.picture_coding_type == H263_VOP_TYPE_B) {// VOP.vop_quant = mQuantBVOP; } else { VOP.vop_quant = mQuantPVOP; } EncodePicture_Header(); if (VOP.picture_coding_type == H263_VOP_TYPE_I) EncodeIVOP(); else if (VOP.picture_coding_type == H263_VOP_TYPE_P) EncodePVOP();// else// EncodeBVOP(); bpfEncoded = cBS.GetFullness(); if (mNumIntraMB > mSceneChangeThreshold) return H263_STS_NOERR; bpfEncoded <<= 3; mBitsEncoded += bpfEncoded; mQuantAvg = VOP.vop_quant; if (mRateControl) { PostFrameRC(bpfEncoded); }/* if (VOP.plusptype && VOP.picture_coding_type != H263_VOP_TYPE_B) { if (VOP.picture_coding_type == H263_VOP_TYPE_I) { VOP.vop_rounding_type = 0; // reset rounding_type for next P-VOP } else VOP.vop_rounding_type ^= 1; // switch rounding_type }*/ return H263_STS_NOERR;}int ippVideoEncoderH263::EncodeFrame(int noMoreData){ int isIVOP, isPVOP, isBVOP, nt, sts; if (!mIsInit) return H263_STS_ERR_NOTINIT; // without B-frames if (mBVOPdist == 0) { if (noMoreData) return H263_STS_NODATA; //isIVOP = !(mFrameCount % mIVOPdist); isIVOP = (mFrameCount - mLastIVOP >= mIVOPdist); if (isIVOP) { sts = EncodeVOP(H263_VOP_TYPE_I, 0); mLastIVOP = mFrameCount; } else { sts = EncodeVOP(H263_VOP_TYPE_P, 0); if (mNumIntraMB > mSceneChangeThreshold/* || sts == H263_STS_ERR_BUFOVER*/) { VOP.picture_coding_type = H263_VOP_TYPE_I; mQuantIVOP = mQuantPVOP; cBS.Reset(); sts = EncodeVOP(H263_VOP_TYPE_I, 0); mLastIVOP = mFrameCount; } } //if (sts == H263_STS_NOERR) if (mIVOPdist != 1) { ExpandFrame(mCurrPtrY, mCurrPtrU, mCurrPtrV); h263_Swap(mForwPtrY, mCurrPtrY); h263_Swap(mForwPtrU, mCurrPtrU); h263_Swap(mForwPtrV, mCurrPtrV); } VOP.temporal_reference += VOP.temporal_reference_increment; mVOPtime += VOL.fixed_vop_time_increment; mFrameCount++; return sts; } // with B-frames if (noMoreData) { if (mNumOfFrames == -1) mNumOfFrames = mFrameCount; if (mFrameCount >= mNumOfFrames + mBVOPdist) return H263_STS_NODATA; // last not closed B-frames are coded as P if (mFrameCount >= mNumOfFrames + mBVOPdist - (mNumOfFrames - 1) % mPVOPdist) { int bIndx; bIndx = mIndxBVOP + 1; if (bIndx > 2 + mBVOPdist) bIndx = 2; mCurrPtrY = mPtrY[bIndx]; mCurrPtrU = mPtrU[bIndx]; mCurrPtrV = mPtrV[bIndx]; // set VOP time nt = (int)(mVOPtime - mBVOPdist * VOL.fixed_vop_time_increment - mSyncTime); EncodeVOP(H263_VOP_TYPE_P, nt); mSyncTimeB = nt; // reset Sync Time if (VOP.modulo_time_base != 0) mSyncTime = mVOPtime - VOP.vop_time_increment; mIndxBVOP ++; if (mIndxBVOP > 2 + mBVOPdist) mIndxBVOP = 2; ExpandFrame(mCurrPtrY, mCurrPtrU, mCurrPtrV); h263_Swap(mForwPtrY, mCurrPtrY); h263_Swap(mForwPtrU, mCurrPtrU); h263_Swap(mForwPtrV, mCurrPtrV); mVOPtime += VOL.fixed_vop_time_increment; mFrameCount ++; return H263_STS_NOERR; } } isIVOP = !(mFrameCount % mIVOPdist); isPVOP = !(mFrameCount % mPVOPdist); isBVOP = !(isIVOP || isPVOP); if (!isBVOP) { mCurrPtrY = mBackPtrY; mCurrPtrU = mBackPtrU; mCurrPtrV = mBackPtrV; // set VOP time nt = (int)(mVOPtime - mSyncTime); if (isIVOP) { EncodeVOP(H263_VOP_TYPE_I, nt); } else EncodeVOP(H263_VOP_TYPE_P, nt); mSyncTimeB = nt; // reset Sync Time if (VOP.modulo_time_base != 0) mSyncTime = mVOPtime - VOP.vop_time_increment; if (mIVOPdist != 1) ExpandFrame(mCurrPtrY, mCurrPtrU, mCurrPtrV); } else if (mFrameCount > mBVOPdist) { int bIndx; bIndx = mIndxBVOP + 1; if (bIndx > 2 + mBVOPdist)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -