blob: b7dd271d1be734b38a80eeff7112a90f32029a05 [file] [log] [blame]
/* ///////////////////////////////////////////////////////////////////////
//
// 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) 2008 Intel Corporation. All Rights Reserved.
//
// Description: Parses VC-1 bitstreams.
//
*/
#include "vc1parse.h"
#ifdef VBP
#include "viddec_pm.h"
#endif
/*----------------------------------------------------------------------------*/
/* put one bit into a buffer
* used for bitplane decoding, each bit correspond to a MB
* HW requires row to start at DW (32 bits) boundary
* input: value - bit value
* mbx - image width in MB
* mby - image height in MB
* x - x location (column) of MB in MB unit
* y - y location (row) of MB in MB unit
* output: outp - buffer to fill
*/
//#define put_bit(value,x,y,mbx,mby,invert,outp)
static inline void put_bit( uint32_t value, int x, int y, int mbx, int mby, uint8_t invert, uint32_t* outp)
{
int bit;
uint32_t *out;
bit = mby;
value ^= invert;
if (!value) return; /* assume buffer is initialized with zeros */
out = outp;
/* go to corresponding row location in DW unit */
out += (( mbx + 31 ) >> 5) * y;
out += x >> 5; /* go to corresponding column location in DW unit */
bit = x & 0x1f; /* compute remaining bits */
*out |= 1 << bit; /* put bit */
}
/* if b is the bit at location (x,y)
* b = b^invert
* used for bitplane decoding, each bit correspond to a MB
* HW requires row to start at DW (32 bits) boundary
* input: value - bit value
* x - x location (column) of MB in MB unit
* y - y location (row) of MB in MB unit
* mbx - image width in MB
* output: outp - buffer to fill
* returns bit value
*/
static inline int xor_bit( int x, int y, int mbx, uint32_t invert, uint32_t* outp)
{
int bit;
uint32_t *out;
uint8_t value;
//if (invert == 0) return; /* do nothing if XOR with 0 */
out = outp;
out += (( mbx + 31 ) >> 5) * y; /* go to corresponding row location in DW unit */
out += x >> 5; /* go to corresponding row location in DW unit */
bit = x & 0x1f; /* compute remaining bits */
if (invert == 1)
*out ^= (1 << bit); /* put XOR bit */
value = (*out & (1 << bit)) >> bit; /* return bit value */
return(value);
}
/* get bit at location (x,y)
* used for bitplane decoding, each bit correspond to a MB
* HW requires row to start at DW (32 bits) boundary
* input: value - bit value
* x - x location (column) of MB in MB unit
* y - y location (row) of MB in MB unit
* mbx - image width in MB
* outp - bit buffer in dwords
* returns bit value
*/
static inline int get_bit( int x, int y, int mbx, uint32_t* outp)
{
int bit;
uint32_t *out;
uint8_t value;
out = outp;
out += (( mbx + 31 ) >> 5) * y; /* go to corresponding row location in DW unit */
out += x >> 5; /* go to corresponding row location in DW unit */
bit = x & 0x1f; /* compute remaining bits */
value = (*out & (1 << bit)) >> bit; /* return bit value */
return(value);
}
static void vc1_InverseDiff(vc1_Bitplane *pBitplane, int32_t widthMB, int32_t heightMB)
{
int32_t i, j, previousBit=0, temp;
for (i = 0; i < heightMB; i++)
{
for (j = 0; j < widthMB; j++)
{
if ((i == 0 && j == 0))
{
previousBit=xor_bit(j, i, widthMB, pBitplane->invert,
pBitplane->databits);
}
else if (j == 0) /* XOR with TOP */
{
previousBit = get_bit(0, i-1, widthMB, pBitplane->databits);
temp=xor_bit(j, i, widthMB, previousBit,
pBitplane->databits);
previousBit = temp;
}
//TODO isSameAsTop can be optimized
else if (((i > 0) && (previousBit !=
get_bit(j, i-1, widthMB, pBitplane->databits))))
{
temp=xor_bit(j, i, widthMB, pBitplane->invert,
pBitplane->databits);
previousBit = temp;
}
else
{
temp=xor_bit(j, i, widthMB, previousBit,
pBitplane->databits);
previousBit = temp;
}
}
}
}
/*----------------------------------------------------------------------------*/
/* implement normal 2 mode bitplane decoding, SMPTE 412M 8.7.3.2
* width, height are in MB unit.
*/
static void vc1_Norm2ModeDecode(void* ctxt, vc1_Bitplane *pBitplane,
int32_t width, int32_t height)
{
int32_t i;
int32_t tmp_databits = 0;
int32_t row[2], col[2];
int8_t tmp=0;
/* disable pBitplane->invert in the Norm2 decode stage of
VC1_BITPLANE_DIFF2_MODE */
if (pBitplane->imode == VC1_BITPLANE_DIFF2_MODE)
{
tmp = pBitplane->invert;
pBitplane->invert=0;
}
// By default, initialize the values for the even case
col[0] = 0; /* i%width; */
row[0] = 0; /* i/width; */
col[1] = 1; /* (i+1)%width; */
row[1] = 0; /* (i+1)/width; */
// If width*height is odd, the first bit is the value of the bitplane
// for the first macroblock
if ((width*height) & 1) /* first bit if size is odd */
{
VC1_GET_BITS(1, tmp_databits);
put_bit(tmp_databits, 0, 0, width, height, pBitplane->invert,
pBitplane->databits);
// Modify initialization for odd sizes
col[0] = 1; /* i%width; */
col[1] = 2; /* (i+1)%width; */
// Consider special case where width is 1
if(width == 1)
{
col[0] = 0; /* i%width; */
row[0] = 1; /* i/width; */
col[1] = 0; /* (i+1)%width; */
row[1] = 2; /* (i+1)/width; */
}
}
/* decode every pair of bits in natural scan order */
for (i = (width*height) & 1; i < (width*height/2)*2; i += 2)
{
int32_t tmp = 0;
//col[0]=i%width;
//row[0]=i/width;
//col[1]=(i+1)%width;
//row[1]=(i+1)/width;
VC1_GET_BITS(1, tmp);
if (tmp == 0)
{
put_bit(0, col[0],row[0], width, height, pBitplane->invert,
pBitplane->databits);
put_bit(0, col[1],row[1], width, height, pBitplane->invert,
pBitplane->databits);
}
else
{
VC1_GET_BITS(1, tmp);
if (tmp == 1)
{
put_bit(1, col[0],row[0], width, height, pBitplane->invert,
pBitplane->databits);
put_bit(1, col[1],row[1], width, height, pBitplane->invert,
pBitplane->databits);
}
else
{
VC1_GET_BITS(1, tmp);
if (tmp == 0)
{
put_bit(1, col[0],row[0], width, height, pBitplane->invert,
pBitplane->databits);
put_bit(0, col[1],row[1], width, height, pBitplane->invert,
pBitplane->databits);
}
else
{
put_bit(0, col[0],row[0], width, height, pBitplane->invert,
pBitplane->databits);
put_bit(1, col[1],row[1], width, height, pBitplane->invert,
pBitplane->databits);
}
}
}
// Consider special case where width is 1
if(width == 1)
{
row[0] += 2;
row[1] += 2;
}
else
{
col[0] += 2; /* i%width; */
if ( col[0] >= width )
{
// For odd sizes, col[0] can alternatively start at 0 and 1
col[0] -= width;
row[0]++;
}
col[1] += 2; /* (i+1)%width; */
if ( col[1] >= width )
{
// For odd sizes, col[1] can alternatively start at 0 and 1
col[1] -= width;
row[1]++;
}
}
}
/* restore value */
pBitplane->invert=tmp;
}
/*----------------------------------------------------------------------------*/
/* compute Normal-6 mode bitplane decoding
* algorithm is described in SMPTE 421M 8.7.3.4
* width, height are in MB unit.
*/
static void vc1_Norm6ModeDecode(void* ctxt, vc1_Bitplane *pBitplane,
int32_t width, int32_t height)
{
vc1_Status status;
int32_t i, j, k;
int32_t ResidualX = 0;
int32_t ResidualY = 0;
uint8_t _2x3tiled = (((width%3)!=0)&&((height%3)==0));
int32_t row, col;
int8_t tmp=0;
/* disable pBitplane->invert in the Norm2 decode stage of
VC1_BITPLANE_DIFF2_MODE */
if (pBitplane->imode == VC1_BITPLANE_DIFF6_MODE)
{
tmp = pBitplane->invert;
pBitplane->invert=0;
}
if (_2x3tiled)
{
int32_t sizeW = width/2;
int32_t sizeH = height/3;
for (i = 0; i < sizeH; i++)
{
row = 3*i; /* compute row location for tile */
for (j = 0; j < sizeW; j++)
{
col = 2*j + (width & 1); /* compute column location for tile */
/* get k=sum(bi2^i) were i is the ith bit of the tile */
status = vc1_DecodeHuffmanOne(ctxt, &k, VC1_BITPLANE_K_TBL);
VC1_ASSERT(status == VC1_STATUS_OK);
/* put bits in tile */
put_bit(k&1, col, row, width, height, pBitplane->invert,
pBitplane->databits);
put_bit(((k&2)>>1), col+1, row, width, height,
pBitplane->invert,pBitplane->databits);
put_bit(((k&4)>>2), col, row+1, width, height,
pBitplane->invert,pBitplane->databits);
put_bit(((k&8)>>3), col+1, row+1, width, height,
pBitplane->invert,pBitplane->databits);
put_bit(((k&16)>>4), col, row+2, width, height,
pBitplane->invert,pBitplane->databits);
put_bit(((k&32)>>5), col+1, row+2, width,
height,pBitplane->invert, pBitplane->databits);
}
}
ResidualX = width & 1;
ResidualY = 0;
}
else /* 3x2 tile */
{
int32_t sizeW = width/3;
int32_t sizeH = height/2;
for (i = 0; i < sizeH; i++)
{
row = 2*i + (height&1) ; /* compute row location for tile */
for (j = 0; j < sizeW; j++)
{
col = 3*j + (width%3); /* compute column location for tile */
/* get k=sum(bi2^i) were i is the ith bit of the tile */
status = vc1_DecodeHuffmanOne(ctxt, &k, VC1_BITPLANE_K_TBL);
VC1_ASSERT(status == VC1_STATUS_OK);
put_bit(k&1, col, row, width, height,pBitplane->invert,
pBitplane->databits);
put_bit((k&2)>>1, col+1, row, width, height, pBitplane->invert,
pBitplane->databits);
put_bit((k&4)>>2, col+2, row, width, height, pBitplane->invert,
pBitplane->databits);
put_bit((k&8)>>3, col, row+1, width, height,pBitplane->invert,
pBitplane->databits);
put_bit((k&16)>>4, col+1, row+1, width,
height,pBitplane->invert, pBitplane->databits);
put_bit((k&32)>>5, col+2, row+1, width,
height,pBitplane->invert, pBitplane->databits);
}
}
ResidualX = width % 3;
ResidualY = height & 1;
}
for (i = 0; i < ResidualX; i++)
{
int32_t ColSkip;
VC1_GET_BITS(1, ColSkip);
//if (1 == ColSkip)
{
for(j = 0; j < height; j++)
{
int32_t Value = 0;
if (1 == ColSkip) VC1_GET_BITS(1, Value);
put_bit(Value, i, j, width, height,pBitplane->invert,pBitplane->databits);
}
}
}
for (j = 0; j < ResidualY; j++)
{
int32_t RowSkip;
VC1_GET_BITS(1, RowSkip);
//if (1 == RowSkip)
{
for (i = ResidualX; i < width; i++)
{
int32_t Value = 0;
if (1 == RowSkip) VC1_GET_BITS(1, Value);
put_bit(Value, i, j, width, height,pBitplane->invert,pBitplane->databits);
}
}
}
/* restore value */
pBitplane->invert=tmp;
}
/*----------------------------------------------------------------------------*/
/* initialize bitplane to array of zeros
* each row begins with a dword
* input:
* width: widh in MB unit
* height: height in MB unit
* returns even bitplane size in dwords
*/
int initBitplane(vc1_Bitplane *pBitplane,uint32_t width, uint32_t height)
{
int i;
int numDword = 0;
numDword = ((width + 31)>>5) * height;
numDword += numDword & 1; /* add 1 in case numDword is odd */
for (i=0;i<numDword;i++) pBitplane->databits[i] = 0;
return(numDword);
}
/*----------------------------------------------------------------------------*/
/* modified IPP code for bitplane decoding
* width: width in MB unit
* height: height in MB unit
*/
vc1_Status vc1_DecodeBitplane(void* ctxt, vc1_Info *pInfo,
uint32_t width, uint32_t height, vc1_bpp_type_t bpnum)
{
uint32_t i, j;
uint32_t tempValue;
vc1_Status status = VC1_STATUS_OK;
uint32_t biplaneSz; /* bitplane sz in dwords */
vc1_Bitplane bp;
vc1_Bitplane *bpp = &bp;
// By default, set imode to raw
pInfo->metadata.bp_raw[bpnum - VIDDEC_WORKLOAD_VC1_BITPLANE0] = true;
// bitplane data would be temporarily stored in the vc1 context
bpp->databits = pInfo->bitplane;
/* init bitplane to zero, function retunr bitplane buffer size in dword */
biplaneSz = initBitplane(bpp, width, height);
VC1_GET_BITS(1, tempValue);
bpp->invert = (uint8_t) tempValue;
if ((status = vc1_DecodeHuffmanOne(ctxt, &bpp->imode,VC1_BITPLANE_IMODE_TBL)) != VC1_STATUS_OK)
{
return status;
}
// If the imode is VC1_BITPLANE_RAW_MODE: bitplane information is in the MB layer
// there is no need to parse for bitplane information in the picture layer
// Only bits need to be appropriately set in the block control register
// In all other modes, bitplane information follows and needs to be parsed and sent to the decoder
if (bpp->imode == VC1_BITPLANE_NORM2_MODE)
{
vc1_Norm2ModeDecode(ctxt, bpp, width, height);
}
else if (bpp->imode == VC1_BITPLANE_DIFF2_MODE)
{
vc1_Norm2ModeDecode(ctxt, bpp, width, height);
vc1_InverseDiff(bpp, width, height);
}
else if (bpp->imode == VC1_BITPLANE_NORM6_MODE)
{
vc1_Norm6ModeDecode(ctxt, bpp, width, height);
}
else if (bpp->imode == VC1_BITPLANE_DIFF6_MODE)
{
vc1_Norm6ModeDecode(ctxt, bpp, width, height);
vc1_InverseDiff(bpp, width, height);
}
else if (bpp->imode == VC1_BITPLANE_ROWSKIP_MODE)
{
for (i = 0; i < height; i++)
{
VC1_GET_BITS(1, tempValue);
/* if tempValue==0, put row of zeros Dwords*/
if (tempValue == 1)
{
for (j = 0; j < width; j++)
{
VC1_GET_BITS(1, tempValue);
put_bit( tempValue, j, i, width, height, bpp->invert,bpp->databits);
}
}
else if (bpp->invert) { //TO TEST
for (j = 0; j < width; j++) {
put_bit( 0, j, i, width, height, bpp->invert, bpp->databits);
}
}
}
}
else if (bpp->imode == VC1_BITPLANE_COLSKIP_MODE)
{
for (i = 0; i < width; i++)
{
VC1_GET_BITS(1, tempValue);
/* if tempValue==0, and invert == 0, fill column with zeros */
if (tempValue == 1)
{
for (j = 0; j < height; j++)
{
VC1_GET_BITS(1, tempValue);
put_bit( tempValue, i, j, width, height, bpp->invert, bpp->databits);
}
}
else if (bpp->invert) { // fill column with ones
for (j = 0; j < height; j++) {
put_bit( 0, i, j, width, height, bpp->invert, bpp->databits);
}
}//end for else
}
}
if(bpp->imode != VC1_BITPLANE_RAW_MODE)
{
uint32_t* pl;
int sizeinbytes,nitems,i;
viddec_workload_item_t wi;
uint32_t *bit_dw;
pInfo->metadata.bp_raw[bpnum - VIDDEC_WORKLOAD_VC1_BITPLANE0] = false;
sizeinbytes = ((( width + 31 ) / 32)) * (height) * 4;
pl = bpp->databits;
bit_dw = bpp->databits;
// How many payloads must be generated
nitems = (sizeinbytes + (sizeof(wi.data.data_payload) - 1)) /
sizeof(wi.data.data_payload);
// Dump DMEM to an array of workitems
for( i = 0; i < nitems; i++ )
{
wi.vwi_type = bpnum;
wi.data.data_offset = (char *)pl - (char *)bit_dw; // offset within struct
wi.data.data_payload[0] = pl[0];
wi.data.data_payload[1] = pl[1];
pl += 2;
viddec_pm_append_workitem( ctxt, &wi, false);
}
}
#ifdef VBP
{
viddec_pm_cxt_t *cxt = (viddec_pm_cxt_t *)ctxt;
vc1_viddec_parser_t *parser = (vc1_viddec_parser_t *)(cxt->codec_data);
if (biplaneSz > 4096)
{
/* bigger than we got, so let's bail with a non meaningful error. */
return VC1_STATUS_ERROR;
}
/* At this point bp contains the information we need for the bit-plane */
/* bpnum is the enumeration that tells us which bitplane this is for. */
/* pInfo->picLayerHeader.ACPRED is one of the bitplanes I need to fill.*/
switch (bpnum)
{
case VIDDEC_WORKLOAD_VC1_BITPLANE0:
if (pInfo->picLayerHeader.PTYPE == VC1_B_FRAME)
{
if(bp.imode != VC1_BITPLANE_RAW_MODE)
{
pInfo->picLayerHeader.FORWARDMB.invert = bp.invert;
pInfo->picLayerHeader.FORWARDMB.imode = bp.imode;
for (i = 0; i < biplaneSz; i++)
{
parser->bp_forwardmb[i] = bp.databits[i];
}
pInfo->picLayerHeader.FORWARDMB.databits = parser->bp_forwardmb;
}
else
{
pInfo->picLayerHeader.raw_FORWARDMB = 1;
}
}
if ( (pInfo->picLayerHeader.PTYPE == VC1_I_FRAME)
|| (pInfo->picLayerHeader.PTYPE == VC1_BI_FRAME) )
{
if(bp.imode != VC1_BITPLANE_RAW_MODE)
{
pInfo->picLayerHeader.ACPRED.invert = bp.invert;
pInfo->picLayerHeader.ACPRED.imode = bp.imode;
for (i = 0; i < biplaneSz; i++)
{
parser->bp_acpred[i] = bp.databits[i];
}
pInfo->picLayerHeader.ACPRED.databits = parser->bp_acpred;
}
else
{
pInfo->picLayerHeader.raw_ACPRED = 1;
}
}
if (pInfo->picLayerHeader.PTYPE == VC1_P_FRAME)
{
if(bp.imode != VC1_BITPLANE_RAW_MODE)
{
pInfo->picLayerHeader.MVTYPEMB.invert = bp.invert;
pInfo->picLayerHeader.MVTYPEMB.imode = bp.imode;
for (i = 0; i < biplaneSz; i++)
{
parser->bp_mvtypemb[i] = bp.databits[i];
}
pInfo->picLayerHeader.MVTYPEMB.databits = parser->bp_mvtypemb;
}
else
{
pInfo->picLayerHeader.raw_MVTYPEMB = 1;
}
}
break;
case VIDDEC_WORKLOAD_VC1_BITPLANE1:
if ( (pInfo->picLayerHeader.PTYPE == VC1_I_FRAME)
|| (pInfo->picLayerHeader.PTYPE == VC1_BI_FRAME) )
{
if(bp.imode != VC1_BITPLANE_RAW_MODE)
{
pInfo->picLayerHeader.OVERFLAGS.invert = bp.invert;
pInfo->picLayerHeader.OVERFLAGS.imode = bp.imode;
for (i = 0; i < biplaneSz; i++)
{
parser->bp_overflags[i] = bp.databits[i];
}
pInfo->picLayerHeader.OVERFLAGS.databits = parser->bp_overflags;
}
else
{
pInfo->picLayerHeader.raw_OVERFLAGS = 1;
}
}
if ( (pInfo->picLayerHeader.PTYPE == VC1_P_FRAME)
|| (pInfo->picLayerHeader.PTYPE == VC1_B_FRAME) )
{
if(bp.imode != VC1_BITPLANE_RAW_MODE)
{
pInfo->picLayerHeader.SKIPMB.invert = bp.invert;
pInfo->picLayerHeader.SKIPMB.imode = bp.imode;
for (i = 0; i < biplaneSz; i++)
{
parser->bp_skipmb[i] = bp.databits[i];
}
pInfo->picLayerHeader.SKIPMB.databits = parser->bp_skipmb;
}
else
{
pInfo->picLayerHeader.raw_SKIPMB = 1;
}
}
break;
case VIDDEC_WORKLOAD_VC1_BITPLANE2:
if ( (pInfo->picLayerHeader.PTYPE == VC1_P_FRAME)
|| (pInfo->picLayerHeader.PTYPE == VC1_B_FRAME) )
{
if(bp.imode != VC1_BITPLANE_RAW_MODE)
{
pInfo->picLayerHeader.DIRECTMB.invert = bp.invert;
pInfo->picLayerHeader.DIRECTMB.imode = bp.imode;
for (i = 0; i < biplaneSz; i++)
{
parser->bp_directmb[i] = bp.databits[i];
}
pInfo->picLayerHeader.DIRECTMB.databits = parser->bp_directmb;
}
else
{
pInfo->picLayerHeader.raw_DIRECTMB = 1;
}
}
if ( (pInfo->picLayerHeader.PTYPE == VC1_I_FRAME)
|| (pInfo->picLayerHeader.PTYPE == VC1_BI_FRAME) )
{
if(bp.imode != VC1_BITPLANE_RAW_MODE)
{
pInfo->picLayerHeader.FIELDTX.invert = bp.invert;
pInfo->picLayerHeader.FIELDTX.imode = bp.imode;
for (i = 0; i < biplaneSz; i++)
{
parser->bp_fieldtx[i] = bp.databits[i];
}
pInfo->picLayerHeader.FIELDTX.databits = parser->bp_fieldtx;
}
else
{
pInfo->picLayerHeader.raw_FIELDTX = 1;
}
}
break;
}
}
#endif
return status;
}