📄 umc_h264_segment_decoder_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-2007 Intel Corporation. All Rights Reserved.
//
//
*/
#include "umc_defs.h"
#if defined (UMC_ENABLE_H264_VIDEO_DECODER)
#include "umc_h264_segment_decoder.h"
#include "umc_h264_dec.h"
#include "umc_h264_bitstream_inlines.h"
#include "vm_debug.h"
namespace UMC
{
// 0 1 4 5
// 2 3 6 7
// 8 9 c d
// a b e f
const
Ipp8u block2lin[16] =
{
0, 1, 4, 5,
2, 3, 6, 7,
8, 9,12,13,
10,11,14,15
};
void H264SegmentDecoder::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 = NULL; // 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_gmbinfo->MV[ListNum];
RefIdxs = m_gmbinfo->RefIdxs[ListNum];
gmbs = m_gmbinfo->mbs;
if (m_pSliceHeader->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;
return;
}
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;
return;
}
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;
return;
}
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;
return;
}
}
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;
return;
}
}
//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 = 0, top_edge_block = 0, right_edge_block = 0;
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=
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -