📄 umc_h264_pack.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) 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 + -