OpenCores
URL https://opencores.org/ocsvn/bluespec-h264/bluespec-h264/trunk

Subversion Repositories bluespec-h264

[/] [bluespec-h264/] [trunk/] [test/] [decoder/] [ldecod/] [src/] [macroblock.c] - Rev 100

Compare with Previous | Blame | View Log

 
/*!
 ***********************************************************************
 * \file macroblock.c
 *
 * \brief
 *     Decode a Macroblock
 *
 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
 *    - Inge Lille-Langøy               <inge.lille-langoy@telenor.com>
 *    - Rickard Sjoberg                 <rickard.sjoberg@era.ericsson.se>
 *    - Jani Lainema                    <jani.lainema@nokia.com>
 *    - Sebastian Purreiter             <sebastian.purreiter@mch.siemens.de>
 *    - Thomas Wedi                     <wedi@tnt.uni-hannover.de>
 *    - Detlev Marpe                    <marpe@hhi.de>
 *    - Gabi Blaettermann               <blaetter@hhi.de>
 *    - Ye-Kui Wang                     <wyk@ieee.org>
 *    - Lowell Winger                   <lwinger@lsil.com>
 ***********************************************************************
*/
 
#include "contributors.h"
 
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
 
#include "global.h"
#include "mbuffer.h"
#include "elements.h"
#include "errorconcealment.h"
#include "macroblock.h"
#include "fmo.h"
#include "cabac.h"
#include "vlc.h"
#include "image.h"
#include "mb_access.h"
#include "biaridecod.h"
 
#include "transform8x8.h"
 
#if TRACE
#define TRACE_STRING(s) strncpy(currSE.tracestring, s, TRACESTRING_SIZE)
#else
#define TRACE_STRING(s) // do nothing
#endif
 
extern int last_dquant;
extern ColocatedParams *Co_located;
 
 
static void SetMotionVectorPredictor (struct img_par  *img,
                                      short           pmv[2],
                                      char            ref_frame,
                                      byte            list,
                                      char            ***refPic,
                                      short           ****tmp_mv,
                                      int             block_x,
                                      int             block_y,
                                      int             blockshape_x,
                                      int             blockshape_y);
 
 
/*!
 ************************************************************************
 * \brief
 *    initializes the current macroblock
 ************************************************************************
 */
void start_macroblock(struct img_par *img,int CurrentMBInScanOrder)
{
  int l,j;
  Macroblock *currMB;   // intialization code deleted, see below, StW
 
  assert (img->current_mb_nr < img->PicSizeInMbs);
 
  currMB = &img->mb_data[img->current_mb_nr];
 
  /* Update coordinates of the current macroblock */
  if (img->MbaffFrameFlag)
  {
    img->mb_x = (img->current_mb_nr)%((2*img->width)/MB_BLOCK_SIZE);
    img->mb_y = 2*((img->current_mb_nr)/((2*img->width)/MB_BLOCK_SIZE));
 
    if (img->mb_x & 0x01)
    {
      img->mb_y++;
    }
 
    img->mb_x /= 2;
  }
  else
  {
    img->mb_x = PicPos[img->current_mb_nr][0];
    img->mb_y = PicPos[img->current_mb_nr][1];
  }
 
  /* Define vertical positions */
  img->block_y = img->mb_y * BLOCK_SIZE;      /* luma block position */
  img->pix_y   = img->mb_y * MB_BLOCK_SIZE;   /* luma macroblock position */
  img->pix_c_y = img->mb_y * img->mb_cr_size_y; /* chroma macroblock position */
 
  /* Define horizontal positions */
  img->block_x = img->mb_x * BLOCK_SIZE;      /* luma block position */
  img->pix_x   = img->mb_x * MB_BLOCK_SIZE;   /* luma pixel position */
  img->pix_c_x = img->mb_x * img->mb_cr_size_x; /* chroma pixel position */
 
  // Save the slice number of this macroblock. When the macroblock below
  // is coded it will use this to decide if prediction for above is possible
  currMB->slice_nr = img->current_slice_nr;
 
  if (img->current_slice_nr >= MAX_NUM_SLICES)
  {
    error ("maximum number of supported slices exceeded, please recompile with increased value for MAX_NUM_SLICES", 200);
  }
 
  dec_picture->slice_id[img->mb_y][img->mb_x] = img->current_slice_nr;
  if (img->current_slice_nr > dec_picture->max_slice_id)
  {
    dec_picture->max_slice_id=img->current_slice_nr;
  }
 
  CheckAvailabilityOfNeighbors();
 
  // Reset syntax element entries in MB struct
  currMB->qp          = img->qp ;
  currMB->mb_type     = 0;
  currMB->delta_quant = 0;
  currMB->cbp         = 0;
  currMB->cbp_blk     = 0;
  currMB->c_ipred_mode= DC_PRED_8; //GB
 
  for (l=0; l < 2; l++)
    for (j=0; j < BLOCK_MULTIPLE; j++)
      memset(&(currMB->mvd[l][j][0][0]),0, BLOCK_MULTIPLE * 2 * sizeof(int));
 
  currMB->cbp_bits   = 0;
 
  // initialize img->m7
  memset(&(img->m7[0][0]), 0, MB_BLOCK_PIXELS * sizeof(int));
 
  // store filtering parameters for this MB
  currMB->LFDisableIdc = img->currentSlice->LFDisableIdc;
  currMB->LFAlphaC0Offset = img->currentSlice->LFAlphaC0Offset;
  currMB->LFBetaOffset = img->currentSlice->LFBetaOffset;
 
}
 
/*!
 ************************************************************************
 * \brief
 *    set coordinates of the next macroblock
 *    check end_of_slice condition
 ************************************************************************
 */
Boolean exit_macroblock(struct img_par *img,struct inp_par *inp,int eos_bit)
{
 //! The if() statement below resembles the original code, which tested
  //! img->current_mb_nr == img->PicSizeInMbs.  Both is, of course, nonsense
  //! In an error prone environment, one can only be sure to have a new
  //! picture by checking the tr of the next slice header!
 
// printf ("exit_macroblock: FmoGetLastMBOfPicture %d, img->current_mb_nr %d\n", FmoGetLastMBOfPicture(), img->current_mb_nr);
  img->num_dec_mb++;
 
  if (img->num_dec_mb == img->PicSizeInMbs)
//  if (img->current_mb_nr == FmoGetLastMBOfPicture(currSlice->structure))
  {
//thb
/*
    if (currSlice->next_header != EOS)
      currSlice->next_header = SOP;
*/
//the
//    assert (nal_startcode_follows (img, eos_bit) == TRUE);
    return TRUE;
  }
  // ask for last mb in the slice  UVLC
  else
  {
// printf ("exit_macroblock: Slice %d old MB %d, now using MB %d\n", img->current_slice_nr, img->current_mb_nr, FmoGetNextMBNr (img->current_mb_nr));
 
    img->current_mb_nr = FmoGetNextMBNr (img->current_mb_nr);
 
    if (img->current_mb_nr == -1)     // End of Slice group, MUST be end of slice
    {
      assert (nal_startcode_follows (img, eos_bit) == TRUE);
      return TRUE;
    }
 
    if(nal_startcode_follows(img, eos_bit) == FALSE)
      return FALSE;
 
    if(img->type == I_SLICE  || img->type == SI_SLICE || active_pps->entropy_coding_mode_flag == CABAC)
      return TRUE;
    if(img->cod_counter<=0)
      return TRUE;
    return FALSE;
  }
}
 
/*!
 ************************************************************************
 * \brief
 *    Interpret the mb mode for P-Frames
 ************************************************************************
 */
void interpret_mb_mode_P(struct img_par *img)
{
  const int ICBPTAB[6] = {0,16,32,15,31,47};
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];
  int         mbmode = currMB->mb_type;
 
#define ZERO_P8x8     (mbmode==5)
#define MODE_IS_P8x8  (mbmode==4 || mbmode==5)
#define MODE_IS_I4x4  (mbmode==6)
#define I16OFFSET     (mbmode-7)
#define MODE_IS_IPCM  (mbmode==31)
 
  if(mbmode <4)
  {
    currMB->mb_type = mbmode;
    memset(&currMB->b8mode[0],mbmode,4 * sizeof(char));
    memset(&currMB->b8pdir[0],0,4 * sizeof(char));
  }
  else if(MODE_IS_P8x8)
  {
    currMB->mb_type = P8x8;
    img->allrefzero = ZERO_P8x8;
  }
  else if(MODE_IS_I4x4)
  {
    currMB->mb_type = I4MB;
    memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
  else if(MODE_IS_IPCM)
  {
    currMB->mb_type=IPCM;
    currMB->cbp= -1;
    currMB->i16mode = 0;
 
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
  else
  {
    currMB->mb_type = I16MB;
    currMB->cbp= ICBPTAB[(I16OFFSET)>>2];
    currMB->i16mode = (I16OFFSET) & 0x03;
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
}
 
/*!
 ************************************************************************
 * \brief
 *    Interpret the mb mode for I-Frames
 ************************************************************************
 */
void interpret_mb_mode_I(struct img_par *img)
{
  const int ICBPTAB[6] = {0,16,32,15,31,47};
  Macroblock *currMB   = &img->mb_data[img->current_mb_nr];
  int         mbmode   = currMB->mb_type;
 
  if (mbmode==0)
  {
    currMB->mb_type = I4MB;
    memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
  else if(mbmode==25)
  {
    currMB->mb_type=IPCM;
    currMB->cbp= -1;
    currMB->i16mode = 0;
 
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
  else
  {
    currMB->mb_type = I16MB;
    currMB->cbp= ICBPTAB[(mbmode-1)>>2];
    currMB->i16mode = (mbmode-1) & 0x03;
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
}
 
/*!
 ************************************************************************
 * \brief
 *    Interpret the mb mode for B-Frames
 ************************************************************************
 */
void interpret_mb_mode_B(struct img_par *img)
{
  static const int offset2pdir16x16[12]   = {0, 0, 1, 2, 0,0,0,0,0,0,0,0};
  static const int offset2pdir16x8[22][2] = {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{1,1},{0,0},{0,1},{0,0},{1,0},
                                             {0,0},{0,2},{0,0},{1,2},{0,0},{2,0},{0,0},{2,1},{0,0},{2,2},{0,0}};
  static const int offset2pdir8x16[22][2] = {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{1,1},{0,0},{0,1},{0,0},
                                             {1,0},{0,0},{0,2},{0,0},{1,2},{0,0},{2,0},{0,0},{2,1},{0,0},{2,2}};
 
  const int ICBPTAB[6] = {0,16,32,15,31,47};
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];
 
  int i, mbmode;
  int mbtype  = currMB->mb_type;
 
  //--- set mbtype, b8type, and b8pdir ---
  if (mbtype==0)       // direct
  {
    mbmode=0;
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],2,4 * sizeof(char));
  }
  else if (mbtype==23) // intra4x4
  {
    mbmode=I4MB;
    memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
  else if ((mbtype>23) && (mbtype<48) ) // intra16x16
  {
    mbmode=I16MB;
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
 
    currMB->cbp     = ICBPTAB[(mbtype-24)>>2];
    currMB->i16mode = (mbtype-24) & 0x03;
  }
  else if (mbtype==22) // 8x8(+split)
  {
    mbmode=P8x8;       // b8mode and pdir is transmitted in additional codewords
  }
  else if (mbtype<4)   // 16x16
  {
    mbmode=1;
    memset(&currMB->b8mode[0], 1,4 * sizeof(char));
    memset(&currMB->b8pdir[0],offset2pdir16x16[mbtype],4 * sizeof(char));
  }
  else if(mbtype==48)
  {
    mbmode=IPCM;
    memset(&currMB->b8mode[0], 0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
 
    currMB->cbp= -1;
    currMB->i16mode = 0;
  }
 
  else if ((mbtype&0x01)==0) // 16x8
  {
    mbmode=2;
    memset(&currMB->b8mode[0], 2,4 * sizeof(char));
    for(i=0;i<4;i++)
    {
      currMB->b8pdir[i]=offset2pdir16x8 [mbtype][i>>1];
    }
  }
  else
  {
    mbmode=3;
    memset(&currMB->b8mode[0], 3,4 * sizeof(char));
    for(i=0;i<4;i++)
    {
      currMB->b8pdir[i]=offset2pdir8x16 [mbtype][i&0x01];
    }
  }
  currMB->mb_type = mbmode;
}
/*!
 ************************************************************************
 * \brief
 *    Interpret the mb mode for SI-Frames
 ************************************************************************
 */
void interpret_mb_mode_SI(struct img_par *img)
{
  const int ICBPTAB[6] = {0,16,32,15,31,47};
  Macroblock *currMB   = &img->mb_data[img->current_mb_nr];
  int         mbmode   = currMB->mb_type;
 
  if (mbmode==0)
  {
    currMB->mb_type = SI4MB;
    memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
    img->siblock[img->mb_y][img->mb_x]=1;
  }
  else if (mbmode==1)
  {
    currMB->mb_type = I4MB;
    memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
  else if(mbmode==26)
  {
    currMB->mb_type=IPCM;
    currMB->cbp= -1;
    currMB->i16mode = 0;
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
 
  else
  {
    currMB->mb_type = I16MB;
    currMB->cbp= ICBPTAB[(mbmode-1)>>2];
    currMB->i16mode = (mbmode-2) & 0x03;
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
}
/*!
 ************************************************************************
 * \brief
 *    init macroblock I and P frames
 ************************************************************************
 */
void init_macroblock(struct img_par *img)
{
  int i,j;
 
  for(j=img->block_y;j<img->block_y+BLOCK_SIZE;j++)
  {                           // reset vectors and pred. modes
    memset(&dec_picture->mv[LIST_0][j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short));
    memset(&dec_picture->mv[LIST_1][j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short));
    memset(&dec_picture->ref_idx[LIST_0][j][img->block_x], -1, BLOCK_SIZE * sizeof(char));
    memset(&dec_picture->ref_idx[LIST_1][j][img->block_x], -1, BLOCK_SIZE * sizeof(char));
    memset(&img->ipredmode[j][img->block_x], DC_PRED, BLOCK_SIZE * sizeof(char));
    for (i=img->block_x;i<img->block_x+BLOCK_SIZE;i++)
    {
      dec_picture->ref_pic_id[LIST_0][j][i] = INT64_MIN;
      dec_picture->ref_pic_id[LIST_1][j][i] = INT64_MIN;
    }
  }
}
 
 
/*!
 ************************************************************************
 * \brief
 *    Sets mode for 8x8 block
 ************************************************************************
 */
void SetB8Mode (struct img_par* img, Macroblock* currMB, int value, int i)
{
  static const int p_v2b8 [ 5] = {4, 5, 6, 7, IBLOCK};
  static const int p_v2pd [ 5] = {0, 0, 0, 0, -1};
  static const int b_v2b8 [14] = {0, 4, 4, 4, 5, 6, 5, 6, 5, 6, 7, 7, 7, IBLOCK};
  static const int b_v2pd [14] = {2, 0, 1, 2, 0, 0, 1, 1, 2, 2, 0, 1, 2, -1};
 
  if (img->type==B_SLICE)
  {
    currMB->b8mode[i]   = b_v2b8[value];
    currMB->b8pdir[i]   = b_v2pd[value];
 
  }
  else
  {
    currMB->b8mode[i]   = p_v2b8[value];
    currMB->b8pdir[i]   = p_v2pd[value];
  }
 
}
 
 
void reset_coeffs()
{
  int i, j;
 
  // reset all coeffs
  for (i=0;i<BLOCK_SIZE;i++)
  {
    for (j=0;j<BLOCK_SIZE +img->num_blk8x8_uv;j++)
      memset(&img->cof[i][j][0][0],0,BLOCK_SIZE * BLOCK_SIZE * sizeof(int));
  }
 
  // CAVLC
  memset(&img->nz_coeff[img->current_mb_nr][0][0],0, BLOCK_SIZE * (BLOCK_SIZE + img->num_blk8x8_uv) * sizeof(int));
}
 
void field_flag_inference()
{
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];
 
  if (currMB->mbAvailA)
  {
    currMB->mb_field = img->mb_data[currMB->mbAddrA].mb_field;
  }
  else
  {
    // check top macroblock pair
    if (currMB->mbAvailB)
    {
      currMB->mb_field = img->mb_data[currMB->mbAddrB].mb_field;
    }
    else
      currMB->mb_field = 0;
  }
 
}
 
void set_chroma_qp(Macroblock* currMB)
{
  int i;
  for (i=0; i<2; i++)
  {
    currMB->qpc[i] = iClip3 ( -img->bitdepth_chroma_qp_scale, 51, currMB->qp + dec_picture->chroma_qp_offset[i] );
    currMB->qpc[i] = currMB->qpc[i] < 0 ? currMB->qpc[i] : QP_SCALE_CR[currMB->qpc[i]];
  }
}
 
 
/*!
 ************************************************************************
 * \brief
 *    Get the syntax elements from the NAL
 ************************************************************************
 */
int read_one_macroblock(struct img_par *img,struct inp_par *inp)
{
  int i;
 
  SyntaxElement currSE;
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];
 
  Slice *currSlice = img->currentSlice;
  DataPartition *dP;
  int *partMap = assignSE2partition[currSlice->dp_mode];
  Macroblock *topMB = NULL;
  int  prevMbSkipped = 0;
  int  img_block_y;
  int  check_bottom, read_bottom, read_top;
 
  if (img->MbaffFrameFlag)
  {
    if (img->current_mb_nr&0x01)
    {
      topMB= &img->mb_data[img->current_mb_nr-1];
      if(!(img->type == B_SLICE))
        prevMbSkipped = (topMB->mb_type == 0);
      else
        prevMbSkipped = topMB->skip_flag;
    }
    else
      prevMbSkipped = 0;
  }
 
  if ((img->current_mb_nr&0x01) == 0)
    currMB->mb_field = 0;
  else
    currMB->mb_field = img->mb_data[img->current_mb_nr-1].mb_field;
 
 
  currMB->qp = img->qp ;
  for (i=0; i<2; i++)
  {
    currMB->qpc[i] = iClip3 ( -img->bitdepth_chroma_qp_scale, 51, img->qp + dec_picture->chroma_qp_offset[i] );
    currMB->qpc[i] = currMB->qpc[i] < 0 ? currMB->qpc[i] : QP_SCALE_CR[currMB->qpc[i]];
  }
 
  currSE.type = SE_MBTYPE;
 
  //  read MB mode *****************************************************************
  dP = &(currSlice->partArr[partMap[currSE.type]]);
 
  if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)   currSE.mapping = linfo_ue;
 
  if(img->type == I_SLICE || img->type == SI_SLICE)
  {
    // read MB aff
    if (img->MbaffFrameFlag && (img->current_mb_nr&0x01)==0)
    {
      TRACE_STRING("mb_field_decoding_flag");
      if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
      {
        currSE.len = 1;
        readSyntaxElement_FLC(&currSE, dP->bitstream);
      }
      else
      {
        currSE.reading = readFieldModeInfo_CABAC;
        dP->readSyntaxElement(&currSE,img,dP);
      }
      currMB->mb_field = currSE.value1;
    }
    if(active_pps->entropy_coding_mode_flag  == CABAC)
      CheckAvailabilityOfNeighborsCABAC();
 
    //  read MB type
    TRACE_STRING("mb_type");
    currSE.reading = readMB_typeInfo_CABAC;
    dP->readSyntaxElement(&currSE,img,dP);
 
    currMB->mb_type = currSE.value1;
    if(!dP->bitstream->ei_flag)
      currMB->ei_flag = 0;
  }
  // non I/SI-slice CABAC
  else if (active_pps->entropy_coding_mode_flag == CABAC)
  {
    // read MB skip_flag
    if (img->MbaffFrameFlag && ((img->current_mb_nr&0x01) == 0||prevMbSkipped))
      field_flag_inference();
 
    CheckAvailabilityOfNeighborsCABAC();
    TRACE_STRING("mb_skip_flag");
    currSE.reading = readMB_skip_flagInfo_CABAC;
    dP->readSyntaxElement(&currSE,img,dP);
 
    currMB->mb_type   = currSE.value1;
    currMB->skip_flag = !(currSE.value1);
 
    if (img->type==B_SLICE)
      currMB->cbp = currSE.value2;
 
    if(!dP->bitstream->ei_flag)
      currMB->ei_flag = 0;
 
    if ((img->type==B_SLICE) && currSE.value1==0 && currSE.value2==0)
      img->cod_counter=0;
 
    // read MB AFF
    if (img->MbaffFrameFlag)
    {
      check_bottom=read_bottom=read_top=0;
      if ((img->current_mb_nr&0x01)==0)
      {
        check_bottom =  currMB->skip_flag;
        read_top = !check_bottom;
      }
      else
      {
        read_bottom = (topMB->skip_flag && (!currMB->skip_flag));
       }
 
      if (read_bottom || read_top)
      {
        TRACE_STRING("mb_field_decoding_flag");
        currSE.reading = readFieldModeInfo_CABAC;
        dP->readSyntaxElement(&currSE,img,dP);
        currMB->mb_field = currSE.value1;
      }
      if (check_bottom)
        check_next_mb_and_get_field_mode_CABAC(&currSE,img,dP);
 
    }
 
    CheckAvailabilityOfNeighborsCABAC();
 
    // read MB type
    if (currMB->mb_type != 0 )
    {
      currSE.reading = readMB_typeInfo_CABAC;
      TRACE_STRING("mb_type");
      dP->readSyntaxElement(&currSE,img,dP);
      currMB->mb_type = currSE.value1;
      if(!dP->bitstream->ei_flag)
        currMB->ei_flag = 0;
    }
  }
  // VLC Non-Intra
  else
  {
    if(img->cod_counter == -1)
    {
      TRACE_STRING("mb_skip_run");
      dP->readSyntaxElement(&currSE,img,dP);
      img->cod_counter = currSE.value1;
    }
    if (img->cod_counter==0)
    {
      // read MB aff
      if ((img->MbaffFrameFlag) && (((img->current_mb_nr&0x01)==0) || ((img->current_mb_nr&0x01) && prevMbSkipped)))
      {
        TRACE_STRING("mb_field_decoding_flag");
        currSE.len = 1;
        readSyntaxElement_FLC(&currSE, dP->bitstream);
        currMB->mb_field = currSE.value1;
      }
 
      // read MB type
      TRACE_STRING("mb_type");
      dP->readSyntaxElement(&currSE,img,dP);
      if(img->type == P_SLICE || img->type == SP_SLICE)
        currSE.value1++;
      currMB->mb_type = currSE.value1;
      if(!dP->bitstream->ei_flag)
        currMB->ei_flag = 0;
      img->cod_counter--;
      currMB->skip_flag = 0;
    }
    else
    {
      img->cod_counter--;
      currMB->mb_type = 0;
      currMB->ei_flag = 0;
      currMB->skip_flag = 1;
 
      // read field flag of bottom block
      if(img->MbaffFrameFlag)
      {
        if(img->cod_counter == 0 && ((img->current_mb_nr&0x01) == 0))
        {
          TRACE_STRING("mb_field_decoding_flag (of coded bottom mb)");
          currSE.len = 1;
          readSyntaxElement_FLC(&currSE, dP->bitstream);
          dP->bitstream->frame_bitoffset--;
          currMB->mb_field = currSE.value1;
        }
        else if(img->cod_counter > 0 && ((img->current_mb_nr&0x01) == 0))
        {
          // check left macroblock pair first
          if (mb_is_available(img->current_mb_nr-2, img->current_mb_nr)&&((img->current_mb_nr%(img->PicWidthInMbs*2))!=0))
          {
            currMB->mb_field = img->mb_data[img->current_mb_nr-2].mb_field;
          }
          else
          {
            // check top macroblock pair
            if (mb_is_available(img->current_mb_nr-2*img->PicWidthInMbs, img->current_mb_nr))
            {
              currMB->mb_field = img->mb_data[img->current_mb_nr-2*img->PicWidthInMbs].mb_field;
            }
            else
              currMB->mb_field = 0;
          }
        }
      }
    }
  }
 
  dec_picture->mb_field[img->current_mb_nr] = currMB->mb_field;
 
  img->siblock[img->mb_y][img->mb_x]=0;
 
  if ((img->type==P_SLICE ))    // inter frame
    interpret_mb_mode_P(img);
  else if (img->type==I_SLICE)                                  // intra frame
    interpret_mb_mode_I(img);
  else if ((img->type==B_SLICE))       // B frame
    interpret_mb_mode_B(img);
  else if ((img->type==SP_SLICE))     // SP frame
    interpret_mb_mode_P(img);
  else if (img->type==SI_SLICE)     // SI frame
    interpret_mb_mode_SI(img);
 
  if(img->MbaffFrameFlag)
  {
    if(currMB->mb_field)
    {
      img->num_ref_idx_l0_active <<=1;
      img->num_ref_idx_l1_active <<=1;
    }
  }
 
  //init NoMbPartLessThan8x8Flag
  currMB->NoMbPartLessThan8x8Flag = (IS_DIRECT(currMB) && !(active_sps->direct_8x8_inference_flag))? 0: 1;
 
  //====== READ 8x8 SUB-PARTITION MODES (modes of 8x8 blocks) and Intra VBST block modes ======
  if (IS_P8x8 (currMB))
  {
    currSE.type    = SE_MBTYPE;
    dP = &(currSlice->partArr[partMap[SE_MBTYPE]]);
 
    for (i=0; i<4; i++)
    {
      if (active_pps->entropy_coding_mode_flag ==UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_ue;
      else                                                  currSE.reading = readB8_typeInfo_CABAC;
 
      TRACE_STRING("sub_mb_type");
      dP->readSyntaxElement (&currSE, img, dP);
      SetB8Mode (img, currMB, currSE.value1, i);
 
      //set NoMbPartLessThan8x8Flag for P8x8 mode
      currMB->NoMbPartLessThan8x8Flag &= (currMB->b8mode[i]==0 && active_sps->direct_8x8_inference_flag) ||
                                         (currMB->b8mode[i]==4);
    }
    //--- init macroblock data ---
    init_macroblock       (img);
    readMotionInfoFromNAL (img, inp);
  }
 
 
  //============= Transform Size Flag for INTRA MBs =============
  //-------------------------------------------------------------
  //transform size flag for INTRA_4x4 and INTRA_8x8 modes
  if (currMB->mb_type == I4MB && img->Transform8x8Mode)
  {
    currSE.type   =  SE_HEADER;
    dP = &(currSlice->partArr[partMap[SE_HEADER]]);
    currSE.reading = readMB_transform_size_flag_CABAC;
    TRACE_STRING("transform_size_8x8_flag");
 
    // read UVLC transform_size_8x8_flag
    if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
    {
      currSE.len = 1;
      readSyntaxElement_FLC(&currSE, dP->bitstream);
    }
    else
    {
      dP->readSyntaxElement(&currSE,img,dP);
    }
 
    currMB->luma_transform_size_8x8_flag = currSE.value1;
 
    if (currMB->luma_transform_size_8x8_flag)
    {
      currMB->mb_type = I8MB;
      for (i=0;i<4;i++)
      {
        currMB->b8mode[i]=I8MB;
        currMB->b8pdir[i]=-1;
      }
    }
  }
  else
  {
    currMB->luma_transform_size_8x8_flag = 0;
  }
 
  if(active_pps->constrained_intra_pred_flag && (img->type==P_SLICE|| img->type==B_SLICE))        // inter frame
  {
    if( !IS_INTRA(currMB) )
    {
      img->intra_block[img->current_mb_nr] = 0;
    }
  }
 
  //! TO for error concealment
  //! If we have an INTRA Macroblock and we lost the partition
  //! which contains the intra coefficients Copy MB would be better
  //! than just a gray block.
  //! Seems to be a bit at the wrong place to do this right here, but for this case
  //! up to now there is no other way.
  dP = &(currSlice->partArr[partMap[SE_CBP_INTRA]]);
  if(IS_INTRA (currMB) && dP->bitstream->ei_flag && img->number)
  {
    currMB->mb_type = 0;
    currMB->ei_flag = 1;
    for (i=0;i<4;i++) {currMB->b8mode[i]=currMB->b8pdir[i]=0; }
  }
  dP = &(currSlice->partArr[partMap[currSE.type]]);
  //! End TO
 
 
  //--- init macroblock data ---
  if (!IS_P8x8 (currMB))
    init_macroblock       (img);
 
  if (IS_DIRECT (currMB) && img->cod_counter >= 0)
  {
    currMB->cbp = 0;
    reset_coeffs();
 
    if (active_pps->entropy_coding_mode_flag ==CABAC)
      img->cod_counter=-1;
 
    return DECODE_MB;
  }
 
  if (IS_COPY (currMB)) //keep last macroblock
  {
    int i, j, k;
    short pmv[2];
    int zeroMotionAbove;
    int zeroMotionLeft;
    PixelPos mb_a, mb_b;
    int      a_mv_y = 0;
    int      a_ref_idx = 0;
    int      b_mv_y = 0;
    int      b_ref_idx = 0;
    int      list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? 4 : 2 : 0;
    short ***cur_mv = dec_picture->mv[LIST_0];
    getLuma4x4Neighbour(img->current_mb_nr,-1, 0, &mb_a);
    getLuma4x4Neighbour(img->current_mb_nr, 0,-1, &mb_b);
 
    if (mb_a.available)
    {
      a_mv_y    = cur_mv[mb_a.pos_y][mb_a.pos_x][1];
      a_ref_idx = dec_picture->ref_idx[LIST_0][mb_a.pos_y][mb_a.pos_x];
 
      if (currMB->mb_field && !img->mb_data[mb_a.mb_addr].mb_field)
      {
        a_mv_y    /=2;
        a_ref_idx *=2;
      }
      if (!currMB->mb_field && img->mb_data[mb_a.mb_addr].mb_field)
      {
        a_mv_y    *=2;
        a_ref_idx >>=1;
      }
    }
 
    if (mb_b.available)
    {
      b_mv_y    = cur_mv[mb_b.pos_y][mb_b.pos_x][1];
      b_ref_idx = dec_picture->ref_idx[LIST_0][mb_b.pos_y][mb_b.pos_x];
 
      if (currMB->mb_field && !img->mb_data[mb_b.mb_addr].mb_field)
      {
        b_mv_y    /=2;
        b_ref_idx *=2;
      }
      if (!currMB->mb_field && img->mb_data[mb_b.mb_addr].mb_field)
      {
        b_mv_y    *=2;
        b_ref_idx >>=1;
      }
    }
 
    zeroMotionLeft  = !mb_a.available ? 1 : a_ref_idx==0 && cur_mv[mb_a.pos_y][mb_a.pos_x][0]==0 && a_mv_y==0 ? 1 : 0;
    zeroMotionAbove = !mb_b.available ? 1 : b_ref_idx==0 && cur_mv[mb_b.pos_y][mb_b.pos_x][0]==0 && b_mv_y==0 ? 1 : 0;
 
    currMB->cbp = 0;
    reset_coeffs();
 
    img_block_y   = img->block_y;
 
    if (zeroMotionAbove || zeroMotionLeft)
    {
      for(j=img_block_y;j<img_block_y + BLOCK_SIZE;j++)
      {
        memset(&cur_mv[j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short));
      }
    }
    else
    {
      SetMotionVectorPredictor (img, pmv, 0, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);
 
      for(j=img_block_y;j<img_block_y + BLOCK_SIZE;j++)
      {
        for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++)
          for (k=0;k<2;k++)
          {
            cur_mv[j][i][k] = pmv[k];
          }
      }
    }
    for(j=img_block_y;j< img_block_y + BLOCK_SIZE;j++)
    {
      for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++)
      {
        dec_picture->ref_idx[LIST_0][j][i] = 0;
        dec_picture->ref_pic_id[LIST_0][j][i] =
          dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->ref_idx[LIST_0][j][i]];
      }
    }
    return DECODE_MB;
  }
  if(currMB->mb_type!=IPCM)
  {
 
    // intra prediction modes for a macroblock 4x4 **********************************************
    read_ipred_modes(img,inp);
 
    // read inter frame vector data *********************************************************
    if (IS_INTERMV (currMB) && (!IS_P8x8(currMB)))
    {
      readMotionInfoFromNAL (img, inp);
    }
    // read CBP and Coeffs  ***************************************************************
    readCBPandCoeffsFromNAL (img,inp);
  }
  else
  {
    //read pcm_alignment_zero_bit and pcm_byte[i]
 
    // here dP is assigned with the same dP as SE_MBTYPE, because IPCM syntax is in the
    // same category as MBTYPE
    dP = &(currSlice->partArr[partMap[SE_MBTYPE]]);
    readIPCMcoeffsFromNAL(img,inp,dP);
  }
 
 
  return DECODE_MB;
}
 
 
 
/*!
 ************************************************************************
 * \brief
 *    Initialize decoding engine after decoding an IPCM macroblock
 *    (for IPCM CABAC  28/11/2003)
 *
 * \author
 *    Dong Wang <Dong.Wang@bristol.ac.uk>
 ************************************************************************
 */
void init_decoding_engine_IPCM(struct img_par *img)
{
  Slice *currSlice = img->currentSlice;
  Bitstream *currStream;
  int ByteStartPosition;
  int PartitionNumber;
  int i;
 
  if(currSlice->dp_mode==PAR_DP_1)
    PartitionNumber=1;
  else if(currSlice->dp_mode==PAR_DP_3)
    PartitionNumber=3;
  else
  {
    printf("Partition Mode is not supported\n");
    exit(1);
  }
 
  for(i=0;i<PartitionNumber;i++)
  {
    currStream = currSlice->partArr[i].bitstream;
    ByteStartPosition = currStream->read_len;
 
 
    arideco_start_decoding (&currSlice->partArr[i].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len, img->type);
  }
}
 
 
 
 
/*!
 ************************************************************************
 * \brief
 *    Read IPCM pcm_alignment_zero_bit and pcm_byte[i] from stream to img->cof
 *    (for IPCM CABAC and IPCM CAVLC)
 *
 * \author
 *    Dong Wang <Dong.Wang@bristol.ac.uk>
 ************************************************************************
 */
 
void readIPCMcoeffsFromNAL(struct img_par *img, struct inp_par *inp, struct datapartition *dP)
{
  SyntaxElement currSE;
  int i,j;
 
  //For CABAC, we don't need to read bits to let stream byte aligned
  //  because we have variable for integer bytes position
  if(active_pps->entropy_coding_mode_flag  == CABAC)
  {
    //read luma and chroma IPCM coefficients
    currSE.len=8;
    TRACE_STRING("pcm_byte luma");
 
    for(i=0;i<MB_BLOCK_SIZE;i++)
    {
      for(j=0;j<MB_BLOCK_SIZE;j++)
      {
        readIPCMBytes_CABAC(&currSE, dP->bitstream);
        img->cof[(i>>2)][(j>>2)][i & 0x03][j & 0x03]=currSE.value1;
      }
    }
    if (dec_picture->chroma_format_idc != YUV400)
    {
      TRACE_STRING("pcm_byte chroma");
      for(i=0;i<img->mb_cr_size_y;i++)
      {
        for(j=0;j<img->mb_cr_size_x;j++)
        {
          readIPCMBytes_CABAC(&currSE, dP->bitstream);
          img->cof[(i>>2)][(j>>2)+4][i & 0x03][j & 0x03]=currSE.value1;
        }
      }
      for(i=0;i<img->mb_cr_size_y;i++)
      {
        for(j=0;j<img->mb_cr_size_x;j++)
        {
          readIPCMBytes_CABAC(&currSE, dP->bitstream);
          img->cof[(i>>2)+2][(j>>2)+4][i & 0x03][j & 0x03]=currSE.value1;
        }
      }
    }
    //If the decoded MB is IPCM MB, decoding engine is initialized
 
    // here the decoding engine is directly initialized without checking End of Slice
    // The reason is that, whether current MB is the last MB in slice or not, there is
    // at least one 'end of slice' syntax after this MB. So when fetching bytes in this
    // initialisation process, we can guarantee there is bits available in bitstream.
 
    init_decoding_engine_IPCM(img);
  }
  else
  {
    //read bits to let stream byte aligned
 
    if((dP->bitstream->frame_bitoffset)%8!=0)
    {
      TRACE_STRING("pcm_alignment_zero_bit");
      currSE.len=8-(dP->bitstream->frame_bitoffset)%8;
      readSyntaxElement_FLC(&currSE, dP->bitstream);
    }
 
    //read luma and chroma IPCM coefficients
    currSE.len=img->bitdepth_luma;
    TRACE_STRING("pcm_sample_luma");
 
    for(i=0;i<MB_BLOCK_SIZE;i++)
    {
      for(j=0;j<MB_BLOCK_SIZE;j++)
      {
        readSyntaxElement_FLC(&currSE, dP->bitstream);
        img->cof[(i>>2)][(j>>2)][i & 0x03][j & 0x03]=currSE.value1;
      }
    }
    currSE.len=img->bitdepth_chroma;
    if (dec_picture->chroma_format_idc != YUV400)
    {
      TRACE_STRING("pcm_sample_chroma (u)");
      for(i=0;i<img->mb_cr_size_y;i++)
      {
        for(j=0;j<img->mb_cr_size_x;j++)
        {
          readSyntaxElement_FLC(&currSE, dP->bitstream);
          img->cof[(i>>2)][(j>>2)+4][i & 0x03][j & 0x03]=currSE.value1;
        }
      }
      TRACE_STRING("pcm_sample_chroma (v)");
      for(i=0;i<img->mb_cr_size_y;i++)
      {
        for(j=0;j<img->mb_cr_size_x;j++)
        {
          readSyntaxElement_FLC(&currSE, dP->bitstream);
          img->cof[(i>>2)+2][(j>>2)+4][i & 0x03][j & 0x03]=currSE.value1;
        }
      }
    }
  }
}
 
 
 
void read_ipred_modes(struct img_par *img,struct inp_par *inp)
{
  int b8,i,j,bi,bj,bx,by,dec;
  SyntaxElement currSE;
  Slice *currSlice;
  DataPartition *dP;
  int *partMap;
  Macroblock *currMB;
  int ts, ls;
  int mostProbableIntraPredMode;
  int upIntraPredMode;
  int leftIntraPredMode;
  int IntraChromaPredModeFlag;
  int bs_x, bs_y;
  int ii,jj;
 
  PixelPos left_block;
  PixelPos top_block;
 
  currMB = &img->mb_data[img->current_mb_nr];
 
  IntraChromaPredModeFlag = IS_INTRA(currMB);
 
  currSlice = img->currentSlice;
  partMap = assignSE2partition[currSlice->dp_mode];
 
  currSE.type = SE_INTRAPREDMODE;
 
  TRACE_STRING("intra4x4_pred_mode");
  dP = &(currSlice->partArr[partMap[currSE.type]]);
 
  if (!(active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag))
    currSE.reading = readIntraPredMode_CABAC;
 
  for(b8=0;b8<4;b8++)  //loop 8x8 blocks
  {
    if((currMB->b8mode[b8]==IBLOCK )||(currMB->b8mode[b8]==I8MB))
    {
      bs_x = bs_y = (currMB->b8mode[b8] == I8MB)?8:4;
 
      IntraChromaPredModeFlag = 1;
 
      ii=(bs_x>>2);
      jj=(bs_y>>2);
 
      for(j=0;j<2;j+=jj)  //loop subblocks
      {
        by = (b8&2) + j;
        bj = img->block_y + by;
        for(i=0;i<2;i+=ii)
        {
          bx = ((b8&1)<<1) + i;
          bi = img->block_x + bx;
          //get from stream
          if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
            readSyntaxElement_Intra4x4PredictionMode(&currSE,img,dP);
          else
          {
            currSE.context=(b8<<2)+(j<<1)+i;
            dP->readSyntaxElement(&currSE,img,dP);
          }
 
          getLuma4x4Neighbour(img->current_mb_nr, (bx<<2) - 1, (by<<2),     &left_block);
          getLuma4x4Neighbour(img->current_mb_nr, (bx<<2),     (by<<2) - 1, &top_block);
 
          //get from array and decode
 
          if (active_pps->constrained_intra_pred_flag)
          {
            left_block.available = left_block.available ? img->intra_block[left_block.mb_addr] : 0;
            top_block.available  = top_block.available  ? img->intra_block[top_block.mb_addr]  : 0;
          }
 
          // !! KS: not sure if the following is still correct...
          ts = ls = 0;   // Check to see if the neighboring block is SI
          if (IS_OLDINTRA(currMB) && img->type == SI_SLICE)           // need support for MBINTLC1
          {
            if (left_block.available)
              if (img->siblock [left_block.pos_y][left_block.pos_x])
                ls=1;
 
            if (top_block.available)
              if (img->siblock [top_block.pos_y][top_block.pos_x])
                ts=1;
          }
 
          upIntraPredMode            = (top_block.available  &&(ts == 0)) ? img->ipredmode[top_block.pos_y ][top_block.pos_x ] : -1;
          leftIntraPredMode          = (left_block.available &&(ls == 0)) ? img->ipredmode[left_block.pos_y][left_block.pos_x] : -1;
 
          mostProbableIntraPredMode  = (upIntraPredMode < 0 || leftIntraPredMode < 0) ? DC_PRED : upIntraPredMode < leftIntraPredMode ? upIntraPredMode : leftIntraPredMode;
 
          dec = (currSE.value1 == -1) ? mostProbableIntraPredMode : currSE.value1 + (currSE.value1 >= mostProbableIntraPredMode);
 
          //set
          for(jj=0;jj<(bs_y>>2);jj++)   //loop 4x4s in the subblock for 8x8 prediction setting
            memset(&img->ipredmode[bj+jj][bi], dec, (bs_x>>2) * sizeof(char));
        }
      }
    }
  }
 
  if (IntraChromaPredModeFlag && dec_picture->chroma_format_idc != YUV400)
  {
    currSE.type = SE_INTRAPREDMODE;
    TRACE_STRING("intra_chroma_pred_mode");
    dP = &(currSlice->partArr[partMap[currSE.type]]);
 
    if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_ue;
    else                                                    currSE.reading = readCIPredMode_CABAC;
 
    dP->readSyntaxElement(&currSE,img,dP);
    currMB->c_ipred_mode = currSE.value1;
 
    if (currMB->c_ipred_mode < DC_PRED_8 || currMB->c_ipred_mode > PLANE_8)
    {
      error("illegal chroma intra pred mode!\n", 600);
    }
  }
}
 
/*!
 ************************************************************************
 * \brief
 *    Set motion vector predictor
 ************************************************************************
 */
static void SetMotionVectorPredictor (struct img_par  *img,
                                      short           pmv[2],
                                      char            ref_frame,
                                      byte            list,
                                      char            ***refPic,
                                      short           ****tmp_mv,
                                      int             block_x,
                                      int             block_y,
                                      int             blockshape_x,
                                      int             blockshape_y)
{
  int mb_x                 = BLOCK_SIZE*block_x;
  int mb_y                 = BLOCK_SIZE*block_y;
  int mb_nr                = img->current_mb_nr;
 
  int mv_a, mv_b, mv_c, pred_vec=0;
  int mvPredType, rFrameL, rFrameU, rFrameUR;
  int hv;
 
 
  PixelPos block_a, block_b, block_c, block_d;
 
  getLuma4x4Neighbour(mb_nr, mb_x - 1,            mb_y,     &block_a);
  getLuma4x4Neighbour(mb_nr, mb_x,                mb_y - 1, &block_b);
  getLuma4x4Neighbour(mb_nr, mb_x + blockshape_x, mb_y - 1, &block_c);
  getLuma4x4Neighbour(mb_nr, mb_x - 1,            mb_y - 1, &block_d);
 
  if (mb_y > 0)
  {
    if (mb_x < 8)  // first column of 8x8 blocks
    {
      if (mb_y==8)
      {
        if (blockshape_x == 16)      block_c.available  = 0;
      }
      else
      {
        if (mb_x+blockshape_x == 8)  block_c.available  = 0;
      }
    }
    else
    {
      if (mb_x+blockshape_x == 16)   block_c.available  = 0;
    }
  }
 
  if (!block_c.available)
  {
    block_c=block_d;
  }
 
  mvPredType = MVPRED_MEDIAN;
 
  if (!img->MbaffFrameFlag)
  {
    rFrameL    = block_a.available    ? refPic[list][block_a.pos_y][block_a.pos_x] : -1;
    rFrameU    = block_b.available    ? refPic[list][block_b.pos_y][block_b.pos_x] : -1;
    rFrameUR   = block_c.available    ? refPic[list][block_c.pos_y][block_c.pos_x] : -1;
  }
  else
  {
    if (img->mb_data[img->current_mb_nr].mb_field)
    {
      rFrameL    = block_a.available    ?
        img->mb_data[block_a.mb_addr].mb_field ?
        refPic[list][block_a.pos_y][block_a.pos_x]:
        refPic[list][block_a.pos_y][block_a.pos_x] * 2:
        -1;
      rFrameU    = block_b.available    ?
        img->mb_data[block_b.mb_addr].mb_field ?
        refPic[list][block_b.pos_y][block_b.pos_x]:
        refPic[list][block_b.pos_y][block_b.pos_x] * 2:
        -1;
      rFrameUR    = block_c.available    ?
        img->mb_data[block_c.mb_addr].mb_field ?
        refPic[list][block_c.pos_y][block_c.pos_x]:
        refPic[list][block_c.pos_y][block_c.pos_x] * 2:
        -1;
    }
    else
    {
      rFrameL    = block_a.available    ?
        img->mb_data[block_a.mb_addr].mb_field ?
        refPic[list][block_a.pos_y][block_a.pos_x] >>1:
        refPic[list][block_a.pos_y][block_a.pos_x] :
        -1;
      rFrameU    = block_b.available    ?
        img->mb_data[block_b.mb_addr].mb_field ?
        refPic[list][block_b.pos_y][block_b.pos_x] >>1:
        refPic[list][block_b.pos_y][block_b.pos_x] :
        -1;
      rFrameUR    = block_c.available    ?
        img->mb_data[block_c.mb_addr].mb_field ?
        refPic[list][block_c.pos_y][block_c.pos_x] >>1:
        refPic[list][block_c.pos_y][block_c.pos_x] :
        -1;
    }
  }
 
 
  /* Prediction if only one of the neighbors uses the reference frame
   * we are checking
   */
  if(rFrameL == ref_frame && rFrameU != ref_frame && rFrameUR != ref_frame)       mvPredType = MVPRED_L;
  else if(rFrameL != ref_frame && rFrameU == ref_frame && rFrameUR != ref_frame)  mvPredType = MVPRED_U;
  else if(rFrameL != ref_frame && rFrameU != ref_frame && rFrameUR == ref_frame)  mvPredType = MVPRED_UR;
  // Directional predictions
  if(blockshape_x == 8 && blockshape_y == 16)
  {
    if(mb_x == 0)
    {
      if(rFrameL == ref_frame)
        mvPredType = MVPRED_L;
    }
    else
    {
      if( rFrameUR == ref_frame)
        mvPredType = MVPRED_UR;
    }
  }
  else if(blockshape_x == 16 && blockshape_y == 8)
  {
    if(mb_y == 0)
    {
      if(rFrameU == ref_frame)
        mvPredType = MVPRED_U;
    }
    else
    {
      if(rFrameL == ref_frame)
        mvPredType = MVPRED_L;
    }
  }
 
  for (hv=0; hv < 2; hv++)
  {
    if (!img->MbaffFrameFlag || hv==0)
    {
      mv_a = block_a.available  ? tmp_mv[list][block_a.pos_y][block_a.pos_x][hv] : 0;
      mv_b = block_b.available  ? tmp_mv[list][block_b.pos_y][block_b.pos_x][hv] : 0;
      mv_c = block_c.available  ? tmp_mv[list][block_c.pos_y][block_c.pos_x][hv] : 0;
    }
    else
    {
      if (img->mb_data[img->current_mb_nr].mb_field)
      {
        mv_a = block_a.available  ? img->mb_data[block_a.mb_addr].mb_field?
          tmp_mv[list][block_a.pos_y][block_a.pos_x][hv]:
          tmp_mv[list][block_a.pos_y][block_a.pos_x][hv] / 2:
          0;
        mv_b = block_b.available  ? img->mb_data[block_b.mb_addr].mb_field?
          tmp_mv[list][block_b.pos_y][block_b.pos_x][hv]:
          tmp_mv[list][block_b.pos_y][block_b.pos_x][hv] / 2:
          0;
        mv_c = block_c.available  ? img->mb_data[block_c.mb_addr].mb_field?
          tmp_mv[list][block_c.pos_y][block_c.pos_x][hv]:
          tmp_mv[list][block_c.pos_y][block_c.pos_x][hv] / 2:
          0;
      }
      else
      {
        mv_a = block_a.available  ? img->mb_data[block_a.mb_addr].mb_field?
          tmp_mv[list][block_a.pos_y][block_a.pos_x][hv] * 2:
          tmp_mv[list][block_a.pos_y][block_a.pos_x][hv]:
          0;
        mv_b = block_b.available  ? img->mb_data[block_b.mb_addr].mb_field?
          tmp_mv[list][block_b.pos_y][block_b.pos_x][hv] * 2:
          tmp_mv[list][block_b.pos_y][block_b.pos_x][hv]:
          0;
        mv_c = block_c.available  ? img->mb_data[block_c.mb_addr].mb_field?
          tmp_mv[list][block_c.pos_y][block_c.pos_x][hv] * 2:
          tmp_mv[list][block_c.pos_y][block_c.pos_x][hv]:
          0;
      }
    }
 
    switch (mvPredType)
    {
    case MVPRED_MEDIAN:
      if(!(block_b.available || block_c.available))
        pred_vec = mv_a;
      else
        pred_vec = mv_a+mv_b+mv_c-imin(mv_a,imin(mv_b,mv_c))-imax(mv_a,imax(mv_b,mv_c));
      break;
    case MVPRED_L:
      pred_vec = mv_a;
      break;
    case MVPRED_U:
      pred_vec = mv_b;
      break;
    case MVPRED_UR:
      pred_vec = mv_c;
      break;
    default:
      break;
    }
 
    pmv[hv] = pred_vec;
  }
}
 
 
/*!
 ************************************************************************
 * \brief
 *    Set context for reference frames
 ************************************************************************
 */
int
BType2CtxRef (int btype)
{
  if (btype<4)  return 0;
  else          return 1;
}
 
/*!
 ************************************************************************
 * \brief
 *    Read motion info
 ************************************************************************
 */
void readMotionInfoFromNAL (struct img_par *img, struct inp_par *inp)
{
  int i,j,k;
  int step_h,step_v;
  int curr_mvd;
  Macroblock *currMB  = &img->mb_data[img->current_mb_nr];
  SyntaxElement currSE;
  Slice *currSlice    = img->currentSlice;
  DataPartition *dP;
  int *partMap        = assignSE2partition[currSlice->dp_mode];
  int bframe          = (img->type==B_SLICE);
  int partmode        = (IS_P8x8(currMB)?4:currMB->mb_type);
  int step_h0         = BLOCK_STEP [partmode][0];
  int step_v0         = BLOCK_STEP [partmode][1];
 
  int mv_mode, i0, j0;
  char refframe;
  short pmv[2];
  int j4, i4, ii,jj;
  int vec;
 
  int mv_scale = 0;
 
  int flag_mode;
 
  int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? 4 : 2 : 0;
 
  byte  **    moving_block;
  short ****  co_located_mv;
  char  ***   co_located_ref_idx;
  int64 ***   co_located_ref_id;
 
  if ((img->MbaffFrameFlag)&&(currMB->mb_field))
  {
    if(img->current_mb_nr&0x01)
    {
      moving_block = Co_located->bottom_moving_block;
      co_located_mv = Co_located->bottom_mv;
      co_located_ref_idx = Co_located->bottom_ref_idx;
      co_located_ref_id = Co_located->bottom_ref_pic_id;
    }
    else
    {
      moving_block = Co_located->top_moving_block;
      co_located_mv = Co_located->top_mv;
      co_located_ref_idx = Co_located->top_ref_idx;
      co_located_ref_id = Co_located->top_ref_pic_id;
    }
  }
  else
  {
    moving_block = Co_located->moving_block;
    co_located_mv = Co_located->mv;
    co_located_ref_idx = Co_located->ref_idx;
    co_located_ref_id = Co_located->ref_pic_id;
  }
 
  if (bframe && IS_P8x8 (currMB))
  {
    if (img->direct_spatial_mv_pred_flag)
    {
      int imgblock_y= ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? (img->block_y-4)>>1:img->block_y>>1: img->block_y;
      int l0_rFrameL, l0_rFrameU, l0_rFrameUL, l0_rFrameUR;
      int l1_rFrameL, l1_rFrameU, l1_rFrameUL, l1_rFrameUR;
 
      PixelPos mb_left, mb_up, mb_upleft, mb_upright;
 
      char  l0_rFrame,l1_rFrame;
      short pmvl0[2]={0,0}, pmvl1[2]={0,0};
 
      getLuma4x4Neighbour(img->current_mb_nr, -1,  0, &mb_left);
      getLuma4x4Neighbour(img->current_mb_nr,  0, -1, &mb_up);
      getLuma4x4Neighbour(img->current_mb_nr, 16, -1, &mb_upright);
      getLuma4x4Neighbour(img->current_mb_nr, -1, -1, &mb_upleft);
 
      if (!img->MbaffFrameFlag)
      {
        l0_rFrameL = mb_left.available ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] : -1;
        l0_rFrameU = mb_up.available ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : -1;
        l0_rFrameUL = mb_upleft.available ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : -1;
        l0_rFrameUR = mb_upright.available ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL;
 
        l1_rFrameL = mb_left.available ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : -1;
        l1_rFrameU = mb_up.available ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : -1;
        l1_rFrameUL = mb_upleft.available ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : -1;
        l1_rFrameUR = mb_upright.available ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL;
      }
      else
      {
        if (img->mb_data[img->current_mb_nr].mb_field)
        {
          l0_rFrameL = mb_left.available 
            ? img->mb_data[mb_left.mb_addr].mb_field  || dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] < 0
            ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] 
            : dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] * 2: -1;
 
          l0_rFrameU = mb_up.available 
            ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0
            ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] 
            : dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] * 2: -1;
 
          l0_rFrameUL = mb_upleft.available 
            ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0
            ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] 
            : dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] *2: -1;
 
          l0_rFrameUR = mb_upright.available 
            ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 
            ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] 
            : dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] * 2: l0_rFrameUL;
 
          l1_rFrameL = mb_left.available 
            ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x]  < 0 
            ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] 
            : dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] * 2: -1;
 
          l1_rFrameU = mb_up.available 
            ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x]  < 0 
            ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] 
            : dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] * 2: -1;
 
          l1_rFrameUL = mb_upleft.available 
            ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x]  < 0 
            ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] 
            : dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] *2 : -1;
 
          l1_rFrameUR = mb_upright.available 
            ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x]  < 0 
            ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] 
            : dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] * 2: l1_rFrameUL;
 
        }
        else
        {
          l0_rFrameL = mb_left.available ?
            img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]  < 0 ?
            dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] >> 1 :
          dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]: -1;
 
          l0_rFrameU = mb_up.available ?
            img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x]  < 0 ?
            dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] >> 1 :
          dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : -1;
 
          l0_rFrameUL = mb_upleft.available ?
            img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0 ?
            dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]>> 1 :
          dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : -1;
 
          l0_rFrameUR = mb_upright.available ?
            img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x]  < 0 ?
            dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] >> 1 :
          dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL;
 
          l1_rFrameL = mb_left.available ?
            img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] < 0 ?
            dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] >> 1 :
          dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : -1;
          l1_rFrameU = mb_up.available ?
            img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] < 0 ?
            dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] >> 1 :
          dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : -1;
 
          l1_rFrameUL = mb_upleft.available ?
            img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x]  < 0 ?
            dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] >> 1 :
          dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : -1;
 
          l1_rFrameUR = mb_upright.available ?
            img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0 ?
            dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] >> 1:
          dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL;
        }
      }
 
      l0_rFrame = (l0_rFrameL >= 0 && l0_rFrameU >= 0) ? imin(l0_rFrameL,l0_rFrameU): imax(l0_rFrameL,l0_rFrameU);
      l0_rFrame = (l0_rFrame >= 0 && l0_rFrameUR >= 0) ? imin(l0_rFrame,l0_rFrameUR): imax(l0_rFrame,l0_rFrameUR);
 
      l1_rFrame = (l1_rFrameL >= 0 && l1_rFrameU >= 0) ? imin(l1_rFrameL,l1_rFrameU): imax(l1_rFrameL,l1_rFrameU);
      l1_rFrame = (l1_rFrame >= 0 && l1_rFrameUR >= 0) ? imin(l1_rFrame,l1_rFrameUR): imax(l1_rFrame,l1_rFrameUR);
 
 
      if (l0_rFrame >=0)
        SetMotionVectorPredictor (img, pmvl0, l0_rFrame, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);
 
      if (l1_rFrame >=0)
        SetMotionVectorPredictor (img, pmvl1, l1_rFrame, LIST_1, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);
 
 
      for (i=0;i<4;i++)
      {
        if (currMB->b8mode[i] == 0)
        {
          for(j=2*(i>>1);j<2*(i>>1)+2;j++)
          {
            for(k=2*(i&0x01);k<2*(i&0x01)+2;k++)
            {
              int j6 = imgblock_y+j;
              j4 = img->block_y+j;
              i4 = img->block_x+k;
 
 
              if (l0_rFrame >= 0)
              {
                if  (!l0_rFrame  && ((!moving_block[j6][i4]) && (!listX[1+list_offset][0]->is_long_term)))
                {
                  dec_picture->mv  [LIST_0][j4][i4][0] = 0;
                  dec_picture->mv  [LIST_0][j4][i4][1] = 0;
                  dec_picture->ref_idx[LIST_0][j4][i4] = 0;
                }
                else
                {
                  dec_picture->mv  [LIST_0][j4][i4][0] = pmvl0[0];
                  dec_picture->mv  [LIST_0][j4][i4][1] = pmvl0[1];
                  dec_picture->ref_idx[LIST_0][j4][i4] = l0_rFrame;
                }
              }
              else
              {
                dec_picture->mv  [LIST_0][j4][i4][0] = 0;
                dec_picture->mv  [LIST_0][j4][i4][1] = 0;
                dec_picture->ref_idx[LIST_0][j4][i4] = -1;
              }
 
              if (l1_rFrame >= 0)
              {
                if  (l1_rFrame==0 && ((!moving_block[j6][i4])&& (!listX[1+list_offset][0]->is_long_term)))
                {
                  dec_picture->mv  [LIST_1][j4][i4][0] = 0;
                  dec_picture->mv  [LIST_1][j4][i4][1] = 0;
                  dec_picture->ref_idx[LIST_1][j4][i4] = 0;
                }
                else
                {
                  dec_picture->mv  [LIST_1][j4][i4][0] = pmvl1[0];
                  dec_picture->mv  [LIST_1][j4][i4][1] = pmvl1[1];
                  dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame;
                }
              }
              else
              {
                dec_picture->mv  [LIST_1][j4][i4][0] = 0;
                dec_picture->mv  [LIST_1][j4][i4][1] = 0;
                dec_picture->ref_idx[LIST_1][j4][i4] = -1;
              }
 
              if (l0_rFrame <0 && l1_rFrame <0)
              {
                dec_picture->ref_idx[LIST_0][j4][i4] = 0;
                dec_picture->ref_idx[LIST_1][j4][i4] = 0;
              }
            }
          }
        }
      }
    }
    else
    {
      for (i=0;i<4;i++)
      {
        if (currMB->b8mode[i] == 0)
        {
          for(j=2*(i>>1);j<2*(i>>1)+2;j++)
          {
            for(k=2*(i&0x01);k<2*(i&0x01)+2;k++)
            {
 
              int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? 4 : 2 : 0;
              int imgblock_y  = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? (img->block_y-4)>>1 : img->block_y>>1 : img->block_y;
              int refList = co_located_ref_idx[LIST_0 ][imgblock_y+j][img->block_x+k]== -1 ? LIST_1 : LIST_0;
              int ref_idx = co_located_ref_idx[refList][imgblock_y + j][img->block_x + k];
              int mapped_idx=-1, iref;
 
              if (ref_idx == -1)
              {
                dec_picture->ref_idx [LIST_0][img->block_y + j][img->block_x + k] = 0;
                dec_picture->ref_idx [LIST_1][img->block_y + j][img->block_x + k] = 0;
              }
              else
              {
                for (iref=0;iref<imin(img->num_ref_idx_l0_active,listXsize[LIST_0 + list_offset]);iref++)
                {
                  int curr_mb_field = ((img->MbaffFrameFlag)&&(currMB->mb_field));
 
                  if(img->structure==0 && curr_mb_field==0)
                  {
                    // If the current MB is a frame MB and the colocated is from a field picture,
                    // then the co_located_ref_id may have been generated from the wrong value of
                    // frame_poc if it references it's complementary field, so test both POC values
                    if(listX[0][iref]->top_poc*2 == co_located_ref_id[refList][imgblock_y + j][img->block_x + k]
                    || listX[0][iref]->bottom_poc*2 == co_located_ref_id[refList][imgblock_y + j][img->block_x + k])
                    {
                      mapped_idx=iref;
                      break;
                    }
                    else //! invalid index. Default to zero even though this case should not happen
                      mapped_idx=INVALIDINDEX;
                    continue;
                  }
                  if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][imgblock_y + j][img->block_x + k])
                  {
                    mapped_idx=iref;
                    break;
                  }
                  else //! invalid index. Default to zero even though this case should not happen
                    mapped_idx=INVALIDINDEX;
                }
                if (INVALIDINDEX == mapped_idx)
                {
                  error("temporal direct error\ncolocated block has ref that is unavailable",-1111);
                }
                dec_picture->ref_idx [LIST_0][img->block_y + j][img->block_x + k] = mapped_idx;
                dec_picture->ref_idx [LIST_1][img->block_y + j][img->block_x + k] = 0;
              }
            }
          }
        }
      }
    }
  }
 
  //  If multiple ref. frames, read reference frame for the MB *********************************
  if(img->num_ref_idx_l0_active>1)
  {
    flag_mode = ( img->num_ref_idx_l0_active == 2 ? 1 : 0);
 
    currSE.type = SE_REFFRAME;
    dP = &(currSlice->partArr[partMap[SE_REFFRAME]]);
 
    if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)   currSE.mapping = linfo_ue;
    else                                                      currSE.reading = readRefFrame_CABAC;
 
    for (j0=0; j0<4; j0+=step_v0)
    {
      for (i0=0; i0<4; i0+=step_h0)
      {
        k=2*(j0>>1)+(i0>>1);
        if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0)
        {
          TRACE_STRING("ref_idx_l0");
 
          img->subblock_x = i0;
          img->subblock_y = j0;
 
          if (!IS_P8x8 (currMB) || bframe || (!bframe && !img->allrefzero))
          {
            currSE.context = BType2CtxRef (currMB->b8mode[k]);
            if( (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) && flag_mode )
            {
              currSE.len = 1;
              readSyntaxElement_FLC(&currSE, dP->bitstream);
              currSE.value1 = 1 - currSE.value1;
            }
            else
            {
              currSE.value2 = LIST_0;
              dP->readSyntaxElement (&currSE,img,dP);
            }
            refframe = currSE.value1;
 
          }
          else
          {
            refframe = 0;
          }
 
          for (j=img->block_y +j0; j<img->block_y +j0+step_v0;j++)
            memset(&dec_picture->ref_idx[LIST_0][j][img->block_x + i0], refframe, step_h0 * sizeof(char));
        }
      }
    }
  }
  else
  {
    for (j0=0; j0<4; j0+=step_v0)
    {
      for (i0=0; i0<4; i0+=step_h0)
      {
        k=2*(j0>>1)+(i0>>1);
        if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0)
        {
          for (j=img->block_y + j0; j < img->block_y + j0+step_v0;j++)
            memset(&dec_picture->ref_idx[LIST_0][j][img->block_x + i0], 0, step_h0 * sizeof(char));
        }
      }
    }
  }
 
  //  If backward multiple ref. frames, read backward reference frame for the MB *********************************
  if(img->num_ref_idx_l1_active>1)
  {
    flag_mode = ( img->num_ref_idx_l1_active == 2 ? 1 : 0);
 
    currSE.type = SE_REFFRAME;
    dP = &(currSlice->partArr[partMap[SE_REFFRAME]]);
    if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
      currSE.mapping = linfo_ue;
    else
      currSE.reading = readRefFrame_CABAC;
 
    for (j0=0; j0<4; j0+=step_v0)
    {
      for (i0=0; i0<4; i0+=step_h0)
      {
        k=2*(j0>>1)+(i0>>1);
        if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0)
        {
          TRACE_STRING("ref_idx_l1");
 
          img->subblock_x = i0;
          img->subblock_y = j0;
 
          currSE.context = BType2CtxRef (currMB->b8mode[k]);
          if( (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) && flag_mode )
          {
            currSE.len = 1;
            readSyntaxElement_FLC(&currSE, dP->bitstream);
            currSE.value1 = 1-currSE.value1;
          }
          else
          {
            currSE.value2 = LIST_1;
            dP->readSyntaxElement (&currSE,img,dP);
          }
          refframe = currSE.value1;
 
          for (j=img->block_y + j0; j<img->block_y + j0+step_v0;j++)
          {
            memset(&dec_picture->ref_idx[LIST_1][j][img->block_x + i0], refframe, step_h0 * sizeof(char));
          }
        }
      }
    }
  }
  else
  {
    for (j0=0; j0<4; j0+=step_v0)
    {
      for (i0=0; i0<4; i0+=step_h0)
      {
        k=2*(j0>>1)+(i0>>1);
        if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0)
        {
          for (j=img->block_y + j0; j<img->block_y + j0+step_v0;j++)
            memset(&dec_picture->ref_idx[LIST_1][ j][img->block_x + i0], 0, step_h0 * sizeof(char));
        }
      }
    }
  }
 
  //=====  READ FORWARD MOTION VECTORS =====
  currSE.type = SE_MVD;
  dP = &(currSlice->partArr[partMap[SE_MVD]]);
 
  if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_se;
  else                                                  currSE.reading = readMVD_CABAC;
 
  for (j0=0; j0<4; j0+=step_v0)
    for (i0=0; i0<4; i0+=step_h0)
    {
      k=2*(j0>>1)+(i0>>1);
 
      if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && (currMB->b8mode[k] !=0))//has forward vector
      {
        mv_mode  = currMB->b8mode[k];
        step_h   = BLOCK_STEP [mv_mode][0];
        step_v   = BLOCK_STEP [mv_mode][1];
 
        refframe = dec_picture->ref_idx[LIST_0][img->block_y+j0][img->block_x+i0];
 
        for (j=j0; j<j0+step_v0; j+=step_v)
        {
          j4 = img->block_y+j;
          for (i=i0; i<i0+step_h0; i+=step_h)
          {
            i4 = img->block_x+i;
 
            // first make mv-prediction
            SetMotionVectorPredictor (img, pmv, refframe, LIST_0, dec_picture->ref_idx, dec_picture->mv, i, j, 4*step_h, 4*step_v);
 
            for (k=0; k < 2; k++)
            {
              TRACE_STRING("mvd_l0");
 
              img->subblock_x = i; // position used for context determination
              img->subblock_y = j; // position used for context determination
              currSE.value2 = k<<1; // identifies the component; only used for context determination
              dP->readSyntaxElement(&currSE,img,dP);
              curr_mvd = currSE.value1;
 
              vec=curr_mvd+pmv[k];           /* find motion vector */
 
              for(jj=0;jj<step_v;jj++)
              {
                for(ii=0;ii<step_h;ii++)
                {
                  dec_picture->mv [LIST_0][j4+jj][i4+ii][k] = vec;
                  currMB->mvd     [LIST_0][j +jj][i +ii][k] = curr_mvd;
                }
              }
            }
          }
        }
      }
      else if (currMB->b8mode[k=2*(j0>>1)+(i0>>1)]==0)
      {
        if (!img->direct_spatial_mv_pred_flag)
        {
          int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? 4 : 2 : 0;
          int imgblock_y  = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? (img->block_y-4)>>1:img->block_y>>1 : img->block_y;
 
          int refList = (co_located_ref_idx[LIST_0 ][imgblock_y+j0][img->block_x+i0]== -1 ? LIST_1 : LIST_0);
          int ref_idx =  co_located_ref_idx[refList][imgblock_y+j0][img->block_x+i0];
 
          if (ref_idx==-1)
          {
            for (j4=img->block_y+j0; j4<img->block_y+j0+step_v0; j4++)
            {
              for (i4=img->block_x+i0; i4<img->block_x+i0+step_h0; i4++)
              {
                dec_picture->ref_idx [LIST_1][j4][i4]=0;
                dec_picture->ref_idx [LIST_0][j4][i4]=0;
 
                for (ii=0; ii < 2; ii++)
                {
                  dec_picture->mv [LIST_0][j4][i4][ii]=0;
                  dec_picture->mv [LIST_1][j4][i4][ii]=0;
                }
              }
            }
          }
          else
          {
            int mapped_idx=-1, iref;
            int j6;
 
            for (iref = 0; iref < imin(img->num_ref_idx_l0_active, listXsize[LIST_0 + list_offset]); iref++)
            {
              int curr_mb_field = ((img->MbaffFrameFlag)&&(currMB->mb_field));
 
              if(img->structure==0 && curr_mb_field==0)
              {
                // If the current MB is a frame MB and the colocated is from a field picture,
                // then the co_located_ref_id may have been generated from the wrong value of
                // frame_poc if it references it's complementary field, so test both POC values
                if(listX[0][iref]->top_poc * 2    == co_located_ref_id[refList][imgblock_y + j0][img->block_x + i0]
                || listX[0][iref]->bottom_poc * 2 == co_located_ref_id[refList][imgblock_y + j0][img->block_x + i0])
                {
                  mapped_idx=iref;
                  break;
                }
                else //! invalid index. Default to zero even though this case should not happen
                  mapped_idx=INVALIDINDEX;
                continue;
              }
              if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][imgblock_y+j0][img->block_x+i0])
              {
                mapped_idx=iref;
                break;
              }
              else //! invalid index. Default to zero even though this case should not happen
                mapped_idx=INVALIDINDEX;
            }
 
            if (INVALIDINDEX == mapped_idx)
            {
              error("temporal direct error\ncolocated block has ref that is unavailable",-1111);
            }
 
 
            for (j=j0; j<j0+step_v0; j++)
            {
              j4 = img->block_y+j;
              j6 = imgblock_y + j;
 
              for (i4=img->block_x+i0; i4<img->block_x+i0+step_h0; i4++)
              {                
                mv_scale = img->mvscale[LIST_0 + list_offset][mapped_idx];
 
                dec_picture->ref_idx [LIST_0][j4][i4] = mapped_idx;
                dec_picture->ref_idx [LIST_1][j4][i4] = 0;
 
 
                for (ii=0; ii < 2; ii++)
                {
                  if (mv_scale == 9999 || listX[LIST_0+list_offset][mapped_idx]->is_long_term)
                  {
                    dec_picture->mv  [LIST_0][j4][i4][ii] = co_located_mv[refList][j6][i4][ii];
                    dec_picture->mv  [LIST_1][j4][i4][ii] = 0;
                  }
                  else
                  {
                    dec_picture->mv  [LIST_0][j4][i4][ii] = (mv_scale * co_located_mv[refList][j6][i4][ii] + 128 ) >> 8;
                    dec_picture->mv  [LIST_1][j4][i4][ii] = dec_picture->mv[LIST_0][j4][i4][ii] - co_located_mv[refList][j6][i4][ii];
                  }
                }                
              }
            }
          }
        }
      }
    }
 
  //=====  READ BACKWARD MOTION VECTORS =====
  currSE.type = SE_MVD;
  dP          = &(currSlice->partArr[partMap[SE_MVD]]);
 
  if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_se;
  else                                                    currSE.reading = readMVD_CABAC;
 
  for (j0=0; j0<4; j0+=step_v0)
  {
    for (i0=0; i0<4; i0+=step_h0)
    {
      k=2*(j0>>1)+(i0>>1);
      if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && (currMB->b8mode[k]!=0))//has backward vector
      {
        mv_mode  = currMB->b8mode[k];
        step_h   = BLOCK_STEP [mv_mode][0];
        step_v   = BLOCK_STEP [mv_mode][1];
 
        refframe = dec_picture->ref_idx[LIST_1][img->block_y+j0][img->block_x+i0];
 
        for (j=j0; j<j0+step_v0; j+=step_v)
        {
          j4 = img->block_y+j;
          for (i=i0; i<i0+step_h0; i+=step_h)
          {
            i4 = img->block_x+i;
 
            // first make mv-prediction
            SetMotionVectorPredictor (img, pmv, refframe, LIST_1, dec_picture->ref_idx, dec_picture->mv, i, j, 4*step_h, 4*step_v);
 
            for (k=0; k < 2; k++)
            {
              TRACE_STRING("mvd_l1");
 
              img->subblock_x = i; // position used for context determination
              img->subblock_y = j; // position used for context determination
              currSE.value2   = (k<<1) +1; // identifies the component; only used for context determination
              dP->readSyntaxElement(&currSE,img,dP);
              curr_mvd = currSE.value1;
 
              vec=curr_mvd+pmv[k];           /* find motion vector */
 
              for(jj=0;jj<step_v;jj++)
              {
                for(ii=0;ii<step_h;ii++)
                {
                  dec_picture->mv  [LIST_1][j4+jj][i4+ii][k] = vec;
                  currMB->mvd      [LIST_1][j+jj] [i+ii] [k] = curr_mvd;
                }
              }
            }
          }
        }
      }
    }
  }
  // record reference picture Ids for deblocking decisions
 
 
  for(j4=img->block_y;j4<(img->block_y+4);j4++)
  {
    for(i4=img->block_x;i4<(img->block_x+4);i4++)
    {
      if (dec_picture->ref_idx[LIST_0][j4][i4]>=0)
         dec_picture->ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->ref_idx[LIST_0][j4][i4]];
      else
         dec_picture->ref_pic_id[LIST_0][j4][i4] = INT64_MIN;
      if (dec_picture->ref_idx[LIST_1][j4][i4]>=0)
         dec_picture->ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->ref_idx[LIST_1][j4][i4]];
      else
         dec_picture->ref_pic_id[LIST_1][j4][i4] = INT64_MIN;
    }
  }
}
 
 
 
/*!
 ************************************************************************
 * \brief
 *    Get the Prediction from the Neighboring Blocks for Number of Nonzero Coefficients
 *
 *    Luma Blocks
 ************************************************************************
 */
int predict_nnz(struct img_par *img, int i,int j)
{
  PixelPos pix;
 
  int pred_nnz = 0;
  int cnt      = 0;
  int mb_nr    = img->current_mb_nr;
  Macroblock *currMB = &(img->mb_data[mb_nr]);
 
  // left block
  getLuma4x4Neighbour(mb_nr, (i<<2) - 1, (j<<2), &pix);
 
  if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3))
  {
    pix.available &= img->intra_block[pix.mb_addr];
    if (!pix.available)
      cnt++;
  }
 
  if (pix.available)
  {
    pred_nnz = img->nz_coeff [pix.mb_addr ][pix.x][pix.y];
    cnt++;
  }
 
  // top block
  getLuma4x4Neighbour(mb_nr, (i<<2), (j<<2) - 1, &pix);
 
  if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3))
  {
    pix.available &= img->intra_block[pix.mb_addr];
    if (!pix.available)
      cnt++;
  }
 
  if (pix.available)
  {
    pred_nnz += img->nz_coeff [pix.mb_addr ][pix.x][pix.y];
    cnt++;
  }
 
  if (cnt==2)
  {
    pred_nnz++;
    pred_nnz>>=1;
  }
 
  return pred_nnz;
}
 
 
/*!
 ************************************************************************
 * \brief
 *    Get the Prediction from the Neighboring Blocks for Number of Nonzero Coefficients
 *
 *    Chroma Blocks
 ************************************************************************
 */
int predict_nnz_chroma(struct img_par *img, int i,int j)
{
  PixelPos pix;
 
  int pred_nnz = 0;
  int cnt      =0;
  int mb_nr    = img->current_mb_nr;
  static const int j_off_tab [12] = {0,0,0,0,4,4,4,4,8,8,8,8};
  int j_off = j_off_tab[j];
  Macroblock *currMB = &(img->mb_data[mb_nr]);
 
  if (dec_picture->chroma_format_idc != YUV444)
  {
    //YUV420 and YUV422
    // left block
    getChroma4x4Neighbour(mb_nr, ((i&0x01)<<2) - 1, ((j-4)<<2), &pix);
 
    if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3))
    {
      pix.available &= img->intra_block[pix.mb_addr];
      if (!pix.available)
        cnt++;
    }
 
    if (pix.available)
    {
      pred_nnz = img->nz_coeff [pix.mb_addr ][2 * (i>>1) + pix.x][4 + pix.y];
      cnt++;
    }
 
    // top block
    getChroma4x4Neighbour(mb_nr, ((i&0x01)<<2), ((j-4)<<2) - 1, &pix);
 
    if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3))
    {
      pix.available &= img->intra_block[pix.mb_addr];
      if (!pix.available)
        cnt++;
    }
 
    if (pix.available)
    {
      pred_nnz += img->nz_coeff [pix.mb_addr ][2 * (i>>1) + pix.x][4 + pix.y];
      cnt++;
    }
  }
  else
  {
    //YUV444
    // left block
    getChroma4x4Neighbour(mb_nr, (i<<2) - 1, ((j-j_off)<<2), &pix);
 
    if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3))
    {
      pix.available &= img->intra_block[pix.mb_addr];
      cnt--;
    }
 
    if (pix.available)
    {
      pred_nnz = img->nz_coeff [pix.mb_addr ][pix.x][j_off + pix.y];
      cnt++;
    }
 
    // top block
    getChroma4x4Neighbour(mb_nr, (i<<2), ((j-j_off)<<2) -1, &pix);
 
    if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3))
    {
      pix.available &= img->intra_block[pix.mb_addr];
      cnt--;
    }
 
    if (pix.available)
    {
      pred_nnz += img->nz_coeff [pix.mb_addr ][pix.x][j_off + pix.y];
      cnt++;
    }
  }
 
  if (cnt==2)
  {
    pred_nnz++;
    pred_nnz>>=1;
  }
 
  return pred_nnz;
}
 
 
/*!
 ************************************************************************
 * \brief
 *    Reads coeff of an 4x4 block (CAVLC)
 *
 * \author
 *    Karl Lillevold <karll@real.com>
 *    contributions by James Au <james@ubvideo.com>
 ************************************************************************
 */
 
 
void readCoeff4x4_CAVLC (struct img_par *img,struct inp_par *inp,
                        int block_type,
                        int i, int j, int levarr[16], int runarr[16],
                        int *number_coefficients)
{
  int mb_nr = img->current_mb_nr;
  Macroblock *currMB = &img->mb_data[mb_nr];
  SyntaxElement currSE;
  Slice *currSlice = img->currentSlice;
  DataPartition *dP;
  int *partMap = assignSE2partition[currSlice->dp_mode];
 
 
  int k, code, vlcnum;
  int numcoeff, numtrailingones, numcoeff_vlc;
  int level_two_or_higher;
  int numones, totzeros, level, cdc=0, cac=0;
  int zerosleft, ntr, dptype = 0;
  int max_coeff_num = 0, nnz;
  char type[15];
  static int incVlc[] = {0,3,6,12,24,48,32768};    // maximum vlc = 6
 
  numcoeff = 0;
 
  switch (block_type)
  {
  case LUMA:
    max_coeff_num = 16;
#if TRACE
    sprintf(type, "%s", "Luma");
#endif
    dptype = IS_INTRA (currMB) ? SE_LUM_AC_INTRA : SE_LUM_AC_INTER;
    break;
  case LUMA_INTRA16x16DC:
    max_coeff_num = 16;
#if TRACE
    sprintf(type, "%s", "Lum16DC");
#endif
    dptype = SE_LUM_DC_INTRA;
    break;
  case LUMA_INTRA16x16AC:
    max_coeff_num = 15;
#if TRACE
    sprintf(type, "%s", "Lum16AC");
#endif
    dptype = SE_LUM_AC_INTRA;
    break;
 
  case CHROMA_DC:
    max_coeff_num = img->num_cdc_coeff;
    cdc = 1;
#if TRACE
    sprintf(type, "%s", "ChrDC");
#endif
    dptype = IS_INTRA (currMB) ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER;
    break;
  case CHROMA_AC:
    max_coeff_num = 15;
    cac = 1;
#if TRACE
    sprintf(type, "%s", "ChrAC");
#endif
    dptype = IS_INTRA (currMB) ? SE_CHR_AC_INTRA : SE_CHR_AC_INTER;
    break;
  default:
    error ("readCoeff4x4_CAVLC: invalid block type", 600);
    break;
  }
 
  currSE.type = dptype;
  dP = &(currSlice->partArr[partMap[dptype]]);
 
  img->nz_coeff[img->current_mb_nr][i][j] = 0;
 
 
  if (!cdc)
  {
    // luma or chroma AC
    if (!cac)
    {
      nnz = predict_nnz(img, i, j);
    }
    else
    {
      nnz = predict_nnz_chroma(img, i, j);
    }
 
    if (nnz < 2)
    {
      numcoeff_vlc = 0;
    }
    else if (nnz < 4)
    {
      numcoeff_vlc = 1;
    }
    else if (nnz < 8)
    {
      numcoeff_vlc = 2;
    }
    else //
    {
      numcoeff_vlc = 3;
    }
 
    currSE.value1 = numcoeff_vlc;
 
    readSyntaxElement_NumCoeffTrailingOnes(&currSE, dP, type);
 
    numcoeff =  currSE.value1;
    numtrailingones =  currSE.value2;
 
    img->nz_coeff[img->current_mb_nr][i][j] = numcoeff;
  }
  else
  {
    // chroma DC
    readSyntaxElement_NumCoeffTrailingOnesChromaDC(&currSE, dP);
 
    numcoeff =  currSE.value1;
    numtrailingones =  currSE.value2;
  }
 
 
  for (k = 0; k < max_coeff_num; k++)
  {
    levarr[k] = 0;
    runarr[k] = 0;
  }
 
  numones = numtrailingones;
  *number_coefficients = numcoeff;
 
  if (numcoeff)
  {
    if (numtrailingones)
    {
 
      currSE.len = numtrailingones;
 
#if TRACE
      snprintf(currSE.tracestring,
        TRACESTRING_SIZE, "%s trailing ones sign (%d,%d)", type, i, j);
#endif
 
      readSyntaxElement_FLC (&currSE, dP->bitstream);
 
      code = currSE.inf;
      ntr = numtrailingones;
      for (k = numcoeff-1; k > numcoeff-1-numtrailingones; k--)
      {
        ntr --;
        levarr[k] = (code>>ntr)&1 ? -1 : 1;
      }
    }
 
    // decode levels
    level_two_or_higher = (numcoeff > 3 && numtrailingones == 3)? 0 : 1;
    vlcnum = (numcoeff > 10 && numtrailingones < 3) ? 1 : 0;
 
    for (k = numcoeff - 1 - numtrailingones; k >= 0; k--)
    {
 
#if TRACE
      snprintf(currSE.tracestring,
        TRACESTRING_SIZE, "%s lev (%d,%d) k=%d vlc=%d ", type,
          i, j, k, vlcnum);
#endif
 
      if (vlcnum == 0)
          readSyntaxElement_Level_VLC0(&currSE, dP);
      else
          readSyntaxElement_Level_VLCN(&currSE, vlcnum, dP);
 
      if (level_two_or_higher)
      {
        currSE.inf += (currSE.inf > 0) ? 1 : -1;
        level_two_or_higher = 0;
      }
 
      level = levarr[k] = currSE.inf;
      if (iabs(level) == 1)
        numones ++;
 
      // update VLC table
      if (iabs(level)>incVlc[vlcnum])
        vlcnum++;
 
      if (k == numcoeff - 1 - numtrailingones && iabs(level)>3)
        vlcnum = 2;
 
    }
 
    if (numcoeff < max_coeff_num)
    {
      // decode total run
      vlcnum = numcoeff-1;
      currSE.value1 = vlcnum;
 
#if TRACE
      snprintf(currSE.tracestring,
        TRACESTRING_SIZE, "%s totalrun (%d,%d) vlc=%d ", type, i,j, vlcnum);
#endif
      if (cdc)
        readSyntaxElement_TotalZerosChromaDC(&currSE, dP);
      else
        readSyntaxElement_TotalZeros(&currSE, dP);
 
      totzeros = currSE.value1;
    }
    else
    {
      totzeros = 0;
    }
 
    // decode run before each coefficient
    zerosleft = totzeros;
    i = numcoeff - 1;
    if (zerosleft > 0 && i > 0)
    {
      do
      {
        // select VLC for runbefore
        vlcnum = zerosleft - 1;
        if (vlcnum > RUNBEFORE_NUM - 1)
          vlcnum = RUNBEFORE_NUM - 1;
 
        currSE.value1 = vlcnum;
#if TRACE
        snprintf(currSE.tracestring,
          TRACESTRING_SIZE, "%s run (%d,%d) k=%d vlc=%d ",
            type, i, j, i, vlcnum);
#endif
 
        readSyntaxElement_Run(&currSE, dP);
        runarr[i] = currSE.value1;
 
        zerosleft -= runarr[i];
        i --;
      } while (zerosleft != 0 && i != 0);
    }
    runarr[i] = zerosleft;
 
  } // if numcoeff
}
 
/*!
 ************************************************************************
 * \brief
 *    Calculate the quantisation and inverse quantisation parameters
 *
 ************************************************************************
 */
void CalculateQuant8Param()
{
  int i, j, k, temp;
 
  for(k=0; k<6; k++)
    for(j=0; j<8; j++)
    {
      for(i=0; i<8; i++)
      {
        temp = (i<<3)+j;
        InvLevelScale8x8Luma_Intra[k][i][j] = dequant_coef8[k][j][i]*qmatrix[6][temp];
        InvLevelScale8x8Luma_Inter[k][i][j] = dequant_coef8[k][j][i]*qmatrix[7][temp];
      }
    }
}
 
/*!
************************************************************************
* \brief
*    Get coefficients (run/level) of one 8x8 block
*    from the NAL (CABAC Mode)
************************************************************************
*/
void readLumaCoeff8x8_CABAC (struct img_par *img,struct inp_par *inp, int b8)
{
  int i,j,k;
  int level = 1;
  int mb_nr = img->current_mb_nr;
  Macroblock *currMB = &img->mb_data[mb_nr];
  int cbp = currMB->cbp;
  SyntaxElement currSE;
  Slice *currSlice = img->currentSlice;
  DataPartition *dP;
  int *partMap = assignSE2partition[currSlice->dp_mode];
  int start_scan = 0; // take all coeffs
  int coef_ctr = start_scan - 1;// i0, j0;
  int boff_x, boff_y;
 
  int run, len;
 
  int qp_per    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6;
  int qp_rem    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6;
  Boolean lossless_qpprime = (Boolean) ((img->qp + img->bitdepth_luma_qp_scale)==0 && img->lossless_qpprime_flag==1);
  int (*InvLevelScale8x8)[8] = IS_INTRA(currMB)? InvLevelScale8x8Luma_Intra[qp_rem] : InvLevelScale8x8Luma_Inter[qp_rem];
  // select scan type
  const byte (*pos_scan8x8)[2] = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN8x8 : FIELD_SCAN8x8;
 
  img->is_intra_block = IS_INTRA(currMB);
 
  if (cbp & (1<<b8))  // are there any coeff in current block at all
  {
    // === set offset in current macroblock ===
    boff_x = (b8&0x01) << 3;
    boff_y = (b8 >> 1) << 3;
 
    img->subblock_x = boff_x >> 2; // position for coeff_count ctx
    img->subblock_y = boff_y >> 2; // position for coeff_count ctx
 
    if(!lossless_qpprime)
    {
      for(k=start_scan;(k < 65) && (level != 0);k++)
      {
        //============ read =============
        /*
        * make distinction between INTRA and INTER coded
        * luminance coefficients
        */
        currSE.context = LUMA_8x8;
        currSE.type    = ((img->is_intra_block == 1)
          ? (k==0 ? SE_LUM_DC_INTRA : SE_LUM_AC_INTRA) 
          : (k==0 ? SE_LUM_DC_INTER : SE_LUM_AC_INTER));
 
#if TRACE
        sprintf(currSE.tracestring, "Luma8x8 sng ");
#endif
        dP = &(currSlice->partArr[partMap[currSE.type]]);
        currSE.reading = readRunLevel_CABAC;
 
        dP->readSyntaxElement(&currSE,img,dP);
        level = currSE.value1;
        run   = currSE.value2;
        len   = currSE.len;
 
        //============ decode =============
        if (level != 0)    /* leave if len=1 */
        {
          coef_ctr += run + 1;
 
          i=pos_scan8x8[coef_ctr][0];
          j=pos_scan8x8[coef_ctr][1];
 
          currMB->cbp_blk |= 51 << (4 * b8 - 2 * (b8 & 0x01)); // corresponds to 110011, as if all four 4x4 blocks contain coeff, shifted to block position
          img->m7[boff_y + j][boff_x + i] = rshift_rnd_sf((level * InvLevelScale8x8[j][i]) << qp_per, 6); // dequantization
        }
      }
    }
    else
    {
      for(k=start_scan;(k < 65) && (level != 0);k++)
      {
        //============ read =============
        /*
        * make distinction between INTRA and INTER coded
        * luminance coefficients
        */
        currSE.context = LUMA_8x8;
        currSE.type    = ((img->is_intra_block == 1)
          ? (k==0 ? SE_LUM_DC_INTRA : SE_LUM_AC_INTRA) 
          : (k==0 ? SE_LUM_DC_INTER : SE_LUM_AC_INTER));
 
#if TRACE
        sprintf(currSE.tracestring, "Luma8x8 sng ");
#endif
        dP = &(currSlice->partArr[partMap[currSE.type]]);
        currSE.reading = readRunLevel_CABAC;
 
        dP->readSyntaxElement(&currSE,img,dP);
        level = currSE.value1;
        run   = currSE.value2;
        len   = currSE.len;
 
        //============ decode =============
        if (level != 0)    /* leave if len=1 */
        {
          coef_ctr += run+1;
 
          i=pos_scan8x8[coef_ctr][0];
          j=pos_scan8x8[coef_ctr][1];
 
          currMB->cbp_blk |= 51 << (4 * b8 - 2 * (b8 & 0x01)); // corresponds to 110011, as if all four 4x4 blocks contain coeff, shifted to block position
          img->m7[boff_y + j][boff_x + i] = level;
        }
      }
    }
  }
}
 
/*!
 ************************************************************************
 * \brief
 *    Get coded block pattern and coefficients (run/level)
 *    from the NAL
 ************************************************************************
 */
void readCBPandCoeffsFromNAL(struct img_par *img,struct inp_par *inp)
{
  int i,j,k;
  int level;
  int mb_nr = img->current_mb_nr;
  int ii,jj;
  int m2,jg2;// i1,j1;
  Macroblock *currMB = &img->mb_data[mb_nr];
  int cbp;
  SyntaxElement currSE;
  Slice *currSlice = img->currentSlice;
  DataPartition *dP;
  int *partMap = assignSE2partition[currSlice->dp_mode];
  int coef_ctr, i0, j0, b8;
  int ll;
  int block_x,block_y;
  int start_scan;
  int run, len;
  int levarr[16], runarr[16], numcoeff;
 
  int qp_const;
  int qp_per    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6;
  int qp_rem    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6;
  int smb       = ((img->type==SP_SLICE) && IS_INTER (currMB)) || (img->type == SI_SLICE && currMB->mb_type == SI4MB);
 
  int uv;
  int qp_const_uv[2];
  int qp_per_uv[2];
  int qp_rem_uv[2];
 
  int intra     = IS_INTRA (currMB);
  int temp[4];
 
  int b4;
  int yuv = dec_picture->chroma_format_idc-1;
  int m5[4];
  int m6[4];
 
  int need_transform_size_flag;
  Boolean lossless_qpprime = (Boolean) ((img->qp + img->bitdepth_luma_qp_scale)==0 && img->lossless_qpprime_flag==1);
 
  int (*InvLevelScale4x4)[4] = NULL;
  int (*InvLevelScale8x8)[8] = NULL;
  // select scan type
  const byte (*pos_scan8x8)[2] = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN8x8 : FIELD_SCAN8x8;
  const byte (*pos_scan4x4)[2] = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN : FIELD_SCAN;
 
  if(img->type==SP_SLICE  && currMB->mb_type!=I16MB )
    smb=1;
 
  // QPI
  //init constants for every chroma qp offset
  if (dec_picture->chroma_format_idc != YUV400)
  {
    for (i=0; i<2; i++)
    {
      qp_per_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)/6;
      qp_rem_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)%6;
    }
  }
 
  // read CBP if not new intra mode
  if (!IS_NEWINTRA (currMB))
  {
    //=====   C B P   =====
    //---------------------
    currSE.type = (IS_OLDINTRA (currMB) || currMB->mb_type == SI4MB || currMB->mb_type == I8MB) 
      ? SE_CBP_INTRA
      : SE_CBP_INTER;
 
    dP = &(currSlice->partArr[partMap[currSE.type]]);
 
    if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
    {
      currSE.mapping = (IS_OLDINTRA (currMB) || currMB->mb_type == SI4MB || currMB->mb_type == I8MB)
        ? linfo_cbp_intra
        : linfo_cbp_inter;
    }
    else
    {
      currSE.reading = readCBP_CABAC;
    }
 
    TRACE_STRING("coded_block_pattern");
 
    dP->readSyntaxElement(&currSE,img,dP);
    currMB->cbp = cbp = currSE.value1;
 
 
    //============= Transform size flag for INTER MBs =============
    //-------------------------------------------------------------
    need_transform_size_flag = (((currMB->mb_type >= 1 && currMB->mb_type <= 3)||
                                (IS_DIRECT(currMB) && active_sps->direct_8x8_inference_flag) ||
                                (currMB->NoMbPartLessThan8x8Flag))
                                && currMB->mb_type != I8MB && currMB->mb_type != I4MB
                                && (currMB->cbp&15)
                                && img->Transform8x8Mode);
 
    if (need_transform_size_flag)
    {
      currSE.type   =  SE_HEADER;
      dP = &(currSlice->partArr[partMap[SE_HEADER]]);
      currSE.reading = readMB_transform_size_flag_CABAC;
      TRACE_STRING("transform_size_8x8_flag");
 
      // read UVLC transform_size_8x8_flag
      if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
      {
        currSE.len = 1;
        readSyntaxElement_FLC(&currSE, dP->bitstream);
      } 
      else
      {
        dP->readSyntaxElement(&currSE,img,dP);
      }
      currMB->luma_transform_size_8x8_flag = currSE.value1;
    }
 
    //=====   DQUANT   =====
    //----------------------
    // Delta quant only if nonzero coeffs
    if (cbp !=0)
    {
      currSE.type = (IS_INTER (currMB)) ? SE_DELTA_QUANT_INTER : SE_DELTA_QUANT_INTRA;
 
      dP = &(currSlice->partArr[partMap[currSE.type]]);
 
      if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
      {
        currSE.mapping = linfo_se;
      }
      else
        currSE.reading= readDquant_CABAC; //gabi
 
      TRACE_STRING("mb_qp_delta");
 
      dP->readSyntaxElement(&currSE,img,dP);
      currMB->delta_quant = currSE.value1;
      if ((currMB->delta_quant < -(26 + img->bitdepth_luma_qp_scale/2)) || (currMB->delta_quant > (25 + img->bitdepth_luma_qp_scale/2)))
        error ("mb_qp_delta is out of range", 500);
 
      img->qp= ((img->qp + currMB->delta_quant + 52 + 2*img->bitdepth_luma_qp_scale)%(52+img->bitdepth_luma_qp_scale)) -
                 img->bitdepth_luma_qp_scale;
    }
  }
  else
  {
    cbp = currMB->cbp;
  }
 
  for (i=0;i<BLOCK_SIZE;i++)
    for (j=0;j<BLOCK_SIZE;j++)
      memset(&img->cof[i][j][0][0], 0, BLOCK_SIZE * BLOCK_SIZE * sizeof(int)); // reset luma coeffs
 
 
  if (IS_NEWINTRA (currMB)) // read DC coeffs for new intra modes
  {
    currSE.type = SE_DELTA_QUANT_INTRA;
 
    dP = &(currSlice->partArr[partMap[currSE.type]]);
 
    if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
    {
      currSE.mapping = linfo_se;
    }
    else
    {
      currSE.reading= readDquant_CABAC;
    }
#if TRACE
    snprintf(currSE.tracestring, TRACESTRING_SIZE, "Delta quant ");
#endif
    dP->readSyntaxElement(&currSE,img,dP);
    currMB->delta_quant = currSE.value1;
    if ((currMB->delta_quant < -(26 + img->bitdepth_luma_qp_scale/2)) || (currMB->delta_quant > (25 + img->bitdepth_luma_qp_scale/2)))
      error ("mb_qp_delta is out of range", 500);
 
    img->qp= ((img->qp + currMB->delta_quant + 52 + 2*img->bitdepth_luma_qp_scale)%(52+img->bitdepth_luma_qp_scale)) -
               img->bitdepth_luma_qp_scale;
 
    for (i=0;i<BLOCK_SIZE;i++)
      for (j=0;j<BLOCK_SIZE;j++)
        img->ipredmode[img->block_y+j][img->block_x+i]=DC_PRED;
 
 
    if (active_pps->entropy_coding_mode_flag == UVLC)
    {
      readCoeff4x4_CAVLC(img, inp, LUMA_INTRA16x16DC, 0, 0,
                          levarr, runarr, &numcoeff);
 
      coef_ctr=-1;
      level = 1;                            // just to get inside the loop
      for(k = 0; k < numcoeff; k++)
      {
        if (levarr[k] != 0)                     // leave if len=1
        {
          coef_ctr=coef_ctr+runarr[k]+1;
 
          i0=pos_scan4x4[coef_ctr][0];
          j0=pos_scan4x4[coef_ctr][1];
 
          img->cof[i0][j0][0][0]=levarr[k];// add new intra DC coeff
        }
      }
    }
    else
    {
 
      currSE.type = SE_LUM_DC_INTRA;
      dP = &(currSlice->partArr[partMap[currSE.type]]);
 
      currSE.context      = LUMA_16DC;
      currSE.type         = SE_LUM_DC_INTRA;
      img->is_intra_block = 1;
 
      if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
      {
        currSE.mapping = linfo_levrun_inter;
      }
      else
      {
        currSE.reading = readRunLevel_CABAC;
      }
 
      coef_ctr = -1;
      level = 1;                            // just to get inside the loop
 
      for(k=0;(k<17) && (level!=0);k++)
      {
#if TRACE
        snprintf(currSE.tracestring, TRACESTRING_SIZE, "DC luma 16x16 ");
#endif
        dP->readSyntaxElement(&currSE,img,dP);
        level = currSE.value1;
        run   = currSE.value2;
        len   = currSE.len;
 
        if (level != 0)                     // leave if len=1
        {
          coef_ctr=coef_ctr+run+1;
 
          i0=pos_scan4x4[coef_ctr][0];
          j0=pos_scan4x4[coef_ctr][1];
 
          img->cof[i0][j0][0][0]=level;// add new intra DC coeff
        }
      }
    }
    if(!lossless_qpprime)
      itrans_2(img);// transform new intra DC
  }
 
  currMB->qp = img->qp;
 
  set_chroma_qp(currMB);
 
  qp_per    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6;
  qp_rem    = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6;
  qp_const  = 1<<(3-qp_per);
 
  InvLevelScale4x4 = intra? InvLevelScale4x4Luma_Intra[qp_rem] : InvLevelScale4x4Luma_Inter[qp_rem];
  InvLevelScale8x8 = intra? InvLevelScale8x8Luma_Intra[qp_rem] : InvLevelScale8x8Luma_Inter[qp_rem];
 
  //init constants for every chroma qp offset
  if (dec_picture->chroma_format_idc != YUV400)
  {
    for(i=0; i < 2; i++)
    {
      qp_per_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)/6;
      qp_rem_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)%6;
    }
  }
 
 
  // luma coefficients
  for (block_y=0; block_y < 4; block_y += 2) /* all modes */
  {
    for (block_x=0; block_x < 4; block_x += 2)
    {
 
      b8 = 2*(block_y>>1) + (block_x>>1);
      if (active_pps->entropy_coding_mode_flag == UVLC)
      {
        for (j=block_y; j < block_y+2; j++)
        {
          for (i=block_x; i < block_x+2; i++)
          {
            ii = block_x >> 1;
            jj = block_y >> 1;
            b8 = 2 * jj + ii;
 
            if (cbp & (1<<b8))  /* are there any coeff in current block at all */
            {
              readCoeff4x4_CAVLC(img, inp, (IS_NEWINTRA(currMB) ? LUMA_INTRA16x16AC : LUMA), i, j, levarr, runarr, &numcoeff);
 
              start_scan = IS_NEWINTRA(currMB) ? 1 : 0;
              coef_ctr = start_scan - 1;
 
              if(!lossless_qpprime)
              {
                if (!currMB->luma_transform_size_8x8_flag) // 4x4 transform
                {
                  for (k = 0; k < numcoeff; k++)
                  {
                    if (levarr[k] != 0)
                    {
                      coef_ctr += runarr[k]+1;
 
                      i0 = pos_scan4x4[coef_ctr][0];
                      j0 = pos_scan4x4[coef_ctr][1];
 
                      // inverse quant for 4x4 transform only
                      currMB->cbp_blk      |= (int64) 1 << ((j<<2) + i);
                      img->cof[i][j][j0][i0]= rshift_rnd_sf((levarr[k]*InvLevelScale4x4[j0][i0])<<qp_per, 4);
                    }
                  }
                }
                else // 8x8 transform
                {
                  int b4, iz, jz;
                  for (k = 0; k < numcoeff; k++)
                  {
                    if (levarr[k] != 0)
                    {
                      coef_ctr += runarr[k]+1;
 
                      // do same as CABAC for deblocking: any coeff in the 8x8 marks all the 4x4s
                      //as containing coefficients
                      currMB->cbp_blk  |= 51 << ((block_y<<2) + block_x);
 
                      b4 = 2*(j - block_y)+(i - block_x);
 
                      iz = pos_scan8x8[(coef_ctr << 2) + b4][0];
                      jz = pos_scan8x8[(coef_ctr << 2) + b4][1];
 
                      img->m7[block_y*4 +jz][block_x*4 +iz] = rshift_rnd_sf((levarr[k]*InvLevelScale8x8[jz][iz])<<qp_per, 6); // dequantization
                    }
                  }//else (!currMB->luma_transform_size_8x8_flag)
                }
              }
              else
              {
                if (!currMB->luma_transform_size_8x8_flag) // inverse quant for 4x4 transform
                {
                  for (k = 0; k < numcoeff; k++)
                  {
                    if (levarr[k] != 0)
                    {
                      coef_ctr += runarr[k]+1;
 
                      i0=pos_scan4x4[coef_ctr][0];
                      j0=pos_scan4x4[coef_ctr][1];
 
                      currMB->cbp_blk      |= (int64) 1 << ((j<<2) + i);
                      img->cof[i][j][j0][i0]= levarr[k];
                    }
                  }
                }
                else // inverse quant for 8x8 transform
                {
                  int b4, iz, jz;
                  for (k = 0; k < numcoeff; k++)
                  {
                    if (levarr[k] != 0)
                    {
                      coef_ctr += runarr[k]+1;
 
                      // do same as CABAC for deblocking: any coeff in the 8x8 marks all the 4x4s
                      //as containing coefficients
                      currMB->cbp_blk  |= 51 << ((block_y<<2) + block_x);
 
                      b4 = 2*(j-block_y)+(i-block_x);
 
                      iz=pos_scan8x8[coef_ctr*4+b4][0];
                      jz=pos_scan8x8[coef_ctr*4+b4][1];
 
                      img->m7[block_y*4 +jz][block_x*4 +iz] = levarr[k];
                    }
                  }
                }//else (!currMB->luma_transform_size_8x8_flag)
              }
            }
            else
            {
              img->nz_coeff[img->current_mb_nr][i][j] = 0;
            }
          }
        }
      } // VLC
      else
      {
        if(currMB->luma_transform_size_8x8_flag)
          readLumaCoeff8x8_CABAC(img, inp, b8); //======= 8x8 trannsform size & CABAC ========
        else
        {
          //======= Other Modes & CABAC ========
          //------------------------------------
          for (j=block_y; j < block_y+2; j++)
          {
            for (i=block_x; i < block_x+2; i++)
            {
              start_scan = IS_NEWINTRA (currMB)? 1 : 0;
 
              img->subblock_x = i; // position for coeff_count ctx
              img->subblock_y = j; // position for coeff_count ctx
 
              if (cbp & (1<<b8))  // are there any coeff in current block at all
              {
                coef_ctr = start_scan - 1;
                level    = 1;
                img->is_intra_block = IS_INTRA(currMB);
 
                if(!lossless_qpprime)
                {
                  for(k=start_scan;(k<17) && (level!=0);k++)
                  {
                    /*
                    * make distinction between INTRA and INTER coded
                    * luminance coefficients
                    */
                    currSE.context      = (IS_NEWINTRA(currMB) ? LUMA_16AC : LUMA_4x4);
                    currSE.type         = (img->is_intra_block 
                      ? (k==0 ? SE_LUM_DC_INTRA : SE_LUM_AC_INTRA) 
                      : (k==0 ? SE_LUM_DC_INTER : SE_LUM_AC_INTER));                                      
 
#if TRACE
                    sprintf(currSE.tracestring, "Luma sng ");
#endif
                    dP = &(currSlice->partArr[partMap[currSE.type]]);
 
                    if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)  
                      currSE.mapping = linfo_levrun_inter;
                    else                                                     
                      currSE.reading = readRunLevel_CABAC;
 
                    dP->readSyntaxElement(&currSE,img,dP);
                    level = currSE.value1;
                    run   = currSE.value2;
                    len   = currSE.len;
 
                    if (level != 0)    /* leave if len=1 */
                    {
                      coef_ctr += run+1;
 
                      i0=pos_scan4x4[coef_ctr][0];
                      j0=pos_scan4x4[coef_ctr][1];
 
                      currMB->cbp_blk |= (int64)1 << ((j<<2) + i) ;
                      img->cof[i][j][j0][i0]= rshift_rnd_sf((level*InvLevelScale4x4[j0][i0]) << qp_per, 4);
                    }
                  }
                }
                else
                {
                  for(k=start_scan;(k<17) && (level!=0);k++)
                  {
                    /*
                    * make distinction between INTRA and INTER coded
                    * luminance coefficients
                    */
                    currSE.context      = (IS_NEWINTRA(currMB) ? LUMA_16AC : LUMA_4x4);
                    currSE.type         = (img->is_intra_block 
                      ? (k==0 ? SE_LUM_DC_INTRA : SE_LUM_AC_INTRA) 
                      : (k==0 ? SE_LUM_DC_INTER : SE_LUM_AC_INTER));                                      
 
#if TRACE
                    sprintf(currSE.tracestring, "Luma sng ");
#endif
                    dP = &(currSlice->partArr[partMap[currSE.type]]);
 
                    if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)  
                      currSE.mapping = linfo_levrun_inter;
                    else                                                     
                      currSE.reading = readRunLevel_CABAC;
 
                    dP->readSyntaxElement(&currSE,img,dP);
                    level = currSE.value1;
                    run   = currSE.value2;
                    len   = currSE.len;
 
                    if (level != 0)    /* leave if len=1 */
                    {
                      coef_ctr += run+1;
 
                      i0=pos_scan4x4[coef_ctr][0];
                      j0=pos_scan4x4[coef_ctr][1];
 
                      currMB->cbp_blk |= (int64)1 << ((j<<2) + i) ;
 
                      img->cof[i][j][j0][i0]= level;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
 
  if (dec_picture->chroma_format_idc != YUV400)
  {
 
    for (j=4;j<(4+img->num_blk8x8_uv);j++) // reset all chroma coeffs before read
    for (i=0;i<4;i++)
      memset(&img->cof[i][j][0][0], 0, 16 * sizeof(int));
 
    m2  = img->mb_x * 2;
    jg2 = img->mb_y * 2;
 
    qp_const_uv[0] = 1<<(3-qp_per_uv[0]);
    qp_const_uv[1] = 1<<(3-qp_per_uv[1]);
 
 
    //========================== CHROMA DC ============================
    //-----------------------------------------------------------------
    // chroma DC coeff
    if(cbp>15)
    {
      for (ll=0;ll<3;ll+=2)
      {
        uv = ll>>1;
 
        if (dec_picture->chroma_format_idc == YUV420)
        {
          int (*InvLevelScale4x4Chroma)[4] = intra
            ? InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]] 
            : InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]];
 
          //===================== CHROMA DC YUV420 ======================
          memset(&img->cofu[0], 0, 4 *sizeof(int));
 
          if (active_pps->entropy_coding_mode_flag == UVLC)
          {
            readCoeff4x4_CAVLC(img, inp, CHROMA_DC, 0, 0,
                               levarr, runarr, &numcoeff);
            coef_ctr=-1;
            level=1;
            for(k = 0; k < numcoeff; k++)
            {
              if (levarr[k] != 0)
              {
                currMB->cbp_blk |= 0xf0000 << (ll<<1) ;
                coef_ctr=coef_ctr+runarr[k]+1;
                img->cofu[coef_ctr]=levarr[k];
              }
            }
          }
          else
          {
            coef_ctr=-1;
            level=1;
            for(k=0;(k<(img->num_cdc_coeff+1))&&(level!=0);k++)
            {
              currSE.context      = CHROMA_DC;
              currSE.type         = (IS_INTRA(currMB) ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER);
              img->is_intra_block =  IS_INTRA(currMB);
              img->is_v_block     = ll;
 
  #if TRACE
              snprintf(currSE.tracestring, TRACESTRING_SIZE, "2x2 DC Chroma ");
  #endif
              dP = &(currSlice->partArr[partMap[currSE.type]]);
 
              if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
                currSE.mapping = linfo_levrun_c2x2;
              else
                currSE.reading = readRunLevel_CABAC;
 
              dP->readSyntaxElement(&currSE,img,dP);
              level = currSE.value1;
              run = currSE.value2;
              len = currSE.len;
              if (level != 0)
              {
                currMB->cbp_blk |= 0xf0000 << (ll<<1) ;
                coef_ctr=coef_ctr+run+1;
                // Bug: img->cofu has only 4 entries, hence coef_ctr MUST be <4 (which is
                // caught by the assert().  If it is bigger than 4, it starts patching the
                // img->predmode pointer, which leads to bugs later on.
                //
                // This assert() should be left in the code, because it captures a very likely
                // bug early when testing in error prone environments (or when testing NAL
                // functionality).
                assert (coef_ctr < img->num_cdc_coeff);
                img->cofu[coef_ctr]=level;
              }
            }
          }
 
          if (smb // check to see if MB type is SPred or SIntra4x4
              || lossless_qpprime)
          {
            img->cof[0+ll][4][0][0]=img->cofu[0];
            img->cof[1+ll][4][0][0]=img->cofu[1];
            img->cof[0+ll][5][0][0]=img->cofu[2];
            img->cof[1+ll][5][0][0]=img->cofu[3];
          }
          else
          {
            temp[0]=(img->cofu[0]+img->cofu[1]+img->cofu[2]+img->cofu[3]);
            temp[1]=(img->cofu[0]-img->cofu[1]+img->cofu[2]-img->cofu[3]);
            temp[2]=(img->cofu[0]+img->cofu[1]-img->cofu[2]-img->cofu[3]);
            temp[3]=(img->cofu[0]-img->cofu[1]-img->cofu[2]+img->cofu[3]);
 
            for (i=0;i<img->num_cdc_coeff;i++)
            {
              if(qp_per_uv[uv]<5)
              {
                  temp[i]=(temp[i]*InvLevelScale4x4Chroma[0][0])>>(5-qp_per_uv[uv]);
              }
              else
              {
                  temp[i]=(temp[i]*InvLevelScale4x4Chroma[0][0])<<(qp_per_uv[uv]-5);
              }
            }
            img->cof[0+ll][4][0][0]=temp[0];
            img->cof[1+ll][4][0][0]=temp[1];
            img->cof[0+ll][5][0][0]=temp[2];
            img->cof[1+ll][5][0][0]=temp[3];
          }
        }
        else if (dec_picture->chroma_format_idc == YUV422)
        {
          int i,j,j1;
          int uv_idx = ll;
          int m3[2][4] = {{0,0,0,0},{0,0,0,0}};
          int m4[2][4] = {{0,0,0,0},{0,0,0,0}};
          int qp_per_uv_dc = (currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale)/6;       //for YUV422 only
          int qp_rem_uv_dc = (currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale)%6;       //for YUV422 only
 
          //===================== CHROMA DC YUV422 ======================
          if (active_pps->entropy_coding_mode_flag == UVLC)
          {
            readCoeff4x4_CAVLC(img, inp, CHROMA_DC, 0, 0,
                               levarr, runarr, &numcoeff);
            coef_ctr=-1;
            level=1;
            for(k = 0; k < numcoeff; k++)
            {
              if (levarr[k] != 0)
              {
                currMB->cbp_blk |= ((int64)0xff0000) << (ll<<2);
                coef_ctr=coef_ctr+runarr[k]+1;
                i0 = SCAN_YUV422[coef_ctr][0];
                j0 = SCAN_YUV422[coef_ctr][1];
 
                m3[i0][j0]=levarr[k];
              }
            }
          }
          else
          {
            coef_ctr=-1;
            level=1;
            for(k=0;(k<9)&&(level!=0);k++)
            {
              currSE.context      = CHROMA_DC_2x4;
              currSE.type         = (IS_INTRA(currMB) ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER);
              img->is_intra_block =  IS_INTRA(currMB);
              img->is_v_block     = ll;
 
  #if TRACE
              snprintf(currSE.tracestring, TRACESTRING_SIZE, "2x4 DC Chroma ");
  #endif
              dP = &(currSlice->partArr[partMap[currSE.type]]);
 
              if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
                currSE.mapping = linfo_levrun_c2x2;
              else
                currSE.reading = readRunLevel_CABAC;
 
              dP->readSyntaxElement(&currSE,img,dP);
              level = currSE.value1;
              run = currSE.value2;
              len = currSE.len;
              if (level != 0)
              {
                currMB->cbp_blk |= ((int64)0xff0000) << (ll<<2) ;
                coef_ctr=coef_ctr+run+1;
                assert (coef_ctr < img->num_cdc_coeff);
                i0=SCAN_YUV422[coef_ctr][0];
                j0=SCAN_YUV422[coef_ctr][1];
 
                m3[i0][j0]=level;
              }
            }
          }
          // inverse CHROMA DC YUV422 transform
          // horizontal
          if(!lossless_qpprime)
          {
            m4[0][0] = m3[0][0] + m3[1][0];
            m4[0][1] = m3[0][1] + m3[1][1];
            m4[0][2] = m3[0][2] + m3[1][2];
            m4[0][3] = m3[0][3] + m3[1][3];
 
            m4[1][0] = m3[0][0] - m3[1][0];
            m4[1][1] = m3[0][1] - m3[1][1];
            m4[1][2] = m3[0][2] - m3[1][2];
            m4[1][3] = m3[0][3] - m3[1][3];
          }
          else
          {
            for(i=0;i<2;i++)
              for(j=0;j<4;j++)
                img->cof[i+uv_idx][j+4][0][0]=m3[i][j];
          }
 
          // vertical
          for (i=0;i<2 && !lossless_qpprime;i++)
          {
            int (*imgcof)[4][4] = img->cof[i+uv_idx];
            for (j=0; j < 4;j++)    //TODO: remove m5 with m4
              m5[j]=m4[i][j];
 
            m6[0]=m5[0]+m5[2];
            m6[1]=m5[0]-m5[2];
            m6[2]=m5[1]-m5[3];
            m6[3]=m5[1]+m5[3];
 
            for (j=0;j<2;j++)
            {
              j1=3-j;
              if(qp_per_uv_dc<4)
              {
                if(intra == 1)
                {
                  imgcof[j +4][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
                  imgcof[j1+4][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
                }
                else
                {
                  imgcof[j +4][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
                  imgcof[j1+4][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2;
                }
              }
              else
              {
                if(intra == 1)
                {
                  imgcof[j +4][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
                  imgcof[j1+4][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
                }
                else
                {
                  imgcof[j +4][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
                  imgcof[j1+4][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2;
                }
              }
            }//for (j=0;j<2;j++)
          }//for (i=0;i<2;i++)
        }//else if (dec_picture->chroma_format_idc == YUV422)
        else
        {
          //===================== CHROMA DC YUV444 ======================
          int i,j,i1,j1;
          int uv_idx = 4 + (ll<<1);
 
          if (active_pps->entropy_coding_mode_flag == UVLC)
          {
            readCoeff4x4_CAVLC(img, inp, CHROMA_DC, 0, 0,
                               levarr, runarr, &numcoeff);
            coef_ctr=-1;
            level=1;
            for(k = 0; k < numcoeff; k++)
            {
              if (levarr[k] != 0)
              {
                currMB->cbp_blk |= ((int64)0xffff0000) << (ll<<3) ;
                coef_ctr=coef_ctr+runarr[k]+1;
                i0=SNGL_SCAN[coef_ctr][0];
                j0=SNGL_SCAN[coef_ctr][1];
 
                img->cof[i0][j0+uv_idx][0][0]=levarr[k];
              }
            }
          }
          else
          {
            coef_ctr=-1;
            level=1;
            for(k=0;(k<17)&&(level!=0);k++)
            {
              currSE.context      = CHROMA_DC_4x4;
              currSE.type         = (IS_INTRA(currMB) ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER);
              img->is_intra_block =  IS_INTRA(currMB);
              img->is_v_block     = ll;
 
  #if TRACE
              snprintf(currSE.tracestring, TRACESTRING_SIZE, "DC Chroma ");
  #endif
              dP = &(currSlice->partArr[partMap[currSE.type]]);
 
              if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
                currSE.mapping = linfo_levrun_c2x2;
              else
                currSE.reading = readRunLevel_CABAC;
 
              dP->readSyntaxElement(&currSE,img,dP);
              level = currSE.value1;
              run = currSE.value2;
              len = currSE.len;
              if (level != 0)
              {
                currMB->cbp_blk |= ((int64)0xffff0000) << (ll<<3) ;
                coef_ctr=coef_ctr+run+1;
                assert (coef_ctr < img->num_cdc_coeff);
                i0=SNGL_SCAN[coef_ctr][0];
                j0=SNGL_SCAN[coef_ctr][1];
 
                img->cof[i0][j0+uv_idx][0][0]=level;
              }
            }
          }
 
          // inverse CHROMA DC YUV444 transform
          // horizontal
          for (j=uv_idx; (j < 4+uv_idx) && !lossless_qpprime;j++)
          {
            for (i=0;i<4;i++)
              m5[i]=img->cof[i][j][0][0];
 
            m6[0]=m5[0]+m5[2];
            m6[1]=m5[0]-m5[2];
            m6[2]=m5[1]-m5[3];
            m6[3]=m5[1]+m5[3];
 
            for (i=0;i<2;i++)
            {
              i1=3-i;
              img->cof[i][j][0][0]= m6[i]+m6[i1];
              img->cof[i1][j][0][0]=m6[i]-m6[i1];
            }
          }
 
          // vertical
          for (i=0;i<4 && !lossless_qpprime;i++)
          {
            for (j=0; j < 4;j++)
              m5[j]=img->cof[i][j+uv_idx][0][0];
 
            m6[0]=m5[0]+m5[2];
            m6[1]=m5[0]-m5[2];
            m6[2]=m5[1]-m5[3];
            m6[3]=m5[1]+m5[3];
 
            for (j=0;j<2;j++)
            {
              j1=3-j;
              if(qp_per_uv[uv]<4)
              {
                if(intra == 1)
                {
                  img->cof[i][j +uv_idx][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]][0][0]+(1<<(3-qp_per_uv[uv])))>>(4-qp_per_uv[uv]))+2)>>2;
                  img->cof[i][j1+uv_idx][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]][0][0]+(1<<(3-qp_per_uv[uv])))>>(4-qp_per_uv[uv]))+2)>>2;
                }
                else
                {
                  img->cof[i][j +uv_idx][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]][0][0]+(1<<(3-qp_per_uv[uv])))>>(4-qp_per_uv[uv]))+2)>>2;
                  img->cof[i][j1+uv_idx][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]][0][0]+(1<<(3-qp_per_uv[uv])))>>(4-qp_per_uv[uv]))+2)>>2;
                }
              }
              else
              {
                if(intra == 1)
                {
                  img->cof[i][j +uv_idx][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]][0][0])<<(qp_per_uv[uv]-4))+2)>>2;
                  img->cof[i][j1+uv_idx][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]][0][0])<<(qp_per_uv[uv]-4))+2)>>2;
                }
                else
                {
                  img->cof[i][j +uv_idx][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]][0][0])<<(qp_per_uv[uv]-4))+2)>>2;
                  img->cof[i][j1+uv_idx][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]][0][0])<<(qp_per_uv[uv]-4))+2)>>2;
                }
              }
            }
          }//for (i=0;i<4;i++)
        }//else (dec_picture->chroma_format_idc == YUV444)
      }//for (ll=0;ll<3;ll+=2)
    }
 
    // chroma AC coeff, all zero fram start_scan
    if (cbp<=31)
        for (i=0; i < 4; i++)
          memset(&img->nz_coeff [img->current_mb_nr ][i][4], 0, img->num_blk8x8_uv * sizeof(int));
 
 
    //========================== CHROMA AC ============================
    //-----------------------------------------------------------------
    // chroma AC coeff, all zero fram start_scan
    if (cbp>31)
    {
      for (b8=0; b8 < img->num_blk8x8_uv; b8++)
      {
        int uvc = (b8 > ((img->num_blk8x8_uv>>1) - 1 ));
        int (*InvLevelScale4x4Chroma)[4] = intra
          ? InvLevelScale4x4Chroma_Intra[uvc][qp_rem_uv[uvc]] 
          : InvLevelScale4x4Chroma_Inter[uvc][qp_rem_uv[uvc]];
 
        img->is_v_block = uv = uvc;
 
        for (b4=0; b4 < 4; b4++)
        {
          i = cofuv_blk_x[yuv][b8][b4];
          j = cofuv_blk_y[yuv][b8][b4];
 
 
          if (active_pps->entropy_coding_mode_flag == UVLC)
          {
            readCoeff4x4_CAVLC(img, inp, CHROMA_AC, i, j,
                                levarr, runarr, &numcoeff);
            coef_ctr=0;
            level=1;
            if(!lossless_qpprime)
            {
              for(k = 0; k < numcoeff;k++)
              {
                if (levarr[k] != 0)
                {
                  currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4];
                  coef_ctr=coef_ctr+runarr[k]+1;
 
                  i0=pos_scan4x4[coef_ctr][0];
                  j0=pos_scan4x4[coef_ctr][1];
 
                  img->cof[i][j][j0][i0] = rshift_rnd_sf((levarr[k]*InvLevelScale4x4Chroma[j0][i0])<<qp_per_uv[uv], 4);
                }
              }
            }
            else
            {
              for(k = 0; k < numcoeff;k++)
              {
                if (levarr[k] != 0)
                {
                  currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4];
                  coef_ctr=coef_ctr+runarr[k]+1;
 
                  i0=pos_scan4x4[coef_ctr][0];
                  j0=pos_scan4x4[coef_ctr][1];
 
                  img->cof[i][j][j0][i0]=levarr[k];
                }
              }
            }
          }
          else
          {
            coef_ctr=0;
            level=1;
 
            img->subblock_y = subblk_offset_y[yuv][b8][b4]>>2;
            img->subblock_x = subblk_offset_x[yuv][b8][b4]>>2;
 
            currSE.context      = CHROMA_AC;
            currSE.type         = (IS_INTRA(currMB) ? SE_CHR_AC_INTRA : SE_CHR_AC_INTER);
            img->is_intra_block =  IS_INTRA(currMB);
 
            if(!lossless_qpprime)
            {
              for(k=0;(k<16)&&(level!=0);k++)
              {
#if TRACE
                snprintf(currSE.tracestring, TRACESTRING_SIZE, "AC Chroma ");
#endif
                dP = &(currSlice->partArr[partMap[currSE.type]]);
 
                if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
                  currSE.mapping = linfo_levrun_inter;
                else
                  currSE.reading = readRunLevel_CABAC;
 
                dP->readSyntaxElement(&currSE,img,dP);
                level = currSE.value1;
                run = currSE.value2;
                len = currSE.len;
 
                if (level != 0)
                {
                  currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4];
                  coef_ctr += (run + 1);
 
                  i0=pos_scan4x4[coef_ctr][0];
                  j0=pos_scan4x4[coef_ctr][1];
 
                  img->cof[i][j][j0][i0] = rshift_rnd_sf((level*InvLevelScale4x4Chroma[j0][i0])<<qp_per_uv[uv], 4);
                }
              } //for(k=0;(k<16)&&(level!=0);k++)
            }
            else
            {
              for(k=0;(k<16)&&(level!=0);k++)
              {
#if TRACE
                snprintf(currSE.tracestring, TRACESTRING_SIZE, "AC Chroma ");
#endif
                dP = &(currSlice->partArr[partMap[currSE.type]]);
 
                if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
                  currSE.mapping = linfo_levrun_inter;
                else
                  currSE.reading = readRunLevel_CABAC;
 
                dP->readSyntaxElement(&currSE,img,dP);
                level = currSE.value1;
                run = currSE.value2;
                len = currSE.len;
 
                if (level != 0)
                {
                  currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4];
                  coef_ctr += (run + 1);
 
                  i0=pos_scan4x4[coef_ctr][0];
                  j0=pos_scan4x4[coef_ctr][1];
 
                  img->cof[i][j][j0][i0]=level;
                }
              } //for(k=0;(k<16)&&(level!=0);k++)
            }
          } //else / if (active_pps->entropy_coding_mode_flag == UVLC)
        } //for (b4=0; b4 < 4; b4++)
      } //for (b8=0; b8 < img->num_blk8x8_uv; b8++)
    } //if (cbp>31)
  } //if (dec_picture->chroma_format_idc != YUV400)
}
 
 
/*!
 ************************************************************************
 * \brief
 *    Copy IPCM coefficients to decoded picture buffer and set parameters for this MB
 *    (for IPCM CABAC and IPCM CAVLC  28/11/2003)
 *
 * \author
 *    Dong Wang <Dong.Wang@bristol.ac.uk>
 ************************************************************************
 */
 
void decode_ipcm_mb(struct img_par *img)
{
  int i,j;
 
  Macroblock *currMb = &img->mb_data[img->current_mb_nr];
 
  //Copy coefficients to decoded picture buffer
  //IPCM coefficients are stored in img->cof which is set in function readIPCMcoeffsFromNAL()
 
  for(i=0;i<16;i++)
    for(j=0;j<16;j++)
      dec_picture->imgY[img->pix_y+i][img->pix_x+j]=img->cof[(i>>2)][(j>>2)][i & 0x03][j & 0x03];
 
  if (dec_picture->chroma_format_idc != YUV400)
  {
    for(i=0;i<img->mb_cr_size_y;i++)
      for(j=0;j<img->mb_cr_size_x;j++)
        dec_picture->imgUV[0][img->pix_c_y+i][img->pix_c_x+j]=img->cof[(i>>2)  ][(j>>2)+4][i & 0x03][j & 0x03];  
 
    for(i=0;i<img->mb_cr_size_y;i++)
      for(j=0;j<img->mb_cr_size_x;j++)
        dec_picture->imgUV[1][img->pix_c_y+i][img->pix_c_x+j]=img->cof[(i>>2)+2][(j>>2)+4][i & 0x03][j & 0x03]; 
  }
 
  // for deblocking filter
  currMb->qp=0;
  set_chroma_qp(currMb);
 
  // for CAVLC: Set the nz_coeff to 16.
  // These parameters are to be used in CAVLC decoding of neighbour blocks
  for(i=0;i<4;i++)
    for (j=0;j<(4 + img->num_blk8x8_uv);j++)
      img->nz_coeff[img->current_mb_nr][i][j]=16;
 
 
  // for CABAC decoding of MB skip flag
  currMb->skip_flag = 0;
 
  //for deblocking filter CABAC
  currMb->cbp_blk=0xFFFF;
 
  //For CABAC decoding of Dquant
  last_dquant=0;
}
 
/*!
 ************************************************************************
 * \brief
 *    decode one macroblock
 ************************************************************************
 */
 
int decode_one_macroblock(struct img_par *img,struct inp_par *inp)
{
  int tmp_block[BLOCK_SIZE][BLOCK_SIZE];
  int tmp_blockbw[BLOCK_SIZE][BLOCK_SIZE];
  int i=0,j=0,k,l,ii=0,jj=0,i1=0,j1=0,j4=0,i4=0;
  int uv, hv;
  int vec1_x=0,vec1_y=0,vec2_x=0,vec2_y=0;
  int ioff,joff;
  int block8x8;   // needed for ABT
 
  int bw_pred=0, fw_pred=0, pred, ifx;
  int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0;
  int mv_mul, f1_x, f1_y, f2_x, f2_y, f3, f4;
 
  static const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15};
 
  Macroblock *currMB   = &img->mb_data[img->current_mb_nr];
  short ref_idx, l0_refframe=-1, l1_refframe=-1;
  int mv_mode, pred_dir, intra_prediction; // = currMB->ref_frame;
  short l0_ref_idx=-1, l1_ref_idx=-1;
  int alpha_l0, alpha_l1, wp_offset;
 
  short  *** mv_array, ***l0_mv_array, ***l1_mv_array;
 
  int mv_scale;
 
  int mb_nr     = img->current_mb_nr;
  int smb       = ((img->type==SP_SLICE) && IS_INTER (currMB)) || (img->type == SI_SLICE && currMB->mb_type == SI4MB);
  int list_offset;
  int max_y_cr;
 
  StorablePicture **list;
 
  int jf;
 
  char l0_rFrame = -1, l1_rFrame = -1;
 
  short pmvl0[2]={0,0},
        pmvl1[2]={0,0};
 
  int direct_pdir=-1;
 
  int curr_mb_field = ((img->MbaffFrameFlag)&&(currMB->mb_field));
 
  byte  **    moving_block;
  short ****  co_located_mv;
  char  ***   co_located_ref_idx;
  int64 ***   co_located_ref_id;
 
  int need_4x4_transform = (!currMB->luma_transform_size_8x8_flag);
 
  int b8, b4;
  int uv_shift;
  int yuv = dec_picture->chroma_format_idc - 1;
 
  if(img->type==SP_SLICE && currMB->mb_type!=I16MB)
    smb=1;// modif ES added
 
  if(currMB->mb_type==IPCM)
  {
    //copy readed data into imgY and set parameters
    decode_ipcm_mb(img);
    return 0;
  }
 
//////////////////////////
 
  // find out the correct list offsets
  if (curr_mb_field)
  {
    if(mb_nr&0x01)
    {
      list_offset = 4; // top field mb
      moving_block = Co_located->bottom_moving_block;
      co_located_mv = Co_located->bottom_mv;
      co_located_ref_idx = Co_located->bottom_ref_idx;
      co_located_ref_id = Co_located->bottom_ref_pic_id;
    }
    else
    {
      list_offset = 2; // bottom field mb
      moving_block = Co_located->top_moving_block;
      co_located_mv = Co_located->top_mv;
      co_located_ref_idx = Co_located->top_ref_idx;
      co_located_ref_id = Co_located->top_ref_pic_id;
    }
    max_y_cr = (dec_picture->size_y_cr>>1)-1;
  }
  else
  {
    list_offset = 0;  // no mb aff or frame mb
    moving_block = Co_located->moving_block;
    co_located_mv = Co_located->mv;
    co_located_ref_idx = Co_located->ref_idx;
    co_located_ref_id = Co_located->ref_pic_id;
    max_y_cr = dec_picture->size_y_cr-1;
  }
 
  if (!img->MbaffFrameFlag)
  {
    for (l = LIST_0 + list_offset; l <= (LIST_1 + list_offset); l++)
    {
      for(k = 0; k < listXsize[l]; k++)
      {
        listX[l][k]->chroma_vector_adjustment= 0;
        if(img->structure == TOP_FIELD && img->structure != listX[l][k]->structure)
          listX[l][k]->chroma_vector_adjustment = -2;
        if(img->structure == BOTTOM_FIELD && img->structure != listX[l][k]->structure)
          listX[l][k]->chroma_vector_adjustment = 2;
      }
    }
  }
  else
  {
    if (curr_mb_field)
    {
      for (l = LIST_0 + list_offset; l <= (LIST_1 + list_offset); l++)
      {
        for(k = 0; k < listXsize[l]; k++)
        {
          listX[l][k]->chroma_vector_adjustment= 0;
          if(img->current_mb_nr % 2 == 0 && listX[l][k]->structure == BOTTOM_FIELD)
            listX[l][k]->chroma_vector_adjustment = -2;
          if(img->current_mb_nr % 2 == 1 && listX[l][k]->structure == TOP_FIELD)
            listX[l][k]->chroma_vector_adjustment = 2;
        }
      }
    }
    else
    {
      for (l = LIST_0 + list_offset; l <= (LIST_1 + list_offset); l++)
      {
        for(k = 0; k < listXsize[l]; k++)
        {
          listX[l][k]->chroma_vector_adjustment= 0;
        }
      }
    }
  }
 
  mv_mul=4;
 
  // luma decoding **************************************************
 
  // get prediction for INTRA_MB_16x16
  if (IS_NEWINTRA (currMB))
  {
    intrapred_luma_16x16(img, currMB->i16mode);
  }
 
  if (img->type==B_SLICE && img->direct_spatial_mv_pred_flag && (IS_DIRECT (currMB) ||
    (IS_P8x8(currMB) && !(currMB->b8mode[0] && currMB->b8mode[1] && currMB->b8mode[2] && currMB->b8mode[3]))))
  {
    char l0_rFrameL, l0_rFrameU, l0_rFrameUL, l0_rFrameUR;
    char l1_rFrameL, l1_rFrameU, l1_rFrameUL, l1_rFrameUR;
 
    PixelPos mb_left, mb_up, mb_upleft, mb_upright;
 
    getLuma4x4Neighbour(img->current_mb_nr, -1,  0, &mb_left);
    getLuma4x4Neighbour(img->current_mb_nr,  0, -1, &mb_up);
    getLuma4x4Neighbour(img->current_mb_nr, 16, -1, &mb_upright);
    getLuma4x4Neighbour(img->current_mb_nr, -1, -1, &mb_upleft);
 
    if (!img->MbaffFrameFlag)
    {
      l0_rFrameL  = mb_left.available    ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]       : -1;
      l0_rFrameU  = mb_up.available      ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x]           : -1;
      l0_rFrameUL = mb_upleft.available  ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]   : -1;
      l0_rFrameUR = mb_upright.available ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL;
 
      l1_rFrameL = mb_left.available     ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x]       : -1;
      l1_rFrameU = mb_up.available       ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x]           : -1;
      l1_rFrameUL = mb_upleft.available  ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x]   : -1;
      l1_rFrameUR = mb_upright.available ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL;
    }
    else
    {
      if (img->mb_data[img->current_mb_nr].mb_field)
      {
        l0_rFrameL = mb_left.available ?
          img->mb_data[mb_left.mb_addr].mb_field  || dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] < 0?
          dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] :
          dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] * 2: -1;
 
        l0_rFrameU = mb_up.available ?
          img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0?
          dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] :
        dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] * 2: -1;
 
        l0_rFrameUL = mb_upleft.available ?
          img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0?
          dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] :
        dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] *2: -1;
 
        l0_rFrameUR = mb_upright.available ?
          img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0?
          dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] :
        dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] * 2: l0_rFrameUL;
 
        l1_rFrameL = mb_left.available ?
          img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] < 0?
          dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] :
        dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] * 2: -1;
 
        l1_rFrameU = mb_up.available ?
          img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] < 0?
          dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] :
        dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] * 2: -1;
 
        l1_rFrameUL = mb_upleft.available ?
          img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] < 0?
          dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] :
        dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] *2: -1;
 
        l1_rFrameUR = mb_upright.available ?
          img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0?
          dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] :
        dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] * 2: l1_rFrameUL;
      }
      else
      {
        l0_rFrameL = mb_left.available ?
          img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]  < 0 ?
          dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] >> 1 :
        dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]: -1;
 
        l0_rFrameU = mb_up.available ?
          img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0 ?
          dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] >> 1 :
        dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : -1;
 
        l0_rFrameUL = mb_upleft.available ?
          img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0 ?
          dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]>> 1 :
        dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : -1;
 
        l0_rFrameUR = mb_upright.available ?
          img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 ?
          dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] >> 1 :
        dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL;
 
        l1_rFrameL = mb_left.available ?
          img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] < 0 ?
          dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] >> 1 :
        dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : -1;
 
        l1_rFrameU = mb_up.available ?
          img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] < 0 ?
          dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] >> 1 :
        dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : -1;
 
        l1_rFrameUL = mb_upleft.available ?
          img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] < 0 ?
          dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] >> 1 :
        dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : -1;
 
        l1_rFrameUR = mb_upright.available ?
          img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0 ?
          dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] >> 1:
        dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL;
      }
    }
 
    l0_rFrame = (l0_rFrameL >= 0 && l0_rFrameU >= 0) ? imin(l0_rFrameL,l0_rFrameU): imax(l0_rFrameL,l0_rFrameU);
    l0_rFrame = (l0_rFrame >= 0 && l0_rFrameUR >= 0) ? imin(l0_rFrame,l0_rFrameUR): imax(l0_rFrame,l0_rFrameUR);
 
    l1_rFrame = (l1_rFrameL >= 0 && l1_rFrameU >= 0) ? imin(l1_rFrameL,l1_rFrameU): imax(l1_rFrameL,l1_rFrameU);
    l1_rFrame = (l1_rFrame >= 0 && l1_rFrameUR >= 0) ? imin(l1_rFrame,l1_rFrameUR): imax(l1_rFrame,l1_rFrameUR);
 
    if (l0_rFrame >=0)
      SetMotionVectorPredictor (img, pmvl0, l0_rFrame, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);
 
    if (l1_rFrame >=0)
      SetMotionVectorPredictor (img, pmvl1, l1_rFrame, LIST_1, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);
  }
 
  for (block8x8=0; block8x8<4; block8x8++)
  {
    if (currMB->b8mode[block8x8] == I8MB)
    {
      //=========== 8x8 BLOCK TYPE ============
      ioff = 8*(block8x8&0x01);
      joff = 8*(block8x8>>1);
 
      //PREDICTION
      intrapred8x8(img, block8x8);
      itrans8x8(img,ioff,joff);      // use DCT transform and make 8x8 block m7 from prediction block mpr
 
      for(jj=joff;jj<joff + 8;jj++)
      {
        for(ii=ioff;ii<ioff + 8;ii++)
        {
          dec_picture->imgY[img->pix_y + jj][img->pix_x + ii] = img->m7[jj][ii]; // construct picture from 4x4 blocks
        }
      }
      continue;
    }
 
    for (k = block8x8*4; k < block8x8*4+4; k ++)
    {
      i =  (decode_block_scan[k] & 3);
      j = ((decode_block_scan[k] >> 2) & 3);
 
      ioff = (i << 2);
      i4   = img->block_x + i;
 
      joff = (j << 2);
      j4   = img->block_y + j;
 
      mv_mode  = currMB->b8mode[2*(j>>1)+(i>>1)];
      pred_dir = currMB->b8pdir[2*(j>>1)+(i>>1)];
 
      assert (pred_dir<=2);
 
      // PREDICTION
      if (mv_mode==IBLOCK)
      {
        //===== INTRA PREDICTION =====
        if (intrapred(img,ioff,joff,i4,j4)==SEARCH_SYNC)  /* make 4x4 prediction block mpr from given prediction img->mb_mode */
          return SEARCH_SYNC;                   /* bit error */
      }
      else if (!IS_NEWINTRA (currMB))
      {
        if (pred_dir != 2)
        {
          //===== FORWARD/BACKWARD PREDICTION =====
          l0_refframe = ref_idx  = dec_picture->ref_idx[LIST_0 + pred_dir][j4][i4];
          mv_array = dec_picture->mv[LIST_0 + pred_dir];
          list     = listX[0+list_offset+ pred_dir];
          vec1_x = i4*4*mv_mul + mv_array[j4][i4][0];
 
          if (!curr_mb_field)
          {
            vec1_y = j4 * 4 * mv_mul + mv_array[j4][i4][1];
          }
          else
          {
            if ((mb_nr&0x01) == 0)
              vec1_y = (img->block_y * 2 + joff) * mv_mul + mv_array[j4][i4][1];
            else
              vec1_y = ((img->block_y-4) * 2 + joff)* mv_mul + mv_array[j4][i4][1];
          }
 
          get_block (ref_idx, list, vec1_x, vec1_y, img, tmp_block);
 
          if (img->apply_weights)
          {
            if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))||
              (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field)
            {
              ref_idx >>=1;
            }
 
            alpha_l0  = img->wp_weight[pred_dir][ref_idx][0];
            wp_offset = img->wp_offset[pred_dir][l0_refframe>>curr_mb_field][0];
            for(jj=0;jj<BLOCK_SIZE;jj++)
            {
              int jpos = jj+joff;
              for(ii=0;ii<BLOCK_SIZE;ii++)
                img->mpr[jpos][ii+ioff] = iClip1(img->max_imgpel_value, 
                (rshift_rnd_sf((alpha_l0 *  tmp_block[jj][ii]), img->luma_log2_weight_denom)  + wp_offset ));
            }
          }
          else
          {
            for(jj=0;jj<BLOCK_SIZE;jj++)
            {
              int jpos = jj+joff;
              for(ii=0;ii<BLOCK_SIZE;ii++)
                img->mpr[jpos][ii+ioff] = tmp_block[jj][ii];
            }
          }
        }
        else
        {
          if (mv_mode != 0)
          {
            //===== BI-DIRECTIONAL PREDICTION =====
            l0_mv_array = dec_picture->mv[LIST_0];
            l1_mv_array = dec_picture->mv[LIST_1];
 
            l0_refframe = dec_picture->ref_idx[LIST_0][j4][i4];
            l1_refframe = dec_picture->ref_idx[LIST_1][j4][i4];
            l0_ref_idx  = l0_refframe;
            l1_ref_idx  = l1_refframe;
          }
          else
          {
            //===== DIRECT PREDICTION =====
            l0_mv_array = dec_picture->mv[LIST_0];
            l1_mv_array = dec_picture->mv[LIST_1];
            l1_refframe = 0;
 
            if (img->direct_spatial_mv_pred_flag )
            {
              int imgblock_y= ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? (img->block_y-4)>>1:img->block_y>>1: img->block_y;
              int j6 = imgblock_y + j;
 
              if (l0_rFrame >=0)
              {
                if (!l0_rFrame  && ((!moving_block[j6][i4]) && (!listX[1+list_offset][0]->is_long_term)))
                {
                  dec_picture->mv  [LIST_0][j4][i4][0] = 0;
                  dec_picture->mv  [LIST_0][j4][i4][1] = 0;
                  dec_picture->ref_idx[LIST_0][j4][i4] = 0;
                }
                else
                {
                  dec_picture->mv  [LIST_0][j4][i4][0] = pmvl0[0];
                  dec_picture->mv  [LIST_0][j4][i4][1] = pmvl0[1];
                  dec_picture->ref_idx[LIST_0][j4][i4] = l0_rFrame;
                }
              }
              else
              {
                dec_picture->ref_idx[LIST_0][j4][i4] = -1;
                dec_picture->mv  [LIST_0][j4][i4][0] = 0;
                dec_picture->mv  [LIST_0][j4][i4][1] = 0;
              }
 
              if (l1_rFrame >=0)
              {
                if  (l1_rFrame==0 && ((!moving_block[j6][i4]) && (!listX[1+list_offset][0]->is_long_term)))
                {
 
                  dec_picture->mv  [LIST_1][j4][i4][0] = 0;
                  dec_picture->mv  [LIST_1][j4][i4][1] = 0;
                  dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame;
 
                }
                else
                {
                  dec_picture->mv  [LIST_1][j4][i4][0] = pmvl1[0];
                  dec_picture->mv  [LIST_1][j4][i4][1] = pmvl1[1];
                  dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame;
                }
              }
              else
              {
                dec_picture->mv  [LIST_1][j4][i4][0] = 0;
                dec_picture->mv  [LIST_1][j4][i4][1] = 0;
                dec_picture->ref_idx[LIST_1][j4][i4] = -1;
              }
 
              if (l0_rFrame < 0 && l1_rFrame < 0)
              {
                dec_picture->ref_idx[LIST_0][j4][i4] = 0;
                dec_picture->ref_idx[LIST_1][j4][i4] = 0;
              }
 
              l0_refframe = (dec_picture->ref_idx[LIST_0][j4][i4]!=-1) ? dec_picture->ref_idx[LIST_0][j4][i4] : 0;
              l1_refframe = (dec_picture->ref_idx[LIST_1][j4][i4]!=-1) ? dec_picture->ref_idx[LIST_1][j4][i4] : 0;
 
              l0_ref_idx = l0_refframe;
              l1_ref_idx = l1_refframe;
 
              if      (dec_picture->ref_idx[LIST_1][j4][i4]==-1) 
                direct_pdir = 0;
              else if (dec_picture->ref_idx[LIST_0][j4][i4]==-1) 
                direct_pdir = 1;
              else                                               
                direct_pdir = 2;
 
            }
            else // Temporal Mode
            {
 
              int imgblock_y= ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? (img->block_y-4)>>1:img->block_y>>1: img->block_y;
              int j6= imgblock_y + j;
 
              int refList = (co_located_ref_idx[LIST_0][j6][i4]== -1 ? LIST_1 : LIST_0);
              int ref_idx =  co_located_ref_idx[refList][j6][i4];
 
 
              if(ref_idx==-1) // co-located is intra mode
              {
                for(hv=0; hv<2; hv++)
                {
                  dec_picture->mv  [LIST_0][j4][i4][hv]=0;
                  dec_picture->mv  [LIST_1][j4][i4][hv]=0;
                }
 
                dec_picture->ref_idx[LIST_0][j4][i4] = 0;
                dec_picture->ref_idx[LIST_1][j4][i4] = 0;
 
                l0_refframe = 0;
                l0_ref_idx = 0;
              }
              else // co-located skip or inter mode
              {
                int mapped_idx=0;
                int iref;
 
                {
                  for (iref=0;iref<imin(img->num_ref_idx_l0_active,listXsize[LIST_0 + list_offset]);iref++)
                  {
                    if(img->structure==0 && curr_mb_field==0)
                    {
                      // If the current MB is a frame MB and the colocated is from a field picture,
                      // then the co_located_ref_id may have been generated from the wrong value of
                      // frame_poc if it references it's complementary field, so test both POC values
                      if(listX[0][iref]->top_poc*2 == co_located_ref_id[refList][j6][i4] || listX[0][iref]->bottom_poc*2 == co_located_ref_id[refList][j6][i4])
                      {
                        mapped_idx=iref;
                        break;
                      }
                      else //! invalid index. Default to zero even though this case should not happen
                        mapped_idx=INVALIDINDEX;
                      continue;
                    }
 
                    if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][j6][i4])
                    {
                      mapped_idx=iref;
                      break;
                    }
                    else //! invalid index. Default to zero even though this case should not happen
                    {
                      mapped_idx=INVALIDINDEX;
                    }
                  }
                  if (INVALIDINDEX == mapped_idx)
                  {
                    error("temporal direct error\ncolocated block has ref that is unavailable",-1111);
                  }
                }
 
                l0_ref_idx = mapped_idx;
                mv_scale = img->mvscale[LIST_0 + list_offset][mapped_idx];
 
                //! In such case, an array is needed for each different reference.
                if (mv_scale == 9999 || listX[LIST_0+list_offset][mapped_idx]->is_long_term)
                {
                  dec_picture->mv  [LIST_0][j4][i4][0]=co_located_mv[refList][j6][i4][0];
                  dec_picture->mv  [LIST_0][j4][i4][1]=co_located_mv[refList][j6][i4][1];
 
                  dec_picture->mv  [LIST_1][j4][i4][0]=0;
                  dec_picture->mv  [LIST_1][j4][i4][1]=0;
                }
                else
                {
                  dec_picture->mv  [LIST_0][j4][i4][0]=(mv_scale * co_located_mv[refList][j6][i4][0] + 128 ) >> 8;
                  dec_picture->mv  [LIST_0][j4][i4][1]=(mv_scale * co_located_mv[refList][j6][i4][1] + 128 ) >> 8;
 
                  dec_picture->mv  [LIST_1][j4][i4][0]=dec_picture->mv[LIST_0][j4][i4][0] - co_located_mv[refList][j6][i4][0] ;
                  dec_picture->mv  [LIST_1][j4][i4][1]=dec_picture->mv[LIST_0][j4][i4][1] - co_located_mv[refList][j6][i4][1] ;
                }
 
                l0_refframe = dec_picture->ref_idx[LIST_0][j4][i4] = mapped_idx; //listX[1][0]->ref_idx[refList][j4][i4];
                l1_refframe = dec_picture->ref_idx[LIST_1][j4][i4] = 0;
 
                l0_ref_idx = l0_refframe;
                l1_ref_idx = l1_refframe;
              }
            }
            // store reference picture ID determined by direct mode
            dec_picture->ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->ref_idx[LIST_0][j4][i4]];
            dec_picture->ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->ref_idx[LIST_1][j4][i4]];
          }
 
          if (mv_mode==0 && img->direct_spatial_mv_pred_flag )
          {
            if (dec_picture->ref_idx[LIST_0][j4][i4] >= 0)
            {
 
              vec1_x = i4*4*mv_mul + l0_mv_array[j4][i4][0];
              if (!curr_mb_field)
              {
                vec1_y = j4*4*mv_mul + l0_mv_array[j4][i4][1];
              }
              else
              {
                if ((mb_nr&0x01) == 0)
                {
                  vec1_y = (img->block_y * 2 + joff) * mv_mul + l0_mv_array[j4][i4][1];
                }
                else
                {
                  vec1_y = ((img->block_y-4) * 2 + joff)* mv_mul + l0_mv_array[j4][i4][1];
                }
              }
              get_block(l0_refframe, listX[0+list_offset], vec1_x, vec1_y, img, tmp_block);
            }
 
            if (dec_picture->ref_idx[LIST_1][j4][i4] >= 0)
            {
              vec2_x = i4*4*mv_mul + l1_mv_array[j4][i4][0];
              if (!curr_mb_field)
              {
                vec2_y = j4*4*mv_mul + l1_mv_array[j4][i4][1];
              }
              else
              {
                if ((mb_nr&0x01) == 0)
                {
                  vec2_y = (img->block_y * 2 + joff) * mv_mul + l1_mv_array[j4][i4][1];
                }
                else
                {
                  vec2_y = ((img->block_y-4) * 2 + joff)* mv_mul + l1_mv_array[j4][i4][1];
                }
              }
              get_block(l1_refframe, listX[1+list_offset], vec2_x, vec2_y, img, tmp_blockbw);
            }
          }
          else
          {
            vec1_x = i4 * 4 * mv_mul + l0_mv_array[j4][i4][0];
            vec2_x = i4 * 4 * mv_mul + l1_mv_array[j4][i4][0];
 
            if (!curr_mb_field)
            {
              vec1_y = j4 * 4 * mv_mul + l0_mv_array[j4][i4][1];
              vec2_y = j4 * 4 * mv_mul + l1_mv_array[j4][i4][1];
            }
            else
            {
              if ((mb_nr&0x01) == 0)
              {
                vec1_y = (img->block_y * 2 + joff) * mv_mul + l0_mv_array[j4][i4][1];
                vec2_y = (img->block_y * 2 + joff) * mv_mul + l1_mv_array[j4][i4][1];
              }
              else
              {
                vec1_y = ((img->block_y-4) * 2 + joff)* mv_mul + l0_mv_array[j4][i4][1];
                vec2_y = ((img->block_y-4) * 2 + joff)* mv_mul + l1_mv_array[j4][i4][1];
              }
            }
 
            get_block(l0_refframe, listX[0+list_offset], vec1_x, vec1_y, img, tmp_block);
            get_block(l1_refframe, listX[1+list_offset], vec2_x, vec2_y, img, tmp_blockbw);
          }
 
          if (mv_mode==0 && img->direct_spatial_mv_pred_flag && direct_pdir==0)
          {
            if (img->apply_weights)
            {
              if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))||
                (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field)
              {
                l0_ref_idx >>=1;
              }
 
              alpha_l0  = img->wp_weight[LIST_0][l0_ref_idx][0];
              wp_offset = img->wp_offset[LIST_0][l0_refframe>>curr_mb_field][0];
 
              for(jj=0;jj<BLOCK_SIZE;jj++)
                for(ii=0;ii<BLOCK_SIZE;ii++)
                  img->mpr[jj+joff][ii+ioff] = iClip1(img->max_imgpel_value, 
                  (rshift_rnd_sf((alpha_l0 * tmp_block[jj][ii]), img->luma_log2_weight_denom) + wp_offset));
            }
            else
            {
              for(jj=0;jj<BLOCK_SIZE;jj++)
                for(ii=0;ii<BLOCK_SIZE;ii++)
                  img->mpr[jj+joff][ii+ioff] = tmp_block[jj][ii];
            }
          }
          else if (mv_mode==0 && img->direct_spatial_mv_pred_flag && direct_pdir==1)
          {
            if (img->apply_weights)
            {
              if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))||
                (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field)
              {
                l1_ref_idx >>=1;
              }
              alpha_l1  = img->wp_weight[LIST_1][l1_ref_idx][0];
              wp_offset = img->wp_offset[LIST_1][l1_refframe>>curr_mb_field][0];
 
              for(jj=0;jj<BLOCK_SIZE;jj++)
                for(ii=0;ii<BLOCK_SIZE;ii++)
                  img->mpr[jj+joff][ii+ioff] = iClip1(img->max_imgpel_value, 
                  (rshift_rnd_sf((alpha_l1 * tmp_blockbw[jj][ii]), img->luma_log2_weight_denom) + wp_offset));
            }
            else
            {
              for(jj=0;jj<BLOCK_SIZE;jj++)
                for(ii=0;ii<BLOCK_SIZE;ii++)
                  img->mpr[jj+joff][ii+ioff] = tmp_blockbw[jj][ii];
            }
          }
          else if(img->apply_weights)
          {
            int wt_list_offset = (active_pps->weighted_bipred_idc==2)?list_offset:0;
 
            if (mv_mode==0 && img->direct_spatial_mv_pred_flag==0 )l1_ref_idx=0;    //temporal direct
 
            if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))||
              (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field)
            {
              l0_ref_idx >>=1;
              l1_ref_idx >>=1;
            }
 
            alpha_l0  =   img->wbp_weight[LIST_0 + wt_list_offset][l0_ref_idx][l1_ref_idx][0];
            alpha_l1  =   img->wbp_weight[LIST_1 + wt_list_offset][l0_ref_idx][l1_ref_idx][0];
            wp_offset = ((img->wp_offset [LIST_0 + wt_list_offset][l0_ref_idx][0] + img->wp_offset[LIST_1 + wt_list_offset][l1_ref_idx][0] + 1) >>1);
 
            for(ii=0;ii<BLOCK_SIZE;ii++)
              for(jj=0;jj<BLOCK_SIZE;jj++)
                img->mpr[jj+joff][ii+ioff] = (int)iClip1(img->max_imgpel_value, 
                (rshift_rnd_sf((alpha_l0 * tmp_block[jj][ii] + alpha_l1 * tmp_blockbw[jj][ii]), (img->luma_log2_weight_denom + 1)) + wp_offset));
          }
          else
          {
            for(jj=0;jj<BLOCK_SIZE;jj++)
              for(ii=0;ii<BLOCK_SIZE;ii++)
                img->mpr[jj+joff][ii+ioff] = (tmp_block[jj][ii]+tmp_blockbw[jj][ii]+1)>>1;
          }
        }
      }
 
      // =============== 4x4 itrans ================
      // -------------------------------------------
      if (smb && mv_mode!=IBLOCK)
      {
        if(!IS_NEWINTRA (currMB))// modif ES added
          itrans_sp(img,ioff,joff,i,j);
        else //modif ES added
          itrans(img,ioff,joff,i,j,0); // modif ES added
      }
      else
      {
        if(need_4x4_transform)
        {
          if(img->type==SP_SLICE && currMB->mb_type != I16MB) // ES added
            itrans_sp(img,ioff,joff,i,j);//ES added
          else
            itrans   (img,ioff,joff,i,j, 0);      // use DCT transform and make 4x4 block m7 from prediction block mpr
        }
      }
      if(need_4x4_transform)
      {
        int j_pos = j4 * BLOCK_SIZE;
        int i_pos = i4 * BLOCK_SIZE;
 
        for(jj=0;jj<BLOCK_SIZE;jj++)
        {
          for(ii=0;ii<BLOCK_SIZE;ii++)
          {
            dec_picture->imgY[j_pos + jj][i_pos + ii]=img->m7[jj][ii]; // construct picture from 4x4 blocks
          }
        }
      }// if(need_4x4_transform)
    }
 
    if(!need_4x4_transform)
    {
      // =============== 8x8 itrans ================
      // -------------------------------------------
      ioff = 8*(block8x8&0x01);
      joff = 8*(block8x8>>1);
 
      itrans8x8(img,ioff,joff);      // use DCT transform and make 8x8 block m7 from prediction block mpr
 
      for(jj=joff;jj<joff + 8;jj++)
      {
        for(ii=ioff;ii<ioff + 8;ii++)
        {
          dec_picture->imgY[img->pix_y + jj][img->pix_x + ii]=img->m7[jj][ii]; // construct picture from 4x4 blocks
        }
      }
    }
  }
 
  if (dec_picture->chroma_format_idc != YUV400)
  {
    // chroma decoding *******************************************************
    f1_x = 64/img->mb_cr_size_x;
    f2_x = f1_x-1;
 
    f1_y = 64/img->mb_cr_size_y;
    f2_y = f1_y-1;
 
    f3 = f1_x*f1_y;
    f4 = f3>>1;
 
    for(uv=0;uv<2;uv++)
    {
      uv_shift = uv*(img->num_blk8x8_uv>>1);
      intra_prediction = IS_INTRA (currMB);
 
      if (intra_prediction)
      {
        intrapred_chroma(img, uv);
      }
 
      for (b8=0;b8<(img->num_blk8x8_uv>>1);b8++)
      {
        for(b4=0;b4<4;b4++)
        {
          joff = subblk_offset_y[yuv][b8][b4];
          j4   = img->pix_c_y+joff;
          ioff = subblk_offset_x[yuv][b8][b4];
          i4   = img->pix_c_x+ioff;
 
          mv_mode  = currMB->b8mode[block8x8_idx[yuv][b8][b4]];
          pred_dir = currMB->b8pdir[block8x8_idx[yuv][b8][b4]];
          assert (pred_dir<=2);
 
 
          if (!intra_prediction)
          {
            if (pred_dir != 2)
            {
              int jpos;
              //--- FORWARD/BACKWARD PREDICTION ---
              mv_array = dec_picture->mv[LIST_0 + pred_dir];
              list = listX[0+list_offset+pred_dir];
 
              for(jj=0;jj<4;jj++)
              {
                jf=(j4+jj)/(img->mb_size_blk[1][1]);     // jf  = Subblock_y-coordinate
 
                if (!curr_mb_field)
                  jpos=(j4+jj)*f1_y;
                else
                {
                  if ((mb_nr&0x01) == 0)
                    jpos=(((img->pix_c_y)>>1)                   + jj + joff)*f1_y;
                  else
                    jpos=(((img->pix_c_y-img->mb_cr_size_y)>>1) + jj + joff)*f1_y;
                }
 
                for(ii=0;ii<4;ii++)
                {
                  ifx=(i4+ii)/(img->mb_size_blk[1][0]);  // ifx = Subblock_x-coordinate
                  l0_refframe = ref_idx = dec_picture->ref_idx[LIST_0+pred_dir][jf][ifx];
                  i1=(i4+ii)*f1_x+mv_array[jf][ifx][0];
 
                  j1 = jpos+mv_array[jf][ifx][1];
                  if (active_sps->chroma_format_idc == 1)
                    j1 += list[ref_idx]->chroma_vector_adjustment;
 
                  ii0 = iClip3 (0, img->width_cr_m1, i1/f1_x);
                  jj0 = iClip3 (0, max_y_cr, j1/f1_y);
                  ii1 = iClip3 (0, img->width_cr_m1, ((i1+f2_x)/f1_x));
                  jj1 = iClip3 (0, max_y_cr, ((j1+f2_y)/f1_y));
 
                  if1=(i1 & f2_x);
                  jf1=(j1 & f2_y);
                  if0=f1_x-if1;
                  jf0=f1_y-jf1;
 
                  if (img->apply_weights)
                  {
                    imgpel **curUV = list[ref_idx]->imgUV[uv];
                    pred = (if0*jf0*curUV[jj0][ii0] + if1*jf0*curUV[jj0][ii1]+
                      if0*jf1*curUV[jj1][ii0] + if1*jf1*curUV[jj1][ii1]+f4)/f3;
 
                    if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))||
                      (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field)
                    {
                      ref_idx >>=1;
                    }
 
                    img->mpr[jj+joff][ii+ioff] = iClip1(img->max_imgpel_value_uv, (((img->wp_weight[pred_dir][ref_idx][uv+1] * pred  + img->wp_round_chroma)>>img->chroma_log2_weight_denom) + img->wp_offset[pred_dir][ref_idx][uv+1]));
                  }
                  else
                  {
                    imgpel **curUV = list[ref_idx]->imgUV[uv];
                    img->mpr[jj+joff][ii+ioff]=(
                      if0*jf0*curUV[jj0][ii0] + if1*jf0*curUV[jj0][ii1]+
                      if0*jf1*curUV[jj1][ii0] + if1*jf1*curUV[jj1][ii1]+f4)/f3;
                  }
                }
              }
            }
            else
            {
              l0_mv_array = dec_picture->mv[LIST_0];
              l1_mv_array = dec_picture->mv[LIST_1];
 
              for(jj=0;jj<4;jj++)
              {
                int jpos;
                jf=(j4+jj)/(img->mb_size_blk[1][1]);     // jf  = Subblock_y-coordinate
 
                if (!curr_mb_field)
                {
                  jpos=(j4+jj)*f1_y;
                }
                else
                {
                  if ((mb_nr&0x01) == 0)
                    jpos=(((img->pix_c_y)>>1)                   + jj + joff)*f1_y;
                  else
                    jpos=(((img->pix_c_y-img->mb_cr_size_y)>>1) + jj + joff)*f1_y;
                }
 
                for(ii=0;ii<4;ii++)
                {
                  ifx=(i4+ii)/(img->mb_size_blk[1][0]);  // ifx = Subblock_x-coordinate
                  direct_pdir = 2;
 
                  if (mv_mode == 0 && img->direct_spatial_mv_pred_flag)
                  {
                    //===== DIRECT PREDICTION =====
                    if (dec_picture->ref_idx[LIST_0][2*(jf>>1)][(ifx>>1)*2]!=-1)
                    {
                      l0_refframe = dec_picture->ref_idx[LIST_0][2*(jf>>1)][(ifx>>1)*2];
                      l0_ref_idx = l0_refframe;
                    }
                    if (dec_picture->ref_idx[LIST_1][2*(jf>>1)][(ifx>>1)*2]!=-1)
                    {
                      l1_refframe = dec_picture->ref_idx[LIST_1][2*(jf>>1)][(ifx>>1)*2];
                      l1_ref_idx = l1_refframe;
                    }
 
                    if      (dec_picture->ref_idx[LIST_1][2*(jf>>1)][(ifx>>1)*2]==-1) direct_pdir = 0;
                    else if (dec_picture->ref_idx[LIST_0][2*(jf>>1)][(ifx>>1)*2]==-1) direct_pdir = 1;
 
                    if (direct_pdir == 0 || direct_pdir == 2)
                    {
                      i1=(i4+ii)*f1_x+l0_mv_array[jf][ifx][0];
 
                      j1=jpos+l0_mv_array[jf][ifx][1];
                      if (active_sps->chroma_format_idc == 1)
                        j1 += listX[0+list_offset][l0_refframe]->chroma_vector_adjustment;
 
                      ii0 = iClip3 (0, img->width_cr_m1, i1/f1_x);
                      jj0 = iClip3 (0, max_y_cr, j1/f1_y);
                      ii1 = iClip3 (0, img->width_cr_m1, ((i1+f2_x)/f1_x));
                      jj1 = iClip3 (0, max_y_cr, ((j1+f2_y)/f1_y));
 
 
                      if1=(i1 & f2_x);
                      jf1=(j1 & f2_y);
                      if0=f1_x-if1;
                      jf0=f1_y-jf1;
 
                      {
                        imgpel **curUV = listX[LIST_0 + list_offset][l0_refframe]->imgUV[uv];
                        fw_pred=(if0*jf0 * curUV[jj0][ii0]+
                          if1*jf0 * curUV[jj0][ii1]+
                          if0*jf1 * curUV[jj1][ii0]+
                          if1*jf1 * curUV[jj1][ii1]+f4)/f3;
                      }
                    }
                    if (direct_pdir == 1 || direct_pdir == 2)
                    {
                      i1=(i4+ii)*f1_x+l1_mv_array[jf][ifx][0];
 
                      j1=jpos+l1_mv_array[jf][ifx][1];
                      if (active_sps->chroma_format_idc == 1)
                        j1 += listX[1+list_offset][l1_refframe]->chroma_vector_adjustment;
 
                      ii0 = iClip3 (0, img->width_cr_m1, i1/f1_x);
                      jj0 = iClip3 (0, max_y_cr, j1/f1_y);
                      ii1 = iClip3 (0, img->width_cr_m1, ((i1+f2_x)/f1_x));
                      jj1 = iClip3 (0, max_y_cr, ((j1+f2_y)/f1_y));
 
                      if1=(i1 & f2_x);
                      jf1=(j1 & f2_y);
                      if0=f1_x-if1;
                      jf0=f1_y-jf1;
 
                      {
                        imgpel **curUV = listX[1+list_offset][l1_refframe]->imgUV[uv];
                        bw_pred=(if0*jf0*curUV[jj0][ii0] + if1*jf0*curUV[jj0][ii1]+
                          if0*jf1*curUV[jj1][ii0] + if1*jf1*curUV[jj1][ii1]+f4)/f3;
                      }
                    }
 
                  }
                  else
                  {
                    //===== BI-DIRECTIONAL PREDICTION =====
                    l0_refframe = dec_picture->ref_idx[LIST_0][jf][ifx];
                    l1_refframe = dec_picture->ref_idx[LIST_1][jf][ifx];
 
                    l0_ref_idx = l0_refframe;
                    l1_ref_idx = l1_refframe;
 
                    i1=(i4+ii)*f1_x+l0_mv_array[jf][ifx][0];
 
                    j1=jpos+l0_mv_array[jf][ifx][1];
                    if (active_sps->chroma_format_idc == 1)
                      j1 += listX[0+list_offset][l0_refframe]->chroma_vector_adjustment;
 
                    ii0 = iClip3 (0, img->width_cr_m1, i1/f1_x);
                    jj0 = iClip3 (0, max_y_cr, j1/f1_y);
                    ii1 = iClip3 (0, img->width_cr_m1, ((i1+f2_x)/f1_x));
                    jj1 = iClip3 (0, max_y_cr, ((j1+f2_y)/f1_y));
 
                    if1=(i1 & f2_x);
                    jf1=(j1 & f2_y);
                    if0=f1_x-if1;
                    jf0=f1_y-jf1;
                    {
                      imgpel **curUV = listX[0+list_offset][l0_refframe]->imgUV[uv];
 
                      fw_pred=(if0*jf0*curUV[jj0][ii0]+
                        if1*jf0*curUV[jj0][ii1]+
                        if0*jf1*curUV[jj1][ii0]+
                        if1*jf1*curUV[jj1][ii1]+f4)/f3;
                    }
                    i1=(i4+ii)*f1_x+l1_mv_array[jf][ifx][0];
 
                    j1=jpos+l1_mv_array[jf][ifx][1];
                    if (active_sps->chroma_format_idc == 1)
                      j1 += listX[1+list_offset][l1_refframe]->chroma_vector_adjustment;
 
                    ii0 = iClip3 (0, img->width_cr_m1, i1/f1_x);
                    jj0 = iClip3 (0, max_y_cr, j1/f1_y);
                    ii1 = iClip3 (0, img->width_cr_m1, ((i1+f2_x)/f1_x));
                    jj1 = iClip3 (0, max_y_cr, ((j1+f2_y)/f1_y));
 
 
                    if1=(i1 & f2_x);
                    jf1=(j1 & f2_y);
                    if0=f1_x-if1;
                    jf0=f1_y-jf1;
 
                    {
                      imgpel **curUV = listX[1+list_offset][l1_refframe]->imgUV[uv];
                      bw_pred=(if0*jf0*curUV[jj0][ii0]+ if1*jf0*curUV[jj0][ii1]+
                        if0*jf1*curUV[jj1][ii0]+if1*jf1*curUV[jj1][ii1]+f4)/f3;
                    }
 
                  }
 
                  if (img->apply_weights)
                  {
                    if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))||
                      (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field)
                    {
                      l0_ref_idx >>=1;
                      l1_ref_idx >>=1;
                    }
 
                    if (img->direct_spatial_mv_pred_flag && direct_pdir==1)
                    {
                      img->mpr[jj+joff][ii+ioff]= iClip1(img->max_imgpel_value_uv, 
                        (((img->wp_weight[1][l1_ref_idx][uv+1] * bw_pred  + img->wp_round_chroma)>>img->chroma_log2_weight_denom) + img->wp_offset[1][l1_refframe>>curr_mb_field][uv+1]));   // Replaced with integer only operations
                    }
                    else if (img->direct_spatial_mv_pred_flag && direct_pdir==0)
                    {
                      img->mpr[jj+joff][ii+ioff]=iClip1(img->max_imgpel_value_uv, (((img->wp_weight[0][l0_ref_idx][uv+1] * fw_pred + img->wp_round_chroma)>>img->chroma_log2_weight_denom) + img->wp_offset[0][l0_refframe>>curr_mb_field][uv+1]));   // Replaced with integer only operations
                    }
                    else
                    {
                      int wt_list_offset = (active_pps->weighted_bipred_idc==2)?list_offset:0;
 
                      alpha_l0 = img->wbp_weight[0+wt_list_offset][l0_ref_idx][l1_ref_idx][uv+1];
                      alpha_l1 = img->wbp_weight[1+wt_list_offset][l0_ref_idx][l1_ref_idx][uv+1];
 
                      img->mpr[jj+joff][ii+ioff]= iClip1(img->max_imgpel_value_uv, (((alpha_l0 * fw_pred + alpha_l1 * bw_pred  + (1<<img->chroma_log2_weight_denom)) >> (img->chroma_log2_weight_denom + 1))+ ((img->wp_offset[wt_list_offset + 0][l0_ref_idx][uv+1] + img->wp_offset[wt_list_offset + 1][l1_ref_idx][uv+1] + 1)>>1)));
                    }
                  }
                  else
                  {
                    if (img->direct_spatial_mv_pred_flag && direct_pdir==1)
                    {
                      img->mpr[jj+joff][ii+ioff]=bw_pred;
                    }
                    else if (img->direct_spatial_mv_pred_flag && direct_pdir==0)
                    {
                      img->mpr[jj+joff][ii+ioff]=fw_pred;
                    }
                    else
                    {
                      img->mpr[jj+joff][ii+ioff]=(fw_pred + bw_pred + 1 )>>1;
                    }
                  }
                }
              }
            }
          } //if (!intra_prediction)
 
          if (!smb)
          {
            imgpel **curUV = dec_picture->imgUV[uv];
            itrans(img,ioff,joff, cofuv_blk_x[yuv][b8+uv_shift][b4], cofuv_blk_y[yuv][b8+uv_shift][b4], 1);
 
            for(jj=0;jj<4;jj++)
              for(ii=0;ii<4;ii++)
              {
                curUV[j4+jj][i4+ii]=img->m7[jj][ii];
              }
          }
        }
      }
 
      if(smb)
      {
        imgpel **curUV = dec_picture->imgUV[uv];
        itrans_sp_chroma(img,2*uv);
 
        for (j=4;j<6;j++)
        {
          joff=(j-4)*4;
          j4=img->pix_c_y+joff;
          for(i=0;i<2;i++)
          {
            ioff=i*4;
            i4=img->pix_c_x+ioff;
            itrans(img,ioff,joff,2*uv+i,j, 1);
 
            for(jj=0;jj<4;jj++)
              for(ii=0;ii<4;ii++)
              {
                curUV[j4+jj][i4+ii]=img->m7[jj][ii];
              }
          }
        }
      }
    }
  }
 
  return 0;
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.