www.pudn.com > jm74.zip > mb_access.c


 
/*! 
 ************************************************************************************* 
 * \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" 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    returns 1 if the macroblock at the given address is available 
 ************************************************************************ 
 */ 
int mb_is_available(int mbAddr, int currMbAddr) 
{ 
  if ((mbAddr < 0) || (mbAddr > ((int)img->PicSizeInMbs - 1))) 
    return 0; 
 
  // the following line checks both: slice number and if the mb has been decoded 
  if (img->mb_data[mbAddr].slice_nr != img->mb_data[currMbAddr].slice_nr) 
    return 0; 
   
  return 1; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Checks the availability of neighboring macroblocks of 
 *    the current macroblock for prediction and context determination; 
 ************************************************************************ 
 */ 
void CheckAvailabilityOfNeighbors() 
{ 
  const int mb_nr = img->current_mb_nr; 
  Macroblock *currMB = &img->mb_data[mb_nr]; 
 
  // mark all neighbors as unavailable 
  currMB->mb_available_up   = NULL; 
  currMB->mb_available_left = NULL; 
 
  if (img->MbaffFrameFlag) 
  { 
    currMB->mbAddrA = 2 * (mb_nr/2 - 1); 
    currMB->mbAddrB = 2 * (mb_nr/2 - img->PicWidthInMbs); 
    currMB->mbAddrC = 2 * (mb_nr/2 - img->PicWidthInMbs + 1); 
    currMB->mbAddrD = 2 * (mb_nr/2 - img->PicWidthInMbs - 1); 
     
    currMB->mbAvailA = mb_is_available(currMB->mbAddrA, mb_nr) && ((mb_nr/2 % img->PicWidthInMbs)!=0); 
    currMB->mbAvailB = mb_is_available(currMB->mbAddrB, mb_nr); 
    currMB->mbAvailC = mb_is_available(currMB->mbAddrC, mb_nr) && (((mb_nr/2 +1) % img->PicWidthInMbs)!=0); 
    currMB->mbAvailD = mb_is_available(currMB->mbAddrD, mb_nr) && ((mb_nr/2 % img->PicWidthInMbs)!=0); 
  } 
  else 
  { 
    currMB->mbAddrA = mb_nr - 1; 
    currMB->mbAddrB = mb_nr - img->PicWidthInMbs; 
    currMB->mbAddrC = mb_nr - img->PicWidthInMbs + 1; 
    currMB->mbAddrD = mb_nr - img->PicWidthInMbs - 1; 
 
    currMB->mbAvailA = mb_is_available(currMB->mbAddrA, mb_nr) && ((mb_nr % img->PicWidthInMbs)!=0); 
    currMB->mbAvailB = mb_is_available(currMB->mbAddrB, mb_nr); 
    currMB->mbAvailC = mb_is_available(currMB->mbAddrC, mb_nr) && (((mb_nr+1) % img->PicWidthInMbs)!=0); 
    currMB->mbAvailD = mb_is_available(currMB->mbAddrD, mb_nr) && ((mb_nr % img->PicWidthInMbs)!=0); 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    returns the x and y macroblock coordinates for a given MbAddress 
 ************************************************************************ 
 */ 
void get_mb_block_pos (int mb_addr, int *x, int*y) 
{ 
 
  if (img->MbaffFrameFlag) 
  { 
    *x = ((mb_addr/2) % img->PicWidthInMbs); 
    *y = ( ((mb_addr/2) / img->PicWidthInMbs)  * 2 + (mb_addr%2)); 
  } 
  else 
  { 
    *x = (mb_addr % img->PicWidthInMbs); 
    *y = (mb_addr / img->PicWidthInMbs); 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    returns the x and y sample coordinates for a given MbAddress 
 ************************************************************************ 
 */ 
void get_mb_pos (int mb_addr, int *x, int*y) 
{ 
  get_mb_block_pos(mb_addr, x, y); 
   
  (*x) *= MB_BLOCK_SIZE; 
  (*y) *= MB_BLOCK_SIZE; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    get neighbouring positions for non-aff coding 
 * \param curr_mb_nr 
 *   current macroblock number (decoding order) 
 * \param xN 
 *    input x position 
 * \param yN 
 *    input y position 
 * \param luma 
 *    1 if luma coding, 0 for chroma 
 * \param pix 
 *    returns position informations 
 ************************************************************************ 
 */ 
void getNonAffNeighbour(int curr_mb_nr, int xN, int yN, int luma, PixelPos *pix) 
{ 
  Macroblock *currMb = &img->mb_data[curr_mb_nr]; 
  int maxWH; 
 
  if (luma) 
    maxWH = 16; 
  else 
    maxWH = 8; 
 
  if ((xN<0)&&(yN<0)) 
  { 
    pix->mb_addr   = currMb->mbAddrD; 
    pix->available = currMb->mbAvailD; 
  } 
  else 
  if ((xN<0)&&((yN>=0)&&(yNmb_addr  = currMb->mbAddrA; 
    pix->available = currMb->mbAvailA; 
  } 
  else 
  if (((xN>=0)&&(xNmb_addr  = currMb->mbAddrB; 
    pix->available = currMb->mbAvailB; 
  } 
  else 
  if (((xN>=0)&&(xN=0)&&(yNmb_addr  = curr_mb_nr; 
    pix->available = 1; 
  } 
  else 
  if ((xN>=maxWH)&&(yN<0)) 
  { 
    pix->mb_addr  = currMb->mbAddrC; 
    pix->available = currMb->mbAvailC; 
  } 
  else  
  { 
    pix->available = 0; 
  } 
  if (pix->available || img->DeblockCall) 
  { 
    pix->x = (xN + maxWH) % maxWH; 
    pix->y = (yN + maxWH) % maxWH; 
    get_mb_pos(pix->mb_addr, &(pix->pos_x), &(pix->pos_y)); 
    if (luma) 
    { 
      pix->pos_x += pix->x; 
      pix->pos_y += pix->y; 
    } 
    else 
    { 
      pix->pos_x = (pix->pos_x/2) + pix->x; 
      pix->pos_y = (pix->pos_y/2) + pix->y; 
    } 
  } 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    get neighbouring positions for aff coding 
 * \param curr_mb_nr 
 *   current macroblock number (decoding order) 
 * \param xN 
 *    input x position 
 * \param yN 
 *    input y position 
 * \param luma 
 *    1 if luma coding, 0 for chroma 
 * \param pix 
 *    returns position informations 
 ************************************************************************ 
 */ 
void getAffNeighbour(int curr_mb_nr, int xN, int yN, int luma, PixelPos *pix) 
{ 
  Macroblock *currMb = &img->mb_data[curr_mb_nr]; 
  int maxWH; 
  int yM = -1; 
 
  if (luma) 
    maxWH = 16; 
  else 
    maxWH = 8; 
 
  // initialize to "not available" 
  pix->available = 0; 
 
  if(yN > (maxWH - 1)) 
  { 
    return; 
  } 
  if ((xN > (maxWH -1)) && ((yN >= 0)&&(yN < (maxWH )))) 
  { 
    return; 
  } 
 
  if (xN < 0) 
  { 
    if (yN < 0) 
    { 
      if(!currMb->mb_field) 
      { 
        // frame 
        if (curr_mb_nr%2 == 0) 
        { 
          // top 
          pix->mb_addr  = currMb->mbAddrD  + 1; 
          pix->available = currMb->mbAvailD; 
           yM      = yN; 
        } 
        else 
        { 
          // bottom 
          pix->mb_addr  = currMb->mbAddrA; 
          pix->available = currMb->mbAvailA; 
          if (currMb->mbAvailA) 
          { 
            if(!img->mb_data[currMb->mbAddrA].mb_field) 
            { 
               yM = yN; 
            } 
            else 
            { 
              (pix->mb_addr)++; 
               yM = (yN + maxWH) >> 1; 
            } 
          } 
        } 
      } 
      else 
      { 
        // field 
        if(curr_mb_nr % 2 == 0) 
        { 
          // top 
          pix->mb_addr  = currMb->mbAddrD; 
          pix->available = currMb->mbAvailD; 
          if (currMb->mbAvailD) 
          { 
            if(!img->mb_data[currMb->mbAddrD].mb_field) 
            { 
              (pix->mb_addr)++; 
               yM = 2 * yN; 
            } 
            else 
            { 
               yM = yN; 
            } 
          } 
        } 
        else 
        { 
          // bottom 
          pix->mb_addr  = currMb->mbAddrD+1; 
          pix->available = currMb->mbAvailD; 
           yM      = yN; 
        } 
      } 
    } 
    else 
    { // xN < 0 && yN >= 0 
      if ((yN >= 0) && (yN mb_field) 
        { 
          // frame 
          if(curr_mb_nr % 2 == 0) 
          { 
            // top 
            pix->mb_addr  = currMb->mbAddrA; 
            pix->available = currMb->mbAvailA; 
            if (currMb->mbAvailA) 
            { 
              if(!img->mb_data[currMb->mbAddrA].mb_field) 
              { 
                 yM = yN; 
              } 
              else 
              { 
                if (yN %2 == 0) 
                { 
                   yM = yN>> 1; 
                } 
                else 
                { 
                  (pix->mb_addr)++; 
                   yM = yN>> 1; 
                } 
              } 
            } 
          } 
          else 
          { 
            // bottom 
            pix->mb_addr  = currMb->mbAddrA; 
            pix->available = currMb->mbAvailA; 
            if (currMb->mbAvailA) 
            { 
              if(!img->mb_data[currMb->mbAddrA].mb_field) 
              { 
                (pix->mb_addr)++; 
                 yM = yN; 
              } 
              else 
              { 
                if (yN %2 == 0) 
                { 
                   yM = (yN + maxWH) >> 1; 
                } 
                else 
                { 
                  (pix->mb_addr)++; 
                   yM = (yN + maxWH) >> 1; 
                } 
              } 
            } 
          } 
        } 
        else 
        { 
          // field 
          if (curr_mb_nr % 2 == 0) 
          { 
            // top 
            pix->mb_addr  = currMb->mbAddrA; 
            pix->available = currMb->mbAvailA; 
            if (currMb->mbAvailA) 
            { 
              if(!img->mb_data[currMb->mbAddrA].mb_field) 
              { 
                if (yN < (maxWH / 2)) 
                { 
                   yM = yN << 1; 
                } 
                else 
                { 
                  (pix->mb_addr)++; 
                   yM = (yN << 1 ) - maxWH; 
                } 
              } 
              else 
              { 
                 yM = yN; 
              } 
            } 
          } 
          else 
          { 
            // bottom 
            pix->mb_addr  = currMb->mbAddrA; 
            pix->available = currMb->mbAvailA; 
            if (currMb->mbAvailA) 
            { 
              if(!img->mb_data[currMb->mbAddrA].mb_field) 
              { 
                if (yN < (maxWH / 2)) 
                { 
                   yM = (yN << 1) + 1; 
                } 
                else 
                { 
                  (pix->mb_addr)++; 
                   yM = (yN << 1 ) + 1 - maxWH; 
                } 
              } 
              else 
              { 
                 (pix->mb_addr)++; 
                 yM = yN; 
              } 
            } 
          } 
        } 
      } 
    } 
  } 
  else 
  { 
    // xN >= 0 
    if ((xN >= 0)&&(xN mb_field) 
        { 
          //frame 
          if (curr_mb_nr % 2 == 0) 
          { 
            //top 
            pix->mb_addr  = currMb->mbAddrB; 
            // 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 (!(img->DeblockCall == 1 && (img->mb_data[currMb->mbAddrB]).mb_field)) 
              pix->mb_addr  += 1; 
 
            pix->available = currMb->mbAvailB; 
             yM      = yN; 
          } 
          else 
          { 
            // bottom 
            pix->mb_addr  = curr_mb_nr - 1; 
            pix->available = 1; 
             yM      = yN; 
          } 
        } 
        else 
        { 
          // field 
          if (curr_mb_nr % 2 == 0) 
          { 
            // top 
            pix->mb_addr  = currMb->mbAddrB; 
            pix->available = currMb->mbAvailB; 
            if (currMb->mbAvailB) 
            { 
              if(!img->mb_data[currMb->mbAddrB].mb_field) 
              { 
                (pix->mb_addr)++; 
                 yM = 2* yN; 
              } 
              else 
              { 
                 yM = yN; 
              } 
            } 
          } 
          else 
          { 
            // bottom 
            pix->mb_addr  = currMb->mbAddrB + 1; 
            pix->available = currMb->mbAvailB; 
             yM      = yN; 
          } 
        } 
      } 
      else 
      { 
        // yN >=0 
        // for the deblocker if this is the extra edge then do this special stuff 
        if (yN == 0 && img->DeblockCall == 2) 
        { 
          pix->mb_addr  = currMb->mbAddrB + 1; 
          pix->available = 1; 
           yM      = yN - 1; 
        } 
 
        else if ((yN >= 0) && (yN mb_addr  = curr_mb_nr; 
          pix->available = 1; 
           yM      = yN; 
        } 
      } 
    } 
    else 
    { 
      // xN >= maxWH 
      if(yN < 0) 
      { 
        if (!currMb->mb_field) 
        { 
          // frame 
          if (curr_mb_nr % 2 == 0) 
          { 
            // top 
            pix->mb_addr  = currMb->mbAddrC + 1; 
            pix->available = currMb->mbAvailC; 
             yM      = yN; 
          } 
          else 
          { 
            // bottom 
            pix->available = 0; 
          } 
        } 
        else 
        { 
          // field 
          if (curr_mb_nr % 2 == 0) 
          { 
            // top 
            pix->mb_addr  = currMb->mbAddrC; 
            pix->available = currMb->mbAvailC; 
            if (currMb->mbAvailC) 
            { 
              if(!img->mb_data[currMb->mbAddrC].mb_field) 
              { 
                (pix->mb_addr)++; 
                 yM = 2* yN; 
              } 
              else 
              { 
                 yM = yN; 
              } 
            } 
          } 
          else 
          { 
            // bottom 
            pix->mb_addr  = currMb->mbAddrC + 1; 
            pix->available = currMb->mbAvailC; 
             yM      = yN; 
          } 
        } 
      } 
    } 
  } 
  if (pix->available || img->DeblockCall) 
  { 
    pix->x = (xN + maxWH) % maxWH; 
    pix->y = (yM + maxWH) % maxWH; 
    get_mb_pos(pix->mb_addr, &(pix->pos_x), &(pix->pos_y)); 
    if (luma) 
    { 
      pix->pos_x += pix->x; 
      pix->pos_y += pix->y; 
    } 
    else 
    { 
      pix->pos_x = (pix->pos_x/2) + pix->x; 
      pix->pos_y = (pix->pos_y/2) + pix->y; 
    } 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    get neighbouring positions. MB AFF is automatically used from img structure 
 * \param curr_mb_nr 
 *   current macroblock number (decoding order) 
 * \param xN 
 *    input x position 
 * \param yN 
 *    input y position 
 * \param luma 
 *    1 if luma coding, 0 for chroma 
 * \param pix 
 *    returns position informations 
 ************************************************************************ 
 */ 
void getNeighbour(int curr_mb_nr, int xN, int yN, int luma, PixelPos *pix) 
{ 
  if (img->MbaffFrameFlag) 
    getAffNeighbour(curr_mb_nr, xN, yN, luma, pix); 
  else 
    getNonAffNeighbour(curr_mb_nr, xN, yN, luma, pix); 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    get neighbouring  get neighbouring 4x4 luma block 
 * \param curr_mb_nr 
 *   current macroblock number (decoding order) 
 * \param block_x 
 *    input x block position 
 * \param block_y 
 *    input y block position 
 * \param rel_x 
 *    relative x position of neighbor 
 * \param rel_y 
 *    relative y position of neighbor 
 * \param pix 
 *    returns position informations 
 ************************************************************************ 
 */ 
void getLuma4x4Neighbour (int curr_mb_nr, int block_x, int block_y, int rel_x, int rel_y, PixelPos *pix) 
{ 
  int x = 4* block_x + rel_x; 
  int y = 4* block_y + rel_y; 
 
  getNeighbour(curr_mb_nr, x, y, 1, pix); 
 
  if (pix->available) 
  { 
    pix->x /= 4; 
    pix->y /= 4; 
    pix->pos_x /= 4; 
    pix->pos_y /= 4; 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    get neighbouring 4x4 chroma block 
 * \param curr_mb_nr 
 *   current macroblock number (decoding order) 
 * \param block_x 
 *    input x block position 
 * \param block_y 
 *    input y block position 
 * \param rel_x 
 *    relative x position of neighbor 
 * \param rel_y 
 *    relative y position of neighbor 
 * \param pix 
 *    returns position informations 
 ************************************************************************ 
 */ 
void getChroma4x4Neighbour (int curr_mb_nr, int block_x, int block_y, int rel_x, int rel_y, PixelPos *pix) 
{ 
  int x = 4* block_x + rel_x; 
  int y = 4* block_y + rel_y; 
 
  getNeighbour(curr_mb_nr, x, y, 0, pix); 
 
  if (pix->available) 
  { 
    pix->x /= 4; 
    pix->y /= 4; 
    pix->pos_x /= 4; 
    pix->pos_y /= 4; 
  } 
}