📄 umc_h264_dec_decode_mb.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) 2003-2005 Intel Corporation. All Rights Reserved.////*/#include "umc_h264_dec.h"namespace UMC{// 0 1 4 5// 2 3 6 7// 8 9 c d// a b e fconst Ipp8u block2lin[16]={ 0, 1, 4, 5, 2, 3, 6, 7, 8, 9,12,13, 10,11,14,15};const Ipp8u Addition[4]={ 0, 1, 4, 5};#define MEDIAN_OF_3(a, b, c) (MIN((a),(b))) ^ (MIN((b),(c))) ^ (MIN((c),(a)))voidH264VideoDecoder::ComputeMotionVectorPredictors( const Ipp8u ListNum, Ipp8s RefIndex, // reference index for this part const Ipp32s block, // block or subblock number, depending on mbtype Ipp32s *pMVx, // resulting MV predictors Ipp32s *pMVy ){ Ipp32s px0, px1, px2; Ipp32s py0, py1, py2; // Ipp32s diff; Ipp32s isRightUnavailable=false; // Indicates whether the (above) right block, subblock or // macroblock can be used for motion vector prediction. // This is not a true boolean, in that we use bitwise operations // so that any non-zero value, not just the value true, // is considered true. Ipp32s isLeftUnavailable=false; // Indicates whether the (above) left block, subblock or // macroblock can be used for motion vector prediction. // Only used when isRightUnavailable is non-zero. H264DecoderMotionVector *sl; // pointer to sb to the left H264DecoderMotionVector *sa; // pointer to sb above H264DecoderMotionVector *sr; // pointer to sb above right Ipp8s *pRefIxl; // pointer to corresponding RefIndex sb Ipp8s *pRefIxa; Ipp8s *pRefIxr; H264DecoderMotionVector *sonly; // pointer to only MV this ref H264DecoderMotionVector null = {0,0}; Ipp8s nullRefIx = -1; Ipp32u uSameRefPicCount = 3; // To code the rule that if only one of the three reference MV is to // the same reference picture as the MV being computed, then that one // MV is used as the MV predictor. Initialize to all same, then decrement // as "different reference picture" are found. H264DecoderBlockLocation Left={-1,-1},Top={-1,-1},TopRight={-1,-1},TopLeft={-1,-1}; H264DecoderMacroblockMVs *MVs; H264DecoderMacroblockRefIdxs *RefIdxs; H264DecoderMacroblockGlobalInfo *gmbs; MVs = m_pCurrentFrame->m_mbinfo.MV[ListNum]; RefIdxs = m_pCurrentFrame->m_mbinfo.RefIdxs[ListNum]; gmbs = m_pCurrentFrame->m_mbinfo.mbs; if (m_CurSliceHeader.MbaffFrameFlag) { Ipp32u lbls=0,lbrs=0,tbls=0,tbrs=0,rbls=0,rbrs=0; switch (m_cur_mb.GlobalMacroblockInfo->mbtype) { case MBTYPE_FORWARD: case MBTYPE_BACKWARD: case MBTYPE_BIDIR: case MBTYPE_SKIPPED: VM_ASSERT(block == 0); Left = m_cur_mb.CurrentBlockNeighbours.mbs_left[0]; Top = m_cur_mb.CurrentBlockNeighbours.mb_above; TopRight = m_cur_mb.CurrentBlockNeighbours.mb_above_right; TopLeft= m_cur_mb.CurrentBlockNeighbours.mb_above_left; isRightUnavailable = (TopRight.mb_num<0); isLeftUnavailable = (TopLeft.mb_num<0); break; case MBTYPE_INTER_16x8: VM_ASSERT(block >= 0 && block <= 1); // First check for availability of directional predictor which is // just used if available. if (block == 0) { // upper half, use predictor from above Top= m_cur_mb.CurrentBlockNeighbours.mb_above; if (Top.mb_num>=0) { tbls=(pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo)-GetMBFieldDecodingFlag(gmbs[Top.mb_num]))>0; tbrs=(pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo)-GetMBFieldDecodingFlag(gmbs[Top.mb_num]))<0; if (IS_INTER_MBTYPE(gmbs[Top.mb_num].mbtype) && (((RefIdxs[Top.mb_num].RefIdxs[Top.block_num]<<tbls)>>tbrs) == RefIndex)) { *pMVx = MVs[Top.mb_num].MotionVectors[Top.block_num].mvx; *pMVy = ((MVs[Top.mb_num].MotionVectors[Top.block_num].mvy+((MVs[Top.mb_num].MotionVectors[Top.block_num].mvy<0)&&tbls))<<tbrs)>>tbls; goto done; } else { goto median16x8_0_aff; } } else {median16x8_0_aff: Left = m_cur_mb.CurrentBlockNeighbours.mbs_left[0]; TopRight = m_cur_mb.CurrentBlockNeighbours.mb_above_right; TopLeft = m_cur_mb.CurrentBlockNeighbours.mb_above_left; // init vars for median prediction isRightUnavailable = (TopRight.mb_num<0); if (isRightUnavailable) isLeftUnavailable = (TopLeft.mb_num<0); } } else { Left = m_cur_mb.CurrentBlockNeighbours.mbs_left[2]; // lower half, use predictor from left if ( Left.mb_num>=0) { lbls=(pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo)-GetMBFieldDecodingFlag(gmbs[Left.mb_num]))>0; lbrs=(pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo)-GetMBFieldDecodingFlag(gmbs[Left.mb_num]))<0; if (IS_INTER_MBTYPE(gmbs[Left.mb_num].mbtype) && (((RefIdxs[Left.mb_num].RefIdxs[Left.block_num]<<lbls)>>lbrs) == RefIndex)) { *pMVx = MVs[Left.mb_num].MotionVectors[Left.block_num].mvx; *pMVy = ((MVs[Left.mb_num].MotionVectors[Left.block_num].mvy+((MVs[Left.mb_num].MotionVectors[Left.block_num].mvy<0)&&lbls))<<lbrs)>>lbls; goto done; } else { goto median_16x8_1_aff; } } else {median_16x8_1_aff: Top.mb_num = m_CurMBAddr; Top.block_num = 4; TopLeft.block_num = 8; GetTopLeftLocationForCurrentMBLumaMBAFF(&TopLeft); // init vars for median prediction isRightUnavailable = 1; isLeftUnavailable = (Left.mb_num<0); } } break; case MBTYPE_INTER_8x16: VM_ASSERT(block >= 0 && block <= 1); // First check for availability of directional predictor which is // just used if available. if (block == 0) { // left half, use predictor from left //LeftBlockNum = block; //LeftMB=GetLeftBlock(pMBInfo,LeftBlockNum); Left = m_cur_mb.CurrentBlockNeighbours.mbs_left[0]; if (Left.mb_num>=0) { lbls=(pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo)-GetMBFieldDecodingFlag(gmbs[Left.mb_num]))>0; lbrs=(pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo)-GetMBFieldDecodingFlag(gmbs[Left.mb_num]))<0; if (IS_INTER_MBTYPE(gmbs[Left.mb_num].mbtype) && (((RefIdxs[Left.mb_num].RefIdxs[Left.block_num]<<lbls)>>lbrs) == RefIndex)) { *pMVx = MVs[Left.mb_num].MotionVectors[Left.block_num].mvx; *pMVy = ((MVs[Left.mb_num].MotionVectors[Left.block_num].mvy+((MVs[Left.mb_num].MotionVectors[Left.block_num].mvy<0)&&lbls))<<lbrs)>>lbls; goto done; } else { goto median_8x16_0_aff; } } else {median_8x16_0_aff: /* TopBlockNum=0; TopLeftBlockNum=0; TopRightBlockNum=1; TopMB=GetTopBlock(pMBInfo,TopBlockNum); TopLeftMB=GetTopLeftBlock(pMBInfo,TopLeftBlockNum); TopRightMB=GetTopRightBlock(pMBInfo,TopRightBlockNum);*/ Top = m_cur_mb.CurrentBlockNeighbours.mb_above; TopRight = m_cur_mb.CurrentBlockNeighbours.mb_above; TopLeft= m_cur_mb.CurrentBlockNeighbours.mb_above_left; TopRight.block_num+=2; // init vars for median prediction isRightUnavailable = (Top.mb_num<0); if (isRightUnavailable) isLeftUnavailable = (TopLeft.mb_num<0); } } else { // right half, use predictor from above right unless unavailable, // then try above left //TopRightBlockNum=3; //TopRightMB=GetTopRightBlock(pMBInfo,TopRightBlockNum); //TopBlockNum=2; //TopMB=GetTopBlock(pMBInfo,TopBlockNum); TopRight= m_cur_mb.CurrentBlockNeighbours.mb_above_right; Top= m_cur_mb.CurrentBlockNeighbours.mb_above; Top.block_num+=2; if ( TopRight.mb_num>=0) { rbls=(pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo)-GetMBFieldDecodingFlag(gmbs[TopRight.mb_num]))>0; rbrs=(pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo)-GetMBFieldDecodingFlag(gmbs[TopRight.mb_num]))<0; if (IS_INTER_MBTYPE(gmbs[TopRight.mb_num].mbtype) && (((RefIdxs[TopRight.mb_num].RefIdxs[TopRight.block_num]<<rbls)>>rbrs) == RefIndex)) { *pMVx = MVs[TopRight.mb_num].MotionVectors[TopRight.block_num].mvx; *pMVy = ((MVs[TopRight.mb_num].MotionVectors[TopRight.block_num].mvy+((MVs[TopRight.mb_num].MotionVectors[TopRight.block_num].mvy<0)&&rbls))<<rbrs)>>rbls; goto done; } } else if ( Top.mb_num>=0) { tbls=(pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo)-GetMBFieldDecodingFlag(gmbs[Top.mb_num]))>0; tbrs=(pGetMBFieldDecodingFlag(m_cur_mb.GlobalMacroblockInfo)-GetMBFieldDecodingFlag(gmbs[Top.mb_num]))<0; if (IS_INTER_MBTYPE(gmbs[Top.mb_num].mbtype) && (((RefIdxs[Top.mb_num].RefIdxs[Top.block_num-1]<<tbls)>>tbrs) == RefIndex)) { *pMVx = MVs[Top.mb_num].MotionVectors[Top.block_num-1].mvx; *pMVy = ((MVs[Top.mb_num].MotionVectors[Top.block_num-1].mvy+((MVs[Top.mb_num].MotionVectors[Top.block_num-1].mvy<0)&&tbls))<<tbrs)>>tbls; goto done; } } //LeftBlockNum=2; //LeftMB=GetLeftBlock(pMBInfo,LeftBlockNum); Left.mb_num=m_CurMBAddr; Left.block_num=1; TopLeft=m_cur_mb.CurrentBlockNeighbours.mb_above; TopLeft.block_num++; // init vars for median prediction isRightUnavailable = (TopRight.mb_num<0); if (isRightUnavailable) isLeftUnavailable = (Top.mb_num<0); } // diff = 2; break; case MBTYPE_INTER_8x8: case MBTYPE_INTER_8x8_REF0: // Each 8x8 block of a macroblock can be subdivided into subblocks, // each having its own MV. The parameter 'block' has block and // subblock information: // block 0..3, bits 2-3 // subblock 0..3, bits 0-1 Ipp32s left_edge_block, top_edge_block, right_edge_block; switch (m_cur_mb.GlobalMacroblockInfo->sbtype[block>>2]) { case SBTYPE_8x8: Top.block_num= Left.block_num= TopLeft.block_num= block2lin[block]; TopRight.block_num= block2lin[block]+1; GetLeftLocationForCurrentMBLumaMBAFF(&Left); GetTopLocationForCurrentMBLumaMBAFF(&Top,0); GetTopRightLocationForCurrentMBLumaMBAFF(&TopRight); GetTopLeftLocationForCurrentMBLumaMBAFF(&TopLeft); switch (block>>2) { case 0: left_edge_block = 1; top_edge_block = 1; isRightUnavailable = (Top.mb_num<0); isLeftUnavailable = (TopLeft.mb_num<0); break; case 1: left_edge_block = 0; top_edge_block = 1; isRightUnavailable = (TopRight.mb_num<0); isLeftUnavailable = (Top.mb_num<0); break; case 2: left_edge_block = 1; top_edge_block = 0; isRightUnavailable = 0; break; case 3: left_edge_block = 0; top_edge_block = 0; isRightUnavailable = 1; isLeftUnavailable = 0; break; } // block right_edge_block = left_edge_block == 0 ? 1 : 0; break; case SBTYPE_8x4: Top.block_num= Left.block_num= TopLeft.block_num= block2lin[block&(-4)]+4*(block&1); TopRight.block_num= block2lin[block&(-4)]+4*(block&1)+1; GetLeftLocationForCurrentMBLumaMBAFF(&Left); GetTopLocationForCurrentMBLumaMBAFF(&Top,0); GetTopRightLocationForCurrentMBLumaMBAFF(&TopRight); GetTopLeftLocationForCurrentMBLumaMBAFF(&TopLeft); left_edge_block = left_edge_tab16_8x4[block]; top_edge_block = top_edge_tab16_8x4[block]; right_edge_block = right_edge_tab16_8x4[block]; if (!top_edge_block) { isRightUnavailable = (above_right_avail_8x4[block] == 0); if (isRightUnavailable) if (left_edge_block) isLeftUnavailable = (Left.mb_num<0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -