/*! ************************************************************************************* * \file mb_access.c * * \brief * Functions for macroblock neighborhoods * * \author * Main contributors (see contributors.h for copyright, address and affiliation details) * - Karsten Sühring ************************************************************************************* */ #include "global.h" #include "mbuffer.h" #include "mb_access.h" /*! ************************************************************************ * \brief * returns 1 if the macroblock at the given address is available ************************************************************************ */ Boolean mb_is_available(int mbAddr, const Macroblock *currMB) { VideoParameters *p_Vid = currMB->p_Vid; if ((mbAddr < 0) || (mbAddr > ((int)p_Vid->dec_picture->PicSizeInMbs - 1))) return FALSE; // the following line checks both: slice number and if the mb has been decoded if (!p_Vid->DeblockCall) { if (p_Vid->mb_data[mbAddr].slice_nr != currMB->slice_nr) return FALSE; } return TRUE; } /*! ************************************************************************ * \brief * Checks the availability of neighboring macroblocks of * the current macroblock for prediction and context determination; ************************************************************************ */ void CheckAvailabilityOfNeighbors(Macroblock *currMB) { VideoParameters *p_Vid = currMB->p_Vid; const int mb_nr = currMB->mbAddrX; // mark all neighbors as unavailable currMB->mb_up = NULL; currMB->mb_left = NULL; if (p_Vid->dec_picture->mb_aff_frame_flag) { int cur_mb_pair = mb_nr >> 1; currMB->mb_addr_left = 2 * (cur_mb_pair - 1); currMB->mb_addr_up = 2 * (cur_mb_pair - p_Vid->dec_picture->PicWidthInMbs); currMB->mb_addr_upper_right = 2 * (cur_mb_pair - p_Vid->dec_picture->PicWidthInMbs + 1); currMB->mb_addr_upper_left = 2 * (cur_mb_pair - p_Vid->dec_picture->PicWidthInMbs - 1); currMB->mb_avail_left = (Boolean) (mb_is_available(currMB->mb_addr_left, currMB) && ((p_Vid->PicPos[cur_mb_pair ][0])!=0)); currMB->mb_avail_up = (Boolean) (mb_is_available(currMB->mb_addr_up, currMB)); currMB->mb_avail_upper_right = (Boolean) (mb_is_available(currMB->mb_addr_upper_right, currMB) && ((p_Vid->PicPos[cur_mb_pair + 1][0])!=0)); currMB->mb_avail_upper_left = (Boolean) (mb_is_available(currMB->mb_addr_upper_left, currMB) && ((p_Vid->PicPos[cur_mb_pair ][0])!=0)); } else { currMB->mb_addr_left = mb_nr - 1; // left? currMB->mb_addr_up = mb_nr - p_Vid->dec_picture->PicWidthInMbs; // up? currMB->mb_addr_upper_right = mb_nr - p_Vid->dec_picture->PicWidthInMbs + 1; // upper right? currMB->mb_addr_upper_left = mb_nr - p_Vid->dec_picture->PicWidthInMbs - 1; // upper left? currMB->mb_avail_left = (Boolean) (mb_is_available(currMB->mb_addr_left, currMB) && ((p_Vid->PicPos[mb_nr ][0])!=0)); currMB->mb_avail_up = (Boolean) (mb_is_available(currMB->mb_addr_up, currMB)); currMB->mb_avail_upper_right = (Boolean) (mb_is_available(currMB->mb_addr_upper_right, currMB) && ((p_Vid->PicPos[mb_nr + 1][0])!=0)); currMB->mb_avail_upper_left = (Boolean) (mb_is_available(currMB->mb_addr_upper_left, currMB) && ((p_Vid->PicPos[mb_nr ][0])!=0)); } if (currMB->mb_avail_left) currMB->mb_left = &(p_Vid->mb_data[currMB->mb_addr_left]); if (currMB->mb_avail_up) currMB->mb_up = &(p_Vid->mb_data[currMB->mb_addr_up]); } /*! ************************************************************************ * \brief * returns the x and y macroblock coordinates for a given MbAddress ************************************************************************ */ void get_mb_block_pos_normal (const h264_pic_position *PicPos, int mb_addr, short *x, short *y) { *x = (short) PicPos[ mb_addr ][0]; *y = (short) PicPos[ mb_addr ][1]; } /*! ************************************************************************ * \brief * returns the x and y macroblock coordinates for a given MbAddress * for mbaff type slices ************************************************************************ */ void get_mb_block_pos_mbaff (const h264_pic_position *PicPos, int mb_addr, short *x, short *y) { *x = (short) PicPos[mb_addr>>1][0]; *y = (short) ((PicPos[mb_addr>>1][1] << 1) + (mb_addr & 0x01)); } /*! ************************************************************************ * \brief * returns the x and y sample coordinates for a given MbAddress ************************************************************************ */ void get_mb_pos (VideoParameters *p_Vid, int mb_addr, const int mb_size[2], short *x, short *y) { p_Vid->get_mb_block_pos(p_Vid->PicPos, mb_addr, x, y); (*x) = (short) ((*x) * mb_size[0]); (*y) = (short) ((*y) * mb_size[1]); } /*! ************************************************************************ * \brief * get neighbouring positions for non-aff coding * \param currMB * current macroblock * \param xN * input x position * \param yN * input y position * \param mb_size * Macroblock size in pixel (according to luma or chroma MB access) * \param pix * returns position informations ************************************************************************ */ void getNonAffNeighbour(const Macroblock *currMB, int xN, int yN, const int mb_size[2], PixelPos *pix) { VideoParameters *p_Vid = currMB->p_Vid; int maxW = mb_size[0], maxH = mb_size[1]; if (xN < 0) { if (yN < 0) { pix->mb_addr = currMB->mb_addr_upper_left; pix->available = currMB->mb_avail_upper_left; } else if (yN < maxH) { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; } else { pix->available = FALSE; } } else if (xN < maxW) { if (yN<0) { pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; } else if (yN < maxH) { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } else { pix->available = FALSE; } } else if (yN < 0) { pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; } else { pix->available = FALSE; } if (pix->available || p_Vid->DeblockCall && pix->mb_addr) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (xN & (maxW - 1)); pix->pos_x = (short) (pix->x + *(CurPos++) * maxW); pix->y = (short) (yN & (maxH - 1)); pix->pos_y = (short) (pix->y + *CurPos * maxH); } } void getNonAffNeighbourXP_NoPos(const Macroblock *currMB, int xN, int yN, const int mb_size[2], PixelPos *pix) { VideoParameters *p_Vid = currMB->p_Vid; int maxW = mb_size[0], maxH = mb_size[1]; if (xN < 0) { if (yN < maxH) { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; } else { pix->available = FALSE; } } else if (xN < maxW) { if (yN < maxH) { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } else { pix->available = FALSE; } } else { pix->available = FALSE; } if (pix->available) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (xN & (maxW - 1)); pix->y = (short) (yN & (maxH - 1)); } } void getNonAffNeighbourPX_NoPos(const Macroblock *currMB, int xN, int yN, const int mb_size[2], PixelPos *pix) { VideoParameters *p_Vid = currMB->p_Vid; int maxW = mb_size[0], maxH = mb_size[1]; if (xN < maxW) { if (yN<0) { pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; } else if (yN < maxH) { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } else { pix->available = FALSE; } } else if (yN < 0) { pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; } else { pix->available = FALSE; } if (pix->available) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (xN & (maxW - 1)); pix->y = (short) (yN & (maxH - 1)); } } void getNonAffNeighbourLuma(const Macroblock *currMB, int xN, int yN, PixelPos *pix) { VideoParameters *p_Vid = currMB->p_Vid; if (xN < 0) { if (yN < 0) { pix->mb_addr = currMB->mb_addr_upper_left; pix->available = currMB->mb_avail_upper_left; } else if (yN < 16) { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; } else { pix->available = FALSE; } } else if (xN < 16) { if (yN<0) { pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; } else if (yN < 16) { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } else { pix->available = FALSE; } } else if (yN < 0) { pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; } else { pix->available = FALSE; } if (pix->available || p_Vid->DeblockCall && pix->mb_addr) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (xN & 15); pix->pos_x = (short) (pix->x + *(CurPos++) * 16); pix->y = (short) (yN & 15); pix->pos_y = (short) (pix->y + *CurPos * 16); } } void getNonAffNeighbourXPLuma(const Macroblock *currMB, int xN, int yN, PixelPos *pix) // yN >= 0 { VideoParameters *p_Vid = currMB->p_Vid; if (xN < 0) { if (yN < 16) { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; } else { pix->available = FALSE; } } else if (xN < 16) { if (yN < 16) { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } else { pix->available = FALSE; } } else { pix->available = FALSE; } if (pix->available || p_Vid->DeblockCall && pix->mb_addr) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (xN & 15); pix->pos_x = (short) (pix->x + *(CurPos++) * 16); pix->y = (short) (yN & 15); pix->pos_y = (short) (pix->y + *CurPos * 16); } } void getNonAffNeighbourXPLumaNB(const Macroblock *currMB, int xN, int yN, PixelPos *pix) // yN >= 0 { VideoParameters *p_Vid = currMB->p_Vid; assert(!p_Vid->DeblockCall); if (xN < 0) { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; } else { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } if (pix->available) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->pos_x = (short) ((xN & 15) + *(CurPos++) * 16); pix->pos_y = (short) (yN + *CurPos * 16); } } void getNonAffNeighbourPPLumaNB(const Macroblock *currMB, int xN, int yN, PixelPos *pix) // yN >= 0, xN >= 0 { VideoParameters *p_Vid = currMB->p_Vid; assert(!p_Vid->DeblockCall); pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->pos_x = (short) ((xN & 15) + *(CurPos++) * 16); pix->pos_y = (short) (yN + *CurPos * 16); } } void getNonAffNeighbourXPLumaNB_NoPos(const Macroblock *currMB, int xN, int yN, PixelPos *pix) // yN >= 0 { assert(!currMB->p_Vid->DeblockCall); if (xN < 0) { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; } else { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } if (pix->available) { pix->x = (short) (xN & 15); pix->y = (short) (yN); } } void getNonAffNeighbourNPLumaNB(const Macroblock *currMB, int yN, PixelPos *pix) // xN = -1, yN >= 0 && yN < 16 { VideoParameters *p_Vid = currMB->p_Vid; pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (pix->available || p_Vid->DeblockCall && pix->mb_addr) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; //pix->x = (short) (-1 & 15); pix->pos_x = (short) ((-1 & 15) + *(CurPos++) * 16); pix->y = (short) (yN); pix->pos_y = (short) (yN + *CurPos * 16); } } void getNonAffNeighbourPXLuma(const Macroblock *currMB, int xN, int yN, PixelPos *pix) // xN is >= 0 { VideoParameters *p_Vid = currMB->p_Vid; if (xN < 16) { if (yN<0) { pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; } else if (yN < 16) { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } else { pix->available = FALSE; } } else if (yN < 0) { pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; } else { pix->available = FALSE; } if (pix->available || p_Vid->DeblockCall && pix->mb_addr) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (xN & 15); pix->pos_x = (short) (pix->x + *(CurPos++) * 16); pix->y = (short) (yN & 15); pix->pos_y = (short) (pix->y + *CurPos * 16); } } void getNonAffNeighbourPXLumaNB(const Macroblock *currMB, int xN, int yN, PixelPos *pix) // xN is >= 0 { VideoParameters *p_Vid = currMB->p_Vid; assert(!p_Vid->DeblockCall); if (yN<0) { pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; } else { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } if (pix->available) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->pos_x = (short) (xN + *(CurPos++) * 16); pix->pos_y = (short) ((yN & 15) + *CurPos * 16); } } void getNonAffNeighbourPXLumaNB_NoPos(const Macroblock *currMB, int yN, PixelPos *pix) // xN is >= 0 { assert(!currMB->p_Vid->DeblockCall); if (yN<0) { pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; } else { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } if (pix->available) { pix->y = (short) (yN & 15); } } void getNonAffNeighbourN0Luma(const Macroblock *currMB, PixelPos *pix) // xN = -1, yN = 0 { VideoParameters *p_Vid = currMB->p_Vid; assert(p_Vid->DeblockCall == 0); pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (pix->available) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (-1 & 15); pix->pos_x = (short) (pix->x + *(CurPos++) * 16); pix->y = 0; pix->pos_y = (short) (*CurPos * 16); } } void getNonAffNeighbourN0(const Macroblock *currMB, const int mb_size[2], PixelPos *pix) // xN = -1, yN = 0 { VideoParameters *p_Vid = currMB->p_Vid; int maxW = mb_size[0], maxH = mb_size[1]; assert(maxH != 0); assert(p_Vid->DeblockCall == 0); pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (pix->available) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (-1 & (maxW - 1)); pix->pos_x = (short) (pix->x + *(CurPos++) * maxW); pix->y = 0; pix->pos_y = (short) (*CurPos * maxH); } } void getNonAffNeighbour0N(const Macroblock *currMB, const int mb_size[2], PixelPos *pix) // xN = 0, yN = -1 { VideoParameters *p_Vid = currMB->p_Vid; int maxW = mb_size[0], maxH = mb_size[1]; assert(maxW != 0); pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; if (pix->available) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = 0; pix->pos_x = (short) (*(CurPos++) * maxW); pix->y = (short) (-1 & (maxH - 1)); pix->pos_y = (short) (pix->y + *CurPos * maxH); } } void getNonAffNeighbour0NLuma(const Macroblock *currMB, PixelPos *pix) // xN = 0, yN = -1 { VideoParameters *p_Vid = currMB->p_Vid; pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; if (pix->available) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = 0; pix->pos_x = (short) (*(CurPos++) * 16); pix->y = (short) (-1 & (16 - 1)); pix->pos_y = (short) (pix->y + *CurPos * 16); } } void getNonAffNeighbourNX(const Macroblock *currMB, int yN, const int mb_size[2], PixelPos *pix) // xN = -1, yN full range { VideoParameters *p_Vid = currMB->p_Vid; int maxW = mb_size[0], maxH = mb_size[1]; if (yN < 0) { pix->mb_addr = currMB->mb_addr_upper_left; pix->available = currMB->mb_avail_upper_left; } else if (yN < maxH) { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; } else { pix->available = FALSE; } if (pix->available || p_Vid->DeblockCall && pix->mb_addr) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (-1 & (maxW - 1)); pix->pos_x = (short) (pix->x + *(CurPos++) * maxW); pix->y = (short) (yN & (maxH - 1)); pix->pos_y = (short) (pix->y + *CurPos * maxH); } } void getNonAffNeighbourNXLuma(const Macroblock *currMB, int yN, PixelPos *pix) // xN = -1, yN full range { VideoParameters *p_Vid = currMB->p_Vid; if (yN < 0) { pix->mb_addr = currMB->mb_addr_upper_left; pix->available = currMB->mb_avail_upper_left; } else if (yN < 16) { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; } else { pix->available = FALSE; } if (pix->available || p_Vid->DeblockCall && pix->mb_addr) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (-1 & (16 - 1)); pix->pos_x = (short) (pix->x + *(CurPos++) * 16); pix->y = (short) (yN & (16 - 1)); pix->pos_y = (short) (pix->y + *CurPos * 16); } } void getNonAffNeighbourNP(const Macroblock *currMB, int yN, const int mb_size[2], PixelPos *pix) // xN < 0, yN >= 0 { VideoParameters *p_Vid = currMB->p_Vid; int maxW = mb_size[0], maxH = mb_size[1]; if (yN < maxH) { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (pix->available) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->pos_x = (short) ((-1 & (maxW - 1)) + *(CurPos++) * maxW); pix->pos_y = (short) (yN + *CurPos * maxH); } } else { pix->available = FALSE; } } void getNonAffNeighbourNPChromaNB(const Macroblock *currMB, int yN, const int mb_size[2], PixelPos *pix) // xN < 0, yN >= 0 { VideoParameters *p_Vid = currMB->p_Vid; int maxW = mb_size[0], maxH = mb_size[1]; pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (pix->available) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->pos_x = (short) ((-1 & (maxW - 1)) + *(CurPos++) * maxW); pix->pos_y = (short) (yN + *CurPos * maxH); } } void getNonAffNeighbour0X(const Macroblock *currMB, int yN, const int mb_size[2], PixelPos *pix) // xN is guaranteed to be zero { VideoParameters *p_Vid = currMB->p_Vid; int maxW = mb_size[0], maxH = mb_size[1]; if (0 < maxW) { if (yN<0) { pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; } else if (yN < maxH) { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } else { pix->available = FALSE; } } else if (yN < 0) { pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; } else { pix->available = FALSE; } if (pix->available || p_Vid->DeblockCall && pix->mb_addr) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = 0; pix->pos_x = (short) (*(CurPos++) * maxW); pix->y = (short) (yN & (maxH - 1)); pix->pos_y = (short) (pix->y + *CurPos * maxH); } } void getNonAffNeighbour0XLuma(const Macroblock *currMB, int yN, PixelPos *pix) // xN is guaranteed to be zero { VideoParameters *p_Vid = currMB->p_Vid; int maxW = 16, maxH = 16; if (yN<0) { pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; } else if (yN < 16) { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } else { pix->available = FALSE; } if (pix->available || p_Vid->DeblockCall && pix->mb_addr) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = 0; pix->pos_x = (short) (*(CurPos++) * maxW); pix->y = (short) (yN & (maxH - 1)); pix->pos_y = (short) (pix->y + *CurPos * maxH); } } void getNonAffNeighbourX0(const Macroblock *currMB, int xN, const int mb_size[2], PixelPos *pix) // xN is full range, yN is 0 { VideoParameters *p_Vid = currMB->p_Vid; int maxW = mb_size[0], maxH = mb_size[1]; if (xN < 0) { if (0 < maxH) { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; } else { pix->available = FALSE; } } else if (xN < maxW) { if (0 < maxH) { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; } else { pix->available = FALSE; } } else { pix->available = FALSE; } if (pix->available || p_Vid->DeblockCall && pix->mb_addr && p_Vid) { const int *CurPos = &p_Vid->PicPos[ pix->mb_addr ][0]; pix->x = (short) (xN & (maxW - 1)); pix->pos_x = (short) (pix->x + *(CurPos++) * maxW); pix->y = 0; pix->pos_y = (short) (*CurPos * maxH); } } /*! ************************************************************************ * \brief * get neighboring positions for aff coding * \param currMB * current macroblock * \param xN * input x position * \param yN * input y position * \param mb_size * Macroblock size in pixel (according to luma or chroma MB access) * \param pix * returns position informations ************************************************************************ */ void getAffNeighbour(const Macroblock *currMB, int xN, int yN, const int mb_size[2], PixelPos *pix) { VideoParameters *p_Vid = currMB->p_Vid; int maxW, maxH; int yM = -1; maxW = mb_size[0]; maxH = mb_size[1]; // initialize to "not available" pix->available = FALSE; if(yN > (maxH - 1)) { return; } if (xN > (maxW - 1) && yN >= 0 && yN < maxH) { return; } if (xN < 0) { if (yN < 0) { if(!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_left + 1; pix->available = currMB->mb_avail_upper_left; yM = yN; } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = yN; } else { (pix->mb_addr)++; yM = (yN + maxH) >> 1; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_left; pix->available = currMB->mb_avail_upper_left; if (currMB->mb_avail_upper_left) { if(!p_Vid->mb_data[currMB->mb_addr_upper_left].mb_field) { (pix->mb_addr)++; yM = 2 * yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_upper_left+1; pix->available = currMB->mb_avail_upper_left; yM = yN; } } } else { // xN < 0 && yN >= 0 if (yN mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = yN >> 1; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { (pix->mb_addr)++; yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = (yN + maxH) >> 1; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = yN << 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) - maxH; } } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = (yN << 1) + 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) + 1 - maxH; } } else { (pix->mb_addr)++; yM = yN; } } } } } } } else { // xN >= 0 if (xN >= 0 && xN < maxW) { if (yN<0) { if (!currMB->mb_field) { //frame if ((currMB->mbAddrX & 0x01) == 0) { //top pix->mb_addr = currMB->mb_addr_up; // for the deblocker if the current MB is a frame and the one above is a field // then the neighbor is the top MB of the pair if (currMB->mb_avail_up) { if (!(p_Vid->DeblockCall == 1 && (p_Vid->mb_data[currMB->mb_addr_up]).mb_field)) pix->mb_addr += 1; } pix->available = currMB->mb_avail_up; yM = yN; } else { // bottom pix->mb_addr = currMB->mbAddrX - 1; pix->available = TRUE; yM = yN; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; if (currMB->mb_avail_up) { if(!p_Vid->mb_data[currMB->mb_addr_up].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_up + 1; pix->available = currMB->mb_avail_up; yM = yN; } } } else { // yN >=0 // for the deblocker if this is the extra edge then do this special stuff if (yN == 0 && p_Vid->DeblockCall == 2) { pix->mb_addr = currMB->mb_addr_up + 1; pix->available = TRUE; yM = yN - 1; } else if ((yN mb_addr = currMB->mbAddrX; pix->available = TRUE; yM = yN; } } } else { // xN >= maxW if(yN < 0) { if (!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = yN; } else { // bottom pix->available = FALSE; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; if (currMB->mb_avail_upper_right) { if(!p_Vid->mb_data[currMB->mb_addr_upper_right].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = yN; } } } } } if (pix->available || p_Vid->DeblockCall) { pix->x = (short) (xN & (maxW - 1)); pix->y = (short) (yM & (maxH - 1)); get_mb_pos(p_Vid, pix->mb_addr, mb_size, &(pix->pos_x), &(pix->pos_y)); pix->pos_x = pix->pos_x + pix->x; pix->pos_y = pix->pos_y + pix->y; } } void getAffNeighbourNX(const Macroblock *currMB, int yN, const int mb_size[2], PixelPos *pix) { VideoParameters *p_Vid = currMB->p_Vid; int maxW, maxH; int yM = -1; int xN = -1; maxW = mb_size[0]; maxH = mb_size[1]; // initialize to "not available" pix->available = FALSE; if(yN > (maxH - 1)) { return; } if (xN > (maxW - 1) && yN >= 0 && yN < maxH) { return; } if (xN < 0) { if (yN < 0) { if(!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_left + 1; pix->available = currMB->mb_avail_upper_left; yM = yN; } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = yN; } else { (pix->mb_addr)++; yM = (yN + maxH) >> 1; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_left; pix->available = currMB->mb_avail_upper_left; if (currMB->mb_avail_upper_left) { if(!p_Vid->mb_data[currMB->mb_addr_upper_left].mb_field) { (pix->mb_addr)++; yM = 2 * yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_upper_left+1; pix->available = currMB->mb_avail_upper_left; yM = yN; } } } else { // xN < 0 && yN >= 0 if (yN mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = yN >> 1; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { (pix->mb_addr)++; yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = (yN + maxH) >> 1; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = yN << 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) - maxH; } } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = (yN << 1) + 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) + 1 - maxH; } } else { (pix->mb_addr)++; yM = yN; } } } } } } } else { // xN >= 0 if (xN >= 0 && xN < maxW) { if (yN<0) { if (!currMB->mb_field) { //frame if ((currMB->mbAddrX & 0x01) == 0) { //top pix->mb_addr = currMB->mb_addr_up; // for the deblocker if the current MB is a frame and the one above is a field // then the neighbor is the top MB of the pair if (currMB->mb_avail_up) { if (!(p_Vid->DeblockCall == 1 && (p_Vid->mb_data[currMB->mb_addr_up]).mb_field)) pix->mb_addr += 1; } pix->available = currMB->mb_avail_up; yM = yN; } else { // bottom pix->mb_addr = currMB->mbAddrX - 1; pix->available = TRUE; yM = yN; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; if (currMB->mb_avail_up) { if(!p_Vid->mb_data[currMB->mb_addr_up].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_up + 1; pix->available = currMB->mb_avail_up; yM = yN; } } } else { // yN >=0 // for the deblocker if this is the extra edge then do this special stuff if (yN == 0 && p_Vid->DeblockCall == 2) { pix->mb_addr = currMB->mb_addr_up + 1; pix->available = TRUE; yM = yN - 1; } else if ((yN mb_addr = currMB->mbAddrX; pix->available = TRUE; yM = yN; } } } else { // xN >= maxW if(yN < 0) { if (!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = yN; } else { // bottom pix->available = FALSE; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; if (currMB->mb_avail_upper_right) { if(!p_Vid->mb_data[currMB->mb_addr_upper_right].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = yN; } } } } } if (pix->available || p_Vid->DeblockCall) { pix->x = (short) (xN & (maxW - 1)); pix->y = (short) (yM & (maxH - 1)); get_mb_pos(p_Vid, pix->mb_addr, mb_size, &(pix->pos_x), &(pix->pos_y)); pix->pos_x = pix->pos_x + pix->x; pix->pos_y = pix->pos_y + pix->y; } } void getAffNeighbourNXLuma(const Macroblock *currMB, int yN, PixelPos *pix) { const int mb_size[2]={16,16}; getAffNeighbourNX(currMB, yN, mb_size, pix); } void getAffNeighbourN0(const Macroblock *currMB, const int mb_size[2], PixelPos *pix) { VideoParameters *p_Vid = currMB->p_Vid; int maxW, maxH; int yM = -1; int xN = -1; int yN=0; maxW = mb_size[0]; maxH = mb_size[1]; // initialize to "not available" pix->available = FALSE; if(yN > (maxH - 1)) { return; } if (xN > (maxW - 1) && yN >= 0 && yN < maxH) { return; } if (xN < 0) { if (yN < 0) { if(!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_left + 1; pix->available = currMB->mb_avail_upper_left; yM = yN; } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = yN; } else { (pix->mb_addr)++; yM = (yN + maxH) >> 1; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_left; pix->available = currMB->mb_avail_upper_left; if (currMB->mb_avail_upper_left) { if(!p_Vid->mb_data[currMB->mb_addr_upper_left].mb_field) { (pix->mb_addr)++; yM = 2 * yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_upper_left+1; pix->available = currMB->mb_avail_upper_left; yM = yN; } } } else { // xN < 0 && yN >= 0 if (yN mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = yN >> 1; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { (pix->mb_addr)++; yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = (yN + maxH) >> 1; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = yN << 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) - maxH; } } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = (yN << 1) + 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) + 1 - maxH; } } else { (pix->mb_addr)++; yM = yN; } } } } } } } else { // xN >= 0 if (xN >= 0 && xN < maxW) { if (yN<0) { if (!currMB->mb_field) { //frame if ((currMB->mbAddrX & 0x01) == 0) { //top pix->mb_addr = currMB->mb_addr_up; // for the deblocker if the current MB is a frame and the one above is a field // then the neighbor is the top MB of the pair if (currMB->mb_avail_up) { if (!(p_Vid->DeblockCall == 1 && (p_Vid->mb_data[currMB->mb_addr_up]).mb_field)) pix->mb_addr += 1; } pix->available = currMB->mb_avail_up; yM = yN; } else { // bottom pix->mb_addr = currMB->mbAddrX - 1; pix->available = TRUE; yM = yN; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; if (currMB->mb_avail_up) { if(!p_Vid->mb_data[currMB->mb_addr_up].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_up + 1; pix->available = currMB->mb_avail_up; yM = yN; } } } else { // yN >=0 // for the deblocker if this is the extra edge then do this special stuff if (yN == 0 && p_Vid->DeblockCall == 2) { pix->mb_addr = currMB->mb_addr_up + 1; pix->available = TRUE; yM = yN - 1; } else if ((yN mb_addr = currMB->mbAddrX; pix->available = TRUE; yM = yN; } } } else { // xN >= maxW if(yN < 0) { if (!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = yN; } else { // bottom pix->available = FALSE; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; if (currMB->mb_avail_upper_right) { if(!p_Vid->mb_data[currMB->mb_addr_upper_right].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = yN; } } } } } if (pix->available || p_Vid->DeblockCall) { pix->x = (short) (xN & (maxW - 1)); pix->y = (short) (yM & (maxH - 1)); get_mb_pos(p_Vid, pix->mb_addr, mb_size, &(pix->pos_x), &(pix->pos_y)); pix->pos_x = pix->pos_x + pix->x; pix->pos_y = pix->pos_y + pix->y; } } void getAffNeighbourLuma(const Macroblock *currMB, int xN, int yN, PixelPos *pix) { VideoParameters *p_Vid = currMB->p_Vid; const int maxW=16, maxH=16; int yM = -1; // initialize to "not available" pix->available = FALSE; if(yN > (maxH - 1)) { return; } if (xN > (maxW - 1) && yN >= 0 && yN < maxH) { return; } if (xN < 0) { if (yN < 0) { if(!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_left + 1; pix->available = currMB->mb_avail_upper_left; yM = yN; } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = yN; } else { (pix->mb_addr)++; yM = (yN + maxH) >> 1; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_left; pix->available = currMB->mb_avail_upper_left; if (currMB->mb_avail_upper_left) { if(!p_Vid->mb_data[currMB->mb_addr_upper_left].mb_field) { (pix->mb_addr)++; yM = 2 * yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_upper_left+1; pix->available = currMB->mb_avail_upper_left; yM = yN; } } } else { // xN < 0 && yN >= 0 if (yN mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = yN >> 1; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { (pix->mb_addr)++; yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = (yN + maxH) >> 1; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = yN << 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) - maxH; } } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = (yN << 1) + 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) + 1 - maxH; } } else { (pix->mb_addr)++; yM = yN; } } } } } } } else { // xN >= 0 if (xN >= 0 && xN < maxW) { if (yN<0) { if (!currMB->mb_field) { //frame if ((currMB->mbAddrX & 0x01) == 0) { //top pix->mb_addr = currMB->mb_addr_up; // for the deblocker if the current MB is a frame and the one above is a field // then the neighbor is the top MB of the pair if (currMB->mb_avail_up) { if (!(p_Vid->DeblockCall == 1 && (p_Vid->mb_data[currMB->mb_addr_up]).mb_field)) pix->mb_addr += 1; } pix->available = currMB->mb_avail_up; yM = yN; } else { // bottom pix->mb_addr = currMB->mbAddrX - 1; pix->available = TRUE; yM = yN; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; if (currMB->mb_avail_up) { if(!p_Vid->mb_data[currMB->mb_addr_up].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_up + 1; pix->available = currMB->mb_avail_up; yM = yN; } } } else { // yN >=0 // for the deblocker if this is the extra edge then do this special stuff if (yN == 0 && p_Vid->DeblockCall == 2) { pix->mb_addr = currMB->mb_addr_up + 1; pix->available = TRUE; yM = yN - 1; } else if (yN mb_addr = currMB->mbAddrX; pix->available = TRUE; yM = yN; } } } else { // xN >= maxW if(yN < 0) { if (!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = yN; } else { // bottom pix->available = FALSE; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; if (currMB->mb_avail_upper_right) { if(!p_Vid->mb_data[currMB->mb_addr_upper_right].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = yN; } } } } } if (pix->available || p_Vid->DeblockCall) { pix->x = (short) (xN & (maxW - 1)); pix->y = (short) (yM & (maxH - 1)); get_mb_block_pos_mbaff(p_Vid->PicPos, pix->mb_addr, &(pix->pos_x), &(pix->pos_y)); pix->pos_x = 16*pix->pos_x + pix->x; pix->pos_y = 16*pix->pos_y + pix->y; } } void getAffNeighbourPXLumaNB(const Macroblock *currMB, int xN, int yN, PixelPos *pix) { // xN >= 0, yN < 16, xN < 16 VideoParameters *p_Vid = currMB->p_Vid; const int maxW=16, maxH=16; int yM = -1; // initialize to "not available" pix->available = FALSE; if (yN<0) { if (!currMB->mb_field) { //frame if ((currMB->mbAddrX & 0x01) == 0) { //top pix->mb_addr = currMB->mb_addr_up; // for the deblocker if the current MB is a frame and the one above is a field // then the neighbor is the top MB of the pair if (currMB->mb_avail_up) { if (!(p_Vid->DeblockCall == 1 && (p_Vid->mb_data[currMB->mb_addr_up]).mb_field)) pix->mb_addr += 1; } pix->available = currMB->mb_avail_up; yM = yN; } else { // bottom pix->mb_addr = currMB->mbAddrX - 1; pix->available = TRUE; yM = yN; } } else { // field pix->available = currMB->mb_avail_up; if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_up; if (currMB->mb_avail_up) { if(!p_Vid->mb_data[currMB->mb_addr_up].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_up + 1; yM = yN; } } } else { // yN >=0 // for the deblocker if this is the extra edge then do this special stuff if (yN == 0 && p_Vid->DeblockCall == 2) { pix->mb_addr = currMB->mb_addr_up + 1; pix->available = TRUE; yM = yN - 1; } else { pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; yM = yN; } } if (pix->available || p_Vid->DeblockCall) { pix->x = (short) (xN); pix->y = (short) (yM & (maxH - 1)); get_mb_block_pos_mbaff(p_Vid->PicPos, pix->mb_addr, &(pix->pos_x), &(pix->pos_y)); pix->pos_x = 16*pix->pos_x + pix->x; pix->pos_y = 16*pix->pos_y + pix->y; } } void getAffNeighbourPXLumaNB_NoPos(const Macroblock *currMB, int yN, PixelPos *pix) { // xN >= 0, yN < 16, xN < 16, DeblockCall == 0 VideoParameters *p_Vid = currMB->p_Vid; int yM = -1; // initialize to "not available" pix->available = FALSE; if (yN<0) { if (!currMB->mb_field) { //frame if ((currMB->mbAddrX & 0x01) == 0) { //top pix->mb_addr = currMB->mb_addr_up; // for the deblocker if the current MB is a frame and the one above is a field // then the neighbor is the top MB of the pair if (currMB->mb_avail_up) { pix->mb_addr += 1; } pix->available = currMB->mb_avail_up; yM = yN; } else { // bottom pix->mb_addr = currMB->mbAddrX - 1; pix->available = TRUE; yM = yN; } } else { // field pix->available = currMB->mb_avail_up; if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_up; if (currMB->mb_avail_up) { if(!p_Vid->mb_data[currMB->mb_addr_up].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_up + 1; yM = yN; } } } else { // yN >=0 pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; yM = yN; } if (pix->available) { pix->y = (short) (yM & 15); } } void getAffNeighbourXPLuma(const Macroblock *currMB, int xN, int yN, PixelPos *pix) { // yN >= 0 VideoParameters *p_Vid = currMB->p_Vid; const int maxW=16, maxH=16; int yM = -1; // initialize to "not available" pix->available = FALSE; if(yN > (maxH - 1)) { return; } if (xN > (maxW - 1) && yN < maxH) { return; } if (xN < 0) { if (!currMB->mb_field) { // frame pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if ((currMB->mbAddrX & 0x01) == 0) { // top if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = yN >> 1; } } } else { // bottom if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { (pix->mb_addr)++; yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = (yN + maxH) >> 1; } } } } else { pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; // field if ((currMB->mbAddrX & 0x01) == 0) { // top if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = yN << 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) - maxH; } } else { yM = yN; } } } else { // bottom if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = (yN << 1) + 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) + 1 - maxH; } } else { (pix->mb_addr)++; yM = yN; } } } } } else if (xN < maxW) { // xN >= 0 // yN >=0 // for the deblocker if this is the extra edge then do this special stuff if (yN == 0 && p_Vid->DeblockCall == 2) { pix->mb_addr = currMB->mb_addr_up + 1; pix->available = TRUE; yM = yN - 1; } else if (yN mb_addr = currMB->mbAddrX; pix->available = TRUE; yM = yN; } } if (pix->available || p_Vid->DeblockCall) { pix->x = (short) (xN & (maxW - 1)); pix->y = (short) (yM & (maxH - 1)); get_mb_block_pos_mbaff(p_Vid->PicPos, pix->mb_addr, &(pix->pos_x), &(pix->pos_y)); pix->pos_x = 16*pix->pos_x + pix->x; pix->pos_y = 16*pix->pos_y + pix->y; } } void getAffNeighbourPPLumaNB(const Macroblock *currMB, int xN, int yN, PixelPos *pix) { VideoParameters *p_Vid = currMB->p_Vid; // xN >= 0 // yN >=0 pix->mb_addr = currMB->mbAddrX; pix->available = TRUE; pix->x = (short) (xN & (16 - 1)); pix->y = (short) (yN & (16 - 1)); get_mb_block_pos_mbaff(p_Vid->PicPos, pix->mb_addr, &(pix->pos_x), &(pix->pos_y)); pix->pos_x = 16*pix->pos_x + pix->x; pix->pos_y = 16*pix->pos_y + pix->y; } void getAffNeighbourNPLuma(const Macroblock *currMB, int yN, PixelPos *pix) { // yN >= 0 VideoParameters *p_Vid = currMB->p_Vid; const int maxW=16, maxH=16; int yM = -1; // initialize to "not available" pix->available = FALSE; if(yN > (maxH - 1)) { return; } if (yN mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = yN >> 1; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { (pix->mb_addr)++; yM = yN; } else { (pix->mb_addr)+= ((yN & 0x01) != 0); yM = (yN + maxH) >> 1; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = yN << 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) - maxH; } } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (yN < (maxH >> 1)) { yM = (yN << 1) + 1; } else { (pix->mb_addr)++; yM = (yN << 1 ) + 1 - maxH; } } else { (pix->mb_addr)++; yM = yN; } } } } } if (pix->available || p_Vid->DeblockCall) { pix->x = (short) (-1 & (maxW - 1)); pix->y = (short) (yM & (maxH - 1)); get_mb_block_pos_mbaff(p_Vid->PicPos, pix->mb_addr, &(pix->pos_x), &(pix->pos_y)); pix->pos_x = 16*pix->pos_x + pix->x; pix->pos_y = 16*pix->pos_y + pix->y; } } void getAffNeighbourN0Luma(const Macroblock *currMB, PixelPos *pix) { // xN = -1 && yN == 0 VideoParameters *p_Vid = currMB->p_Vid; //const int maxW=16, maxH=16; int yM = -1; // initialize to "not available" pix->available = FALSE; if (!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { yM = 0; } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { (pix->mb_addr)++; yM = 0; } else { yM = 8; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { yM = 0; } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { yM = 1; } else { (pix->mb_addr)++; yM = 0; } } } } if (pix->available || p_Vid->DeblockCall) { pix->x = (short) (-1 & 15); pix->y = (short) (yM & 15); get_mb_block_pos_mbaff(p_Vid->PicPos, pix->mb_addr, &(pix->pos_x), &(pix->pos_y)); pix->pos_x = 16*pix->pos_x + pix->x; pix->pos_y = 16*pix->pos_y + pix->y; } } void getAffNeighbourX0(const Macroblock *currMB, int xN, const int mb_size[2], PixelPos *pix) { VideoParameters *p_Vid = currMB->p_Vid; int maxW, maxH; int yM = -1; maxW = mb_size[0]; maxH = mb_size[1]; // initialize to "not available" pix->available = FALSE; if(0 > (maxH - 1)) { return; } if (xN > (maxW - 1) && 0 < maxH) { return; } if (xN < 0) { if (0 mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { yM = 0; } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { (pix->mb_addr)++; yM = 0; } else { yM = (0 + maxH) >> 1; } } } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (0 < (maxH >> 1)) { yM = 0; } else { (pix->mb_addr)++; yM = (0) - maxH; } } else { yM = 0; } } } else { // bottom pix->mb_addr = currMB->mb_addr_left; pix->available = currMB->mb_avail_left; if (currMB->mb_avail_left) { if(!p_Vid->mb_data[currMB->mb_addr_left].mb_field) { if (0 < (maxH >> 1)) { yM = 1; } else { (pix->mb_addr)++; yM = 1 - maxH; } } else { (pix->mb_addr)++; yM = 0; } } } } } } else { // xN >= 0 if (xN >= 0 && xN < maxW) { // yN >=0 // for the deblocker if this is the extra edge then do this special stuff if (p_Vid->DeblockCall == 2) { pix->mb_addr = currMB->mb_addr_up + 1; pix->available = TRUE; yM = 0 - 1; } else if (0 mb_addr = currMB->mbAddrX; pix->available = TRUE; yM = 0; } } } if (pix->available || p_Vid->DeblockCall) { pix->x = (short) (xN & (maxW - 1)); pix->y = (short) (yM & (maxH - 1)); get_mb_pos(p_Vid, pix->mb_addr, mb_size, &(pix->pos_x), &(pix->pos_y)); pix->pos_x = pix->pos_x + pix->x; pix->pos_y = pix->pos_y + pix->y; } } void getAffNeighbour0X(const Macroblock *currMB, int yN, const int mb_size[2], PixelPos *pix) // xN == 0, yN full range { VideoParameters *p_Vid = currMB->p_Vid; int maxW, maxH; int yM = -1; maxW = mb_size[0]; maxH = mb_size[1]; // initialize to "not available" pix->available = FALSE; if(yN > (maxH - 1)) { return; } if (0 > (maxW - 1) && yN >= 0 && yN < maxH) { return; } if (0 < maxW) { if (yN<0) { if (!currMB->mb_field) { //frame if ((currMB->mbAddrX & 0x01) == 0) { //top pix->mb_addr = currMB->mb_addr_up; // for the deblocker if the current MB is a frame and the one above is a field // then the neighbor is the top MB of the pair if (currMB->mb_avail_up) { if (!(p_Vid->DeblockCall == 1 && (p_Vid->mb_data[currMB->mb_addr_up]).mb_field)) pix->mb_addr += 1; } pix->available = currMB->mb_avail_up; yM = yN; } else { // bottom pix->mb_addr = currMB->mbAddrX - 1; pix->available = TRUE; yM = yN; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; if (currMB->mb_avail_up) { if(!p_Vid->mb_data[currMB->mb_addr_up].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_up + 1; pix->available = currMB->mb_avail_up; yM = yN; } } } else { // yN >=0 // for the deblocker if this is the extra edge then do this special stuff if (yN == 0 && p_Vid->DeblockCall == 2) { pix->mb_addr = currMB->mb_addr_up + 1; pix->available = TRUE; yM = yN - 1; } else if ((yN >= 0) && (yN mb_addr = currMB->mbAddrX; pix->available = TRUE; yM = yN; } } } else { // xN >= maxW if(yN < 0) { if (!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = yN; } else { // bottom pix->available = FALSE; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; if (currMB->mb_avail_upper_right) { if(!p_Vid->mb_data[currMB->mb_addr_upper_right].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = yN; } } } } if (pix->available || p_Vid->DeblockCall) { pix->x = 0; pix->y = (short) (yM & (maxH - 1)); get_mb_pos(p_Vid, pix->mb_addr, mb_size, &(pix->pos_x), &(pix->pos_y)); pix->pos_y = pix->pos_y + pix->y; } } void getAffNeighbour0XLuma(const Macroblock *currMB, int yN, PixelPos *pix) // xN == 0, yN full range { VideoParameters *p_Vid = currMB->p_Vid; int maxW, maxH; int yM = -1; maxW = 16; maxH = 16; // initialize to "not available" pix->available = FALSE; if(yN > 15) { return; } if (yN<0) { if (!currMB->mb_field) { //frame if ((currMB->mbAddrX & 0x01) == 0) { //top pix->mb_addr = currMB->mb_addr_up; // for the deblocker if the current MB is a frame and the one above is a field // then the neighbor is the top MB of the pair if (currMB->mb_avail_up) { if (!(p_Vid->DeblockCall == 1 && (p_Vid->mb_data[currMB->mb_addr_up]).mb_field)) pix->mb_addr += 1; } pix->available = currMB->mb_avail_up; yM = yN; } else { // bottom pix->mb_addr = currMB->mbAddrX - 1; pix->available = TRUE; yM = yN; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; if (currMB->mb_avail_up) { if(!p_Vid->mb_data[currMB->mb_addr_up].mb_field) { (pix->mb_addr)++; yM = 2* yN; } else { yM = yN; } } } else { // bottom pix->mb_addr = currMB->mb_addr_up + 1; pix->available = currMB->mb_avail_up; yM = yN; } } } else { // yN >=0 // for the deblocker if this is the extra edge then do this special stuff if (yN == 0 && p_Vid->DeblockCall == 2) { pix->mb_addr = currMB->mb_addr_up + 1; pix->available = TRUE; yM = yN - 1; } else if ((yN >= 0) && (yN mb_addr = currMB->mbAddrX; pix->available = TRUE; yM = yN; } } if (pix->available || p_Vid->DeblockCall) { const int mb_size[2] = {16,16}; pix->x = 0; pix->y = (short) (yM & (maxH - 1)); get_mb_pos(p_Vid, pix->mb_addr, mb_size, &(pix->pos_x), &(pix->pos_y)); pix->pos_y = pix->pos_y + pix->y; } } void getAffNeighbour0N(const Macroblock *currMB, const int mb_size[2], PixelPos *pix) // xN == 0, yN = -1 { VideoParameters *p_Vid = currMB->p_Vid; int maxW, maxH; int yM = -1; maxW = mb_size[0]; maxH = mb_size[1]; // initialize to "not available" pix->available = FALSE; if (0 < maxW) { if (!currMB->mb_field) { //frame if ((currMB->mbAddrX & 0x01) == 0) { //top pix->mb_addr = currMB->mb_addr_up; // for the deblocker if the current MB is a frame and the one above is a field // then the neighbor is the top MB of the pair if (currMB->mb_avail_up) { if (!(p_Vid->DeblockCall == 1 && (p_Vid->mb_data[currMB->mb_addr_up]).mb_field)) pix->mb_addr += 1; } pix->available = currMB->mb_avail_up; yM = -1; } else { // bottom pix->mb_addr = currMB->mbAddrX - 1; pix->available = TRUE; yM = -1; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; if (currMB->mb_avail_up) { if(!p_Vid->mb_data[currMB->mb_addr_up].mb_field) { (pix->mb_addr)++; yM = -2; } else { yM = -1; } } } else { // bottom pix->mb_addr = currMB->mb_addr_up + 1; pix->available = currMB->mb_avail_up; yM = -1; } } } else { // xN >= maxW if (!currMB->mb_field) { // frame if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = -1; } else { // bottom pix->available = FALSE; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_upper_right; pix->available = currMB->mb_avail_upper_right; if (currMB->mb_avail_upper_right) { if(!p_Vid->mb_data[currMB->mb_addr_upper_right].mb_field) { (pix->mb_addr)++; yM = -2; } else { yM = -1; } } } else { // bottom pix->mb_addr = currMB->mb_addr_upper_right + 1; pix->available = currMB->mb_avail_upper_right; yM = -1; } } } if (pix->available || p_Vid->DeblockCall) { pix->x = 0; pix->y = (short) (yM & (maxH - 1)); get_mb_pos(p_Vid, pix->mb_addr, mb_size, &(pix->pos_x), &(pix->pos_y)); pix->pos_y = pix->pos_y + pix->y; } } void getAffNeighbour0NLuma(const Macroblock *currMB, PixelPos *pix) // xN == 0, yN = -1 { VideoParameters *p_Vid = currMB->p_Vid; const int maxW=16, maxH=16; int yM = -1; // initialize to "not available" pix->available = FALSE; if (!currMB->mb_field) { //frame if ((currMB->mbAddrX & 0x01) == 0) { //top pix->mb_addr = currMB->mb_addr_up; // for the deblocker if the current MB is a frame and the one above is a field // then the neighbor is the top MB of the pair if (currMB->mb_avail_up) { if (!(p_Vid->DeblockCall == 1 && (p_Vid->mb_data[currMB->mb_addr_up]).mb_field)) pix->mb_addr += 1; } pix->available = currMB->mb_avail_up; yM = -1; } else { // bottom pix->mb_addr = currMB->mbAddrX - 1; pix->available = TRUE; yM = -1; } } else { // field if ((currMB->mbAddrX & 0x01) == 0) { // top pix->mb_addr = currMB->mb_addr_up; pix->available = currMB->mb_avail_up; if (currMB->mb_avail_up) { if(!p_Vid->mb_data[currMB->mb_addr_up].mb_field) { (pix->mb_addr)++; yM = -2; } else { yM = -1; } } } else { // bottom pix->mb_addr = currMB->mb_addr_up + 1; pix->available = currMB->mb_avail_up; yM = -1; } } if (pix->available || p_Vid->DeblockCall) { const int mb_size[2] = {16,16}; pix->x = 0; pix->y = (short) (yM & (maxH - 1)); get_mb_pos(p_Vid, pix->mb_addr, mb_size, &(pix->pos_x), &(pix->pos_y)); pix->pos_y = pix->pos_y + pix->y; } } /*! ************************************************************************ * \brief * get neighboring 4x4 block * \param currMB * current macroblock * \param block_x * input x block position * \param block_y * input y block position * \param mb_size * Macroblock size in pixel (according to luma or chroma MB access) * \param pix * returns position informations ************************************************************************ */ void get4x4Neighbour(const Macroblock *currMB, int block_x, int block_y, const int mb_size[2], PixelPos *pix) { currMB->p_Vid->getNeighbour(currMB, block_x, block_y, mb_size, pix); if (pix->available) { pix->x >>= 2; pix->y >>= 2; pix->pos_x >>= 2; pix->pos_y >>= 2; } } void get4x4NeighbourLuma(const Macroblock *currMB, int block_x, int block_y, PixelPos *pix) { currMB->p_Vid->getNeighbourLuma(currMB, block_x, block_y, pix); if (pix->available) { pix->x >>= 2; pix->y >>= 2; pix->pos_x >>= 2; pix->pos_y >>= 2; } }