📄 errorconcealment.c
字号:
} } if (found == -1) pEc->dirUp = 0; return found;}/* * * selectOneMB: * * Parameters: * pEc EC object * * Function: * Select the MB to be concealed, which has the highest rank. * * Returns: * The index of the selected MB * -1, if no MB is selected */static int selectOneMB(errorConcealment_s* pEc, int *isUpOrDown){ int found = -1; if (pEc->dir == 0) { // going downwards found = selectDownwards(pEc); *isUpOrDown = 0; if (found == -1) { found = selectUpwards(pEc); *isUpOrDown = 1; } if (pEc->dirUp) // change the dir pEc->dir = 1; } else if (pEc->dir == 1) { // going upwards found = selectUpwards(pEc); *isUpOrDown = 1; if (found == -1) { found = selectDownwards(pEc); *isUpOrDown = 0; } if (pEc->dirDown) pEc->dir = 0; } return found;}/* * * blkIntraConceal: * * Parameters: * pEc EC object * predY Return pointer for predicted luma pixels * predC Return pointer for predicted chroma pixels * currPic The picture to be concealed * idxX The position of the MB to be intra concealed * idxY The position of the MB to be intra concealed * * Function: * Do Intra concealment for an MB. * * Returns: * - */static void blkIntraConceal(errorConcealment_s *pEc, u_int8 predY[MBK_SIZE][MBK_SIZE], u_int8 predC[MBK_SIZE/2][MBK_SIZE], frmBuf_s *currPic, int idxX, int idxY){ int pxlX, pxlY, x, y, weight, i, comp; int picWidth = pEc->widthMbs * MBK_SIZE; int picWidthC = picWidth >> 1; u_int32 tmp; int neighbourExist = 0; u_int8 *pred, *currY, *currU, *currV, *currC, *src1, *src2; u_int8 srcTop[MBK_SIZE]; u_int8 srcBottom[MBK_SIZE]; u_int8 srcLeft[MBK_SIZE]; u_int8 srcRight[MBK_SIZE]; int tmpPix, step; int gradX, gradY; static const int8 weightTab[16] = {0, 0, 0, 0, 0, 16, 31, 16, 0, 1, 16, 1, 0, 16, 31, 16}; static const int8 gradXtab[16] = {0, 0, 0, 0, 0, -1, -1, -1, 0, 1, 1, 1, 0, 0, 0, 0}; static const int8 gradYtab[16] = {0, 0, 0, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0}; pxlX = idxX * MBK_SIZE; pxlY = idxY * MBK_SIZE; currY = currPic->y + pxlY * picWidth + pxlX; currU = currPic->u + (pxlY>>1) * picWidthC + (pxlX>>1); currV = currPic->v + (pxlY>>1) * picWidthC + (pxlX>>1); // check if correctly received neighbours exist // when the top mb is available if ( idxY > 0 && pEc->decodedMbs[idxY-1][idxX] == 1 ) neighbourExist |= MASK_TOP; // when the bottom mb is available if ( idxY < (pEc->heightMbs-1) && pEc->decodedMbs[idxY+1][idxX] == 1 ) neighbourExist |= MASK_BOTTOM; // when the left mb is available if ( idxX > 0 && pEc->decodedMbs[idxY][idxX-1] == 1 ) neighbourExist |= MASK_LEFT; // when the right mb is available if ( idxX < (pEc->widthMbs-1) && pEc->decodedMbs[idxY][idxX+1] == 1 ) neighbourExist |= MASK_RIGHT; if (neighbourExist == 0) { // Correctly received neighbours does no exist, check if concealed neighbours exist // when the top mb is available if ( idxY > 0 && pEc->decodedMbs[idxY-1][idxX] == 2 ) neighbourExist |= MASK_TOP; // when the bottom mb is available if ( idxY < (pEc->heightMbs-1) && pEc->decodedMbs[idxY+1][idxX] == 2 ) neighbourExist |= MASK_BOTTOM; // when the left mb is available if ( idxX > 0 && pEc->decodedMbs[idxY][idxX-1] == 2 ) neighbourExist |= MASK_LEFT; // when the right mb is available if ( idxX < (pEc->widthMbs-1) && pEc->decodedMbs[idxY][idxX+1] == 2 ) neighbourExist |= MASK_RIGHT; } if (neighbourExist & MASK_TOP) { for (i = 0; i < MBK_SIZE; i++) srcTop[i] = currY[-picWidth + i]; } if (neighbourExist & MASK_BOTTOM) { for (i = 0; i < MBK_SIZE; i++) srcBottom[i] = currY[MBK_SIZE*picWidth + i]; } if (neighbourExist & MASK_LEFT) { for (i = 0; i < MBK_SIZE; i++) srcLeft[i] = currY[i*picWidth-1]; } if (neighbourExist & MASK_RIGHT) { for (i = 0; i < MBK_SIZE; i++) srcRight[i] = currY[i*picWidth + MBK_SIZE]; } if (neighbourExist & (MASK_TOP|MASK_BOTTOM)) { /* * Top and/or bottom macroblocks is available. Perform vertical linear * interpolation. */ if (neighbourExist & MASK_TOP) { src1 = srcTop; src2 = (neighbourExist & MASK_BOTTOM) ? srcBottom : srcTop; } else src1 = src2 = srcBottom; pred = &predY[0][0]; for (x = 0; x < MBK_SIZE; x++) { tmpPix = src1[x] * 16; step = src2[x] - src1[x]; for (y = 0; y < MBK_SIZE; y++) { *pred = (u_int8)((tmpPix + 8) >> 4); pred += MBK_SIZE; tmpPix += step; } pred = pred - MBK_SIZE*MBK_SIZE + 1; } if (neighbourExist & (MASK_LEFT|MASK_RIGHT)) { /* * Left and/or right macroblocks is available. Perform horizontal linear * interpolation and combine results with vertical interpolation results. */ if (neighbourExist & MASK_LEFT) { src1 = srcLeft; src2 = (neighbourExist & MASK_RIGHT) ? srcRight : srcLeft; } else src1 = src2 = srcRight; weight = weightTab[neighbourExist]; // weight at top left corner gradX = gradXtab[neighbourExist]; // change in weight in horizontal direction gradY = gradYtab[neighbourExist]; // change in weight in vertical direction pred = &predY[0][0]; for (y = 0; y < MBK_SIZE; y++) { tmpPix = src1[y] * 16; step = src2[y] - src1[y]; for (x = 0; x < MBK_SIZE; x++) { tmp = (u_int32)weight*tmpPix + (u_int32)(32-weight)*16*(*pred); *pred++ = (u_int8)((tmp + 256) >> 9); tmpPix += step; weight += gradX; } weight = weight - MBK_SIZE*gradX + gradY; } } } else { /* * Left and/or right macroblocks is available. Perform horizontal linear * interpolation. Top and bottom macroblocks are not available. */ if (neighbourExist & MASK_LEFT) { src1 = srcLeft; src2 = (neighbourExist & MASK_RIGHT) ? srcRight : srcLeft; } else src1 = src2 = srcRight; /* Horizontal linear interpolation */ pred = &predY[0][0]; for (y = 0; y < MBK_SIZE; y++) { tmpPix = src1[y] * 16; step = src2[y] - src1[y]; for (x = 0; x < MBK_SIZE; x++) { *pred++ = (u_int8)((tmpPix + 8) >> 4); tmpPix += step; } } } currC = currU; for (comp = 0; comp < 2; comp++) { if (neighbourExist & 0x1) { for (i = 0; i < MBK_SIZE/2; i++) srcTop[i] = currC[-picWidthC + i]; } if (neighbourExist & 0x2) { for (i = 0; i < MBK_SIZE/2; i++) srcBottom[i] = currC[(MBK_SIZE/2)*picWidthC + i]; } if (neighbourExist & 0x4) { for (i = 0; i < MBK_SIZE/2; i++) srcLeft[i] = currC[i*picWidthC-1]; } if (neighbourExist & 0x8) { for (i = 0; i < MBK_SIZE/2; i++) srcRight[i] = currC[i*picWidthC + MBK_SIZE/2]; } if (neighbourExist & (MASK_TOP|MASK_BOTTOM)) { /* * Top and/or bottom macroblocks is available. Perform vertical linear * interpolation. */ if (neighbourExist & MASK_TOP) { src1 = srcTop; src2 = (neighbourExist & MASK_BOTTOM) ? srcBottom : srcTop; } else src1 = src2 = srcBottom; pred = &predC[0][comp*(MBK_SIZE/2)]; for (x = 0; x < MBK_SIZE/2; x++) { tmpPix = src1[x] * 8; step = src2[x] - src1[x]; for (y = 0; y < MBK_SIZE/2; y++) { *pred = (u_int8)((tmpPix + 4) >> 3); pred += MBK_SIZE; tmpPix += step; } pred = pred - (MBK_SIZE/2)*MBK_SIZE + 1; } if (neighbourExist & (MASK_LEFT|MASK_RIGHT)) { /* * Left and/or right macroblocks is available. Perform horizontal linear * interpolation and combine results with vertical interpolation results. */ if (neighbourExist & MASK_LEFT) { src1 = srcLeft; src2 = (neighbourExist & MASK_RIGHT) ? srcRight : srcLeft; } else src1 = src2 = srcRight; weight = weightTab[neighbourExist]; // weight at top left corner gradX = 2*gradXtab[neighbourExist]; // change in weight in horizontal direction gradY = 2*gradYtab[neighbourExist]; // change in weight in vertical direction pred = &predC[0][comp*(MBK_SIZE/2)]; for (y = 0; y < MBK_SIZE/2; y++) { tmpPix = src1[y] * 8; step = src2[y] - src1[y]; for (x = 0; x < MBK_SIZE/2; x++) { tmp = (u_int32)weight*tmpPix + (u_int32)(32-weight)*8*(*pred); *pred++ = (u_int8)((tmp + 128) >> 8); tmpPix += step; weight += gradX; } pred += MBK_SIZE/2; weight = weight - (MBK_SIZE/2)*gradX + gradY; } } } else { /* * Left and/or right macroblocks is available. Perform horizontal linear * interpolation. Top and bottom macroblocks are not available. */ if (neighbourExist & MASK_LEFT) { src1 = srcLeft; src2 = (neighbourExist & MASK_RIGHT) ? srcRight : srcLeft; } else src1 = src2 = srcRight; /* Horizontal linear interpolation */ pred = &predC[0][comp*(MBK_SIZE/2)]; for (y = 0; y < MBK_SIZE/2; y++) { tmpPix = src1[y] * 8; step = src2[y] - src1[y]; for (x = 0; x < MBK_SIZE/2; x++) { *pred++ = (u_int8)((tmpPix + 4) >> 3); tmpPix += step; } pred += MBK_SIZE/2; } } currC = currV; }}/* * * useIntra: * * Parameters: * pEc EC object * refIdxTable Reference Index table * idxX The position of the MB to be concealed * idxY The position of the MB to be concealed * * Function: * Make the decision to do Intra concealment or Inter concealment * * Returns: * 1 Do Intra concealment * 0 Do Inter concealment */static int useIntra(errorConcealment_s* pEc, int8 *refIdxTable, int idxX, int idxY){ int flag = 0; int mbX, mbY; if (refIdxTable == NULL) return 1; // top mbX = idxX; mbY = idxY - 1; if (mbY >= 0) { if (refIdxTable[mbX+mbY*pEc->widthMbs] == -1 && pEc->decodedMbs[mbY][mbX] == 1) flag++; } // bottom mbX = idxX; mbY = idxY + 1; if (mbY < pEc->heightMbs) { if (refIdxTable[mbX+mbY*pEc->widthMbs] == -1 && pEc->decodedMbs[mbY][mbX] == 1) flag++; } // left mbX = idxX - 1; mbY = idxY; if (mbX >= 0) { if (refIdxTable[mbX+mbY*pEc->widthMbs] == -1 && pEc->decodedMbs[mbY][mbX] == 1) flag++; } // right mbX = idxX + 1; mbY = idxY; if (mbX < pEc->widthMbs) { if (refIdxTable[mbX+mbY*pEc->widthMbs] == -1 && pEc->decodedMbs[mbY][mbX] == 1) flag++; } if (flag >= 4) return 1; else return 0;}/* * * bySceneCutDetection: * * Parameters: * pEc EC object * currPic The picture to be concealed * * Function: * Check if the picture is scene cut picture by partly received picture. * * Returns: * 0: Not scene cut picture, or failed in the algorithm * 1: Scene cut picture */#define DEBUG_SCENE_CUT_DETECTION 0static int bySceneCutDetection(errorConcealment_s *pEc, frmBuf_s *currPic, dpb_s *dpb){ frmBuf_s *prevPic; int numMBs; int numSelectedMbs; int countMbs; int i; int j; int k; int x; int y; int xDir; int yDir; int mbOffset; int pixelOffset; int32 diff; int leftBound; int rightBound; int topBound; int bottomBound; int visit; int diffTh = 44/2;#if DEBUG_SCENE_CUT_DETECTION int debugNum[11][9]; FILE *fp; static int count = 0; unsigned char *curr, *prev; #endif#if DEBUG_SCENE_CUT_DETECTION for (y = 0; y < 9; y++) { for (x = 0; x < 11; x++) debugNum[x][y] = -1; } curr = malloc(176*144); prev = malloc(176*144); if (curr == NULL|| prev == NULL) { printf("Error!"); exit(0); } memset(curr, 0, 176*144); memset(prev, 0, 176*144);#endif /* Find the latest decoded ref pic */ if (dpb->fullness > 0) prevPic = dpb->buffers[0]; else prevPic = NULL; /* No stored pictures, we assume the current pictures to be a scene cut picture */ if (prevPic == NULL) return 1; /* 20% Mbs will be used for scene cut detection */ numMBs = pEc->widthMbs * pEc->heightMbs; numSelectedMbs = numMBs / 5; /* As per box-out order to select the MBs to do the scene cut detection */ // init position x = pEc->widthMbs / 2; y = pEc->heightMbs / 2; // init dir xDir = 0; yDir = -1; // init bound leftBound = x; rightBound = x; topBound = y; bottomBound = y; visit = 0; k = 0; countMbs = 0; diff = 0; do { /* calculate the diff */ if (!visit && pEc->decodedMbs[y][x] == 1 && pEc->prevDecodedMbs[y][x] == 1) {#if DEBUG_SCENE_CUT_DETECTION debugNum[x][y] = k;#endif countMbs++; mbOffset = (y * pEc->widthMbs << 8) + (x << 4); // y * MBK_SIZE * pEc->widthMbs * MBK_SIZE + x * MBK_SIZE; for (j = 0; j < MBK_SIZE; j+=2) { for (i = 0; i < MBK_SIZE; i++) { pixelOffset = mbOffset + j * pEc->widthMbs * MBK_SIZE + i; diff += abs(currPic->y[pixelOffset] - prevPic->y[pixelOffset]);#if DEBUG_SCENE_CUT_DETECTION prev[pixelOffset] = prevPic->y[pixelOffset]; curr[pixelOffset] = currPic->y[pixelOffset];#endif } } } if (!visit) k++; if ( xDir == -1 && x == leftBound ) { if (leftBound == 0) visit = 1; else { visit = 0; leftBound = leftBound - 1; x = leftBound; } xDir = 0; yDir = -1; } else if ( xDir == 1 && x == rightBound ) { if (rightBound == pEc->widthMbs - 1) visit = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -