www.pudn.com > jm50g.zip > fmo.c


/* 
*********************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2001, International Telecommunications Union, Geneva 
* 
* DISCLAIMER OF WARRANTY 
* 
* These software programs are available to the user without any 
* license fee or royalty on an "as is" basis. The ITU disclaims 
* any and all warranties, whether express, implied, or 
* statutory, including any implied warranties of merchantability 
* or of fitness for a particular purpose.  In no event shall the 
* contributor or the ITU be liable for any incidental, punitive, or 
* consequential damages of any kind whatsoever arising from the 
* use of these programs. 
* 
* This disclaimer of warranty extends to the user of these programs 
* and user's customers, employees, agents, transferees, successors, 
* and assigns. 
* 
* The ITU does not represent or warrant that the programs furnished 
* hereunder are free of infringement of any third-party patents. 
* Commercial implementations of ITU-T Recommendations, including 
* shareware, may be subject to royalty fees to patent holders. 
* Information regarding the ITU-T patent policy is available from 
* the ITU Web site at http://www.itu.int. 
* 
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE ITU-T PATENT POLICY. 
************************************************************************ 
*/ 
 
/*! 
 ***************************************************************************** 
 * 
 * \file scatter.c 
 * 
 * \brief 
 *    Support for Flexible Macroblock Ordering (FMO) 
 * 
 * \date 
 *    19 June, 2002 
 * 
 * \author 
 *    Stephan Wenger   stewe@cs.tu-berlin.de 
 *****************************************************************************/ 
 
#include  
#include  
#include  
#include  
#include  
#include  
 
 
#include "global.h" 
#include "elements.h" 
#include "defines.h" 
#include "header.h" 
#include "fmo.h" 
 
int *MBAmap;    
 
static int PictureXSize, PictureYSize, PictureSizeInMBs; 
static int NumberOfSliceGroups;    // the number of slice groups -1 (0 == scan order, 7 == maximum) 
 
// JVT-D095, JVT-D097 
static int FmoGenerateType3MBAmap (struct img_par *img, struct inp_par *inp, int NumSliceGroups, int XSize, int YSize, int *MBAmap); 
static int FmoBoxoutCounterClockwise (struct img_par *img, struct inp_par *inp, int XSize, int YSize, int *MBAmap); 
static int FmoBoxoutClockwise (struct img_par *img, struct inp_par *inp, int XSize, int YSize, int *MBAmap); 
static int FmoRasterScan(struct img_par *img, struct inp_par *inp, int XSize, int YSize, int *MBAmap); 
static int FmoInverseRasterScan(struct img_par *img, struct inp_par *inp, int XSize, int YSize, int *MBAmap); 
static int FmoWipeRight(struct img_par *img, struct inp_par *inp, int XSize, int YSize, int *MBAmap); 
static int FmoWipeLeft(struct img_par *img, struct inp_par *inp, int XSize, int YSize, int *MBAmap); 
// End JVT-D095, JVT-D097 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    FmoInit: Initializes (called always when a Parameter Set with a 
 *    new MBAmap is used).  Current simplification: we have only one 
 *    ParameterSet, hence it is sufficient to run this function whenever 
 *    a new PUP is received.  this needs to be fixed when using multiple 
 *    Parameter Sets (including a consistsency check that the MBAmap 
 *    stays identical within a picture) 
 * 
 * \par Input: 
 *    xs, ys: size of picture (in MBs, 11, 9 for QCIF) 
 *    pattern: scatter pattern, or NULL for default pattern 
 * 
 ************************************************************************ 
 */ 
 
int FmoInit (struct img_par *img, struct inp_par *inp, int xs, int ys, int NewMBAmap[], int SizeOfNewMBAmap) 
{ 
  int i, FmoMode; 
 
  NumberOfSliceGroups = 0; 
  PictureXSize = xs; 
  PictureYSize = ys; 
  PictureSizeInMBs = xs*ys; 
 
// printf ("In FMOInit\n"); 
 
  if (MBAmap != NULL) 
    free (MBAmap); 
  if ((MBAmap = malloc (PictureSizeInMBs * sizeof (int))) == NULL) 
  { 
    printf ("cannot allocated %d bytes for MBAmap, exit\n", PictureSizeInMBs * sizeof (int)); 
    exit (-1); 
  } 
 
  if (NewMBAmap == NULL || SizeOfNewMBAmap == 0)    // no new MBAmap ->default MBAmap 
  { 
    memset (MBAmap, 0, PictureSizeInMBs * sizeof (int)); 
    return 0; 
  } 
 
  for (i=0; i NumberOfSliceGroups) 
      NumberOfSliceGroups = MBAmap[i]; 
  } 
 
  // JVT-D095, JVT-D097 
  NumberOfSliceGroups = img->num_slice_groups_minus1; 
  FmoMode = img->mb_allocation_map_type; 
  if (NumberOfSliceGroups && FmoMode >= 3) 
  { 
    switch (FmoMode) 
    { 
    case 3: 
      FmoGenerateType3MBAmap (img, inp, NumberOfSliceGroups, xs, ys, MBAmap); 
      break; 
    case 4: 
    case 5: 
    case 6: 
      assert(NumberOfSliceGroups == 1); 
      //FmoInitEvolvingMBAmap (img, inp, FmoMode, PictureXSize, PictureYSize, MBAmap); // need to be updated before coding of each picture 
      break; 
    default: 
      printf ("Illegal FmoMode %d , exit \n", FmoMode); 
      exit (-1); 
    } 
  } 
  // End JVT-D095, JVT-D097 
 
/* 
printf ("FmoInit: Using MBAmap as follows\n"); 
for (y=0;y=0; i--) 
    if (FmoMB2Slice (i) == SliceGroup) 
      return i; 
  return -1; 
 
}; 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    FmoMB2Slice: Returns SliceGroupID for a given MB 
 * 
 * \par Input: 
 *    Macroblock Nr (in scan order) 
 ************************************************************************ 
 */ 
 
int FmoMB2Slice (int mb) 
{ 
  assert (mb < PictureSizeInMBs); 
  assert (MBAmap != NULL); 
  return MBAmap[mb]; 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    FmoGetNextMBBr: Returns the MB-Nr (in scan order) of the next 
 *    MB in the (scattered) Slice, -1 if the slice is finished 
 * 
 * \par Input: 
 *    CurrentMbNumber 
 ************************************************************************ 
 */ 
 
 
int FmoGetNextMBNr (int CurrentMbNr, int structure) 
{ 
  int SliceGroup = FmoMB2Slice (CurrentMbNr); 
  // KS: dirty hack for interlace 
  int PictureSize = PictureSize = (structure?(structure == 3 ? PictureSizeInMBs:PictureSizeInMBs/2):PictureSizeInMBs); 
   
  while (++CurrentMbNr= PictureSize) 
    return -1;    // No further MB in this slice (could be end of picture) 
  else 
    return CurrentMbNr; 
} 
 
 
// JVT-D095 
int FmoGenerateType3MBAmap (struct img_par *img, struct inp_par *inp, int NumSliceGroups, int XSize, int YSize, int *MBAmap) 
{ 
  int x, y, xx; 
  int n = XSize;              // Number of columns 
  int p = NumSliceGroups+1;     // Number of Slice Groups 
 
  int rx0, rx1, ry0, ry1;   // coordinates of the rectangule 
 
  assert (NumSliceGroups == 1); 
 
  rx0 = img->top_left_mb%n; 
  ry0 = img->top_left_mb/n; 
  rx1 = img->bottom_right_mb%n; 
  ry1 = img->bottom_right_mb/n; 
 
  for (y=0; y= rx0 && x <= rx1 && y >= ry0 && y<= ry1) // within the rectangular slice group 
      MBAmap[xx] = 0; 
    else 
      MBAmap[xx] = 1; 
  } 
  return 0; 
} 
// End JVT-D095 
 
// JVT-D097 
int FmoUpdateEvolvingMBAmap (struct img_par *img, struct inp_par *inp, int *MBAmap) 
{ 
  int FmoMode = img->mb_allocation_map_type; 
  int XSize = img->width/16; 
  int YSize = img->height/16; 
  int i; 
 
  for (i=0; islice_group_change_direction == 0) 
      FmoBoxoutClockwise (img, inp, XSize, YSize, MBAmap); 
    else  
      FmoBoxoutCounterClockwise (img, inp, XSize, YSize, MBAmap); 
    break; 
  case 5: 
    if(img->slice_group_change_direction == 0) 
      FmoRasterScan (img, inp, XSize, YSize, MBAmap); 
    else 
      FmoInverseRasterScan (img, inp, XSize, YSize, MBAmap); 
    break; 
  case 6: 
    if(img->slice_group_change_direction == 0) 
      FmoWipeRight (img, inp, XSize, YSize, MBAmap); 
    else 
      FmoWipeLeft (img, inp, XSize, YSize, MBAmap); 
    break; 
  } 
 
/* 
{ 
int xx, yy; 
for (yy=0;yyslice_group_change_cycle+1) * (img->slice_group_change_rate_minus1+1); 
 
  for(i=0; i 0) y--; 
    else if(x > 0) 
    { 
      y = YSize-1; 
      x--; 
    } 
    else  
      break; 
  } 
 
  return 0; 
} 
 
int FmoWipeRight(struct img_par *img, struct inp_par *inp, int XSize, int YSize, int *MBAmap) 
{ 
  int i, x, y, n; 
 
  x = 0;  
  y = 0; 
 
  n = (img->slice_group_change_cycle+1) * (img->slice_group_change_rate_minus1+1); 
 
  for(i=0; islice_group_change_cycle+1) * (img->slice_group_change_rate_minus1+1); 
  nextMBnum = y * XSize + x; 
 
  for(i=0; islice_group_change_cycle+1) * (img->slice_group_change_rate_minus1+1); 
  nextMBnum = y * XSize + x; 
 
  for(i=0; i= XSize*YSize )  
      break; 
  } 
 
  return 0; 
} 
 
int FmoBoxoutCounterClockwise (struct img_par *img, struct inp_par *inp, int XSize, int YSize, int *MBAmap) 
{ 
  int i, n; 
  int W = XSize, H = YSize; 
   
  int x = ( XSize - 1 ) / 2; 
  int y = ( YSize - 1) / 2; 
  int directx = 0; 
  int directy = 1; 
  int left = x; 
  int right = x; 
  int top = y; 
  int bottom = y; 
 
  n = (img->slice_group_change_cycle+1) * (img->slice_group_change_rate_minus1+1); 
 
  for(i=0; i left) x--; 
      else if (x == 0) 
      { 
        y = bottom + 1; 
        bottom++; 
        directx = 1; 
        directy = 0; 
      } 
      else if (x == left) 
      { 
        x--; 
        left--; 
        directx = 0; 
        directy = 1; 
      } 
    } 
    else if ( directx == 1 && directy == 0 ) 
    { 
      if (x < right) x++; 
      else if (x == W - 1) 
      { 
        y = top - 1; 
        top--; 
        directx = -1; 
        directy = 0; 
      } 
      else if (x == right) 
      { 
        x++; 
        right++; 
        directx = 0; 
        directy = -1; 
      } 
    } 
    else if ( directx == 0 && directy == -1 ) 
    { 
      if ( y > top) y--; 
      else if (y == 0) 
      { 
        x = left - 1; 
        left--; 
        directx = 0; 
        directy = 1; 
      } 
      else if (y == top) 
      { 
        y--; 
        top--; 
        directx = -1; 
        directy = 0; 
      } 
    } 
    else if ( directx == 0 && directy == 1 ) 
    { 
      if (y < bottom) y++; 
      else if (y == H - 1) 
      { 
        x = right+1; 
        right++; 
        directx = 0; 
        directy = -1; 
      } 
      else if (y == bottom) 
      { 
        y++; 
        bottom++; 
        directx = 1; 
        directy = 0; 
      } 
    } 
 
    // check whether passed already the last MB in the evolving period 
    if( !(left >= 0 && right < W && top >= 0 && bottom < H) )  
      break; 
  } 
 
  return 0; 
} 
 
int FmoBoxoutClockwise (struct img_par *img, struct inp_par *inp, int XSize, int YSize, int *MBAmap) 
{ 
  int i, n; 
  int W = XSize, H = YSize; 
   
  int x = XSize / 2; 
  int y = YSize / 2; 
  int directx = -1; 
  int directy = 0; 
  int left = x; 
  int right = x; 
  int top = y; 
  int bottom = y; 
 
  n = (img->slice_group_change_cycle+1) * (img->slice_group_change_rate_minus1+1); 
 
  for(i=0; i left) x--; 
      else if (x == 0) 
      { 
        y = top - 1; 
        top--; 
        directx = 1; 
        directy = 0; 
      } 
      else if (x == left) 
      { 
        x--; 
        left--; 
        directx = 0; 
        directy = -1; 
      } 
    } 
    else if ( directx == 1 && directy == 0 ) 
    { 
      if (x < right) x++; 
      else if (x == W - 1) 
      { 
        y = bottom + 1; 
        bottom++; 
        directx = -1; 
        directy = 0; 
      } 
      else if (x == right) 
      { 
        x++; 
        right++; 
        directx = 0; 
        directy = 1; 
      } 
    } 
    else if ( directx == 0 && directy == -1 ) 
    { 
      if ( y > top) y--; 
      else if (y == 0) 
      { 
        x = right + 1; 
        right++; 
        directx = 0; 
        directy = 1; 
      } 
      else if (y == top) 
      { 
        y--; 
        top--; 
        directx = 1; 
        directy = 0; 
      } 
    } 
    else if ( directx == 0 && directy == 1 ) 
    { 
      if (y < bottom) y++; 
      else if (y == H - 1) 
      { 
        x = left - 1; 
        left--; 
        directx = 0; 
        directy = -1; 
      } 
      else if (y == bottom) 
      { 
        y++; 
        bottom++; 
        directx = -1; 
        directy = 0; 
      } 
    } 
 
    // check whether passed already the last MB in the evolving period 
    if( !(left >= 0 && right < W && top >= 0 && bottom < H) )  
      break; 
  } 
 
  return 0; 
} 
// End JVT-D097 
 
 
#if 0 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    ScatterGetFirstMBOfSlice: Returns the MB-Nr (in scan order) of the  
 *    next first MB of the scattered Slice, -1 if no such slice is exists 
 * 
 * \par Input: 
 *    SliceID: Id of Slice 
 ************************************************************************ 
 */ 
 
int ScatterGetFirstMBOfSlice (int SliceID, int structure) 
{ 
  int i = 0; 
  // KS: dirty hack for interlace 
  int PictureSize = PictureSize = (structure?(structure == 3 ? PictureSizeInMBs:PictureSizeInMBs/2):PictureSizeInMBs);; 
 
  while ((i= 0) 
 *    -1 if the slice doesn't exist 
 *    -2 if last MB is unknown (not yet used) 
 ************************************************************************ 
 */ 
 
int ScatterGetLastCodedMBOfSlice (int SliceID, int structure) 
{ 
  int i; 
  int LastMB = -1; 
  // KS: dirty hack for interlace 
  int PictureSize = PictureSize = (structure?(structure == 3 ? PictureSizeInMBs:PictureSizeInMBs/2):PictureSizeInMBs);; 
 
  for (i=0; i