?? erc_do_p.c
字號:
/*!
*************************************************************************************
* \file
* erc_do_p.c
*
* \brief
* Inter (P) frame error concealment algorithms for decoder
*
* \author
* - Viktor Varsa <viktor.varsa@nokia.com>
* - Ye-Kui Wang <wyk@ieee.org>
*
*************************************************************************************
*/
#include <stdlib.h>
#include <assert.h>
#include "mbuffer.h"
#include "global.h"
#include "memalloc.h"
#include "erc_do.h"
#include "image.h"
extern int erc_mvperMB;
struct img_par *erc_img;
// static function declarations
static int concealByCopy(frame *recfr, int currMBNum,
objectBuffer_t *object_list, int32 picSizeX);
static int concealByTrial(frame *recfr, byte *predMB,
int currMBNum, objectBuffer_t *object_list, int predBlocks[],
int32 picSizeX, int32 picSizeY, int *yCondition);
static int edgeDistortion (int predBlocks[], int currYBlockNum, byte *predMB,
byte *recY, int32 picSizeX, int32 regionSize);
static void copyBetweenFrames (frame *recfr,
int currYBlockNum, int32 picSizeX, int32 regionSize);
static void buildPredRegionYUV(struct img_par *img, int32 *mv, int x, int y, byte *predMB);
static void copyPredMB (int currYBlockNum, byte *predMB, frame *recfr,
int32 picSizeX, int32 regionSize);
/*!
************************************************************************
* \brief
* The main function for Inter (P) frame concealment.
* \return
* 0, if the concealment was not successful and simple concealment should be used
* 1, otherwise (even if none of the blocks were concealed)
* \param recfr
* Reconstructed frame buffer
* \param object_list
* Motion info for all MBs in the frame
* \param picSizeX
* Width of the frame in pixels
* \param picSizeY
* Height of the frame in pixels
* \param errorVar
* Variables for error concealment
************************************************************************
*/
int ercConcealInterFrame(frame *recfr, objectBuffer_t *object_list,
int32 picSizeX, int32 picSizeY, ercVariables_t *errorVar )
{
int lastColumn = 0, lastRow = 0, predBlocks[8];
int lastCorruptedRow = -1, firstCorruptedRow = -1, currRow = 0,
row, column, columnInd, areaHeight = 0, i = 0;
byte *predMB;
/* if concealment is on */
if ( errorVar && errorVar->concealment )
{
/* if there are segments to be concealed */
if ( errorVar->nOfCorruptedSegments )
{
predMB = (byte *) malloc(DEF_REGION_SIZE);
if ( predMB == NULL ) no_mem_exit("ercConcealInterFrame: predMB");
lastRow = (int) (picSizeY>>4);
lastColumn = (int) (picSizeX>>4);
for ( columnInd = 0; columnInd < lastColumn; columnInd ++)
{
column = ((columnInd%2) ? (lastColumn - columnInd/2 -1) : (columnInd/2));
for ( row = 0; row < lastRow; row++)
{
if ( errorVar->yCondition[MBxy2YBlock(column, row, 0, picSizeX)] <= ERC_BLOCK_CORRUPTED )
{ // ERC_BLOCK_CORRUPTED (1) or ERC_BLOCK_EMPTY (0)
firstCorruptedRow = row;
/* find the last row which has corrupted blocks (in same continuous area) */
for ( lastCorruptedRow = row+1; lastCorruptedRow < lastRow; lastCorruptedRow++)
{
/* check blocks in the current column */
if (errorVar->yCondition[MBxy2YBlock(column, lastCorruptedRow, 0, picSizeX)] > ERC_BLOCK_CORRUPTED)
{
/* current one is already OK, so the last was the previous one */
lastCorruptedRow --;
break;
}
}
if ( lastCorruptedRow >= lastRow )
{
/* correct only from above */
lastCorruptedRow = lastRow-1;
for ( currRow = firstCorruptedRow; currRow < lastRow; currRow++ )
{
ercCollect8PredBlocks (predBlocks, (currRow<<1), (column<<1),
errorVar->yCondition, (lastRow<<1), (lastColumn<<1), 2, 0);
if(erc_mvperMB >= MVPERMB_THR)
concealByTrial(recfr, predMB,
currRow*lastColumn+column, object_list, predBlocks,
picSizeX, picSizeY,
errorVar->yCondition);
else
concealByCopy(recfr, currRow*lastColumn+column,
object_list, picSizeX);
ercMarkCurrMBConcealed (currRow*lastColumn+column, -1, picSizeX, errorVar);
}
row = lastRow;
}
else if ( firstCorruptedRow == 0 )
{
/* correct only from below */
for ( currRow = lastCorruptedRow; currRow >= 0; currRow-- )
{
ercCollect8PredBlocks (predBlocks, (currRow<<1), (column<<1),
errorVar->yCondition, (lastRow<<1), (lastColumn<<1), 2, 0);
if(erc_mvperMB >= MVPERMB_THR)
concealByTrial(recfr, predMB,
currRow*lastColumn+column, object_list, predBlocks,
picSizeX, picSizeY,
errorVar->yCondition);
else
concealByCopy(recfr, currRow*lastColumn+column,
object_list, picSizeX);
ercMarkCurrMBConcealed (currRow*lastColumn+column, -1, picSizeX, errorVar);
}
row = lastCorruptedRow+1;
}
else
{
/* correct bi-directionally */
row = lastCorruptedRow+1;
areaHeight = lastCorruptedRow-firstCorruptedRow+1;
/*
* Conceal the corrupted area switching between the up and the bottom rows
*/
for ( i = 0; i < areaHeight; i++)
{
if ( i % 2 )
{
currRow = lastCorruptedRow;
lastCorruptedRow --;
}
else
{
currRow = firstCorruptedRow;
firstCorruptedRow ++;
}
ercCollect8PredBlocks (predBlocks, (currRow<<1), (column<<1),
errorVar->yCondition, (lastRow<<1), (lastColumn<<1), 2, 0);
if(erc_mvperMB >= MVPERMB_THR)
concealByTrial(recfr, predMB,
currRow*lastColumn+column, object_list, predBlocks,
picSizeX, picSizeY,
errorVar->yCondition);
else
concealByCopy(recfr, currRow*lastColumn+column,
object_list, picSizeX);
ercMarkCurrMBConcealed (currRow*lastColumn+column, -1, picSizeX, errorVar);
}
}
lastCorruptedRow = -1;
firstCorruptedRow = -1;
}
}
}
free(predMB);
}
return 1;
}
else
return 0;
}
/*!
************************************************************************
* \brief
* It conceals a given MB by simply copying the pixel area from the reference image
* that is at the same location as the macroblock in the current image. This correcponds
* to COPY MBs.
* \return
* Always zero (0).
* \param recfr
* Reconstructed frame buffer
* \param currMBNum
* current MB index
* \param object_list
* Motion info for all MBs in the frame
* \param picSizeX
* Width of the frame in pixels
************************************************************************
*/
static int concealByCopy(frame *recfr, int currMBNum,
objectBuffer_t *object_list, int32 picSizeX)
{
objectBuffer_t *currRegion;
currRegion = object_list+(currMBNum<<2);
currRegion->regionMode = REGMODE_INTER_COPY;
currRegion->xMin = (xPosMB(currMBNum,picSizeX)<<4);
currRegion->yMin = (yPosMB(currMBNum,picSizeX)<<4);
copyBetweenFrames (recfr, MBNum2YBlock(currMBNum,0,picSizeX), picSizeX, 16);
return 0;
}
/*!
************************************************************************
* \brief
* Copies the co-located pixel values from the reference to the current frame.
* Used by concealByCopy
* \param recfr
* Reconstructed frame buffer
* \param currYBlockNum
* index of the block (8x8) in the Y plane
* \param picSizeX
* Width of the frame in pixels
* \param regionSize
* can be 16 or 8 to tell the dimension of the region to copy
************************************************************************
*/
static void copyBetweenFrames (frame *recfr,
int currYBlockNum, int32 picSizeX, int32 regionSize)
{
int j, k, location, xmin, ymin;
/* set the position of the region to be copied */
xmin = (xPosYBlock(currYBlockNum,picSizeX)<<3);
ymin = (yPosYBlock(currYBlockNum,picSizeX)<<3);
for (j = ymin; j < ymin + regionSize; j++)
for (k = xmin; k < xmin + regionSize; k++)
{
location = j * picSizeX + k;
recfr->yptr[location] = dec_picture->imgY[j][k];
}
for (j = ymin / 2; j < (ymin + regionSize) / 2; j++)
for (k = xmin / 2; k < (xmin + regionSize) / 2; k++)
{
location = j * picSizeX / 2 + k;
recfr->uptr[location] = dec_picture->imgUV[0][j][k];
recfr->vptr[location] = dec_picture->imgUV[1][j][k];
}
}
/*!
************************************************************************
* \brief
* It conceals a given MB by using the motion vectors of one reliable neighbor. That MV of a
* neighbor is selected wich gives the lowest pixel difference at the edges of the MB
* (see function edgeDistortion). This corresponds to a spatial smoothness criteria.
* \return
* Always zero (0).
* \param recfr
* Reconstructed frame buffer
* \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
* \param currMBNum
* current MB index
* \param object_list
* array of region structures storing region mode and mv for each region
* \param predBlocks
* status array of the neighboring blocks (if they are OK, concealed or lost)
* \param picSizeX
* Width of the frame in pixels
* \param picSizeY
* Height of the frame in pixels
* \param yCondition
* array for conditions of Y blocks from ercVariables_t
************************************************************************
*/
static int concealByTrial(frame *recfr, byte *predMB,
int currMBNum, objectBuffer_t *object_list, int predBlocks[],
int32 picSizeX, int32 picSizeY, int *yCondition)
{
int predMBNum = 0, numMBPerLine,
compSplit1 = 0, compSplit2 = 0, compLeft = 1, comp = 0, compPred, order = 1,
fInterNeighborExists, numIntraNeighbours,
fZeroMotionChecked, predSplitted = 0,
threshold = ERC_BLOCK_OK,
minDist, currDist, i, k, bestDir;
int32 regionSize;
objectBuffer_t *currRegion;
int32 mvBest[3] , mvPred[3], *mvptr;
numMBPerLine = (int) (picSizeX>>4);
comp = 0;
regionSize = 16;
do
{ /* 4 blocks loop */
currRegion = object_list+(currMBNum<<2)+comp;
/* set the position of the region to be concealed */
currRegion->xMin = (xPosYBlock(MBNum2YBlock(currMBNum,comp,picSizeX),picSizeX)<<3);
currRegion->yMin = (yPosYBlock(MBNum2YBlock(currMBNum,comp,picSizeX),picSizeX)<<3);
do
{ /* reliability loop */
minDist = 0;
fInterNeighborExists = 0;
numIntraNeighbours = 0;
fZeroMotionChecked = 0;
/* loop the 4 neighbours */
for (i = 4; i < 8; i++)
{
/* if reliable, try it */
if (predBlocks[i] >= threshold)
{
switch (i)
{
case 4:
predMBNum = currMBNum-numMBPerLine;
compSplit1 = 2;
compSplit2 = 3;
break;
case 5:
predMBNum = currMBNum-1;
compSplit1 = 1;
compSplit2 = 3;
break;
case 6:
predMBNum = currMBNum+numMBPerLine;
compSplit1 = 0;
compSplit2 = 1;
break;
case 7:
predMBNum = currMBNum+1;
compSplit1 = 0;
compSplit2 = 2;
break;
}
/* try the concealment with the Motion Info of the current neighbour
only try if the neighbour is not Intra */
if (isBlock(object_list,predMBNum,compSplit1,INTRA) ||
isBlock(object_list,predMBNum,compSplit2,INTRA))
{
numIntraNeighbours++;
}
else
{
/* if neighbour MB is splitted, try both neighbour blocks */
for (predSplitted = isSplitted(object_list, predMBNum),
compPred = compSplit1;
predSplitted >= 0;
compPred = compSplit2,
predSplitted -= ((compSplit1 == compSplit2) ? 2 : 1))
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -