📄 umc_h264_core_enc.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 - 2005 Intel Corporation. All Rights Reserved.//#include <string.h>#include <stddef.h>#include "ippdefs.h"#include "umc_h264_video_encoder.h"#include "umc_h264_tables.h"// Table to obtain edge info for a 4x4 block of a MB. The table entry when// OR'd with the edge info for the MB, results in edge info for the block.//// H264 4x4 Block ordering in a 16x16 Macroblock and edge assignments//// ULC = Upper Left Corner, U = Upper Edge// L = Left Edge, R = Right Edge//// luma (Y) chroma (U) chroma (V)//// +-U--+-U--+-U--+-U--+ +-U--+-U--+ +-U--+-U--+// | | | | | | | | | | |// ULC--> L 0 | 1 | 4 | 5 R ULC--> L 16 | 17 R ULC--> L 20 | 21 R// | | | | | | | | | | |// +----+----+----+----+ +----+----+ +----+----+// | | | | | | | | | | |// L 2 | 3 | 6 | 7 R L 18 | 19 R L 22 | 23 R// | | | | | | | | | | |// +----+----+----+----+ +----+----+ +----+----+// | | | | |// L 8 | 9 | 12 | 13 R// | | | | |// +----+----+----+----+// | | | | |// L 10 | 11 | 14 | 15 R// | | | | |// +----+----+----+----+//// This table provides easy look-up by block number to determine// which edges is does NOT border on.using namespace UMC_H264_ENCODER;namespace UMC{const Ipp8u EdgePelCountTable [52] ={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,1,1,1,1, 1,1,2,2,2,2,2,2, 3,3,3,3,3,3,4,4};const Ipp8u uEncNotEdge[24] = { // luma: MBEdgeTypeIsNotRightEdge, // 0 MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotUpperLeftCorner, // 1 MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotUpperLeftCorner, // 2 MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotUpperLeftCorner, // 3 MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotUpperLeftCorner, // 4 MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotUpperLeftCorner, // 5 MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotUpperLeftCorner, // 6 MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotUpperLeftCorner, // 7 MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotUpperLeftCorner, // 8 MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotUpperLeftCorner, // 9 MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotUpperLeftCorner, // 10 MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotRightEdge |MBEdgeTypeIsNotUpperLeftCorner, // 11 MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotUpperLeftCorner, // 12 MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotTopEdge| MBEdgeTypeIsNotUpperLeftCorner, // 13 MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotTopEdge| MBEdgeTypeIsNotUpperLeftCorner, // 14 MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotUpperLeftCorner, // 15 // chroma: MBEdgeTypeIsNotRightEdge, // 16 MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotUpperLeftCorner, // 17 MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotUpperLeftCorner, // 18 MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotUpperLeftCorner, // 19 MBEdgeTypeIsNotRightEdge, // 20 MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotUpperLeftCorner, // 21 MBEdgeTypeIsNotRightEdge | MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotUpperLeftCorner, // 22 MBEdgeTypeIsNotLeftEdge | MBEdgeTypeIsNotTopEdge | MBEdgeTypeIsNotUpperLeftCorner // 23};//////////////////////////////////// Compress one sliceStatusH264VideoEncoder::Compress_Slice( const Ipp16u slice_num // Compression settings){ Ipp32u uNumMBs; Ipp32u uMB; Ipp32u uFirstMB; 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; Ipp8u *pEndBits; Ipp32u uEndBitOffset; Ipp32u uCoeffBits; Ipp8u *pCoeffStartBits; Ipp32u uCoeffStartBitOffset; Ipp8u *pCoeffEndBits; Ipp32u uCoeffEndBitOffset; Ipp32u uRecompressMB; Ipp8u uLastQP; Ipp32u uSaved_Skip_Run; Ipp8u MBHasEdges; Ipp8u bSeenFirstMB = false; Status status = UMC_OK; // If this assert fails, then something has changed that will affect the // size of the m_pSliceDataBase array, among other things // TODO VSI: Update these and the loop below to cover the MBs in one slice. uNumMBs = uHeightInMBs * uWidthInMBs; uFirstMB = 0; int y_line_shift = m_pCurrentFrame->y_line_shift; int pitchY = m_pCurrentFrame->uPitch;// m_m_info = m_info; // loop over all MBs in the picture for (uMB = uFirstMB; uMB < uFirstMB + uNumMBs; uMB++) { // Is this MB in the current slice? If not, move on... if (m_pCurrentFrame->pMBData[uMB].uSlice != 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. m_pCurrentFrame->uMBypos = (uMB / uWidthInMBs); // Don't multiply by 16 until after next calculation m_pCurrentFrame->uMBxpos = (uMB - m_pCurrentFrame->uMBypos * uWidthInMBs) * 16; m_pCurrentFrame->uMBypos *= 16; // reset intra MB counter per slice m_Intra_MB_Counter = 0; m_MB_Counter = 0; m_SliceHeader.slice_type = m_info.current_slice_type; // Fill in the first mb in slice field in the slice header. m_SliceHeader.first_mb_in_slice = uMB; // Fill in the current deblocking filter parameters. m_SliceHeader.slice_alpha_c0_offset = m_pCurrentFrame->pSliceDataBase[slice_num].slice_alpha_c0_offset = m_info.slice_parms.slice_alpha_c0_offset; m_SliceHeader.slice_beta_offset = m_pCurrentFrame->pSliceDataBase[slice_num].slice_beta_offset = m_info.slice_parms.slice_beta_offset; m_SliceHeader.disable_deblocking_filter_idc = m_pCurrentFrame->pSliceDataBase[slice_num].disable_deblocking_filter_idc = m_info.slice_parms.disable_deblocking_filter_idc; m_SliceHeader.cabac_init_idc = m_info.cabac_init_idc; // Write a slice header m_pbitstream->PutSliceHeader(m_SliceHeader, m_PicParamSet, m_SeqParamSet, m_PicClass); bSeenFirstMB = true; // Fill in the correct value for m_uLastXmittedQP, used to correctly code // the per MB QP Delta m_uLastXmittedQP = m_PicParamSet.pic_init_qp + m_SliceHeader.slice_qp_delta; if (m_info.entropy_coding_mode) { //m_pbitstream->InitializeEncodingEngine_CABAC(); if (m_SliceHeader.slice_type==INTRASLICE) m_pbitstream->InitializeContextVariablesIntra_CABAC(m_PicParamSet.pic_init_qp+m_SliceHeader.slice_qp_delta); else m_pbitstream->InitializeContextVariablesInter_CABAC(m_PicParamSet.pic_init_qp+m_SliceHeader.slice_qp_delta,m_info.cabac_init_idc); } // Initialize the MB skip run counter m_uSkipRun = 0; } m_MB_Counter++; m_pbitstream->GetState(&pStartBits, &uStartBitOffset); uLastQP = m_uLastXmittedQP; uSaved_Skip_Run = m_uSkipRun; // To restore it if we recompress uUsePCM = 0; // Don't use the PCM mode initially. do { // this is to recompress MBs that are too big. uMBQP = m_pCurrentFrame->pMBData[uMB].uMBQP; // init all blocks in the MB to empty m_pCurrentFrame->pMBData[uMB].uCBP4x4 = 0; m_pCurrentFrame->pMBData[uMB].uChromaType = 0; // Use edge detection to determine if the MB is a flat region ippiEdgesDetect16x16_8u_C1R(m_pCurrentFrame->m_pYPlane + m_pCurrentFrame->pMBOffsets[uMB].uLumaOffset + y_line_shift, pitchY,uMBQP/2,EdgePelCountTable[uMBQP],&MBHasEdges); //MBEdgeDetect(m_pCurrentFrame->m_pYPlane // + m_pCurrentFrame->pMBOffsets[uMB].uLumaOffset, // m_pCurrentFrame->uPitch, uMBQP); if (m_SliceHeader.slice_type != INTRASLICE) { // find the best INTER mode and vectors for all blocks in MB // results to MBDataCurrent and MVCurrent CMEOneMB(uMB, &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 m_uInterCBP4x4 = m_pCurrentFrame->pMBData[uMB].uCBP4x4; m_uInterMBType = m_pCurrentFrame->pMBData[uMB].uMBType; 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 && (m_uMBInterSAD >= uMinIntraSAD)) { // Estimate 4x4 intra mode SAD for the MB using original pels // as predictors. Also selects a mode for each block as a // byproduct, storing in AIMode for the MB, but it is not used // as the mode selction will be repeated later using (correct) // reconstructed pels as predictors if 4x4 intra mode is chosen. AdvancedIntraModeSelectOneMacroblock(uMB, &uAIMBSAD); // 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(uMB, &uAIMBSAD_16x16, m_pCurrentFrame->pMBEncodeBuffer); // choose better intra (4x4 or 16x16) if (uAIMBSAD_16x16 < uAIMBSAD ) { uBestIntraSAD = uAIMBSAD_16x16; uBestIntraMBType = MBTYPE_INTRA_16x16; } else { uBestIntraSAD = uAIMBSAD; uBestIntraMBType = MBTYPE_INTRA; } } else // either macroblock has no edges or interSAD below threshold { // 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(uMB, &uAIMBSAD_16x16, m_pCurrentFrame->pMBEncodeBuffer); uBestIntraSAD = uAIMBSAD_16x16; uBestIntraMBType = MBTYPE_INTRA_16x16; } if (uBestIntraSAD < m_uMBInterSAD) { m_pCurrentFrame->pMBData[uMB].uMBType = uBestIntraMBType; m_pCurrentFrame->pMBData[uMB].uCBP4x4 = 0xffffff; m_Intra_MB_Counter++; } } // not intra slice else { // intra slice, type is INTRA, no empty blocks yet // For Intra pictures, if the macroblock has edges we check // both 4x4 and 16x16 intra SADs. Otherwise, we just check the // 16x16 intra SAD. if (MBHasEdges) { // Estimate 4x4 intra mode SAD for the MB using original pels // as predictors. Also selects a mode for each block as a // byproduct, storing in AIMode for the MB, but it is not used // as the mode selction will be repeated later using (correct) // reconstructed pels as predictors if 4x4 intra mode is chosen. AdvancedIntraModeSelectOneMacroblock(uMB, &uAIMBSAD); // 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(uMB, &uAIMBSAD_16x16, m_pCurrentFrame->pMBEncodeBuffer); // choose better intra (4x4 or 16x16) if (uAIMBSAD_16x16 < uAIMBSAD) { uBestIntraMBType = MBTYPE_INTRA_16x16; } else { uBestIntraMBType = MBTYPE_INTRA; } } else { // 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(uMB, &uAIMBSAD_16x16, m_pCurrentFrame->pMBEncodeBuffer); uBestIntraMBType = MBTYPE_INTRA_16x16; } m_pCurrentFrame->pMBData[uMB].uMBType = uBestIntraMBType; m_pCurrentFrame->pMBData[uMB].uCBP4x4 = 0xffffff; m_uMBInterSAD = 0xffffffff; // very large SAD m_Intra_MB_Counter++; }#ifdef _INTRA_MODE_SWITCH_ m_uMBIntra16x16SAD = uAIMBSAD_16x16; // Save for mode possible switch later#endif // Code the macroblock, all planes // coefficients -> pRLEBuffer if (m_rate_control) { m_pCurrentFrame->pMBData[uMB].uMBQP = uMBQP = (Ipp8u)m_rate_control->MacroblockRateControl(uMB, m_pCurrentFrame->pMBData[uMB].uMBType,m_pbitstream->GetBitsEncoded(), m_uMBInterSAD); } m_pCurrentFrame->pMBData[uMB].cbp_bits = 0; CEncAndRecMB(uMB);// if (m_PicParamSet.entropy_coding_mode)// PutCABAC_MBHeader(uMB);// else PutVLC_MBHeader(uMB); Ipp32u uHdrBits; m_pbitstream->GetState(&pEndBits, &uEndBitOffset); uHdrBits = (Ipp32u) (pEndBits - pStartBits)*8; if (uEndBitOffset >= uStartBitOffset) uHdrBits += uEndBitOffset - uStartBitOffset; else uHdrBits -= uStartBitOffset - uEndBitOffset; pCoeffStartBits = pEndBits; uCoeffStartBitOffset = uEndBitOffset; Ipp32u uIndex = m_pCurrentFrame->pMBOffsets[uMB].uFirstBlockIndex; // if 16x16 intra MB, code the double transform DC coeffs if (m_pCurrentFrame->pMBData[uMB].uMBType == MBTYPE_INTRA_16x16) { //if (m_info.entropy_coding_mode) // status = PutCABAC_MBCoefficients_DC(uMB, Y_DC_RLE); //else status = PutVLC_MBCoefficients_DC(uMB, Y_DC_RLE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -