📄 swdec_processblock.c
字号:
/*------------------------------------------------------------------------------
-- --
-- This software is confidential and proprietary and may be used --
-- only as expressly authorized by a licensing agreement from --
-- --
-- Hantro Products Oy. --
-- --
-- In the event of publication, the following notice is applicable: --
-- --
-- (C) COPYRIGHT 2004 HANTRO PRODUCTS OY --
-- ALL RIGHTS RESERVED --
-- --
-- The entire notice above must be reproduced on all copies. --
-- --
--------------------------------------------------------------------------------
--
-- Abstract : Block processing after variable length decoding
--
-------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
Table of contents
1. Include headers
2. External identifiers
3. Module defines
4. Module identifiers
5. Functions
5.1 SwDec_ProcessIntraBlock
5.2 SwDec_ProcessInterBlock
5.3 SwDec_GetReference
5.4 SwDec_ChrMv
5.5 SwDec_GetBlock
5.6 SwDec_FillRow
5.7 SwDec_InterpolateNone
5.8 SwDec_InterpolateVertical
5.9 SwDec_InterpolateHorizontal
5.10 SwDec_InterpolateBoth
5.11 SwDec_AcDcPrediction
5.12 SwDec_WriteIntraOutput
5.13 SwDec_WriteInterOutput
5.14 SwDec_CopyOutput
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
1. Include headers
------------------------------------------------------------------------------*/
#include "SwDec_ProcessBlock.h"
#include "SwDec_Utils.h"
#include "SwDec_Idct.h"
/*------------------------------------------------------------------------------
2. External identifiers
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
3. Module defines
------------------------------------------------------------------------------*/
/* macro to perform division with rounding, divisor has to be positive. Macro
* is tested to work for all dc-scaling and quantization purposes, should not
* be used to anything else unless carefully tested */
#ifndef MP4DEC_H263_ONLY
#define DIV_W_ROUND(a,b) (((a) + ((a)<0 ? -1 : 1)*((i32)(b)>>1))/(i32)(b))
#endif
/*lint -e826 -e702 */
/*------------------------------------------------------------------------------
4. Module identifiers
------------------------------------------------------------------------------*/
#ifndef MP4DEC_H263_ONLY
/* luminance dc scaler for each QP */
static const u32 dcScalerLum[32] = { 0, 8, 8, 8, 8,10,12,14,16,17,18,
19,20,21,22,23,24,25,26,27,28,29,
30,31,32,34,36,38,40,42,44,46};
/* chrominance dc scaler for each QP */
static const u32 dcScalerChr[32] = { 0, 8, 8, 8, 8, 9, 9,10,10,11,11,
12,12,13,13,14,14,15,15,16,16,17,
17,18,18,19,20,21,22,23,24,25};
#endif
/* clipping table for output pixel values */
#ifndef MP4DEC_ARM11
static const u8 clip[768] =
{
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,
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,
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,
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,
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,
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,
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,
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,
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
};
#endif
/*------------------------------------------------------------------------------
4. Local function prototypes
------------------------------------------------------------------------------*/
STATIC void SwDec_GetBlock(u8 *, u8 *, i32, i32, u32, u32, u32, u32);
STATIC void SwDec_FillRow(u8 *, u8 *, i32, u32);
STATIC void SwDec_ChrMv(i16 *, i32 *, i32 *);
STATIC void SwDec_InterpolateNone(u8 *pRef, u8 *pOut, u32 width);
STATIC void SwDec_InterpolateVertical(u8 *pRef, u8 *pOut, u32 width, u32 round);
STATIC void SwDec_InterpolateHorizontal(u8 *pRef, u8 *pOut, u32 width, u32 round);
STATIC void SwDec_InterpolateBoth(u8 *pRef, u8 *pOut, u32 width, u32 round);
/*------------------------------------------------------------------------------
5.1 Function name: SwDec_ProcessIntraBlock
Purpose: Intra block processing.
Input:
pDecContainer pointer to decContainer_t
pData pointer to block data after scanning, partially
inverse quantized (excluding first row and col)
mbNum
blockNum
scanDir scanning mode (SCAN_ZIGZAG, SCAN_HOR, SCAN_VER)
Output:
------------------------------------------------------------------------------*/
void SwDec_ProcessIntraBlock(decContainer_t *pDecContainer, i32 *pData,
u32 mbNum, u32 blockNum, u32 scanDir)
{
ASSERT(pDecContainer);
ASSERT(pData);
ASSERT(mbNum < pDecContainer->VopDesc.totalMbInVop);
ASSERT(blockNum < 6);
ASSERT(scanDir < 3);
ASSERT(MB_IS_INTRA(mbNum));
#ifdef MP4DEC_H263_ONLY
/* copy separately decoded dc coefficient into first data element */
pData[0] = pDecContainer->MbDesc[mbNum].data[blockNum];
/* use constant dc_scaler for short video */
pData[0] *= 8;
/* store inverse quantized dc coefficient */
pDecContainer->MbDesc[mbNum].data[blockNum] = pData[0];
#else
/* copy separately decoded dc coefficient into first data element */
if (pDecContainer->MbDesc[mbNum].flags & USE_INTRA_DC_VLC_MASK)
{
pData[0] = pDecContainer->MbDesc[mbNum].data[blockNum];
}
if (!pDecContainer->StrmStorage.shortVideo)
{
SwDec_AcDcPrediction(pDecContainer, pData, mbNum,
blockNum, scanDir);
}
else
{
/* use constant dc_scaler for short video */
pData[0] *= 8;
/* store inverse quantized dc coefficient */
pDecContainer->MbDesc[mbNum].data[blockNum] = (i16)pData[0];
}
#endif
/* do IDCT for intra block. Coefficients are written directly
* to output picture in the IDCT routine */
SwDec_IdctIntra(pDecContainer, pData, mbNum, blockNum);
}
/*------------------------------------------------------------------------------
5.2 Function name: SwDec_ProcessInterBlock
Purpose: Inter block processing
Input:
pDecContainer pointer to decContainer_t
pData pointer to block data after scanning, partially
inverse quantized (excluding dc coefficient)
mbNum
blockNum
Output:
------------------------------------------------------------------------------*/
void SwDec_ProcessInterBlock(decContainer_t *pDecContainer, i32 *pData,
u32 mbNum, u32 blockNum)
{
u32 i;
/* memory for 64 bytes, has to be word aligned */
u32 ref[16];
u8 *pIn = (u8*)ref;
u8 *pOut = (u8*)ref;
i32 tmp1,tmp2,tmp3,tmp4;
#ifndef MP4DEC_ARM11
const u8* pClipTable = clip+256;
#else
u32 tmpx;
u32 width;
u32 rowOffset,colOffset;
#endif
ASSERT(pDecContainer);
ASSERT(mbNum < pDecContainer->VopDesc.totalMbInVop);
ASSERT(blockNum < 6);
ASSERT(MB_IS_INTER(mbNum));
SwDec_GetReference(pDecContainer, (u8*)ref, mbNum, blockNum);
if (pDecContainer->MbDesc[mbNum].codedBits & (0x20>>blockNum))
{
ASSERT(pData);
SwDec_IdctInter(pData, pDecContainer->StrmStorage.numIdctRows);
/* add reference data and clip to [0,255] */
#ifndef MP4DEC_ARM11
for (i = 4; i ; i--)
{
tmp1 = *pIn++;
/*lint --e(613) */
tmp2 = *pData++;
tmp3 = *pIn++;
tmp4 = *pData++;
*pOut++ = pClipTable[tmp1 + tmp2];
tmp1 = *pIn++;
tmp2 = *pData++;
*pOut++ = pClipTable[tmp3 + tmp4];
tmp3 = *pIn++;
tmp4 = *pData++;
*pOut++ = pClipTable[tmp1 + tmp2];
tmp1 = *pIn++;
tmp2 = *pData++;
*pOut++ = pClipTable[tmp3 + tmp4];
tmp3 = *pIn++;
tmp4 = *pData++;
*pOut++ = pClipTable[tmp1 + tmp2];
tmp1 = *pIn++;
tmp2 = *pData++;
*pOut++ = pClipTable[tmp3 + tmp4];
tmp3 = *pIn++;
tmp4 = *pData++;
*pOut++ = pClipTable[tmp1 + tmp2];
*pOut++ = pClipTable[tmp3 + tmp4];
tmp1 = *pIn++;
tmp2 = *pData++;
tmp3 = *pIn++;
tmp4 = *pData++;
*pOut++ = pClipTable[tmp1 + tmp2];
tmp1 = *pIn++;
tmp2 = *pData++;
*pOut++ = pClipTable[tmp3 + tmp4];
tmp3 = *pIn++;
tmp4 = *pData++;
*pOut++ = pClipTable[tmp1 + tmp2];
tmp1 = *pIn++;
tmp2 = *pData++;
*pOut++ = pClipTable[tmp3 + tmp4];
tmp3 = *pIn++;
tmp4 = *pData++;
*pOut++ = pClipTable[tmp1 + tmp2];
tmp1 = *pIn++;
tmp2 = *pData++;
*pOut++ = pClipTable[tmp3 + tmp4];
tmp3 = *pIn++;
tmp4 = *pData++;
*pOut++ = pClipTable[tmp1 + tmp2];
*pOut++ = pClipTable[tmp3 + tmp4];
}
}
SwDec_WriteInterOutput(pDecContainer, (u8*)ref, mbNum, blockNum);
#else
/* calculate output address */
/* luminance */
if (blockNum < 4)
{
width = pDecContainer->VopDesc.vopWidth*16;
rowOffset = pDecContainer->StrmStorage.row[mbNum]*16 +
(blockNum>>1)*8;
colOffset = pDecContainer->StrmStorage.col[mbNum]*16 +
(blockNum&0x1)*8;
pOut = pDecContainer->pOut + rowOffset*width + colOffset;
}
/* chrominance */
else
{
width = pDecContainer->VopDesc.vopWidth*8;
rowOffset = pDecContainer->StrmStorage.row[mbNum]*8;
colOffset = pDecContainer->StrmStorage.col[mbNum]*8;
pOut = pDecContainer->pOut +
(256+(blockNum&0x1)*64)*pDecContainer->VopDesc.vopWidth*
pDecContainer->VopDesc.vopHeight +
rowOffset*width + colOffset;
}
/* add reference data and saturate to [0,255] by
* using ARM11 SIMD instructions. Writes directly to
* output picture */
__asm
{
MOV i, #8;
loop:
LDR tmpx, [pIn], #4; /* load four pixel (ref) */
LDR tmp1, [pData], #4; /* load IDCT coefficients */
LDR tmp2, [pData], #4;
LDR tmp3, [pData], #4;
LDR tmp4, [pData], #4;
PKHBT tmp1, tmp1, tmp3, LSL #16; /* pack two coefficients */
UADD8TO16 tmp1, tmp1, tmpx; /* add two u8 pels to i16 coeff */
USAT16 tmp1, #8, tmp1; /* saturate two pels [0,255] */
PKHBT tmp2, tmp2, tmp4, LSL #16; /* pack next two coeffs. */
UADD8TO16 tmp2, tmp2, tmpx, ROR #8; /* add pels to coeffs. */
USAT16 tmp2, #8, tmp2; /* saturate two pels [0,255] */
ORR tmp1, tmp1, tmp2, LSL #8; /* pack 4 pels to one word */
STR tmp1, [pOut]; /* store 4 pels to output picture */
LDR tmpx, [pIn], #4;
LDR tmp1, [pData], #4;
LDR tmp2, [pData], #4;
LDR tmp3, [pData], #4;
LDR tmp4, [pData], #4;
PKHBT tmp1, tmp1, tmp3, LSL #16;
UADD8TO16 tmp1, tmp1, tmpx;
USAT16 tmp1, #8, tmp1;
PKHBT tmp2, tmp2, tmp4, LSL #16;
UADD8TO16 tmp2, tmp2, tmpx, ROR #8;
USAT16 tmp2, #8, tmp2;
ORR tmp1, tmp1, tmp2, LSL #8;
STR tmp1, [pOut, #4];
ADD pOut,pOut,width;
SUBS i, i, #1;
BNE loop;
}
}
else
{
SwDec_WriteInterOutput(pDecContainer, (u8*)ref, mbNum, blockNum);
}
#endif
}
/*------------------------------------------------------------------------------
5.3 Function name: SwDec_GetReference
Purpose: Get reference block for inter block motion compensation
Input:
pDecContainer pointer to decContainer_t
pOut pointer to output (where reference block is written)
mbNum
blockNum
Output:
------------------------------------------------------------------------------*/
void SwDec_GetReference(decContainer_t *pDecContainer, u8 *pOut,
u32 mbNum, u32 blockNum)
{
i32 row,col;
i32 horMv, verMv;
u8 *pRef;
ASSERT(pDecContainer);
ASSERT(pOut);
ASSERT(mbNum < pDecContainer->VopDesc.totalMbInVop);
ASSERT(blockNum < 6);
row = (i32)pDecContainer->StrmStorage.row[mbNum];
col = (i32)pDecContainer->StrmStorage.col[mbNum];
if (blockNum < 4)
{
/* half pixel positions */
col *= 32;
row *= 32;
if (blockNum & 0x1)
col += 16;
if (blockNum & 0x2)
row += 16;
/* horizontal position */
col += pDecContainer->MbDesc[mbNum].data[blockNum*2];
/* vertical position */
row += pDecContainer->MbDesc[mbNum].data[blockNum*2+1];
pRef = pDecContainer->pRef;
#ifdef MP4DEC_H263_ONLY
SwDec_GetBlock(pRef, pOut, col, row,
pDecContainer->VopDesc.vopWidth * 16,
pDecContainer->VopDesc.vopWidth * 16,
pDecContainer->VopDesc.vopHeight * 16, 1);
#else
SwDec_GetBlock(pRef, pOut, col, row,
pDecContainer->VopDesc.vopWidth * 16,
pDecContainer->VopDesc.vopWidth * 16,
pDecContainer->VopDesc.vopHeight * 16,
(u32)(pDecContainer->VopDesc.vopRoundingType != 1));
#endif
}
else
{
/* half pixel positions */
col *= 16;
row *= 16;
pRef = pDecContainer->pRef +
(256+(blockNum&0x1)*64)*pDecContainer->VopDesc.vopWidth*
pDecContainer->VopDesc.vopHeight;
SwDec_ChrMv(pDecContainer->MbDesc[mbNum].data,
&horMv, &verMv);
/* horizontal position */
col += horMv;
/* vertical position */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -