⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 h263_enc_frame.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* ///////////////////////////////////////////////////////////////////////
//
//               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-2007 Intel Corporation. All Rights Reserved.
//
//  Description:    class ippVideoEncoderH263 (encode Pics)
//  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>
#ifdef PRINT_INFO
#include <math.h>
#endif
#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 Ipp32s SAD_FAVOR_ZERO   = 129 /4;
const Ipp32s SAD_FAVOR_DIRECT = 129 /2;
const Ipp32s SAD_FAVOR_INTER  = 512 /2;   // 500 H.263 App III
const Ipp32s SAD_FAVOR_16x16  = 200; //129;   // 200 H.263 App III
const Ipp32s SAD_FAVOR_PRED   = - SAD_FAVOR_ZERO / 2;
const Ipp32s rangeME_8x8      =   1;   // radius for search 8x8 MVs from 16x16 approximation
const Ipp32s SAD_NOTCODED_THR_LUMA = 10;
const Ipp32s SAD_NOTCODED_THR_CHROMA = 20;
const Ipp32s DEV_FAVOR_INTRA = 100;
const Ipp32s 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 h263e_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 h263e_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 h263e_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 h263e_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 h263e_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 h263e_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 h263e_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 h263e_Add8x8_16s8u(pSrcDst, pResid, srcDstStep) \
    ippiAdd8x8_16s8u_C1IRS(pResid, 16, pSrcDst, srcDstStep)

inline void h263e_ComputeChromaMV(const IppMotionVector *mvLuma, IppMotionVector *mvChroma)
{
    mvChroma->dx = (Ipp16s)h263e_Div2Round(mvLuma->dx);
    mvChroma->dy = (Ipp16s)h263e_Div2Round(mvLuma->dy);
}


static void h263e_ComputeChroma4MV(const IppMotionVector mvLuma[4], IppMotionVector *mvChroma)
{
    Ipp32s  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 = h263e_Abs(dx);
    ady = h263e_Abs(dy);
    cdx = h263e_cCbCrMvRound16_[adx & 15] + (adx >> 4) * 2;
    cdy = h263e_cCbCrMvRound16_[ady & 15] + (ady >> 4) * 2;
    mvChroma->dx = (Ipp16s)((dx >= 0) ? cdx : -cdx);
    mvChroma->dy = (Ipp16s)((dy >= 0) ? cdy : -cdy);
}

static void h263e_Set8x8_8u(Ipp8u *p, Ipp32s 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 Ipp32s h263e_CalcMSE_16x16(Ipp8u *pSrc1, Ipp32s stepSrc1, Ipp8u *pSrc2, Ipp32s stepSrc2)
{
    Ipp32s  e;
    ippiSqrDiff16x16_8u32s(pSrc1, stepSrc1, pSrc2, stepSrc2, IPPVC_MC_APX_FF, &e);
    return e;
}

inline Ipp32s h263e_CalcMSE_8x8(Ipp8u *pSrc1, Ipp32s stepSrc1, Ipp8u *pSrc2, Ipp32s stepSrc2)
{
    Ipp32s  e;
    ippiSSD8x8_8u32s_C1R(pSrc1, stepSrc1, pSrc2, stepSrc2, &e, IPPVC_MC_APX_FF);
    return e;
}

inline Ipp16s h263e_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 h263e_MV_CheckRange(IppMotionVector *mvD, Ipp32s umv)
{
  Ipp32s 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 h263e_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 h263e_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 h263e_NonZeroCount(Ipp16s *coeff, Ipp32s *nzCount)
{
    Ipp32s i;
    Ipp32u c;
    for (i = 0; i < 6; i ++) {
        ippiCountZeros8x8_16s_C1(coeff+i*64, &c);
        nzCount[i] = 64 - c;
    }
}


Ipp32s ippVideoEncoderH263::EncodePic(Ipp32s picType, Ipp32s nt)
{
  Ipp32s sts = H263_STS_NOERR;

  mFrameSkipped = 0;

//  mQuantAvg = 0;
  mPSNR_Y = mPSNR_U = mPSNR_V = 0;
  mNumIntraMB = 0;
  mVideoPicture.picture_coding_type = picType;

  if (mSkipFrame) {
    mFrameSkipped = 1;
    sts = H263_STS_SKIPPED_FRAME;
  } else {
    if (mVideoPicture.picture_coding_type == H263e_PIC_TYPE_I) {
      mVideoPicture.pic_quant = mQuantIPic;
      EncodePicture_Header();
      EncodeIPic();
    } else if (mVideoPicture.picture_coding_type == H263e_PIC_TYPE_P) {
      mVideoPicture.pic_quant = mQuantPPic;
      EncodePicture_Header();
      EncodePPic();
    }
//  else
//    EncodeBPic();
  }

  if (mNumIntraMB > mSceneChangeThreshold)
    return H263_STS_NOERR;

  mBitsEncodedFrame = cBS.GetFullness() << 3;
  mBitsEncodedTotal += mBitsEncodedFrame;


//  mQuantAvg = mVideoPicture.pic_quant;

  if (mRateControl)
    PostFrameRC();
/*
  if (mVideoPicture.plusptype && mVideoPicture.picture_coding_type != H263e_PIC_TYPE_B) {
    if (mVideoPicture.picture_coding_type == H263e_PIC_TYPE_I) {
      mVideoPicture.pic_rounding_type = 0; // reset rounding_type for next P-mVideoPicture
    } else
      mVideoPicture.pic_rounding_type ^= 1; // switch rounding_type
  }
*/
  return sts;
}

Ipp32s ippVideoEncoderH263::EncodeFrame(Ipp32s noMoreData)
{
  Ipp32s isIPic, isPPic, isBPic, nt, sts;
  Ipp32s minBufSize;
  Ipp32s bufTooSmall;

  if (!mIsInit)
    return H263_STS_ERR_NOTINIT;

  /* ??? !!!
  needs to be modified when adding custom format support:
  the buffer allocated in the app for small pictures can be smaller than mBPPmax which is >= 8 kB
  according to the Standard
  */
  if (mRateControl)
    minBufSize = IPP_MIN(mBitsDesiredFrame * 2, mBPPmax);
  else
    minBufSize = mBPPmax;

  minBufSize >>= 3; // bits -> bytes
  bufTooSmall = (cBS.mBuffSize - cBS.GetFullness() < minBufSize);

  // without B-frames
  if (mBPicdist == 0) {
    if (noMoreData)
      return H263_STS_NODATA;

    if (bufTooSmall)
      return H263_STS_ERR_BUFOVER;

    //isIPic = !(mFrameCount % mIPicdist);
    isIPic = (mFrameCount - mLastIPic >= mIPicdist);
    if (isIPic) {
      sts = EncodePic(H263e_PIC_TYPE_I, 0);
      if (sts != H263_STS_SKIPPED_FRAME)
        mLastIPic = mFrameCount;
    } else {
      sts = EncodePic(H263e_PIC_TYPE_P, 0);
      if (mNumIntraMB > mSceneChangeThreshold/* || sts == H263_STS_ERR_BUFOVER*/) {
        mVideoPicture.picture_coding_type = H263e_PIC_TYPE_I;
        mQuantIPic = mQuantPPic;
        cBS.Reset();
        sts = EncodePic(H263e_PIC_TYPE_I, 0);
        mLastIPic = mFrameCount;
      }
    }
    if (sts != H263_STS_SKIPPED_FRAME)
      if (mIPicdist != 1) {
        ExpandFrame(mFrameC->pY, mFrameC->pU, mFrameC->pV);
        h263e_Swap(mFrameF, mFrameC);
      }

#ifdef PRINT_INFO
    if (mCalcPSNR)
      printf("%f \n", 10.0 * log10(255.0 * 255.0 * mSourceWidth * mSourceHeight) - 10.0 * log10((double)mPSNR_Y));
#endif

    mVideoPicture.temporal_reference += mVideoPicture.temporal_reference_increment;
    mPictime += mVideoSequence.fixed_pic_time_increment;
    mFrameCount++;
    return sts;
  }

  // with B-frames
  if (noMoreData) {
    if (mNumOfFrames == -1)
        mNumOfFrames = mFrameCount;
    if (mFrameCount >= mNumOfFrames + mBPicdist)
        return H263_STS_NODATA;
    if (bufTooSmall)
      return H263_STS_ERR_BUFOVER;

    // last not closed B-frames are coded as P
    if (mFrameCount >= mNumOfFrames + mBPicdist - (mNumOfFrames - 1) % mPPicdist) {
      Ipp32s  bIndx;

      bIndx = mIndxBPic + 1;
      if (bIndx > 2 + mBPicdist)
        bIndx = 2;
      mFrameC = &mFrame[bIndx];
      // set mVideoPicture time
      nt = (Ipp32s)(mPictime - mBPicdist * mVideoSequence.fixed_pic_time_increment - mSyncTime);
      EncodePic(H263e_PIC_TYPE_P, nt);
      mSyncTimeB = nt;
      // reset Sync Time
      if (mVideoPicture.modulo_time_base != 0)
        mSyncTime = mPictime - mVideoPicture.pic_time_increment;
      mIndxBPic ++;
      if (mIndxBPic > 2 + mBPicdist)
        mIndxBPic = 2;
      ExpandFrame(mFrameC->pY, mFrameC->pU, mFrameC->pV);
      h263e_Swap(mFrameF, mFrameC);
      mPictime += mVideoSequence.fixed_pic_time_increment;
      mFrameCount ++;
        return H263_STS_NOERR;
    }
  }
  if (bufTooSmall)
    return H263_STS_ERR_BUFOVER;
  isIPic = !(mFrameCount % mIPicdist);
  isPPic = !(mFrameCount % mPPicdist);
  isBPic = !(isIPic || isPPic);
  if (!isBPic) {
    mFrameC = mFrameB;
    // set mVideoPicture time
    nt = (Ipp32s)(mPictime - mSyncTime);
    if (isIPic)
      EncodePic(H263e_PIC_TYPE_I, nt);
    else
      EncodePic(H263e_PIC_TYPE_P, nt);
    mSyncTimeB = nt;
    // reset Sync Time
    if (mVideoPicture.modulo_time_base != 0)
      mSyncTime = mPictime - mVideoPicture.pic_time_increment;
    if (mIPicdist != 1)
      ExpandFrame(mFrameC->pY, mFrameC->pU, mFrameC->pV);
  } else if (mFrameCount > mBPicdist) {
    Ipp32s  bIndx;

    bIndx = mIndxBPic + 1;
    if (bIndx > 2 + mBPicdist)
      bIndx = 2;
    mFrameC = &mFrame[bIndx];
    // set mVideoPicture time
    nt = mSyncTimeB - (mBPicdist - mNumBPic) * mVideoSequence.fixed_pic_time_increment;
    mTRD = mBPicdist + 1;
    mTRB = mNumBPic + 1;
    EncodePic(H263e_PIC_TYPE_B, nt);
  }
  // setup next frame
  if (isBPic) {
    mIndxBPic++;
    if (mIndxBPic > 2 + mBPicdist)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -