?? erc_do_p.c
字號:
/* if Zero Motion Block, do the copying. This option is tried only once */
if (isBlock(object_list, predMBNum, compPred, INTER_COPY))
{
if (fZeroMotionChecked)
{
continue;
}
else
{
fZeroMotionChecked = 1;
mvPred[0] = mvPred[1] = 0;
mvPred[2] = 0;
buildPredRegionYUV(erc_img, mvPred, currRegion->xMin, currRegion->yMin, predMB);
}
}
/* build motion using the neighbour's Motion Parameters */
else if (isBlock(object_list,predMBNum,compPred,INTRA))
{
continue;
}
else
{
mvptr = getParam(object_list, predMBNum, compPred, mv);
mvPred[0] = mvptr[0];
mvPred[1] = mvptr[1];
mvPred[2] = mvptr[2];
buildPredRegionYUV(erc_img, mvPred, currRegion->xMin, currRegion->yMin, predMB);
}
/* measure absolute boundary pixel difference */
currDist = edgeDistortion(predBlocks,
MBNum2YBlock(currMBNum,comp,picSizeX),
predMB, recfr->yptr, picSizeX, regionSize);
/* if so far best -> store the pixels as the best concealment */
if (currDist < minDist || !fInterNeighborExists)
{
minDist = currDist;
bestDir = i;
for (k=0;k<3;k++)
mvBest[k] = mvPred[k];
currRegion->regionMode =
(isBlock(object_list, predMBNum, compPred, INTER_COPY)) ?
((regionSize == 16) ? REGMODE_INTER_COPY : REGMODE_INTER_COPY_8x8) :
((regionSize == 16) ? REGMODE_INTER_PRED : REGMODE_INTER_PRED_8x8);
copyPredMB(MBNum2YBlock(currMBNum,comp,picSizeX), predMB, recfr,
picSizeX, regionSize);
}
fInterNeighborExists = 1;
}
}
}
}
threshold--;
} while ((threshold >= ERC_BLOCK_CONCEALED) && (fInterNeighborExists == 0));
/* always try zero motion */
if (!fZeroMotionChecked)
{
mvPred[0] = mvPred[1] = 0;
mvPred[2] = 0;
buildPredRegionYUV(erc_img, mvPred, currRegion->xMin, currRegion->yMin, predMB);
currDist = edgeDistortion(predBlocks,
MBNum2YBlock(currMBNum,comp,picSizeX),
predMB, recfr->yptr, picSizeX, regionSize);
if (currDist < minDist || !fInterNeighborExists)
{
minDist = currDist;
for (k=0;k<3;k++)
mvBest[k] = mvPred[k];
currRegion->regionMode =
((regionSize == 16) ? REGMODE_INTER_COPY : REGMODE_INTER_COPY_8x8);
copyPredMB(MBNum2YBlock(currMBNum,comp,picSizeX), predMB, recfr,
picSizeX, regionSize);
}
}
for (i=0; i<3; i++)
currRegion->mv[i] = mvBest[i];
yCondition[MBNum2YBlock(currMBNum,comp,picSizeX)] = ERC_BLOCK_CONCEALED;
comp = (comp+order+4)%4;
compLeft--;
} while (compLeft);
return 0;
}
/*!
************************************************************************
* \brief
* Builds the motion prediction pixels from the given location (in 1/4 pixel units)
* of the reference frame. It not only copies the pixel values but builds the interpolation
* when the pixel positions to be copied from is not full pixel (any 1/4 pixel position).
* It copies the resulting pixel vlaues into predMB.
* \param img
* The pointer of img_par struture of current frame
* \param mv
* The pointer of the predicted MV of the current (being concealed) MB
* \param x
* The x-coordinate of the above-left corner pixel of the current MB
* \param y
* The y-coordinate of the above-left corner pixel of the current MB
* \param predMB
* memory area for storing temporary pixel values for a macroblock
* the Y,U,V planes are concatenated y = predMB, u = predMB+256, v = predMB+320
************************************************************************
*/
static void buildPredRegionYUV(struct img_par *img, int32 *mv, int x, int y, byte *predMB)
{
int tmp_block[BLOCK_SIZE][BLOCK_SIZE];
int i=0,j=0,ii=0,jj=0,i1=0,j1=0,j4=0,i4=0;
int jf=0;
int uv;
int vec1_x=0,vec1_y=0;
int ioff,joff;
byte *pMB = predMB;
int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0;
int mv_mul,f1,f2,f3,f4;
int ref_frame = mv[2];
/* Update coordinates of the current concealed macroblock */
img->mb_x = x/MB_BLOCK_SIZE;
img->mb_y = y/MB_BLOCK_SIZE;
img->block_y = img->mb_y * BLOCK_SIZE;
img->pix_c_y = img->mb_y * MB_BLOCK_SIZE/2;
img->block_x = img->mb_x * BLOCK_SIZE;
img->pix_c_x = img->mb_x * MB_BLOCK_SIZE/2;
mv_mul=4;
f1=8;
f2=7;
f3=f1*f1;
f4=f3/2;
// luma *******************************************************
for(j=0;j<MB_BLOCK_SIZE/BLOCK_SIZE;j++)
{
joff=j*4;
j4=img->block_y+j;
for(i=0;i<MB_BLOCK_SIZE/BLOCK_SIZE;i++)
{
ioff=i*4;
i4=img->block_x+i;
vec1_x = i4*4*mv_mul + mv[0];
vec1_y = j4*4*mv_mul + mv[1];
get_block(ref_frame, listX[0], vec1_x,vec1_y,img,tmp_block);
for(ii=0;ii<BLOCK_SIZE;ii++)
for(jj=0;jj<MB_BLOCK_SIZE/BLOCK_SIZE;jj++)
img->mpr[ii+ioff][jj+joff]=tmp_block[ii][jj];
}
}
for (i = 0; i < 16; i++)
{
for (j = 0; j < 16; j++)
{
pMB[i*16+j] = img->mpr[j][i];
}
}
pMB += 256;
// chroma *******************************************************
for(uv=0;uv<2;uv++)
{
for (j=4;j<6;j++)
{
joff=(j-4)*4;
j4=img->pix_c_y+joff;
for(i=0;i<2;i++)
{
ioff=i*4;
i4=img->pix_c_x+ioff;
for(jj=0;jj<4;jj++)
{
jf=(j4+jj)/2;
for(ii=0;ii<4;ii++)
{
if1=(i4+ii)/2;
i1=(img->pix_c_x+ii+ioff)*f1+mv[0];
j1=(img->pix_c_y+jj+joff)*f1+mv[1];
ii0=max (0, min (i1/f1, img->width_cr-1));
jj0=max (0, min (j1/f1, img->height_cr-1));
ii1=max (0, min ((i1+f2)/f1, img->width_cr-1));
jj1=max (0, min ((j1+f2)/f1, img->height_cr-1));
if1=(i1 & f2);
jf1=(j1 & f2);
if0=f1-if1;
jf0=f1-jf1;
img->mpr[ii+ioff][jj+joff]=(if0*jf0*listX[0][ref_frame]->imgUV[uv][jj0][ii0]+
if1*jf0*listX[0][ref_frame]->imgUV[uv][jj0][ii1]+
if0*jf1*listX[0][ref_frame]->imgUV[uv][jj1][ii0]+
if1*jf1*listX[0][ref_frame]->imgUV[uv][jj1][ii1]+f4)/f3;
}
}
}
}
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
pMB[i*8+j] = img->mpr[j][i];
}
}
pMB += 64;
}
}
/*!
************************************************************************
* \brief
* Copies pixel values between a YUV frame and the temporary pixel value storage place. This is
* used to save some pixel values temporarily before overwriting it, or to copy back to a given
* location in a frame the saved pixel values.
* \param currYBlockNum
* index of the block (8x8) in the Y plane
* \param predMB
* memory area where the temporary pixel values are stored
* the Y,U,V planes are concatenated y = predMB, u = predMB+256, v = predMB+320
* \param recfr
* pointer to a YUV frame
* \param picSizeX
* picture width in pixels
* \param regionSize
* can be 16 or 8 to tell the dimension of the region to copy
************************************************************************
*/
static void copyPredMB (int currYBlockNum, byte *predMB, frame *recfr,
int32 picSizeX, int32 regionSize)
{
int j, k, xmin, ymin, xmax, ymax;
int32 locationTmp, locationPred;
xmin = (xPosYBlock(currYBlockNum,picSizeX)<<3);
ymin = (yPosYBlock(currYBlockNum,picSizeX)<<3);
xmax = xmin + regionSize -1;
ymax = ymin + regionSize -1;
for (j = ymin; j <= ymax; j++)
{
for (k = xmin; k <= xmax; k++)
{
locationPred = j * picSizeX + k;
locationTmp = (j-ymin) * 16 + (k-xmin);
dec_picture->imgY[j][k] = predMB[locationTmp];
}
}
for (j = (ymin>>1); j <= (ymax>>1); j++)
{
for (k = (xmin>>1); k <= (xmax>>1); k++)
{
locationPred = j * picSizeX / 2 + k;
locationTmp = (j-(ymin>>1)) * 8 + (k-(xmin>>1)) + 256;
dec_picture->imgUV[0][j][k] = predMB[locationTmp];
locationTmp += 64;
dec_picture->imgUV[1][j][k] = predMB[locationTmp];
}
}
}
/*!
************************************************************************
* \brief
* Calculates a weighted pixel difference between edge Y pixels of the macroblock stored in predMB
* and the pixels in the given Y plane of a frame (recY) that would become neighbor pixels if
* predMB was placed at currYBlockNum block position into the frame. This "edge distortion" value
* is used to determine how well the given macroblock in predMB would fit into the frame when
* considering spatial smoothness. If there are correctly received neighbor blocks (status stored
* in predBlocks) only they are used in calculating the edge distorion; otherwise also the already
* concealed neighbor blocks can also be used.
* \return
* The calculated weighted pixel difference at the edges of the MB.
* \param predBlocks
* status array of the neighboring blocks (if they are OK, concealed or lost)
* \param currYBlockNum
* index of the block (8x8) in the Y plane
* \param predMB
* memory area where the temporary pixel values are stored
* the Y,U,V planes are concatenated y = predMB, u = predMB+256, v = predMB+320
* \param recY
* pointer to a Y plane of a YUV frame
* \param picSizeX
* picture width in pixels
* \param regionSize
* can be 16 or 8 to tell the dimension of the region to copy
************************************************************************
*/
static int edgeDistortion (int predBlocks[], int currYBlockNum, byte *predMB,
byte *recY, int32 picSizeX, int32 regionSize)
{
int i, j, distortion, numOfPredBlocks, threshold = ERC_BLOCK_OK;
byte *currBlock = NULL, *neighbor = NULL;
int32 currBlockOffset = 0;
currBlock = recY + (yPosYBlock(currYBlockNum,picSizeX)<<3)*picSizeX + (xPosYBlock(currYBlockNum,picSizeX)<<3);
do
{
distortion = 0; numOfPredBlocks = 0;
/* loop the 4 neighbours */
for (j = 4; j < 8; j++)
{
/* if reliable, count boundary pixel difference */
if (predBlocks[j] >= threshold)
{
switch (j)
{
case 4:
neighbor = currBlock - picSizeX;
for ( i = 0; i < regionSize; i++ )
{
distortion += mabs(predMB[i] - neighbor[i]);
}
break;
case 5:
neighbor = currBlock - 1;
for ( i = 0; i < regionSize; i++ )
{
distortion += mabs(predMB[i*16] - neighbor[i*picSizeX]);
}
break;
case 6:
neighbor = currBlock + regionSize*picSizeX;
currBlockOffset = (regionSize-1)*16;
for ( i = 0; i < regionSize; i++ )
{
distortion += mabs(predMB[i+currBlockOffset] - neighbor[i]);
}
break;
case 7:
neighbor = currBlock + regionSize;
currBlockOffset = regionSize-1;
for ( i = 0; i < regionSize; i++ )
{
distortion += mabs(predMB[i*16+currBlockOffset] - neighbor[i*picSizeX]);
}
break;
}
numOfPredBlocks++;
}
}
threshold--;
if (threshold < ERC_BLOCK_CONCEALED)
break;
} while (numOfPredBlocks == 0);
if(numOfPredBlocks == 0)
assert (numOfPredBlocks != 0);
return (distortion/numOfPredBlocks);
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -