blob: ab1e5ec788a026a6868f8138ec7791d890e5bdf5 [file] [log] [blame]
/*!
***********************************************************************
* \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],
signed char ref_frame,
byte list,
signed 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],
signed char ref_frame,
byte list,
signed 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;
signed 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;
signed 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;
signed 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;
signed 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;
signed 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;
signed 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]))))
{
signed char l0_rFrameL, l0_rFrameU, l0_rFrameUL, l0_rFrameUR;
signed 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;
}