📄 umc_h264_core_enc.cpp
字号:
// save the frame class
#ifdef TIMING_DETAIL
// update the ME counters which are returned
m_uIntegerSearchCounter = m_pCurrentFrame->uIntegerSearchCounter;
m_uSubpelSearchCounter = m_pCurrentFrame->uSubpelSearchCounter;
m_uDirectBCounter = m_pCurrentFrame->uDirectBCounter;
#endif
done:
if (m_PicParamSet.entropy_coding_mode)
pBitstream->TerminateEncode_CABAC();
// use core timing infrastructure to measure/report deblock filter time
// by measuring the time to get from here to the start of EndPicture.
/* fprintf(stderr, "Real Blocks: %d\n", slice_type);
for( Ipp32s i = 0; i<32; i++ ){
fprintf(stderr,"%d %d | ",i,mbtype_stat[i]);
}
fprintf(stderr,"\n");
*/
return status;
} // Compress_Slice
template <class PixType, class CoeffsType>
Ipp32s H264CoreEncoder<PixType,CoeffsType>::ComputeMBFrameFieldCost(H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice,
bool is_frame)
{
curr_slice->m_CurMB_X = ((curr_slice->m_CurMBAddr>>1) % m_WidthInMBs);
if ((curr_slice->m_CurMBAddr&1)==0)
{
curr_slice->m_CurMB_Y = ((curr_slice->m_CurMBAddr>>1) / m_WidthInMBs)*2;
} else {
curr_slice->m_CurMB_Y = ((curr_slice->m_CurMBAddr>>1) / m_WidthInMBs)*2;
if (!is_frame)
curr_slice->m_CurMB_Y ++;
}
UpdateCurrentMBInfo(curr_slice);
SetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curr_slice->m_CurMBAddr], is_frame ? 0 : 1);
SetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curr_slice->m_CurMBAddr+1], is_frame ? 0 : 1);
curr_slice->m_is_cur_mb_field = pGetMBFieldDecodingFlag(curr_slice->m_cur_mb.GlobalMacroblockInfo);
UpdateNeighbouringAddresses(curr_slice);
UpdateNeighbouringBlocks(curr_slice);
return MB_Decision(curr_slice, curr_slice->m_CurMBAddr);
}
template <class PixType, class CoeffsType>
void H264CoreEncoder<PixType,CoeffsType>::MBFrameFieldSelect(H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice)
{
H264MBAddr &curMBAddr = curr_slice->m_CurMBAddr;
#if 1
Ipp32u uOffset = m_pMBOffsets[curMBAddr].uLumaOffset[true][false];
PixType * curr = m_pCurrentFrame->m_pYPlane + uOffset;
Ipp32s pitchPixels = m_pCurrentFrame->pitchPixels();
Ipp32s pitchBytes = m_pCurrentFrame->pitchBytes();
Ipp32s frame_sad = SAD16x16(curr, pitchBytes, curr + pitchPixels, pitchBytes) + SAD16x16(curr + 16*pitchPixels, pitchBytes, curr + 17*pitchPixels, pitchBytes);
Ipp32s field_sad = SAD16x16(curr, pitchBytes << 2, curr + (pitchPixels << 2), pitchBytes << 2) + SAD16x16(curr + pitchPixels, pitchBytes << 2, curr + (pitchPixels << 2) + pitchPixels, pitchBytes << 2);
if ((frame_sad - field_sad) > 0)
{
SetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curMBAddr], 1);
SetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curMBAddr+1], 1);
} else {
SetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curMBAddr], 0);
SetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curMBAddr+1], 0);
}
#elif 1
Ipp32u field_sad = ComputeMBFrameFieldCost(false);
curMBAddr++;
field_sad += ComputeMBFrameFieldCost(false);
curMBAddr--;
Ipp32u frame_sad = ComputeMBFrameFieldCost(true);
curMBAddr++;
frame_sad += ComputeMBFrameFieldCost(true);
curMBAddr--;
if (field_sad < frame_sad)
{
SetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curMBAddr],1);
SetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curMBAddr+1],1);
curr_slice->m_is_cur_mb_field = pGetMBFieldDecodingFlag(cur_mb.GlobalMacroblockInfo);
}
#else
SetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curMBAddr],0);
SetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curMBAddr+1],0);
#endif
}
template <class PixType, class CoeffsType>
Status H264CoreEncoder<PixType,CoeffsType>::Compress_Slice_MBAFF(H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice)
{
Ipp32s slice_num = curr_slice->m_slice_number;
Ipp32u uAIMBSAD; // MB prediction SAD for INTRA 4x4 mode
Ipp32u uAIMBSAD_16x16; // MB prediction SAD for INTRA 16x16 mode
Ipp32u uBestIntraSAD;
Ipp8u uMBQP;
Ipp32u uMinIntraSAD;
MB_Type uBestIntraMBType;
Ipp8u uUsePCM = 0;
Ipp8u *pStartBits;
Ipp32u uStartBitOffset;
Ipp32u uRecompressMB;
Ipp8s iLastQP;
Ipp32u uSaved_Skip_Run;
Ipp8u bSeenFirstMB = false;
Status status = UMC_OK;
H264CurrentMacroblockDescriptor<PixType, CoeffsType> &cur_mb = curr_slice->m_cur_mb;
H264MBAddr &curMBAddr = curr_slice->m_CurMBAddr;
CH264pBs<PixType,CoeffsType> *pBitstream = curr_slice->m_pbitstream;
Ipp32u uNumMBs = m_HeightInMBs * m_WidthInMBs;
Ipp32u uFirstMB = m_field_index*uNumMBs;
curr_slice->m_use_transform_for_intra_decision = m_info.use_transform_for_intra_decision ?
(curr_slice->m_slice_type == INTRASLICE) : false;
// loop over all MBs in the picture
for (Ipp32u uMB = uFirstMB; uMB < uFirstMB + uNumMBs; uMB++)
{
// Is this MB in the current slice? If not, move on...
if (m_pCurrentFrame->m_mbinfo.mbs[uMB].slice_id != slice_num) {
continue;
} else if (!bSeenFirstMB)
{
// Reset xpos and ypos in framedata struct
// This is necessary because the same slice may be recoded multiple times.
// reset intra MB counter per slice
curr_slice->m_Intra_MB_Counter = 0;
curr_slice->m_MB_Counter = 0;
// Fill in the first mb in slice field in the slice header.
curr_slice->m_first_mb_in_slice = uMB >> 1;
// Fill in the current deblocking filter parameters.
curr_slice->m_slice_alpha_c0_offset = (Ipp8s)m_info.deblocking_filter_alpha;
curr_slice->m_slice_beta_offset = (Ipp8s)m_info.deblocking_filter_beta;
curr_slice->m_disable_deblocking_filter_idc = m_info.deblocking_filter_idc;
curr_slice->m_cabac_init_idc = m_info.cabac_init_idc;
// Write a slice header
pBitstream->PutSliceHeader(m_SliceHeader,
m_PicParamSet,
m_SeqParamSet,
m_PicClass,
curr_slice);
bSeenFirstMB = true;
// Fill in the correct value for m_iLastXmittedQP, used to correctly code
// the per MB QP Delta
curr_slice->m_iLastXmittedQP = m_PicParamSet.pic_init_qp + curr_slice->m_slice_qp_delta;
Ipp32s SliceQPy = curr_slice->m_iLastXmittedQP;
if (m_info.entropy_coding_mode)
{
if (curr_slice->m_slice_type==INTRASLICE)
pBitstream->InitializeContextVariablesIntra_CABAC(SliceQPy);
else
pBitstream->InitializeContextVariablesInter_CABAC(SliceQPy, curr_slice->m_cabac_init_idc);
}
// Initialize the MB skip run counter
curr_slice->m_uSkipRun = 0;
}
curr_slice->m_CurMBAddr = uMB;
if ((uMB&1)==0) MBFrameFieldSelect(curr_slice);
curr_slice->m_CurMB_X = ((curr_slice->m_CurMBAddr>>1) % m_WidthInMBs);
if ((curr_slice->m_CurMBAddr&1)==0)
{
curr_slice->m_CurMB_Y = ((curr_slice->m_CurMBAddr>>1) / m_WidthInMBs)*2;
}
else
{
if (!GetMBFieldDecodingFlag(m_pCurrentFrame->m_mbinfo.mbs[curr_slice->m_CurMBAddr]))
curr_slice->m_CurMB_Y ++;
}
UpdateCurrentMBInfo(curr_slice);
pSetMB8x8TSFlag(cur_mb.GlobalMacroblockInfo, 0);
curr_slice->m_MB_Counter++;
curr_slice->m_pbitstream->GetState(&pStartBits, &uStartBitOffset);
iLastQP = curr_slice->m_iLastXmittedQP;
uSaved_Skip_Run = curr_slice->m_uSkipRun; // To restore it if we recompress
uUsePCM = 0; // Don't use the PCM mode initially.
UpdateNeighbouringAddresses(curr_slice);
UpdateNeighbouringBlocks(curr_slice);
curr_slice->m_is_cur_mb_field = pGetMBFieldDecodingFlag(cur_mb.GlobalMacroblockInfo);
curr_slice->m_InitialOffset = m_InitialOffsets[curr_slice->m_is_cur_mb_field & curMBAddr];
curr_slice->m_is_cur_mb_bottom_field = (curr_slice->m_is_cur_mb_field & curMBAddr) == 1;
do { // this is to recompress MBs that are too big.
uMBQP = getLumaQP51(cur_mb.LocalMacroblockInfo->QP, m_PicParamSet.bit_depth_luma);
cur_mb.LocalMacroblockInfo->cbp_chroma =
cur_mb.LocalMacroblockInfo->cbp_luma =
cur_mb.LocalMacroblockInfo->cbp_bits =
cur_mb.LocalMacroblockInfo->cbp_bits_chroma =
cur_mb.LocalMacroblockInfo->cbp =
cur_mb.LocalMacroblockInfo->intra_chroma_mode = 0;
cur_mb.LocalMacroblockInfo->sbdir[0] =
cur_mb.LocalMacroblockInfo->sbdir[1] =
cur_mb.LocalMacroblockInfo->sbdir[2] =
cur_mb.LocalMacroblockInfo->sbdir[3] = D_DIR_FWD;
Ipp32s MBHasEdges;
// Use edge detection to determine if the MB is a flat region
ippiEdgesDetect16x16(m_pCurrentFrame->m_pYPlane + m_pMBOffsets[uMB].uLumaOffset[m_is_cur_pic_afrm][curr_slice->m_is_cur_mb_field],
m_pCurrentFrame->pitchBytes()<<curr_slice->m_is_cur_mb_field,uMBQP/2,EdgePelCountTable[uMBQP],&MBHasEdges);
if (curr_slice->m_slice_type != INTRASLICE)
{
// find the best INTER mode and vectors for all blocks in MB
// results to MBDataCurrent and MVCurrent
CMEOneMB(curr_slice, uMB, &curr_slice->m_uMBInterSAD);
// MB type classification
// Only need to change anything if INTRA is chosen, as the ME
// function filled in MB info for best INTER mode and cbp's.
// save INTER results for possible later switch back to INTER
curr_slice->m_uInterCBP4x4 = cur_mb.LocalMacroblockInfo->cbp_luma;
curr_slice->m_InterMBType = static_cast<MB_Type>(cur_mb.GlobalMacroblockInfo->mbtype);
curr_slice->m_InterMB8x8PackFlag = pGetMB8x8TSPackFlag(cur_mb.GlobalMacroblockInfo);
uMinIntraSAD = rd_quant_intra_min[uMBQP];
// For non-Intra pictures, if the macroblock has edges and
// m_uMBInterSAD is above a minimum threshold, we will check
// both 4x4 and 16x16 intra SADs. Otherwise, we just check the
// 16x16 intra SAD.
if (MBHasEdges && (curr_slice->m_uMBInterSAD >= uMinIntraSAD))
{
// Compute 16x16 intra mode SAD for the MB, producing luma
// predictor blocks (at pMBEncodeBuffer) and selected mode
// (in AIMode, all blocks) to be used in the encode loop if
// 16x16 intra mode is chosen.
Intra16x16SelectAndPredict(curr_slice, uMB, &uAIMBSAD_16x16,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -