📄 erc_do_p.c
字号:
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, imgpel *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;
imgpel *pMB = predMB;
int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0;
int mv_mul;
//FRExt
int f1_x, f1_y, f2_x, f2_y, f3, f4, ifx;
int b8, b4;
int yuv = dec_picture->chroma_format_idc - 1;
int ref_frame = max (mv[2], 0); // !!KS: quick fix, we sometimes seem to get negative ref_pic here, so restrict to zero an above
/* 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 * img->mb_cr_size_y;
img->block_x = img->mb_x * BLOCK_SIZE;
img->pix_c_x = img->mb_x * img->mb_cr_size_x;
mv_mul=4;
// 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;
if (dec_picture->chroma_format_idc != YUV400)
{
// chroma *******************************************************
f1_x = 64/img->mb_cr_size_x;
f2_x=f1_x-1;
f1_y = 64/img->mb_cr_size_y;
f2_y=f1_y-1;
f3=f1_x*f1_y;
f4=f3>>1;
for(uv=0;uv<2;uv++)
{
for (b8=0;b8<(img->num_blk8x8_uv/2);b8++)
{
for(b4=0;b4<4;b4++)
{
joff = subblk_offset_y[yuv][b8][b4];
j4=img->pix_c_y+joff;
ioff = subblk_offset_x[yuv][b8][b4];
i4=img->pix_c_x+ioff;
for(jj=0;jj<4;jj++)
{
jf=(j4+jj)/(img->mb_cr_size_y/4); // jf = Subblock_y-coordinate
for(ii=0;ii<4;ii++)
{
ifx=(i4+ii)/(img->mb_cr_size_x/4); // ifx = Subblock_x-coordinate
i1=(i4+ii)*f1_x + mv[0];
j1=(j4+jj)*f1_y + mv[1];
ii0=max (0, min (i1/f1_x, dec_picture->size_x_cr-1));
jj0=max (0, min (j1/f1_y, dec_picture->size_y_cr-1));
ii1=max (0, min ((i1+f2_x)/f1_x, dec_picture->size_x_cr-1));
jj1=max (0, min ((j1+f2_y)/f1_y, dec_picture->size_y_cr-1));
if1=(i1 & f2_x);
jf1=(j1 & f2_y);
if0=f1_x-if1;
jf0=f1_y-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, imgpel *predMB, frame *recfr,
int32 picSizeX, int32 regionSize)
{
int j, k, xmin, ymin, xmax, ymax;
int32 locationTmp, locationPred;
int uv_x = uv_div[0][dec_picture->chroma_format_idc];
int uv_y = uv_div[1][dec_picture->chroma_format_idc];
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];
}
}
if (dec_picture->chroma_format_idc != YUV400)
{
for (j = (ymin>>uv_y); j <= (ymax>>uv_y); j++)
{
for (k = (xmin>>uv_x); k <= (xmax>>uv_x); k++)
{
locationPred = ((j * picSizeX) >> uv_x) + k;
locationTmp = (j-(ymin>>uv_y)) * img->mb_cr_size_x + (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, imgpel *predMB,
imgpel *recY, int32 picSizeX, int32 regionSize)
{
int i, j, distortion, numOfPredBlocks, threshold = ERC_BLOCK_OK;
imgpel *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((int)(predMB[i] - neighbor[i]));
}
break;
case 5:
neighbor = currBlock - 1;
for ( i = 0; i < regionSize; i++ )
{
distortion += mabs((int)(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((int)(predMB[i+currBlockOffset] - neighbor[i]));
}
break;
case 7:
neighbor = currBlock + regionSize;
currBlockOffset = regionSize-1;
for ( i = 0; i < regionSize; i++ )
{
distortion += mabs((int)(predMB[i*16+currBlockOffset] - neighbor[i*picSizeX]));
}
break;
}
numOfPredBlocks++;
}
}
threshold--;
if (threshold < ERC_BLOCK_CONCEALED)
break;
} while (numOfPredBlocks == 0);
if(numOfPredBlocks == 0)
{
return 0;
// assert (numOfPredBlocks != 0); !!!KS hmm, trying to continue...
}
return (distortion/numOfPredBlocks);
}
// picture error concealment below
/*!
************************************************************************
* \brief
* The motion prediction pixels are calculated from the given location (in
* 1/4 pixel units) of the referenced frame. It copies the sub block from the
* corresponding reference to the frame to be concealed.
*
*************************************************************************
*/
static void buildPredblockRegionYUV(struct img_par *img, int32 *mv,
int x, int y, imgpel *predMB, int list)
{
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;
imgpel *pMB = predMB;
int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0;
int mv_mul;
//FRExt
int f1_x, f1_y, f2_x, f2_y, f3, f4, ifx;
int yuv = dec_picture->chroma_format_idc - 1;
int ref_frame = mv[2];
/* Update coordinates of the current concealed macroblock */
img->mb_x = x/BLOCK_SIZE;
img->mb_y = y/BLOCK_SIZE;
img->block_y = img->mb_y * BLOCK_SIZE;
img->pix_c_y = img->mb_y * img->mb_cr_size_y/4;
img->block_x = img->mb_x * BLOCK_SIZE;
img->pix_c_x = img->mb_x * img->mb_cr_size_x/4;
mv_mul=4;
// luma *******************************************************
vec1_x = x*mv_mul + mv[0];
vec1_y = y*mv_mul + mv[1];
get_block(ref_frame, listX[list], 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][jj]=tmp_block[ii][jj];
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
pMB[i*4+j] = img->mpr[j][i];
}
}
pMB += 16;
if (dec_picture->chroma_format_idc != YUV400)
{
// chroma *******************************************************
f1_x = 64/(img->mb_cr_size_x);
f2_x=f1_x-1;
f1_y = 64/(img->mb_cr_size_y);
f2_y=f1_y-1;
f3=f1_x*f1_y;
f4=f3>>1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -