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

📄 umc_h264_pack.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) 2004 - 2007 Intel Corporation. All Rights Reserved.
//

#include "umc_h264_video_encoder.h"
#include "umc_h264_core_enc.h"
#include "umc_h264_tables.h"
#include "vm_debug.h"

namespace UMC_H264_ENCODER
{

// Encoder CBP tables, created from decoder CBP tables
static Ipp8u enc_cbp_intra[64];
static Ipp8u enc_cbp_inter[64];
static Ipp8u enc_cbp_intra_monochrome[16];
static Ipp8u enc_cbp_inter_monochrome[16];

#define BIT_SET(x,n)  ((Ipp32s)(((x)&(1<<(n)))>>(n)))

// Intra MB_Type Offset by Slice Type
const Ipp8u IntraMBTypeOffset[5] = {
    5,  // PREDSLICE
    23, // BPREDSLICE
    0,  // INTRASLICE
    5,  // S_PREDSLICE
    1   // S_INTRASLICE
};

    // This macro calculates the Intra_16x16 mb_type from mode, nc and ac.
    // These things are defined in the JVT-FCD.  Briefly:
    // slice_type = As defined in EnumSliceType
    // mode = 0..3 Luma 16x16 prediction mode 0=Vert, 1=Horiz, 2=DC, 3=Plane
    //      VSI: NOTE: This is not what the FCD says: it says DC, Horiz, Vert, Plane...
    // nc = coded chroma cbp (0=all coeffs are 0, 1=some nonzero DC, 2=some nonzero AC
    // ac = flag that indicates where there are coded luma AC coefficients

#define CALC_16x16_INTRA_MB_TYPE(slice, mode, nc, ac) (1+IntraMBTypeOffset[slice]+mode+4*nc+12*ac)
#define CALC_4x4_INTRA_MB_TYPE(slice) (IntraMBTypeOffset[slice])
#define CALC_PCM_MB_TYPE(slice) (IntraMBTypeOffset[slice]+25);

#define StoreDMVs(m_mv_start,min_x,max_x,step_x,min_y,max_y,step_y,mv)   \
if(m_PicParamSet.entropy_coding_mode)                                       \
{                                                                           \
    H264MotionVector   *tmv=m_mv_start;                                     \
    for (Ipp32s ii_=min_y;ii_<max_y;ii_+=step_y)                                     \
        for (Ipp32s j_=min_x;j_<max_x;j_+=step_x)                                 \
        {                                                                   \
            Ipp32s index=ii_*4 + j_;                                              \
            tmv[index] = mv;                                                \
        }                                                                   \
}

template <class PixType, class CoeffsType>
void H264CoreEncoder<PixType,CoeffsType>::ReconstuctCBP(H264CurrentMacroblockDescriptor<PixType, CoeffsType> *cur_mb)
{
    const Ipp8u ICBPTAB[6] = {0,16,32,15,31,47};
    if (cur_mb->GlobalMacroblockInfo->mbtype == MBTYPE_INTRA_16x16){
        Ipp32s N = CALC_16x16_INTRA_MB_TYPE(INTRASLICE,
                                cur_mb->LocalMacroblockInfo->intra_16x16_mode,
                                cur_mb->MacroblockCoeffsInfo->chromaNC,
                                cur_mb->MacroblockCoeffsInfo->lumaAC)-1;
        cur_mb->LocalMacroblockInfo->cbp = ICBPTAB[N>>2];
    }
}

template <class PixType, class CoeffsType>
Status H264CoreEncoder<PixType,CoeffsType>::Put_MB(H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice)
{
    H264CurrentMacroblockDescriptor<PixType, CoeffsType> &cur_mb = curr_slice->m_cur_mb;
    Status status = UMC_OK;

    status = Put_MBHeader(curr_slice );
    if (status != UMC_OK)
        return status;

    if( cur_mb.GlobalMacroblockInfo->mbtype != MBTYPE_SKIPPED ){
        status = Put_MBLuma( curr_slice );

        if( status == UMC_OK && m_PicParamSet.chroma_format_idc != 0)
            status = Put_MBChroma( curr_slice );
    }

    return status;
}

template <class PixType, class CoeffsType>
Status H264CoreEncoder<PixType, CoeffsType>::Put_MBLuma( H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice )
{
    H264CurrentMacroblockDescriptor<PixType, CoeffsType> &cur_mb = curr_slice->m_cur_mb;
    Status status = UMC_OK;

    // if 16x16 intra MB, code the double transform DC coeffs
    if (cur_mb.GlobalMacroblockInfo->mbtype == MBTYPE_INTRA_16x16){
        status = PackDC(curr_slice, Y_DC_RLE);
        if (status != UMC_OK) return status;
    }

    for (Ipp32s i8x8 = 0; i8x8 < 4; i8x8++) {
        if(!pGetMB8x8TSFlag(cur_mb.GlobalMacroblockInfo)
            || !m_PicParamSet.entropy_coding_mode)
        {
            for(Ipp32s i4x4 = 0; i4x4 < 4; i4x4++) // Loop over the all of the luma 4x4 blocks
            {
                Ipp32s i = i8x8*4 + i4x4;
                // skip if no coeff in MB
                if (((cur_mb.GlobalMacroblockInfo->mbtype == MBTYPE_INTRA_16x16) &&
                        (cur_mb.MacroblockCoeffsInfo->lumaAC)) ||
                    (cur_mb.LocalMacroblockInfo->cbp & (1<<i8x8)))
                {
                    status = PackSubBlockLuma(curr_slice, i);
                    if (status != UMC_OK)
                    {
                        return status;
                    }
                }
            }
        }
        else if(cur_mb.LocalMacroblockInfo->cbp & (1<<i8x8)) {
            PackSubBlockLuma(curr_slice, i8x8);
        }
    }

    return status;
}

template <class PixType, class CoeffsType>
Status H264CoreEncoder<PixType, CoeffsType>::Put_MBChroma( H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice )
{
    H264CurrentMacroblockDescriptor<PixType, CoeffsType> &cur_mb = curr_slice->m_cur_mb;
    Status status = UMC_OK;

    if (cur_mb.MacroblockCoeffsInfo->chromaNC){   // DC Residuals?
         status = PackDC(curr_slice, U_DC_RLE);
         if (status != UMC_OK) return status;

         status = PackDC(curr_slice, V_DC_RLE);
         if (status != UMC_OK) return status;
    }

    if (cur_mb.MacroblockCoeffsInfo->chromaNC == 2){    // AC Residuals?
        for (Ipp32s i = 16; i < 16+(4<<m_PicParamSet.chroma_format_idc); i++){
          status = PackSubBlockChroma(curr_slice, i);
          if (status != UMC_OK) return status;
        }
    }

    return status;
}

template <class PixType, class CoeffsType>
void H264CoreEncoder<PixType,CoeffsType>::Encode_transform_size_8x8_flag(H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice)
{
    H264CurrentMacroblockDescriptor<PixType, CoeffsType> &cur_mb = curr_slice->m_cur_mb;
    if(m_PicParamSet.entropy_coding_mode) {
        bool is_left_avail = cur_mb.CurrentBlockNeighbours.mbs_left[0].mb_num >= 0;
        bool is_top_avail = cur_mb.CurrentBlockNeighbours.mb_above.mb_num >= 0;
        Ipp32s  left_c = 0;
        Ipp32s  top_c = 0;

        if(is_left_avail && pGetMB8x8TSFlag(m_pCurrentFrame->m_mbinfo.mbs + cur_mb.CurrentBlockNeighbours.mbs_left[0].mb_num) != 0
            && m_pCurrentFrame->m_mbinfo.mbs[cur_mb.CurrentBlockNeighbours.mbs_left[0].mb_num].mbtype != MBTYPE_SKIPPED)
            left_c = 1;
        if(is_top_avail &&  pGetMB8x8TSFlag(m_pCurrentFrame->m_mbinfo.mbs + cur_mb.CurrentBlockNeighbours.mb_above.mb_num) != 0
            && m_pCurrentFrame->m_mbinfo.mbs[cur_mb.CurrentBlockNeighbours.mb_above.mb_num].mbtype != MBTYPE_SKIPPED)
            top_c = 1;
        curr_slice->m_pbitstream->EncodeSingleBin_CABAC(left_c + top_c + MB_TRANSFORM_SIZE_8X8_FLAG, pGetMB8x8TSFlag(cur_mb.GlobalMacroblockInfo) != 0);
    } else {
        curr_slice->m_pbitstream->PutBit(pGetMB8x8TSFlag(cur_mb.GlobalMacroblockInfo));
    }
    return;
}

////////////////////////////////////////////////////////////////////////////////
//
// Put_MBHeader
//
// Writes one MB header to the bitstream.
//
////////////////////////////////////////////////////////////////////////////////

template <class PixType, class CoeffsType>
Status H264CoreEncoder<PixType,CoeffsType>::Put_MBHeader(H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice )
{
    Status ps = UMC_OK;
    bool bIntra;
    MBTypeValue mb_type;
    H264CurrentMacroblockDescriptor<PixType, CoeffsType> &cur_mb = curr_slice->m_cur_mb;
    Ipp8u uCBP = cur_mb.LocalMacroblockInfo->cbp;
    Ipp32u uCBPLuma;
    CH264pBs<PixType,CoeffsType>  *pBitstream = curr_slice->m_pbitstream;
    EnumSliceType slice_type = curr_slice->m_slice_type;
    Ipp8s &iLastXmittedQP = curr_slice->m_iLastXmittedQP;
    Ipp32s &prev_dquant = curr_slice->m_prev_dquant;

    mb_type = cur_mb.GlobalMacroblockInfo->mbtype;

    StoreDMVs(&cur_mb.MVs[LIST_0 + 2]->MotionVectors[0],0,4,1,0,4,1, null_mv);
    StoreDMVs(&cur_mb.MVs[LIST_1 + 2]->MotionVectors[0],0,4,1,0,4,1, null_mv);

    // set CBP for the MB based upon coded block bits.
    uCBPLuma = cur_mb.LocalMacroblockInfo->cbp_luma;

    if ((mb_type != MBTYPE_INTRA_16x16) && (mb_type != MBTYPE_PCM))
    {
        uCBP = (Ipp8u)
            ((((uCBPLuma >> 0) | (uCBPLuma >> 1) | (uCBPLuma >> 2) | (uCBPLuma >> 3)) & 1) |    // 8x8 - 0
            (((uCBPLuma >> 3) | (uCBPLuma >> 4) | (uCBPLuma >> 5) | (uCBPLuma >> 6)) & 2) |     // 8x8 - 1
            (((uCBPLuma >> 6) | (uCBPLuma >> 7) | (uCBPLuma >> 8) | (uCBPLuma >> 9)) & 4) |     // 8x8 - 2
            (((uCBPLuma >> 9) | (uCBPLuma >> 10) | (uCBPLuma >> 11) | (uCBPLuma >> 12)) & 8));  // 8x8 - 3

        uCBP += (cur_mb.MacroblockCoeffsInfo->chromaNC << 4);

        cur_mb.LocalMacroblockInfo->cbp = uCBP;
    } else  {
        cur_mb.LocalMacroblockInfo->cbp = 0;
    }

    // Shift the CBP to match the decoder in the deblocking filter...
    cur_mb.LocalMacroblockInfo->cbp_luma = ((uCBPLuma & 0xffff)<<1);

    bIntra = IS_INTRA_MBTYPE(mb_type);

    if (slice_type == INTRASLICE)
    {
        // INTRA slice
        if (m_SliceHeader.MbaffFrameFlag && (curr_slice->m_CurMBAddr&1)==0)
        {
            if (m_PicParamSet.entropy_coding_mode)
            {
                Ipp32s left_mb_field = cur_mb.CurrentMacroblockNeighbours.mb_A >=0?
                    GetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[cur_mb.CurrentMacroblockNeighbours.mb_A]) : 0;
                Ipp32s top_mb_field = cur_mb.CurrentMacroblockNeighbours.mb_B >=0 ?
                    GetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[cur_mb.CurrentMacroblockNeighbours.mb_B]) : 0;

                pBitstream->MBFieldModeInfo_CABAC(pGetMBFieldDecodingFlag(cur_mb.GlobalMacroblockInfo),
                    left_mb_field,top_mb_field);
            }
            else
                pBitstream->PutBit(pGetMBFieldDecodingFlag(cur_mb.GlobalMacroblockInfo));

        }
        // Encode Advanced Intra Coding type
        if (mb_type == MBTYPE_INTRA_16x16)
        {
            Encode_AIC_Type_16x16(curr_slice );
            // Always Send Delta_QP for Intra 16x16 mode (needed for DC coeffs)
            if (m_PicParamSet.entropy_coding_mode)
            {
                Ipp32s prevMB = (cur_mb.uMB > 0)? prev_dquant != 0 : 0;
                pBitstream->DQuant_CABAC(cur_mb.LocalMacroblockInfo->QP - iLastXmittedQP, prevMB);
            }
            else
                pBitstream->PutDQUANT(cur_mb.LocalMacroblockInfo->QP,  iLastXmittedQP);

            prev_dquant = cur_mb.LocalMacroblockInfo->QP - iLastXmittedQP;
            iLastXmittedQP = cur_mb.LocalMacroblockInfo->QP;
        }
        else if (mb_type == MBTYPE_INTRA)
        {
            Encode_AIC_Type(curr_slice );
            Encode_CBP(curr_slice);

            if (uCBP > 0) { // Only Send Delta_QP if there are residuals to follow.
                if (m_PicParamSet.entropy_coding_mode)
                {
                    Ipp32s prevMB = (cur_mb.uMB > 0)? curr_slice->m_prev_dquant != 0 : 0;
                    pBitstream->DQuant_CABAC(cur_mb.LocalMacroblockInfo->QP - iLastXmittedQP, prevMB);
                }
                else
                    pBitstream->PutDQUANT(cur_mb.LocalMacroblockInfo->QP,  iLastXmittedQP);

                prev_dquant = cur_mb.LocalMacroblockInfo->QP-iLastXmittedQP;
                iLastXmittedQP = cur_mb.LocalMacroblockInfo->QP;
            } else {
                // Set QP correctly for Loop filter, since it is not transmitted, decoder will use
                // m_iLastXmittedQP.
                cur_mb.LocalMacroblockInfo->QP = iLastXmittedQP;
                prev_dquant = 0;
            }
        }
        else if (mb_type == MBTYPE_PCM) {

            Encode_PCM_MB(curr_slice);

            // Set QP correctly for Loop filter, since it is not transmitted, decoder will use
            // m_iLastXmittedQP.
            cur_mb.LocalMacroblockInfo->QP = iLastXmittedQP;
            prev_dquant = 0;
        } else {
        }
    } else {
        //if (!IS_INTRA_MBTYPE(m_pCurrentFrame->m_mbinfo.mbs[uMB].mbtype))
        //  cur_mb.LocalMacroblockInfo->intra_chroma_mode = 0;
        // Non-INTRA
        // COD
        // check for skipped MB

//        bool can_skip = (((uCBP == 0)) && ((MBTYPE_DIRECT == mb_type) || (MBTYPE_SKIPPED == mb_type)));
//        bool can_skip = ((MBTYPE_DIRECT == mb_type) || (MBTYPE_SKIPPED == mb_type));
        bool can_skip = (MBTYPE_SKIPPED == mb_type);
//            ((MBTYPE_INTER <= mb_type) && Skip_MV_Predicted(curr_slice, uMB, NULL))));

        if (can_skip && m_SliceHeader.MbaffFrameFlag)
        {
            // TODO we could skip top MB if know that bottom MB will not be skipped.
            if (!((curr_slice->m_CurMBAddr&1)==1 && cur_mb.GlobalMacroblockPairInfo->mbtype != MBTYPE_SKIPPED))
            {
                Ipp32s mb_field_decoding_flag = 0;
                if (cur_mb.CurrentMacroblockNeighbours.mb_A < 0)
                {
                    if (cur_mb.CurrentMacroblockNeighbours.mb_B >= 0)
                    {
                        mb_field_decoding_flag = GetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[cur_mb.CurrentMacroblockNeighbours.mb_B]);
                    }
                } else {
                    mb_field_decoding_flag = GetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[cur_mb.CurrentMacroblockNeighbours.mb_A]);
                }

                can_skip = (mb_field_decoding_flag == pGetMBFieldDecodingFlag(cur_mb.GlobalMacroblockInfo));
            }
        }

        if (can_skip)
        {
            // Skipped
            curr_slice->m_uSkipRun++;

            // Set QP correctly for Loop filter, since it is not transmitted, decoder will use
            // m_iLastXmittedQP.
            prev_dquant = 0;
            cur_mb.LocalMacroblockInfo->QP = iLastXmittedQP;
            if (m_PicParamSet.entropy_coding_mode)
            {
                Ipp32s left_c=0, top_c = 0;

⌨️ 快捷键说明

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