View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0000148 | JVT JM H.264/AVC reference software | decoder | public | 2008-12-02 15:37 | 2008-12-15 15:09 |
| Reporter | Eugeniy Belyaev | Assigned To | Karsten Suehring | ||
| Priority | normal | Severity | crash | Reproducibility | always |
| Status | resolved | Resolution | fixed | ||
| Product Version | JM 14.2 | ||||
| Fixed in Version | JM 15.0 | ||||
| Summary | 0000148: Incorrect calculation of lossless_qpprime flag at the decoder. | ||||
| Description | According to the standard, bypass mode shall be invoked when lossless_qpprime_y_zero_flag = 1 and QP'Y = 0. But in decoder sources lossless_qpprime flag is calculated before decoding of currMB->delta_quant value. That's why bypass mode can be invoded for macroblocks with QP'Y != 0, and can be not invoked for macroblocks with QP'Y == 0. See corrected version of macroblock.c in attachment. | ||||
| Tags | No tags attached. | ||||
|
2008-12-02 15:37
|
macroblock.c (177,458 bytes)
/*!
***********************************************************************
* \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
* - Ye-Kui Wang <wyk@ieee.org>
* - Lowell Winger <lwinger@lsil.com>
* - Alexis Michael Tourapis <alexismt@ieee.org>
***********************************************************************
*/
#include "contributors.h"
#include <math.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 "block.h"
#include "transform8x8.h"
#include "transform.h"
#include "mc_prediction.h"
#include "quant.h"
#if TRACE
#define TRACE_STRING(s) strncpy(currSE.tracestring, s, TRACESTRING_SIZE)
#define TRACE_DECBITS(i) dectracebitcnt(1)
#define TRACE_PRINTF(s) sprintf(type, "%s", s);
#define TRACE_STRING_P(s) strncpy(currSE->tracestring, s, TRACESTRING_SIZE)
#else
#define TRACE_STRING(s)
#define TRACE_DECBITS(i)
#define TRACE_PRINTF(s)
#define TRACE_STRING_P(s)
#endif
//! single scan pattern
static const byte SNGL_SCAN[16][2] =
{
{0,0},{1,0},{0,1},{0,2},
{1,1},{2,0},{3,0},{2,1},
{1,2},{0,3},{1,3},{2,2},
{3,1},{3,2},{2,3},{3,3}
};
//! field scan pattern
static const byte FIELD_SCAN[16][2] =
{
{0,0},{0,1},{1,0},{0,2},
{0,3},{1,1},{1,2},{1,3},
{2,0},{2,1},{2,2},{2,3},
{3,0},{3,1},{3,2},{3,3}
};
//! used to control block sizes : Not used/16x16/16x8/8x16/8x8/8x4/4x8/4x4
static const int BLOCK_STEP[8][2]=
{
{0,0},{4,4},{4,2},{2,4},{2,2},{2,1},{1,2},{1,1}
};
const byte QP_SCALE_CR[52]=
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,
12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
28,29,29,30,31,32,32,33,34,34,35,35,36,36,37,37,
37,38,38,38,39,39,39,39
};
//! single scan pattern
const byte SNGL_SCAN8x8[64][2] = {
{0,0}, {1,0}, {0,1}, {0,2}, {1,1}, {2,0}, {3,0}, {2,1}, {1,2}, {0,3}, {0,4}, {1,3}, {2,2}, {3,1}, {4,0}, {5,0},
{4,1}, {3,2}, {2,3}, {1,4}, {0,5}, {0,6}, {1,5}, {2,4}, {3,3}, {4,2}, {5,1}, {6,0}, {7,0}, {6,1}, {5,2}, {4,3},
{3,4}, {2,5}, {1,6}, {0,7}, {1,7}, {2,6}, {3,5}, {4,4}, {5,3}, {6,2}, {7,1}, {7,2}, {6,3}, {5,4}, {4,5}, {3,6},
{2,7}, {3,7}, {4,6}, {5,5}, {6,4}, {7,3}, {7,4}, {6,5}, {5,6}, {4,7}, {5,7}, {6,6}, {7,5}, {7,6}, {6,7}, {7,7}
};
//! field scan pattern
const byte FIELD_SCAN8x8[64][2] = { // 8x8
{0,0}, {0,1}, {0,2}, {1,0}, {1,1}, {0,3}, {0,4}, {1,2}, {2,0}, {1,3}, {0,5}, {0,6}, {0,7}, {1,4}, {2,1}, {3,0},
{2,2}, {1,5}, {1,6}, {1,7}, {2,3}, {3,1}, {4,0}, {3,2}, {2,4}, {2,5}, {2,6}, {2,7}, {3,3}, {4,1}, {5,0}, {4,2},
{3,4}, {3,5}, {3,6}, {3,7}, {4,3}, {5,1}, {6,0}, {5,2}, {4,4}, {4,5}, {4,6}, {4,7}, {5,3}, {6,1}, {6,2}, {5,4},
{5,5}, {5,6}, {5,7}, {6,3}, {7,0}, {7,1}, {6,4}, {6,5}, {6,6}, {6,7}, {7,2}, {7,3}, {7,4}, {7,5}, {7,6}, {7,7}
};
//! single scan pattern
const byte SCAN_YUV422[8][2] =
{
{0,0},{0,1},
{1,0},{0,2},
{0,3},{1,1},
{1,2},{1,3}
};
static unsigned char cbp_blk_chroma[8][4] =
{ {16, 17, 18, 19},
{20, 21, 22, 23},
{24, 25, 26, 27},
{28, 29, 30, 31},
{32, 33, 34, 35},
{36, 37, 38, 39},
{40, 41, 42, 43},
{44, 45, 46, 47} };
//! look up tables for FRExt_chroma support
const unsigned char subblk_offset_x[3][8][4] =
{
{ {0, 4, 0, 4},
{0, 4, 0, 4},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}, },
{ {0, 4, 0, 4},
{0, 4, 0, 4},
{0, 4, 0, 4},
{0, 4, 0, 4},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}, },
{ {0, 4, 0, 4},
{8,12, 8,12},
{0, 4, 0, 4},
{8,12, 8,12},
{0, 4, 0, 4},
{8,12, 8,12},
{0, 4, 0, 4},
{8,12, 8,12} }
};
const unsigned char subblk_offset_y[3][8][4] =
{ { {0, 0, 4, 4},
{0, 0, 4, 4},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}, },
{ {0, 0, 4, 4},
{8, 8,12,12},
{0, 0, 4, 4},
{8, 8,12,12},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0} },
{ {0, 0, 4, 4},
{0, 0, 4, 4},
{8, 8,12,12},
{8, 8,12,12},
{0, 0, 4, 4},
{0, 0, 4, 4},
{8, 8,12,12},
{8, 8,12,12} }
};
const unsigned char cofuv_blk_x[3][8][4] =
{ { {0, 1, 0, 1},
{0, 1, 0, 1},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0} },
{ {0, 1, 0, 1},
{0, 1, 0, 1},
{0, 1, 0, 1},
{0, 1, 0, 1},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0} },
{ {0, 1, 0, 1},
{2, 3, 2, 3},
{0, 1, 0, 1},
{2, 3, 2, 3},
{0, 1, 0, 1},
{2, 3, 2, 3},
{0, 1, 0, 1},
{2, 3, 2, 3} }
};
static const unsigned char cofuv_blk_y[3][8][4] =
{
{ { 0, 0, 1, 1},
{ 0, 0, 1, 1},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0} },
{ { 0, 0, 1, 1},
{ 2, 2, 3, 3},
{ 0, 0, 1, 1},
{ 2, 2, 3, 3},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0} },
{ { 0, 0, 1, 1},
{ 0, 0, 1, 1},
{ 2, 2, 3, 3},
{ 2, 2, 3, 3},
{ 0, 0, 1, 1},
{ 0, 0, 1, 1},
{ 2, 2, 3, 3},
{ 2, 2, 3, 3}}
};
void dectracebitcnt(int count);
extern int last_dquant;
extern ColocatedParams *Co_located;
extern ColocatedParams *Co_located_JV[MAX_PLANE]; //!< Co_located to be used during 4:4:4 independent mode decoding
static void readMotionInfoFromNAL (ImageParameters *img, Macroblock *currMB);
static void read_ipred_modes (ImageParameters *img, Macroblock *currMB);
static void readCBPandCoeffsFromNAL(ImageParameters *img, Macroblock *currMB);
static void readIPCMcoeffsFromNAL (ImageParameters *img, struct datapartition *dP);
// Interpret MB mode
static void (*interpret_mb_mode)(Macroblock *currMB);
/*!
************************************************************************
* \brief
* Set context for reference frames
************************************************************************
*/
int BType2CtxRef (int btype)
{
return (btype >= 4);
}
/*!
************************************************************************
* \brief
* Function pointer for reading the reference picture indices
************************************************************************
*/
static char (*readRefPictureIdx) (SyntaxElement *currSE, DataPartition *dP, char b8mode, int list);
/*!
************************************************************************
* \brief
* Function for reading the reference picture indices using VLC
************************************************************************
*/
static char readRefPictureIdx_VLC(SyntaxElement *currSE, DataPartition *dP, char b8mode, int list)
{
#if TRACE
static char tstring[20];
sprintf( tstring, "ref_idx_l%d", list);
strncpy(currSE->tracestring, tstring, TRACESTRING_SIZE);
#endif
currSE->context = BType2CtxRef (b8mode);
currSE->value2 = list;
dP->readSyntaxElement (currSE,img,dP);
return (char) currSE->value1;
}
/*!
************************************************************************
* \brief
* Function for reading the reference picture indices using FLC
************************************************************************
*/
static char readRefPictureIdx_FLC(SyntaxElement *currSE, DataPartition *dP, char b8mode, int list)
{
#if TRACE
static char tstring[20];
sprintf( tstring, "ref_idx_l%d", list);
strncpy(currSE->tracestring, tstring, TRACESTRING_SIZE);
#endif
currSE->context = BType2CtxRef (b8mode);
currSE->len = 1;
readSyntaxElement_FLC(currSE, dP->bitstream);
currSE->value1 = 1 - currSE->value1;
return (char) currSE->value1;
}
/*!
************************************************************************
* \brief
* Dummy Function for reading the reference picture indices
************************************************************************
*/
static char readRefPictureIdx_Null(SyntaxElement *currSE, DataPartition *dP, char b8mode, int list)
{
return 0;
}
/*!
************************************************************************
* \brief
* Function to prepare reference picture indice function pointer
************************************************************************
*/
static inline void prepareListforRefIdx ( SyntaxElement *currSE, DataPartition *dP, int num_ref_idx_active, int refidx_present)
{
readRefPictureIdx = readRefPictureIdx_Null; // Initialize readRefPictureIdx
if(num_ref_idx_active > 1)
{
if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
{
currSE->mapping = linfo_ue;
if (refidx_present)
{
if (num_ref_idx_active == 2)
readRefPictureIdx = readRefPictureIdx_FLC;
else
readRefPictureIdx = readRefPictureIdx_VLC;
}
}
else
{
currSE->reading = readRefFrame_CABAC;
if (refidx_present)
readRefPictureIdx = readRefPictureIdx_VLC;
}
}
}
void set_chroma_qp(ImageParameters *img, 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]];
currMB->qp_scaled[i + 1] = currMB->qpc[i] + img->bitdepth_chroma_qp_scale;
}
}
/*!
************************************************************************
* \brief
* updates chroma QP according to luma QP and bit depth
************************************************************************
*/
void update_qp(ImageParameters *img, Macroblock *currMB, int qp)
{
currMB->qp = qp;
currMB->qp_scaled[0] = qp + img->bitdepth_luma_qp_scale;
set_chroma_qp(img, currMB);
}
static void read_delta_quant(SyntaxElement *currSE, DataPartition *dP, Slice *currSlice, ImageParameters *img, Macroblock *currMB, int *partMap, int type)
{
currSE->type = type;
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;
TRACE_STRING_P("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;
update_qp(img, currMB, img->qp);
}
/*!
************************************************************************
* \brief
* Function to read reference picture indice values
************************************************************************
*/
static inline void readMBRefPictureIdx (SyntaxElement *currSE, DataPartition *dP, Macroblock *currMB, ImageParameters *img, char **cur_ref_idx, int list, int step_v0, int step_h0)
{
static int k, j, j0, i0;
static char refframe;
for (j0 = 0; j0 < 4; j0 += step_v0)
{
img->subblock_y = j0;
for (i0 = 0; i0 < 4; i0 += step_h0)
{
img->subblock_x = i0;
k = 2 * (j0 >> 1) + (i0 >> 1);
if ((currMB->b8pdir[k] == list || currMB->b8pdir[k] == BI_PRED) && currMB->b8mode[k] != 0)
{
refframe = readRefPictureIdx(currSE, dP, currMB->b8mode[k], list);
for (j = j0; j < j0 + step_v0; j++)
memset(&cur_ref_idx[j][img->block_x + i0], refframe, step_h0 * sizeof(char));
}
}
}
}
/*!
************************************************************************
* \brief
* Function to read reference picture indice values
************************************************************************
*/
static inline void readMBMotionVectors (SyntaxElement *currSE, DataPartition *dP, Macroblock *currMB, ImageParameters *img, int list, int step_h0, int step_v0)
{
static int i, j, k, i4, j4, ii, jj, kk, i0, j0;
static short curr_mvd[2], curr_mv[2], pred_mv[2];
static short (*mvd)[4][2];
static short ***mv;
static int mv_mode, step_h, step_v;
static char cur_ref_idx;
for (j0=0; j0<4; j0+=step_v0)
{
for (i0=0; i0<4; i0+=step_h0)
{
kk = 2 * (j0 >> 1) + (i0 >> 1);
if ((currMB->b8pdir[kk]== list || currMB->b8pdir[kk]== BI_PRED) && (currMB->b8mode[kk] !=0))//has forward vector
{
cur_ref_idx = dec_picture->motion.ref_idx[list][img->block_y+j0][img->block_x+i0];
mv_mode = currMB->b8mode[kk];
step_h = BLOCK_STEP [mv_mode][0];
step_v = BLOCK_STEP [mv_mode][1];
for (j = j0; j < j0 + step_v0; j += step_v)
{
img->subblock_y = j; // position used for context determination
j4 = img->block_y + j;
mv = &dec_picture->motion.mv [list][j4];
mvd = &currMB->mvd [list][j];
for (i = i0; i < i0 + step_h0; i += step_h)
{
img->subblock_x = i; // position used for context determination
i4 = img->block_x + i;
// first make mv-prediction
SetMotionVectorPredictor (img, currMB, pred_mv, cur_ref_idx, (byte) list, dec_picture->motion.ref_idx, dec_picture->motion.mv, BLOCK_SIZE * i, BLOCK_SIZE * j, 4*step_h, 4*step_v);
for (k=0; k < 2; k++)
{
#if TRACE
static char tstring[20];
sprintf( tstring, "mvd_l%d", list);
strncpy(currSE->tracestring, tstring, TRACESTRING_SIZE);
#endif
currSE->value2 = (k << 1) + list; // identifies the component; only used for context determination
dP->readSyntaxElement(currSE,img,dP);
curr_mvd[k] = (short) currSE->value1;
curr_mv [k] = (short)(curr_mvd[k] + pred_mv[k]); // compute motion vector
}
// Init first line (mv)
for(ii = i4; ii < i4 + step_h; ii++)
{
memcpy(&mv[0][ii][0], curr_mv, 2 * sizeof(short));
}
// now copy all other lines
for(jj = 1; jj < step_v; jj++)
{
memcpy(&mv[jj][i4][0], &mv[0][i4][0], 2 * step_h * sizeof(short));
}
// Init first line (mvd)
for(ii = i; ii < i + step_h; ii++)
{
memcpy(&mvd[0][ii][0], curr_mvd, 2 * sizeof(short));
}
// now copy all other lines
for(jj = 1; jj < step_v; jj++)
{
memcpy(&mvd[jj][i][0], &mvd[0][i][0], 2 * step_h * sizeof(short));
}
}
}
}
}
}
}
void invScaleCoeff(ImageParameters *img, Macroblock *currMB, int level, int run, int qp_per, int i, int j, int i0, int j0, int coef_ctr, const byte (*pos_scan4x4)[2], int (*InvLevelScale4x4)[4])
{
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[0][(j<<2) + j0][(i<<2) + i0]= rshift_rnd_sf((level * InvLevelScale4x4[j0][i0]) << qp_per, 4);
}
}
/*!
************************************************************************
* \brief
* initializes the current macroblock
************************************************************************
*/
void start_macroblock(ImageParameters *img, Macroblock **currMB)
{
int mb_nr = img->current_mb_nr;
*currMB = &img->mb_data[mb_nr]; // intialization code deleted, see below, StW
(*currMB)->mbAddrX = mb_nr;
assert (mb_nr < (int) img->PicSizeInMbs);
/* Update coordinates of the current macroblock */
if (img->MbaffFrameFlag)
{
img->mb_x = (mb_nr) % ((2*img->width) / MB_BLOCK_SIZE);
img->mb_y = 2*((mb_nr) / ((2*img->width) / MB_BLOCK_SIZE));
img->mb_y += (img->mb_x & 0x01);
img->mb_x >>= 1;
}
else
{
img->mb_x = PicPos[mb_nr][0];
img->mb_y = PicPos[mb_nr][1];
}
/* Define vertical positions */
img->block_y = img->mb_y * BLOCK_SIZE; /* luma block position */
img->block_y_aff = img->block_y;
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. \nPlease recompile with increased value for MAX_NUM_SLICES", 200);
}
dec_picture->slice_id[img->mb_y][img->mb_x] = (short) img->current_slice_nr;
dec_picture->max_slice_id = (short) imax(img->current_slice_nr, dec_picture->max_slice_id);
CheckAvailabilityOfNeighbors(*currMB);
// 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)->cbp_blk_CbCr[0] = 0;
(*currMB)->cbp_blk_CbCr[1] = 0;
(*currMB)->c_ipred_mode = DC_PRED_8; //GB
memset(&((*currMB)->mvd[0][0][0][0]),0, 2 * BLOCK_MULTIPLE * BLOCK_MULTIPLE * 2 * sizeof(short));
memset((*currMB)->cbp_bits, 0, 3 * sizeof(int64));
memset((*currMB)->cbp_bits_8x8, 0, 3 * sizeof(int64));
// initialize img->mb_rres
memset(&(img->mb_rres[0][0][0]), 0, 3 * MB_PIXELS * sizeof(int));
// store filtering parameters for this MB
(*currMB)->DFDisableIdc = img->currentSlice->DFDisableIdc;
(*currMB)->DFAlphaC0Offset = img->currentSlice->DFAlphaC0Offset;
(*currMB)->DFBetaOffset = img->currentSlice->DFBetaOffset;
}
/*!
************************************************************************
* \brief
* set coordinates of the next macroblock
* check end_of_slice condition
************************************************************************
*/
Boolean exit_macroblock(ImageParameters *img,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)
{
return TRUE;
}
// ask for last mb in the slice UVLC
else
{
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->currentSlice, eos_bit) == TRUE);
return TRUE;
}
if(nal_startcode_follows(img->currentSlice, 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
************************************************************************
*/
static void interpret_mb_mode_P(Macroblock *currMB)
{
const int ICBPTAB[6] = {0,16,32,15,31,47};
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
************************************************************************
*/
static void interpret_mb_mode_I(Macroblock *currMB)
{
static const int ICBPTAB[6] = {0,16,32,15,31,47};
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
************************************************************************
*/
static void interpret_mb_mode_B(Macroblock *currMB)
{
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};
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] = (char) offset2pdir16x8 [mbtype][i>>1];
}
}
else
{
mbmode=3;
memset(&currMB->b8mode[0], 3,4 * sizeof(char));
for(i=0;i<4;i++)
{
currMB->b8pdir[i] = (char) offset2pdir8x16 [mbtype][i&0x01];
}
}
currMB->mb_type = mbmode;
}
/*!
************************************************************************
* \brief
* Interpret the mb mode for SI-Frames
************************************************************************
*/
static void interpret_mb_mode_SI(Macroblock *currMB)
{
const int ICBPTAB[6] = {0,16,32,15,31,47};
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
* Set mode interpretation based on slice type
************************************************************************
*/
void set_interpret_mb_mode(int slice_type)
{
switch (slice_type)
{
case P_SLICE: case SP_SLICE:
interpret_mb_mode = interpret_mb_mode_P;
break;
case B_SLICE:
interpret_mb_mode = interpret_mb_mode_B;
break;
case I_SLICE:
interpret_mb_mode = interpret_mb_mode_I;
break;
case SI_SLICE:
interpret_mb_mode = interpret_mb_mode_SI;
break;
default:
printf("Unsupported slice type\n");
break;
}
}
/*!
************************************************************************
* \brief
* init macroblock I and P frames
************************************************************************
*/
static void init_macroblock(ImageParameters *img)
{
int i, j, k;
for (k = LIST_0; k <= LIST_1; k++)
{
for(j = img->block_y; j < img->block_y + BLOCK_SIZE; j++)
memset(&img->ipredmode[j][img->block_x], DC_PRED, BLOCK_SIZE * sizeof(char));
for(j = img->block_y; j < img->block_y + BLOCK_SIZE; j++)
{ // reset vectors and pred. modes
memset(&dec_picture->motion.mv[k][j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short));
memset(&dec_picture->motion.ref_idx[k][j][img->block_x], -1, BLOCK_SIZE * sizeof(char));
for (i = img->block_x; i < img->block_x + BLOCK_SIZE;i++)
{
dec_picture->motion.ref_pic_id[k][j][i] = INT64_MIN;
}
}
}
}
/*!
************************************************************************
* \brief
* Sets mode for 8x8 block
************************************************************************
*/
void SetB8Mode (ImageParameters* 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] = (char) b_v2b8[value];
currMB->b8pdir[i] = (char) b_v2pd[value];
}
else
{
currMB->b8mode[i] = (char) p_v2b8[value];
currMB->b8pdir[i] = (char) p_v2pd[value];
}
}
void reset_coeffs(void)
{
// reset all coeffs
memset(&img->fcf[0][0][0], 0, 3 * MB_PIXELS * sizeof(int));
memset(&img->cof[0][0][0], 0, 3 * MB_PIXELS * sizeof(int));
// CAVLC
if (active_pps->entropy_coding_mode_flag == UVLC)
memset(&img->nz_coeff[img->current_mb_nr][0][0][0], 0, 3 * BLOCK_SIZE * BLOCK_SIZE * sizeof(int));
}
void field_flag_inference(Macroblock *currMB)
{
if (currMB->mbAvailA)
{
currMB->mb_field = img->mb_data[currMB->mbAddrA].mb_field;
}
else
{
// check top macroblock pair
currMB->mb_field = currMB->mbAvailB ? img->mb_data[currMB->mbAddrB].mb_field : 0;
}
}
void copy_macroblock(ImageParameters *img, Macroblock *currMB)
{
short pred_mv[2];
int zeroMotionAbove;
int zeroMotionLeft;
PixelPos mb_a, mb_b;
int i, j;
int a_mv_y = 0;
int a_ref_idx = 0;
int b_mv_y = 0;
int b_ref_idx = 0;
int img_block_y = img->block_y;
int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr & 0x01) ? 4 : 2 : 0;
short ***cur_mv = dec_picture->motion.mv[LIST_0];
get4x4Neighbour(currMB,-1, 0, img->mb_size[IS_LUMA], &mb_a);
get4x4Neighbour(currMB, 0,-1, img->mb_size[IS_LUMA], &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->motion.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->motion.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();
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, currMB, pred_mv, 0, LIST_0, dec_picture->motion.ref_idx, dec_picture->motion.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++)
memcpy(&cur_mv[j][i][0], &pred_mv[0], 2 * sizeof(short));
}
}
for(j=img_block_y;j< img_block_y + BLOCK_SIZE;j++)
{
memset(&dec_picture->motion.ref_idx[LIST_0][j][img->block_x], 0, BLOCK_SIZE * sizeof(char));
for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++)
{
dec_picture->motion.ref_pic_id[LIST_0][j][i] =
dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->motion.ref_idx[LIST_0][j][i]];
}
}
}
/*!
************************************************************************
* \brief
* Get the syntax elements from the NAL
************************************************************************
*/
void read_one_macroblock(ImageParameters *img, Macroblock *currMB)
{
int i;
SyntaxElement currSE;
int mb_nr = img->current_mb_nr;
Slice *currSlice = img->currentSlice;
DataPartition *dP;
int *partMap = assignSE2partition[currSlice->dp_mode];
Macroblock *topMB = NULL;
int prevMbSkipped = 0;
int check_bottom, read_bottom, read_top;
if (img->MbaffFrameFlag)
{
if (mb_nr&0x01)
{
topMB= &img->mb_data[mb_nr-1];
if(!(img->type == B_SLICE))
prevMbSkipped = (topMB->mb_type == 0);
else
prevMbSkipped = topMB->skip_flag;
}
else
prevMbSkipped = 0;
}
currMB->mb_field = ((mb_nr&0x01) == 0)? 0 : img->mb_data[mb_nr-1].mb_field;
update_qp(img, currMB, img->qp);
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 && (mb_nr&0x01)==0)
{
TRACE_STRING("mb_field_decoding_flag");
if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
{
currSE.len = (int64) 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(currMB);
// 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 && ((mb_nr&0x01) == 0||prevMbSkipped))
field_flag_inference(currMB);
CheckAvailabilityOfNeighborsCABAC(currMB);
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 ((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(currMB);
// 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) && (((mb_nr&0x01)==0) || ((mb_nr&0x01) && prevMbSkipped)))
{
TRACE_STRING("mb_field_decoding_flag");
currSE.len = (int64) 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 && ((mb_nr&0x01) == 0))
{
TRACE_STRING("mb_field_decoding_flag (of coded bottom mb)");
currSE.len = (int64) 1;
readSyntaxElement_FLC(&currSE, dP->bitstream);
dP->bitstream->frame_bitoffset--;
TRACE_DECBITS(1);
currMB->mb_field = currSE.value1;
}
else if(img->cod_counter > 0 && ((mb_nr&0x01) == 0))
{
// check left macroblock pair first
if (mb_is_available(mb_nr-2, currMB)&&((mb_nr%(img->PicWidthInMbs*2))!=0))
{
currMB->mb_field = img->mb_data[mb_nr-2].mb_field;
}
else
{
// check top macroblock pair
if (mb_is_available(mb_nr - 2*img->PicWidthInMbs, currMB))
{
currMB->mb_field = img->mb_data[mb_nr-2*img->PicWidthInMbs].mb_field;
}
else
currMB->mb_field = 0;
}
}
}
}
}
dec_picture->motion.mb_field[mb_nr] = (byte) currMB->mb_field;
img->block_y_aff = ((img->MbaffFrameFlag) && (currMB->mb_field)) ? (mb_nr&0x01) ? (img->block_y - 4)>>1 : img->block_y >> 1 : img->block_y;
img->siblock[img->mb_y][img->mb_x]=0;
interpret_mb_mode(currMB);
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]]);
if (active_pps->entropy_coding_mode_flag ==UVLC || dP->bitstream->ei_flag)
currSE.mapping = linfo_ue;
else
currSE.reading = readB8_typeInfo_CABAC;
for (i=0; i<4; i++)
{
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, currMB);
}
//============= 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 = (int64) 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[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.
/*
!!!KS
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;
}
else if (IS_COPY (currMB)) //keep last macroblock
{
copy_macroblock(img, currMB);
}
else if(currMB->mb_type != IPCM)
{
// intra prediction modes for a macroblock 4x4 **********************************************
if (IS_INTRA(currMB))
read_ipred_modes(img, currMB);
// read inter frame vector data *********************************************************
if (IS_INTERMV (currMB) && (!IS_P8x8(currMB)))
{
readMotionInfoFromNAL (img, currMB);
}
// read CBP and Coeffs ***************************************************************
readCBPandCoeffsFromNAL (img, currMB);
}
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
if ( currSlice->dp_mode && currSlice->dpB_NotPresent )
{
concealIPCMcoeffs(img);
}
else
{
dP = &(currSlice->partArr[partMap[SE_LUM_DC_INTRA]]);
readIPCMcoeffsFromNAL(img, dP);
}
}
return;
}
/*!
************************************************************************
* \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(ImageParameters *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);
}
}
/*!
************************************************************************
* \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>
************************************************************************
*/
static void readIPCMcoeffsFromNAL(ImageParameters *img, 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)
{
readIPCM_CABAC(dP);
init_decoding_engine_IPCM(img);
}
else
{
//read bits to let stream byte aligned
if(((dP->bitstream->frame_bitoffset) & 0x07) != 0)
{
TRACE_STRING("pcm_alignment_zero_bit");
currSE.len = (8 - ((dP->bitstream->frame_bitoffset) & 0x07));
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[0][i][j] = currSE.value1;
img->fcf[0][i][j] = currSE.value1;
}
}
currSE.len=img->bitdepth_chroma;
if ((dec_picture->chroma_format_idc != YUV400) && !IS_INDEPENDENT(img))
{
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[1][i][j] = currSE.value1;
img->fcf[1][i][j] = 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[2][i][j] = currSE.value1;
img->fcf[2][i][j] = currSE.value1;
}
}
}
}
}
/*!
************************************************************************
* \brief
* If data partition B is lost, conceal PCM sample values with DC.
*
************************************************************************
*/
void concealIPCMcoeffs(ImageParameters *img)
{
int i, j, k;
for(i=0;i<MB_BLOCK_SIZE;i++)
{
for(j=0;j<MB_BLOCK_SIZE;j++)
{
img->cof[0][i][j] = img->dc_pred_value_comp[0];
img->fcf[0][i][j] = img->dc_pred_value_comp[0];
}
}
if ((dec_picture->chroma_format_idc != YUV400) && !IS_INDEPENDENT(img))
{
for (k = 0; k < 2; k++)
{
for(i=0;i<img->mb_cr_size_y;i++)
{
for(j=0;j<img->mb_cr_size_x;j++)
{
img->cof[k][i][j] = img->dc_pred_value_comp[k];
img->fcf[k][i][j] = img->dc_pred_value_comp[k];
}
}
}
}
}
static void read_ipred_modes(ImageParameters *img, Macroblock *currMB)
{
int b8,i,j,bi,bj,bx,by,dec;
SyntaxElement currSE;
DataPartition *dP;
Slice *currSlice = img->currentSlice;
int *partMap = assignSE2partition[currSlice->dp_mode];
int ts, ls;
int mostProbableIntraPredMode;
int upIntraPredMode;
int leftIntraPredMode;
char IntraChromaPredModeFlag = IS_INTRA(currMB);
int bs_x, bs_y;
int ii,jj;
PixelPos left_block, top_block;
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->bitstream);
else
{
currSE.context=(b8<<2)+(j<<1) +i;
dP->readSyntaxElement(&currSE,img,dP);
}
get4x4Neighbour(currMB, (bx<<2) - 1, (by<<2), img->mb_size[IS_LUMA], &left_block);
get4x4Neighbour(currMB, (bx<<2), (by<<2) - 1, img->mb_size[IS_LUMA], &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) && (dec_picture->chroma_format_idc != YUV444))
{
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
************************************************************************
*/
void SetMotionVectorPredictor (ImageParameters *img,
Macroblock *currMB,
short pred_mv[2],
char ref_frame,
byte list,
char ***refPic,
short ****tmp_mv,
int mb_x,
int mb_y,
int blockshape_x,
int blockshape_y)
{
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;
get4x4Neighbour(currMB, mb_x - 1, mb_y, img->mb_size[IS_LUMA], &block_a);
get4x4Neighbour(currMB, mb_x, mb_y - 1, img->mb_size[IS_LUMA], &block_b);
get4x4Neighbour(currMB, mb_x + blockshape_x, mb_y - 1, img->mb_size[IS_LUMA], &block_c);
get4x4Neighbour(currMB, mb_x - 1, mb_y - 1, img->mb_size[IS_LUMA], &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;
}
pred_mv[hv] = (short) pred_vec;
}
}
/*!
************************************************************************
* \brief
* Read motion info
************************************************************************
*/
static void readMotionInfoFromNAL (ImageParameters *img, Macroblock *currMB)
{
int i,j,k;
int mb_nr = img->current_mb_nr;
SyntaxElement currSE;
Slice *currSlice = img->currentSlice;
DataPartition *dP = NULL;
int *partMap = assignSE2partition[currSlice->dp_mode];
int bslice = (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 i0, j0, j6;
int j4, i4, ii;
MotionParams *colocated;
int mv_scale = 0;
int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (mb_nr&0x01) ? 4 : 2 : 0;
if (bslice)
{
if ((img->MbaffFrameFlag) && (currMB->mb_field))
{
if(mb_nr&0x01)
{
colocated = &Co_located->bottom;
}
else
{
colocated = &Co_located->top;
}
}
else
{
colocated = &Co_located->frame;
}
if (IS_P8x8 (currMB))
{
if (img->direct_spatial_mv_pred_flag)
{
char l0_rFrame, l1_rFrame;
short pmvl0[2]={0,0}, pmvl1[2]={0,0};
prepare_direct_params(currMB, dec_picture, img, pmvl0, pmvl1, &l0_rFrame, &l1_rFrame);
for (k = 0; k < 4; k++)
{
if (currMB->b8mode[k] == 0)
{
i = img->block_x + 2 * (k & 0x01);
for(j = 2 * (k >> 1); j < 2 * (k >> 1)+2;j++)
{
j6 = img->block_y_aff + j;
j4 = img->block_y + j;
for(i4 = i; i4 < i + 2; i4++)
{
if (l0_rFrame >= 0)
{
if (!l0_rFrame && ((!colocated->moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
{
dec_picture->motion.mv [LIST_0][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_0][j4][i4][1] = 0;
dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
}
else
{
dec_picture->motion.mv [LIST_0][j4][i4][0] = pmvl0[0];
dec_picture->motion.mv [LIST_0][j4][i4][1] = pmvl0[1];
dec_picture->motion.ref_idx[LIST_0][j4][i4] = l0_rFrame;
}
}
else
{
dec_picture->motion.mv [LIST_0][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_0][j4][i4][1] = 0;
dec_picture->motion.ref_idx[LIST_0][j4][i4] = -1;
}
if (l1_rFrame >= 0)
{
if (l1_rFrame==0 && ((!colocated->moving_block[j6][i4])&& (!listX[LIST_1 + list_offset][0]->is_long_term)))
{
dec_picture->motion.mv [LIST_1][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_1][j4][i4][1] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
}
else
{
dec_picture->motion.mv [LIST_1][j4][i4][0] = pmvl1[0];
dec_picture->motion.mv [LIST_1][j4][i4][1] = pmvl1[1];
dec_picture->motion.ref_idx[LIST_1][j4][i4] = l1_rFrame;
}
}
else
{
dec_picture->motion.mv [LIST_1][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_1][j4][i4][1] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = -1;
}
if (l0_rFrame <0 && l1_rFrame <0)
{
dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
}
}
}
}
}
}
else
{
for (k = 0; k < 4; k++) // Scan all blocks
{
if (currMB->b8mode[k] == 0)
{
for(j0 = 2 * (k >> 1); j0 < 2 * (k >> 1) + 2; j0 += step_v0)
{
for(i0 = img->block_x + 2*(k & 0x01); i0 < img->block_x + 2 * (k & 0x01)+2; i0 += step_h0)
{
int refList = colocated->ref_idx[LIST_0 ][img->block_y_aff + j0][i0]== -1 ? LIST_1 : LIST_0;
int ref_idx = colocated->ref_idx[refList][img->block_y_aff + j0][i0];
int mapped_idx = -1, iref;
if (ref_idx == -1)
{
for (j4 = img->block_y + j0; j4 < img->block_y + j0 + step_v0; j4++)
{
memset(&dec_picture->motion.ref_idx [LIST_0][j4][i0], 0, step_h0 * sizeof(char));
memset(&dec_picture->motion.ref_idx [LIST_1][j4][i0], 0, step_h0 * sizeof(char));
memset(&dec_picture->motion.mv [LIST_0][j4][i0][0], 0, 2 * step_h0 * sizeof(short));
memset(&dec_picture->motion.mv [LIST_1][j4][i0][0], 0, 2 * step_h0 * sizeof(short));
}
}
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 colocated->ref_pic_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 == colocated->ref_pic_id[refList][img->block_y_aff + j0][i0]
|| listX[0][iref]->bottom_poc * 2 == colocated->ref_pic_id[refList][img->block_y_aff + j0][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]==colocated->ref_pic_id[refList][img->block_y_aff + j0][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 = img->block_y_aff + j;
for (i4 = i0; i4 < i0 + step_h0; i4++)
{
mv_scale = img->mvscale[LIST_0 + list_offset][mapped_idx];
dec_picture->motion.ref_idx [LIST_0][j4][i4] = (char) mapped_idx;
dec_picture->motion.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->motion.mv [LIST_0][j4][i4][ii] = colocated->mv[refList][j6][i4][ii];
dec_picture->motion.mv [LIST_1][j4][i4][ii] = 0;
}
else
{
dec_picture->motion.mv [LIST_0][j4][i4][ii] = (short) ((mv_scale * colocated->mv[refList][j6][i4][ii] + 128 ) >> 8);
dec_picture->motion.mv [LIST_1][j4][i4][ii] = (short) (dec_picture->motion.mv[LIST_0][j4][i4][ii] - colocated->mv[refList][j6][i4][ii]);
}
}
}
}
}
}
}
}
}
}
}
}
//===== READ REFERENCE PICTURE INDICES =====
currSE.type = SE_REFFRAME;
dP = &(currSlice->partArr[partMap[SE_REFFRAME]]);
// For LIST_0, if multiple ref. pictures, read LIST_0 reference picture indices for the MB ***********
prepareListforRefIdx (&currSE, dP, img->num_ref_idx_l0_active, !IS_P8x8 (currMB) || bslice || (!img->allrefzero));
readMBRefPictureIdx (&currSE, dP, currMB, img, &dec_picture->motion.ref_idx[LIST_0][img->block_y], LIST_0, step_v0, step_h0);
// For LIST_1, if multiple ref. pictures, read LIST_1 reference picture indices for the MB ***********
prepareListforRefIdx (&currSE, dP, img->num_ref_idx_l1_active, !IS_P8x8 (currMB) || bslice || (!img->allrefzero));
readMBRefPictureIdx (&currSE, dP, currMB, img, &dec_picture->motion.ref_idx[LIST_1][img->block_y], LIST_1, step_v0, step_h0);
//===== READ 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;
// LIST_0 Motion vectors
readMBMotionVectors (&currSE, dP, currMB, img, LIST_0, step_h0, step_v0);
// LIST_1 Motion vectors
if (bslice)
readMBMotionVectors (&currSE, dP, currMB, img, LIST_1, step_h0, step_v0);
// record reference picture Ids for deblocking decisions
for (k = LIST_0; k <= (bslice ? LIST_1: LIST_0); k++)
{
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->motion.ref_idx[k][j4][i4]>=0)
dec_picture->motion.ref_pic_id[k][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][k + list_offset][(short)dec_picture->motion.ref_idx[k][j4][i4]];
else
dec_picture->motion.ref_pic_id[k][j4][i4] = INT64_MIN;
}
}
}
}
/*!
************************************************************************
* \brief
* Get the Prediction from the Neighboring Blocks for Number of
* Nonzero Coefficients
*
* Luma Blocks
************************************************************************
*/
int predict_nnz(Macroblock *currMB, int block_type, ImageParameters *img, int i,int j)
{
PixelPos pix;
int pred_nnz = 0;
int cnt = 0;
// left block
get4x4Neighbour(currMB, i - 1, j, img->mb_size[IS_LUMA], &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)
{
switch (block_type)
{
case LUMA:
pred_nnz = img->nz_coeff [pix.mb_addr ][0][pix.y][pix.x];
cnt++;
break;
case CB:
pred_nnz = img->nz_coeff [pix.mb_addr ][1][pix.y][pix.x];
cnt++;
break;
case CR:
pred_nnz = img->nz_coeff [pix.mb_addr ][2][pix.y][pix.x];
cnt++;
break;
default:
error("writeCoeff4x4_CAVLC: Invalid block type", 600);
break;
}
}
// top block
get4x4Neighbour(currMB, i, j - 1, img->mb_size[IS_LUMA], &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)
{
switch (block_type)
{
case LUMA:
pred_nnz += img->nz_coeff [pix.mb_addr ][0][pix.y][pix.x];
cnt++;
break;
case CB:
pred_nnz += img->nz_coeff [pix.mb_addr ][1][pix.y][pix.x];
cnt++;
break;
case CR:
pred_nnz += img->nz_coeff [pix.mb_addr ][2][pix.y][pix.x];
cnt++;
break;
default:
error("writeCoeff4x4_CAVLC: Invalid block type", 600);
break;
}
}
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(Macroblock *currMB, ImageParameters *img, int i,int j)
{
PixelPos pix;
int pred_nnz = 0;
int cnt = 0;
if (dec_picture->chroma_format_idc != YUV444)
{
//YUV420 and YUV422
// left block
get4x4Neighbour(currMB, ((i&0x01)<<2) - 1, j, img->mb_size[IS_CHROMA], &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 ][1][pix.y][2 * (i>>1) + pix.x];
cnt++;
}
// top block
get4x4Neighbour(currMB, ((i&0x01)<<2), j - 1, img->mb_size[IS_CHROMA], &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 ][1][pix.y][2 * (i>>1) + pix.x];
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 (Macroblock *currMB, ImageParameters *img,
int block_type,
int i, int j, int levarr[16], int runarr[16],
int *number_coefficients)
{
int mb_nr = img->current_mb_nr;
SyntaxElement currSE;
Slice *currSlice = img->currentSlice;
DataPartition *dP;
int *partMap = assignSE2partition[currSlice->dp_mode];
static Bitstream *currStream;
int k, code, vlcnum;
static int numcoeff, numtrailingones, numcoeff_vlc;
static int level_two_or_higher;
int numones, totzeros, abslevel, cdc=0, cac=0;
int zerosleft, ntr, dptype = 0;
int max_coeff_num = 0, nnz;
static 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;
TRACE_PRINTF("Luma");
dptype = IS_INTRA (currMB) ? SE_LUM_AC_INTRA : SE_LUM_AC_INTER;
img->nz_coeff[mb_nr][0][j][i] = 0;
break;
case LUMA_INTRA16x16DC:
max_coeff_num = 16;
TRACE_PRINTF("Lum16DC");
dptype = SE_LUM_DC_INTRA;
img->nz_coeff[mb_nr][0][j][i] = 0;
break;
case LUMA_INTRA16x16AC:
max_coeff_num = 15;
TRACE_PRINTF("Lum16AC");
dptype = SE_LUM_AC_INTRA;
img->nz_coeff[mb_nr][0][j][i] = 0;
break;
case CB:
max_coeff_num = 16;
TRACE_PRINTF("Luma_add1");
dptype = (IS_INTRA (currMB)) ? SE_LUM_AC_INTRA : SE_LUM_AC_INTER;
img->nz_coeff[mb_nr][1][j][i] = 0;
break;
case CB_INTRA16x16DC:
max_coeff_num = 16;
TRACE_PRINTF("Luma_add1_16DC");
dptype = SE_LUM_DC_INTRA;
img->nz_coeff[mb_nr][1][j][i] = 0;
break;
case CB_INTRA16x16AC:
max_coeff_num = 15;
TRACE_PRINTF("Luma_add1_16AC");
dptype = SE_LUM_AC_INTRA;
img->nz_coeff[mb_nr][1][j][i] = 0;
break;
case CR:
max_coeff_num = 16;
TRACE_PRINTF("Luma_add2");
dptype = (IS_INTRA (currMB)) ? SE_LUM_AC_INTRA : SE_LUM_AC_INTER;
img->nz_coeff[mb_nr][2][j][i] = 0;
break;
case CR_INTRA16x16DC:
max_coeff_num = 16;
TRACE_PRINTF("Luma_add2_16DC");
dptype = SE_LUM_DC_INTRA;
img->nz_coeff[mb_nr][2][j][i] = 0;
break;
case CR_INTRA16x16AC:
max_coeff_num = 15;
TRACE_PRINTF("Luma_add1_16AC");
dptype = SE_LUM_AC_INTRA;
img->nz_coeff[mb_nr][2][j][i] = 0;
break;
case CHROMA_DC:
max_coeff_num = img->num_cdc_coeff;
cdc = 1;
TRACE_PRINTF("ChrDC");
dptype = IS_INTRA (currMB) ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER;
img->nz_coeff[mb_nr][0][j][i] = 0;
break;
case CHROMA_AC:
max_coeff_num = 15;
cac = 1;
TRACE_PRINTF("ChrDC");
dptype = IS_INTRA (currMB) ? SE_CHR_AC_INTRA : SE_CHR_AC_INTER;
img->nz_coeff[mb_nr][0][j][i] = 0;
break;
default:
error ("readCoeff4x4_CAVLC: invalid block type", 600);
img->nz_coeff[mb_nr][0][j][i] = 0;
break;
}
currSE.type = dptype;
dP = &(currSlice->partArr[partMap[dptype]]);
currStream = dP->bitstream;
if (!cdc)
{
// luma or chroma AC
if(block_type==LUMA || block_type==LUMA_INTRA16x16DC || block_type==LUMA_INTRA16x16AC ||block_type==CHROMA_AC)
{
nnz = (!cac) ? predict_nnz(currMB, LUMA, img, i<<2, j<<2) : predict_nnz_chroma(currMB, img, i, ((j-4)<<2));
}
else if (block_type==CB || block_type==CB_INTRA16x16DC || block_type==CB_INTRA16x16AC)
{
nnz = predict_nnz(currMB, CB, img, i<<2, j<<2);
}
else
{
nnz = predict_nnz(currMB, CR, img, i<<2, j<<2);
}
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, currStream, type);
numcoeff = currSE.value1;
numtrailingones = currSE.value2;
if(block_type==LUMA || block_type==LUMA_INTRA16x16DC || block_type==LUMA_INTRA16x16AC ||block_type==CHROMA_AC)
img->nz_coeff[mb_nr][0][j][i] = numcoeff;
else if (block_type==CB || block_type==CB_INTRA16x16DC || block_type==CB_INTRA16x16AC)
img->nz_coeff[mb_nr][1][j][i] = numcoeff;
else
img->nz_coeff[mb_nr][2][j][i] = numcoeff;
}
else
{
// chroma DC
readSyntaxElement_NumCoeffTrailingOnesChromaDC(&currSE, currStream);
numcoeff = currSE.value1;
numtrailingones = currSE.value2;
}
memset(levarr, 0, max_coeff_num * sizeof(int));
memset(runarr, 0, max_coeff_num * sizeof(int));
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, currStream);
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, currStream);
else
readSyntaxElement_Level_VLCN(&currSE, vlcnum, currStream);
if (level_two_or_higher)
{
currSE.inf += (currSE.inf > 0) ? 1 : -1;
level_two_or_higher = 0;
}
levarr[k] = currSE.inf;
abslevel = iabs(levarr[k]);
if (abslevel == 1)
numones ++;
// update VLC table
if (abslevel > incVlc[vlcnum])
vlcnum++;
if (k == numcoeff - 1 - numtrailingones && abslevel >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, currStream);
else
readSyntaxElement_TotalZeros(&currSE, currStream);
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 = imin(zerosleft - 1, RUNBEFORE_NUM_M1);
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, currStream);
runarr[i] = currSE.value1;
zerosleft -= runarr[i];
i --;
} while (zerosleft != 0 && i != 0);
}
runarr[i] = zerosleft;
} // if numcoeff
}
/*!
************************************************************************
* \brief
* Get coefficients (run/level) of one 8x8 block
* from the NAL (CABAC Mode)
************************************************************************
*/
static void readLumaCoeff8x8_CABAC (ImageParameters *img, Macroblock *currMB, ColorPlane pl, int b8)
{
static int (*tcoeffs)[16];
int i,j,k;
int level = 1;
int cbp = currMB->cbp;
SyntaxElement currSE;
Slice *currSlice = img->currentSlice;
DataPartition *dP;
int *partMap = assignSE2partition[currSlice->dp_mode];
int boff_x, boff_y;
int qp_per, qp_rem;
int uv = pl - 1;
int64 cbp_mask = (int64) 51 << (4 * b8 - 2 * (b8 & 0x01)); // corresponds to 110011, as if all four 4x4 blocks contain coeff, shifted to block position
int64 *cur_cbp;
Boolean lossless_qpprime = (Boolean) ((img->qp + img->bitdepth_luma_qp_scale)==0 && img->lossless_qpprime_flag==1);
int (*InvLevelScale8x8)[8] = NULL;
// select scan type
const byte (*pos_scan8x8) = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN8x8[0] : FIELD_SCAN8x8[0];
if (cbp & (1<<b8)) // are there any coefficients in the current block
{
if (pl)
{
qp_per = qp_per_matrix[ currMB->qp_scaled[pl] ];
qp_rem = qp_rem_matrix[ currMB->qp_scaled[pl] ];
cur_cbp = &currMB->cbp_blk;
}
else
{
qp_per = qp_per_matrix[ currMB->qp_scaled[pl] ];
qp_rem = qp_rem_matrix[ currMB->qp_scaled[pl] ];
cur_cbp = &currMB->cbp_blk_CbCr[uv];
}
InvLevelScale8x8 = IS_INTRA(currMB)? InvLevelScale8x8_Intra[pl][qp_rem] : InvLevelScale8x8_Inter[pl][qp_rem];
img->is_intra_block = IS_INTRA(currMB);
// === set offset in current macroblock ===
boff_x = (b8&0x01) << 3;
boff_y = (b8 >> 1) << 3;
tcoeffs = &img->mb_rres[pl][boff_y];
img->subblock_x = boff_x >> 2; // position for coeff_count ctx
img->subblock_y = boff_y >> 2; // position for coeff_count ctx
if (pl==PLANE_Y || IS_INDEPENDENT(img))
currSE.context = LUMA_8x8;
else if (pl==PLANE_U)
currSE.context = CB_8x8;
else
currSE.context = CR_8x8;
currSE.reading = readRunLevel_CABAC;
if(!lossless_qpprime)
{
// Read DC
currSE.type = ((img->is_intra_block == 1) ? SE_LUM_DC_INTRA : SE_LUM_DC_INTER ); // Intra or Inter?
dP = &(currSlice->partArr[partMap[currSE.type]]);
#if TRACE
if (pl==PLANE_Y)
sprintf(currSE.tracestring, "Luma8x8 DC sng ");
else if (pl==PLANE_U)
sprintf(currSE.tracestring, "Cb 8x8 DC sng ");
else
sprintf(currSE.tracestring, "Cr 8x8 DC sng ");
#endif
dP->readSyntaxElement(&currSE,img,dP);
level = currSE.value1;
//============ decode =============
if (level != 0) /* leave if len=1 */
{
*cur_cbp |= cbp_mask;
pos_scan8x8 += 2 * (currSE.value2);
i = *pos_scan8x8++;
j = *pos_scan8x8++;
tcoeffs[j][boff_x + i] = rshift_rnd_sf((level * InvLevelScale8x8[j][i]) << qp_per, 6); // dequantization
// AC coefficients
currSE.type = ((img->is_intra_block == 1) ? SE_LUM_AC_INTRA : SE_LUM_AC_INTER);
dP = &(currSlice->partArr[partMap[currSE.type]]);
for(k = 1;(k < 65) && (level != 0);k++)
{
#if TRACE
if (pl==PLANE_Y)
sprintf(currSE.tracestring, "Luma8x8 sng ");
else if (pl==PLANE_U)
sprintf(currSE.tracestring, "Cb 8x8 sng ");
else
sprintf(currSE.tracestring, "Cr 8x8 sng ");
#endif
dP->readSyntaxElement(&currSE,img,dP);
level = currSE.value1;
//============ decode =============
if (level != 0) /* leave if len=1 */
{
pos_scan8x8 += 2 * (currSE.value2);
i = *pos_scan8x8++;
j = *pos_scan8x8++;
tcoeffs[ j][boff_x + i] = rshift_rnd_sf((level * InvLevelScale8x8[j][i]) << qp_per, 6); // dequantization
}
}
}
}
else
{
for(k=0; (k < 65) && (level != 0);k++)
{
//============ read =============
/*
* make distinction between INTRA and INTER coded
* luminance coefficients
*/
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
if (pl==PLANE_Y)
sprintf(currSE.tracestring, "Luma8x8 sng ");
else if (pl==PLANE_U)
sprintf(currSE.tracestring, "Cb 8x8 sng ");
else
sprintf(currSE.tracestring, "Cr 8x8 sng ");
#endif
dP = &(currSlice->partArr[partMap[currSE.type]]);
currSE.reading = readRunLevel_CABAC;
dP->readSyntaxElement(&currSE,img,dP);
level = currSE.value1;
//============ decode =============
if (level != 0) /* leave if len=1 */
{
pos_scan8x8 += 2 * (currSE.value2);
i = *pos_scan8x8++;
j = *pos_scan8x8++;
*cur_cbp |= cbp_mask;
tcoeffs[j][boff_x + i] = level;
}
}
}
}
}
/*!
************************************************************************
* \brief
* Data partitioning: Check if neighboring macroblock is needed for
* CAVLC context decoding, and disable current MB if data partition
* is missing.
************************************************************************
*/
static void check_dp_neighbors (Macroblock *currMB)
{
PixelPos up, left;
getNeighbour(currMB, -1, 0, img->mb_size[1], &left);
getNeighbour(currMB, 0, -1, img->mb_size[1], &up);
if (IS_INTER (currMB) || (IS_INTRA (currMB) && !(active_pps->constrained_intra_pred_flag)) )
{
if (left.available)
{
currMB->dpl_flag |= img->mb_data[left.mb_addr].dpl_flag;
}
if (up.available)
{
currMB->dpl_flag |= img->mb_data[up.mb_addr].dpl_flag;
}
}
}
/*!
************************************************************************
* \brief
* Get coded block pattern and coefficients (run/level)
* from the NAL
************************************************************************
*/
static void readCBPandCoeffsFromNAL(ImageParameters *img, Macroblock *currMB)
{
int i,j,k;
int level;
int mb_nr = img->current_mb_nr;
int ii,jj;
int cbp;
SyntaxElement currSE;
Slice *currSlice = img->currentSlice;
DataPartition *dP = NULL;
int *partMap = assignSE2partition[currSlice->dp_mode];
int coef_ctr, i0, j0, b8;
int ll;
int block_x,block_y;
int start_scan;
int levarr[16], runarr[16], numcoeff;
int qp_per = qp_per_matrix[ (img->qp + img->bitdepth_luma_qp_scale) ];
int qp_rem = qp_rem_matrix[ (img->qp + img->bitdepth_luma_qp_scale) ];
int smb = ((img->type==SP_SLICE) && IS_INTER (currMB)) || (img->type == SI_SLICE && currMB->mb_type == SI4MB);
int uv;
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 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;
const byte *pos_scan_4x4 = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN[0] : FIELD_SCAN[0];
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] = qp_per_matrix[ currMB->qp_scaled[i + 1] ];
qp_rem_uv[i] = qp_rem_matrix[ currMB->qp_scaled[i + 1] ];
}
}
// 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)
{
read_delta_quant(&currSE, dP, currSlice, img, currMB, partMap, (IS_INTER (currMB)) ? SE_DELTA_QUANT_INTER : SE_DELTA_QUANT_INTRA);
lossless_qpprime = (Boolean) ((img->qp + img->bitdepth_luma_qp_scale)==0 && img->lossless_qpprime_flag==1);
if (currSlice->dp_mode)
{
if (IS_INTER (currMB) && currSlice->dpC_NotPresent )
currMB->dpl_flag = 1;
if( intra && currSlice->dpB_NotPresent )
{
currMB->ei_flag = 1;
currMB->dpl_flag = 1;
}
// check for prediction from neighbours
check_dp_neighbors (currMB);
if (currMB->dpl_flag)
{
cbp = 0;
currMB->cbp = cbp;
}
}
}
}
else
{
cbp = currMB->cbp;
}
memset(&img->cof[0][0][0], 0, MB_PIXELS * sizeof(int)); // reset luma coeffs
memset(&img->fcf[0][0][0], 0, MB_PIXELS * sizeof(int)); // reset luma coeffs
if (IS_NEWINTRA (currMB)) // read DC coeffs for new intra modes
{
read_delta_quant(&currSE, dP, currSlice, img, currMB, partMap, SE_DELTA_QUANT_INTRA);
for (j=0;j<BLOCK_SIZE;j++)
memset(&img->ipredmode[img->block_y+j][img->block_x], DC_PRED, BLOCK_SIZE * sizeof(byte));
if (currSlice->dp_mode)
{
if (currSlice->dpB_NotPresent)
{
currMB->ei_flag = 1;
currMB->dpl_flag = 1;
}
check_dp_neighbors (currMB);
if (currMB->dpl_flag)
{
currMB->cbp = cbp = 0;
}
}
if (!currMB->dpl_flag)
{
pos_scan_4x4 = pos_scan4x4[0];
if (active_pps->entropy_coding_mode_flag == UVLC)
{
readCoeff4x4_CAVLC(currMB, img, LUMA_INTRA16x16DC, 0, 0, levarr, runarr, &numcoeff);
for(k = 0; k < numcoeff; k++)
{
if (levarr[k] != 0) // leave if len=1
{
pos_scan_4x4 += 2 * runarr[k];
i0 = ((*pos_scan_4x4++) << 2);
j0 = ((*pos_scan_4x4++) << 2);
img->cof[0][j0][i0] = levarr[k];// add new intra DC coeff
img->fcf[0][j0][i0] = 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;
}
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;
if (level != 0) // leave if len=1
{
pos_scan_4x4 += (2 * currSE.value2);
i0 = ((*pos_scan_4x4++) << 2);
j0 = ((*pos_scan_4x4++) << 2);
img->cof[0][j0][i0] = level;// add new intra DC coeff
img->fcf[0][j0][i0] = level;// add new intra DC coeff
}
}
}
if(!lossless_qpprime)
itrans_2(img, currMB, PLANE_Y);// transform new intra DC
}
}
update_qp(img, currMB, img->qp);
qp_per = qp_per_matrix[ currMB->qp_scaled[img->colour_plane_id] ];
qp_rem = qp_rem_matrix[ currMB->qp_scaled[img->colour_plane_id] ];
//init quant parameters for chroma
if (dec_picture->chroma_format_idc != YUV400)
{
for(i=0; i < 2; i++)
{
qp_per_uv[i] = qp_per_matrix[ currMB->qp_scaled[i + 1] ];
qp_rem_uv[i] = qp_rem_matrix[ currMB->qp_scaled[i + 1] ];
}
}
InvLevelScale4x4 = intra? InvLevelScale4x4_Intra[img->colour_plane_id][qp_rem] : InvLevelScale4x4_Inter[img->colour_plane_id][qp_rem];
InvLevelScale8x8 = intra? InvLevelScale8x8_Intra[img->colour_plane_id][qp_rem] : InvLevelScale8x8_Inter[img->colour_plane_id][qp_rem];
// luma coefficients
if (active_pps->entropy_coding_mode_flag == UVLC)
{
start_scan = IS_NEWINTRA(currMB) ? 1 : 0;
if (!lossless_qpprime)
{
if (!currMB->luma_transform_size_8x8_flag) // 4x4 transform
{
if (cbp)
{
int cur_context = IS_NEWINTRA(currMB) ? LUMA_INTRA16x16AC : LUMA;
for (block_y=0; block_y < 4; block_y += 2) /* all modes */
{
for (block_x=0; block_x < 4; block_x += 2)
{
b8 = (block_y + (block_x >> 1));
if (cbp & (1 << b8)) // test if the block contains any coefficients
{
for (j=block_y; j < block_y + 2; j++)
{
for (i=block_x; i < block_x + 2; i++)
{
readCoeff4x4_CAVLC(currMB, img, cur_context, i, j, levarr, runarr, &numcoeff);
pos_scan_4x4 = pos_scan4x4[start_scan];
for (k = 0; k < numcoeff; k++)
{
if (levarr[k] != 0)
{
pos_scan_4x4 += (runarr[k] << 1);
i0 = *pos_scan_4x4++;
j0 = *pos_scan_4x4++;
// inverse quant for 4x4 transform only
currMB->cbp_blk |= (int64) 1 << ((j<<2) + i);
img->cof[0][(j<<2) + j0][(i<<2) + i0]= rshift_rnd_sf((levarr[k] * InvLevelScale4x4[j0][i0])<<qp_per, 4);
img->fcf[0][(j<<2) + j0][(i<<2) + i0]= levarr[k];
}
}
}
}
}
else
{
for (j=block_y; j < block_y + 2; j++)
{
memset(&img->nz_coeff[mb_nr][0][j][block_x], 0, 2 * sizeof(int));
}
}
}
}
}
else
{
memset(&img->nz_coeff[mb_nr][0][0][0], 0, BLOCK_SIZE * BLOCK_SIZE * sizeof(int));
}
}
else // 8x8 transform
{
if (cbp)
{
int cur_context = IS_NEWINTRA(currMB) ? LUMA_INTRA16x16AC : LUMA;
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 (cbp & (1<<b8)) /* are there any coeff in current block at all */
{
for (j=block_y; j < block_y+2; j++)
{
for (i=block_x; i < block_x+2; i++)
{
readCoeff4x4_CAVLC(currMB, img, cur_context, i, j, levarr, runarr, &numcoeff);
coef_ctr = start_scan - 1;
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 = (coef_ctr << 2) + 2*(j - block_y)+(i - block_x);
i0 = pos_scan8x8[b4][0];
j0 = pos_scan8x8[b4][1];
img->mb_rres[0][block_y*4 +j0][block_x*4 +i0] = rshift_rnd_sf((levarr[k] * InvLevelScale8x8[j0][i0])<<qp_per, 6); // dequantization
}
}//else (!currMB->luma_transform_size_8x8_flag)
}
}
}
else
{
for (j=block_y; j < block_y+2; j++)
{
memset(&img->nz_coeff[mb_nr][0][j][block_x], 0, 2 * sizeof(int));
}
}
}
}
}
else
{
memset(&img->nz_coeff[mb_nr][0][0][0], 0, BLOCK_SIZE * BLOCK_SIZE * sizeof(int));
}
}
}
else // if (!lossless_qpprime)
{
int cur_context = IS_NEWINTRA(currMB) ? LUMA_INTRA16x16AC : LUMA;
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);
for (j=block_y; j < block_y+2; j++)
{
for (i=block_x; i < block_x+2; i++)
{
if (cbp & (1<<b8)) /* are there any coeff in current block at all */
{
readCoeff4x4_CAVLC(currMB, img, cur_context, i, j, levarr, runarr, &numcoeff);
coef_ctr = start_scan - 1;
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[0][(j<<2) + j0][(i<<2) + i0]= levarr[k];
img->fcf[0][(j<<2) + j0][(i<<2) + i0]= levarr[k];
}
}
}
else // inverse quant for 8x8 transform
{
int 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->mb_rres[0][block_y*4 +jz][block_x*4 +iz] = levarr[k];
}
}
}//else (!currMB->luma_transform_size_8x8_flag)
}
else
{
img->nz_coeff[mb_nr][0][j][i] = 0;
}
}
}
}
}
}
} // VLC
else
{
//======= Other Modes & CABAC ========
//------------------------------------
if(currMB->luma_transform_size_8x8_flag)
{
for (block_y=0; block_y < 4; block_y += 2) /* all modes */
{
for (b8 = block_y; b8 < block_y + 2; b8 += 1)
{
readLumaCoeff8x8_CABAC(img, currMB, PLANE_Y, b8); //======= 8x8 trannsform size & CABAC ========
}
}
}
else
{
if(!lossless_qpprime)
{
if (cbp)
{
start_scan = IS_NEWINTRA (currMB)? 1 : 0;
img->is_intra_block = intra;
currSE.context = (IS_NEWINTRA(currMB) ? LUMA_16AC : LUMA_4x4);
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 (cbp & (1<<b8)) // are there any coeff in current block at all
{
for (j = (block_y<<2); j < (block_y<<2) + 8; j += 4)
{
img->subblock_y = (j>>2); // position for coeff_count ctx
for (i = block_x; i < block_x + 2; i++)
{
img->subblock_x = i; // position for coeff_count ctx
pos_scan_4x4 = pos_scan4x4[start_scan];
level = 1;
for(k=start_scan;(k<17) && (level!=0);k++)
{
/*
* make distinction between INTRA and INTER coded
* luminance coefficients
*/
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 (dP->bitstream->ei_flag)
currSE.mapping = linfo_levrun_inter;
else
currSE.reading = readRunLevel_CABAC;
dP->readSyntaxElement(&currSE,img,dP);
level = currSE.value1;
if (level != 0) /* leave if len=1 */
{
pos_scan_4x4 += 2 * currSE.value2;
i0 = *pos_scan_4x4++;
j0 = *pos_scan_4x4++;
currMB->cbp_blk |= (int64)1 << (j + i) ;
img->cof[0][j + j0][(i<<2) + i0]= rshift_rnd_sf((level * InvLevelScale4x4[j0][i0]) << qp_per, 4);
img->fcf[0][j + j0][(i<<2) + i0]= level;
}
}
}
}
}
}
}
}
}
else
{
start_scan = IS_NEWINTRA (currMB)? 1 : 0;
img->is_intra_block = intra;
currSE.context = (IS_NEWINTRA(currMB) ? LUMA_16AC : LUMA_4x4);
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);
for (j = block_y; j < block_y + 2; j++)
{
img->subblock_y = j; // position for coeff_count ctx
for (i = block_x; i < block_x + 2; i++)
{
img->subblock_x = i; // 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;
for(k=start_scan;(k<17) && (level!=0);k++)
{
/*
* make distinction between INTRA and INTER coded
* luminance coefficients
*/
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;
if (level != 0) /* leave if len=1 */
{
coef_ctr += currSE.value2+1;
i0=pos_scan4x4[coef_ctr][0];
j0=pos_scan4x4[coef_ctr][1];
currMB->cbp_blk |= (int64)1 << ((j<<2) + i) ;
img->cof[0][(j<<2) + j0][(i<<2) + i0] = level;
img->fcf[0][(j<<2) + j0][(i<<2) + i0] = level;
}
}
}
}
}
}
}
}
}
}
if ( active_sps->chroma_format_idc==YUV444 && !IS_INDEPENDENT(img) )
{
for (uv = 0; uv < 2; uv++ )
{
memset(&img->cof[uv + 1][0][0], 0, MB_PIXELS * sizeof(int));
memset(&img->fcf[uv + 1][0][0], 0, MB_PIXELS * sizeof(int));
/*----------------------16x16DC Luma_Add----------------------*/
if (IS_NEWINTRA (currMB)) // read DC coeffs for new intra modes
{
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)
{
if (uv == 0)
readCoeff4x4_CAVLC(currMB, img, CB_INTRA16x16DC, 0, 0, levarr, runarr, &numcoeff);
else
readCoeff4x4_CAVLC(currMB, img, CR_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 += runarr[k] + 1;
i0=pos_scan4x4[coef_ctr][0];
j0=pos_scan4x4[coef_ctr][1];
img->cof[uv + 1][j0<<2][i0<<2] = levarr[k];// add new intra DC coeff
img->fcf[uv + 1][j0<<2][i0<<2] = levarr[k];// add new intra DC coeff
} //if leavarr[k]
} //k loop
} //UVLC
else // else UVLC
{
currSE.type = SE_LUM_DC_INTRA;
dP = &(currSlice->partArr[partMap[currSE.type]]);
if (uv==0)
currSE.context = CB_16DC;
else
currSE.context = CR_16DC;
if( IS_INDEPENDENT(img) )
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
if (uv == 0)
snprintf(currSE.tracestring, TRACESTRING_SIZE, "DC Cb 16x16 ");
else
snprintf(currSE.tracestring, TRACESTRING_SIZE, "DC Cr 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 += currSE.value2 + 1;
i0=pos_scan4x4[coef_ctr][0];
j0=pos_scan4x4[coef_ctr][1];
img->cof[uv + 1][j0<<2][i0<<2] = level;
img->fcf[uv + 1][j0<<2][i0<<2] = level;
}
} //k loop
} // else UVLC
if(!lossless_qpprime)
{
itrans_2(img, currMB, (ColorPlane) (uv + 1)); // transform new intra DC
}
} //IS_NEWINTRA
update_qp(img, currMB, img->qp);
qp_per = qp_per_matrix[ (img->qp + img->bitdepth_luma_qp_scale) ];
qp_rem = qp_rem_matrix[ (img->qp + img->bitdepth_luma_qp_scale) ];
//init constants for every chroma qp offset
qp_per_uv[uv] = qp_per_matrix[ (currMB->qpc[uv] + img->bitdepth_chroma_qp_scale) ];
qp_rem_uv[uv] = qp_rem_matrix[ (currMB->qpc[uv] + img->bitdepth_chroma_qp_scale) ];
InvLevelScale4x4 = intra? InvLevelScale4x4_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale4x4_Inter[uv + 1][qp_rem_uv[uv]];
InvLevelScale8x8 = intra? InvLevelScale8x8_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale8x8_Inter[uv + 1][qp_rem_uv[uv]];
// luma_add 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 */
{
if (uv==0)
readCoeff4x4_CAVLC(currMB, img, (IS_NEWINTRA(currMB) ? CB_INTRA16x16AC : CB), i, j, levarr, runarr, &numcoeff);
else
readCoeff4x4_CAVLC(currMB, img, (IS_NEWINTRA(currMB) ? CR_INTRA16x16AC : CR), 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_CbCr[uv] |= (int64) 1 << ((j<<2) + i);
img->cof[uv + 1][(j << 2) + j0][(i << 2) + i0] = rshift_rnd_sf((levarr[k] * InvLevelScale4x4[j0][i0])<<qp_per_uv[uv],4);
img->fcf[uv + 1][(j << 2) + j0][(i << 2) + i0] = levarr[k];
} //levarr[k] != 0
}//k loop
} //4x4
else //8x8
{
int 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_CbCr[uv] |= 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->mb_rres[uv+1][block_y*4 +jz][block_x*4 +iz] = rshift_rnd_sf((levarr[k]*InvLevelScale8x8[jz][iz])<<qp_per_uv[uv], 6); // dequantization 444_TEMP_NOTE
} //if levarr
}//8x8
}//k loop
} // !lossless
else //lossless
{
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_CbCr[uv] |= (int64) 1 << ((j<<2) + i);
img->cof[uv + 1][(j << 2) + j0][(i << 2) + i0] = levarr[k];
img->fcf[uv + 1][(j << 2) + j0][(i << 2) + i0] = levarr[k];
} //levarr[k]
} //k loop
} //4x4
else //8x8
{
int 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_CbCr[uv] |= 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->mb_rres[uv+1][block_y*4 +jz][block_x*4 +iz] = levarr[k];
} //levarr[k]
} //k loop
} //8x8
}// loseless
} //if (cbp & (1<<b8))
else //!(cbp & (1<<b8))
{
img->nz_coeff[mb_nr][uv + 1][j][i] = 0;
} //!(cbp & (1<<b8))
} //i=block_x
} //j=block_y
} //UVCL
else // CABAC
{
if(currMB->luma_transform_size_8x8_flag)
{
readLumaCoeff8x8_CABAC(img, currMB, (ColorPlane) (PLANE_U + uv), b8); //======= 8x8 trannsform size & CABAC ========
}
else //4x4
{
//======= 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 = intra;
if(!lossless_qpprime)
{
for(k=start_scan;(k<17) && (level!=0);k++)
{
/*
* make distinction between INTRA and INTER coded
* luminance coefficients
*/
if (uv == 0)
currSE.context = (IS_NEWINTRA(currMB) ? CB_16AC: CB_4x4);
else
currSE.context = (IS_NEWINTRA(currMB) ? CR_16AC: CR_4x4);
if( IS_INDEPENDENT(img) )
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
if (uv == 0)
sprintf(currSE.tracestring, "Cb sng ");
else
sprintf(currSE.tracestring, "Cr 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 += currSE.value2+1;
i0=pos_scan4x4[coef_ctr][0];
j0=pos_scan4x4[coef_ctr][1];
currMB->cbp_blk_CbCr[uv] |= (int64)1 << ((j<<2) + i) ;
img->cof[uv + 1][(j << 2) + j0][(i << 2) + i0] = rshift_rnd_sf((level * InvLevelScale4x4[j0][i0]) << qp_per_uv[uv], 4); //444_TEMP_NOTE
img->fcf[uv + 1][(j << 2) + j0][(i << 2) + i0] = level;
}//level != 0
} //k loop
}//!lossless
else //(lossless_qpprime)
{
for(k=start_scan;(k<17) && (level!=0);k++)
{
/*
* make distinction between INTRA and INTER coded
* luminance coefficients
*/
if (uv == 0)
currSE.context = (IS_NEWINTRA(currMB) ? CB_16AC: CB_4x4);
else
currSE.context = (IS_NEWINTRA(currMB) ? CR_16AC: CR_4x4);
if( IS_INDEPENDENT(img) )
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
if (uv == 0)
sprintf(currSE.tracestring, "Cb sng ");
else
sprintf(currSE.tracestring, "Cr 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 += currSE.value2 + 1;
i0=pos_scan4x4[coef_ctr][0];
j0=pos_scan4x4[coef_ctr][1];
currMB->cbp_blk_CbCr[uv] |= (int64)1 << ((j<<2) + i);
img->cof[uv + 1][(j << 2) + j0][(i << 2) + i0] = level;
img->fcf[uv + 1][(j << 2) + j0][(i << 2) + i0] = level;
} //level != 0
}//k loop
} //lossless
} //(cbp & (1<<b8))
} //i=block_x
}//j=block_y
} //4x4
} //CABAC
} //block_x
} //block_y
} //uv loop
} //444
else if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444))
{
memset(&img->cof[1][0][0], 0, MB_PIXELS * sizeof(int));
memset(&img->cof[2][0][0], 0, MB_PIXELS * sizeof(int));
memset(&img->fcf[1][0][0], 0, MB_PIXELS * sizeof(int));
memset(&img->fcf[2][0][0], 0, MB_PIXELS * sizeof(int));
//========================== CHROMA DC ============================
//-----------------------------------------------------------------
// chroma DC coeff
if(cbp>15)
{
if (dec_picture->chroma_format_idc == YUV420)
{
for (ll=0;ll<3;ll+=2)
{
uv = ll>>1;
if (active_pps->entropy_coding_mode_flag == UVLC)
{
InvLevelScale4x4 = intra ? InvLevelScale4x4_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale4x4_Inter[uv + 1][qp_rem_uv[uv]];
//===================== CHROMA DC YUV420 ======================
memset(&img->cofu[0], 0, 4 *sizeof(int));
readCoeff4x4_CAVLC(currMB, img, CHROMA_DC, 0, 0, levarr, runarr, &numcoeff);
coef_ctr=-1;
for(k = 0; k < numcoeff; k++)
{
if (levarr[k] != 0)
{
currMB->cbp_blk |= 0xf0000 << (ll<<1) ;
coef_ctr += runarr[k] + 1;
img->cofu[coef_ctr]=levarr[k];
}
}
}
else
{
InvLevelScale4x4 = intra ? InvLevelScale4x4_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale4x4_Inter[uv + 1][qp_rem_uv[uv]];
//===================== CHROMA DC YUV420 ======================
memset(&img->cofu[0], 0, 4 *sizeof(int));
coef_ctr=-1;
level=1;
img->is_intra_block = intra;
img->is_v_block = ll;
currSE.context = CHROMA_DC;
currSE.type = (intra ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER);
dP = &(currSlice->partArr[partMap[currSE.type]]);
if (dP->bitstream->ei_flag)
currSE.mapping = linfo_levrun_c2x2;
else
currSE.reading = readRunLevel_CABAC;
for(k = 0; (k < (img->num_cdc_coeff + 1))&&(level!=0);k++)
{
#if TRACE
snprintf(currSE.tracestring, TRACESTRING_SIZE, "2x2 DC Chroma ");
#endif
dP->readSyntaxElement(&currSE,img,dP);
level = currSE.value1;
if (level != 0)
{
currMB->cbp_blk |= 0xf0000 << (ll<<1) ;
coef_ctr += currSE.value2 + 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 || lossless_qpprime) // check to see if MB type is SPred or SIntra4x4
{
img->cof[uv + 1][0][0] = img->cofu[0];
img->cof[uv + 1][4][0] = img->cofu[1];
img->cof[uv + 1][0][4] = img->cofu[2];
img->cof[uv + 1][4][4] = img->cofu[3];
img->fcf[uv + 1][0][0] = img->cofu[0];
img->fcf[uv + 1][4][0] = img->cofu[1];
img->fcf[uv + 1][0][4] = img->cofu[2];
img->fcf[uv + 1][4][4] = img->cofu[3];
}
else
{
ihadamard2x2(img->cofu, temp);
img->fcf[uv + 1][0][0] = temp[0];
img->fcf[uv + 1][0][4] = temp[1];
img->fcf[uv + 1][4][0] = temp[2];
img->fcf[uv + 1][4][4] = temp[3];
for (i=0;i<img->num_cdc_coeff;i++)
{
temp[i]= (((temp[i] * InvLevelScale4x4[0][0])<<qp_per_uv[uv])>>5);
}
img->cof[uv + 1][0][0] = temp[0];
img->cof[uv + 1][0][4] = temp[1];
img->cof[uv + 1][4][0] = temp[2];
img->cof[uv + 1][4][4] = temp[3];
}
}
}
else if (dec_picture->chroma_format_idc == YUV422)
{
for (ll=0;ll<3;ll+=2)
{
int (*InvLevelScale4x4)[4] = NULL;
uv = ll>>1;
{
int (*imgcof)[16] = img->cof[uv + 1];
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 = qp_per_matrix[ (currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale) ]; //for YUV422 only
int qp_rem_uv_dc = qp_rem_matrix[ (currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale) ]; //for YUV422 only
if (intra)
InvLevelScale4x4 = InvLevelScale4x4_Intra[uv + 1][qp_rem_uv_dc];
else
InvLevelScale4x4 = InvLevelScale4x4_Inter[uv + 1][qp_rem_uv_dc];
//===================== CHROMA DC YUV422 ======================
if (active_pps->entropy_coding_mode_flag == UVLC)
{
readCoeff4x4_CAVLC(currMB, img, 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 += 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;
if (level != 0)
{
currMB->cbp_blk |= ((int64)0xff0000) << (ll<<2) ;
coef_ctr += currSE.value2 + 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];
for (i = 0; i < 2; i++)
{
m6[0] = m4[i][0] + m4[i][2];
m6[1] = m4[i][0] - m4[i][2];
m6[2] = m4[i][1] - m4[i][3];
m6[3] = m4[i][1] + m4[i][3];
imgcof[ 0][i<<2] = m6[0] + m6[3];
imgcof[ 4][i<<2] = m6[1] + m6[2];
imgcof[ 8][i<<2] = m6[1] - m6[2];
imgcof[12][i<<2] = m6[0] - m6[3];
}//for (i=0;i<2;i++)
}
else
{
for(j=0;j<4;j++)
{
for(i=0;i<2;i++)
{
img->cof[uv + 1][j<<2][i<<2] = m3[i][j];
img->fcf[uv + 1][j<<2][i<<2] = m3[i][j];
}
}
}
for(j = 0;j < img->mb_cr_size_y; j += BLOCK_SIZE)
{
for(i=0;i < img->mb_cr_size_x;i+=BLOCK_SIZE)
{
imgcof[j][i] = rshift_rnd_sf((imgcof[j][i] * InvLevelScale4x4[0][0]) << qp_per_uv_dc, 6);
}
}
}
}//for (ll=0;ll<3;ll+=2)
}//else if (dec_picture->chroma_format_idc == YUV422)
}
//========================== CHROMA AC ============================
//-----------------------------------------------------------------
// chroma AC coeff, all zero fram start_scan
if (cbp<=31)
{
if (active_pps->entropy_coding_mode_flag == UVLC)
memset(&img->nz_coeff [mb_nr ][1][0][0], 0, 2 * BLOCK_SIZE * BLOCK_SIZE * sizeof(int));
}
else
{
if (active_pps->entropy_coding_mode_flag == UVLC)
{
if(!lossless_qpprime)
{
for (b8=0; b8 < img->num_blk8x8_uv; b8++)
{
img->is_v_block = uv = (b8 > ((img->num_uv_blocks) - 1 ));
InvLevelScale4x4 = intra ? InvLevelScale4x4_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale4x4_Inter[uv + 1][qp_rem_uv[uv]];
for (b4=0; b4 < 4; b4++)
{
i = cofuv_blk_x[yuv][b8][b4];
j = cofuv_blk_y[yuv][b8][b4];
readCoeff4x4_CAVLC(currMB, img, CHROMA_AC, i + 2*uv, j + 4, levarr, runarr, &numcoeff);
coef_ctr = 0;
for(k = 0; k < numcoeff;k++)
{
if (levarr[k] != 0)
{
currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4];
coef_ctr += runarr[k] + 1;
i0=pos_scan4x4[coef_ctr][0];
j0=pos_scan4x4[coef_ctr][1];
img->cof[uv + 1][(j<<2) + j0][(i<<2) + i0] = rshift_rnd_sf((levarr[k] * InvLevelScale4x4[j0][i0])<<qp_per_uv[uv], 4);
img->fcf[uv + 1][(j<<2) + j0][(i<<2) + i0] = levarr[k];
}
}
}
}
}
else
{
for (b8=0; b8 < img->num_blk8x8_uv; b8++)
{
img->is_v_block = uv = (b8 > ((img->num_uv_blocks) - 1 ));
for (b4=0; b4 < 4; b4++)
{
i = cofuv_blk_x[yuv][b8][b4];
j = cofuv_blk_y[yuv][b8][b4];
readCoeff4x4_CAVLC(currMB, img, CHROMA_AC, i, j, levarr, runarr, &numcoeff);
coef_ctr=0;
level=1;
for(k = 0; k < numcoeff;k++)
{
if (levarr[k] != 0)
{
currMB->cbp_blk |= ((int64) 1) << cbp_blk_chroma[b8][b4];
coef_ctr += runarr[k] + 1;
i0 = pos_scan4x4[coef_ctr][0];
j0 = pos_scan4x4[coef_ctr][1];
img->cof[uv + 1][(j<<2) + j0][(i<<2) + i0] = levarr[k];
img->fcf[uv + 1][(j<<2) + j0][(i<<2) + i0] = levarr[k];
}
}
}
}
}
}
else
{
img->is_intra_block = IS_INTRA(currMB);
currSE.context = CHROMA_AC;
currSE.type = (img->is_intra_block ? SE_CHR_AC_INTRA : SE_CHR_AC_INTER);
dP = &(currSlice->partArr[partMap[currSE.type]]);
if (dP->bitstream->ei_flag)
currSE.mapping = linfo_levrun_inter;
else
currSE.reading = readRunLevel_CABAC;
if(!lossless_qpprime)
{
for (b8=0; b8 < img->num_blk8x8_uv; b8++)
{
img->is_v_block = uv = (b8 > ((img->num_uv_blocks) - 1 ));
InvLevelScale4x4 = intra ? InvLevelScale4x4_Intra[uv + 1][qp_rem_uv[uv]] : InvLevelScale4x4_Inter[uv + 1][qp_rem_uv[uv]];
for (b4 = 0; b4 < 4; b4++)
{
i = cofuv_blk_x[yuv][b8][b4];
j = cofuv_blk_y[yuv][b8][b4];
img->subblock_y = subblk_offset_y[yuv][b8][b4]>>2;
img->subblock_x = subblk_offset_x[yuv][b8][b4]>>2;
pos_scan_4x4 = pos_scan4x4[1];
level=1;
for(k = 0; (k < 16) && (level != 0);k++)
{
#if TRACE
snprintf(currSE.tracestring, TRACESTRING_SIZE, "AC Chroma ");
#endif
dP->readSyntaxElement(&currSE,img,dP);
level = currSE.value1;
if (level != 0)
{
currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4];
pos_scan_4x4 += (currSE.value2 << 1);
i0 = *pos_scan_4x4++;
j0 = *pos_scan_4x4++;
img->cof[uv + 1][(j<<2) + j0][(i<<2) + i0] = rshift_rnd_sf((level * InvLevelScale4x4[j0][i0])<<qp_per_uv[uv], 4);
img->fcf[uv + 1][(j<<2) + j0][(i<<2) + i0] = level;
}
} //for(k=0;(k<16)&&(level!=0);k++)
}
}
}
else
{
for (b8=0; b8 < img->num_blk8x8_uv; b8++)
{
img->is_v_block = uv = (b8 > ((img->num_uv_blocks) - 1 ));
for (b4=0; b4 < 4; b4++)
{
i = cofuv_blk_x[yuv][b8][b4];
j = cofuv_blk_y[yuv][b8][b4];
pos_scan_4x4 = pos_scan4x4[1];
level=1;
img->subblock_y = subblk_offset_y[yuv][b8][b4]>>2;
img->subblock_x = subblk_offset_x[yuv][b8][b4]>>2;
for(k=0;(k<16)&&(level!=0);k++)
{
#if TRACE
snprintf(currSE.tracestring, TRACESTRING_SIZE, "AC Chroma ");
#endif
dP->readSyntaxElement(&currSE,img,dP);
level = currSE.value1;
if (level != 0)
{
currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4];
pos_scan_4x4 += (currSE.value2 << 1);
i0 = *pos_scan_4x4++;
j0 = *pos_scan_4x4++;
img->cof[uv + 1][(j<<2) + j0][(i<<2) + i0] = level;
img->fcf[uv + 1][(j<<2) + j0][(i<<2) + i0] = level;
}
}
}
}
} //for (b4=0; b4 < 4; b4++)
} //for (b8=0; b8 < img->num_blk8x8_uv; b8++)
} //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(ImageParameters *img, Macroblock *currMB)
{
int i, j, k;
int mb_nr = 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 < MB_BLOCK_SIZE; i++)
{
for(j = 0;j < MB_BLOCK_SIZE ; j++)
{
dec_picture->imgY[img->pix_y+i][img->pix_x+j] = (imgpel) img->cof[0][i][j];
}
}
if ((dec_picture->chroma_format_idc != YUV400) && !IS_INDEPENDENT(img))
{
for (k = 0; k < 2; k++)
{
for(i = 0; i < img->mb_cr_size_y; i++)
{
for(j = 0;j < img->mb_cr_size_x; j++)
{
dec_picture->imgUV[k][img->pix_c_y+i][img->pix_c_x+j] = (imgpel) img->cof[k + 1][i][j];
}
}
}
}
// for deblocking filter
update_qp(img, currMB, 0);
// for CAVLC: Set the nz_coeff to 16.
// These parameters are to be used in CAVLC decoding of neighbour blocks
for (k = 0; k < 3; k++)
{
for (j = 0; j < BLOCK_SIZE; j++)
{
for(i = 0; i < BLOCK_SIZE; i++)
{
img->nz_coeff[mb_nr][k][j][i] = 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(ImageParameters *img, Macroblock *currMB, StorablePicture *dec_picture)
{
int i=0,j=0,k,l,ii=0,jj=0, j4=0,i4=0, j6;
int refList;
int uv, hv;
int ioff,joff;
int block8x8; // needed for ABT
int j_pos, i_pos;
static const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15};
int mb_nr = img->current_mb_nr;
short ref_idx;
int mv_mode, pred_dir; // = currMB->ref_frame;
int block_size_x, block_size_y;
int mv_scale;
static imgpel **curComp;
static imgpel (*mpr) [16];
static imgpel *cur_line;
static int *cur_m7;
int smb = ((img->type==SP_SLICE) && IS_INTER (currMB)) || (img->type == SI_SLICE && currMB->mb_type == SI4MB);
int list_offset;
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));
static MotionParams *colocated;
int need_4x4_transform = (!currMB->luma_transform_size_8x8_flag);
int yuv = dec_picture->chroma_format_idc - 1;
//For residual DPCM
Boolean lossless_qpprime = (Boolean) (((img->qp + img->bitdepth_luma_qp_scale) == 0) && (img->lossless_qpprime_flag == 1));
ipmode_DPCM = NO_INTRA_PMODE;
if (img->structure != FRAME || (img->MbaffFrameFlag && currMB->mb_field))
img->max_mb_vmv_r = img->max_vmv_r >> 1;
else
img->max_mb_vmv_r = img->max_vmv_r;
if(currMB->mb_type == IPCM)
{
//copy readed data into imgY and set parameters
decode_ipcm_mb(img, currMB);
return 0;
}
if (img->type==SP_SLICE && currMB->mb_type!=I16MB)
smb = 1;// modif ES added
//////////////////////////
// find out the correct list offsets
if (curr_mb_field)
{
if(mb_nr&0x01)
{
list_offset = 4; // top field mb
colocated = &Co_located->bottom;
}
else
{
list_offset = 2; // bottom field mb
colocated = &Co_located->top;
}
}
else
{
list_offset = 0; // no mb aff or frame mb
colocated = &Co_located->frame;
}
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(mb_nr % 2 == 0 && listX[l][k]->structure == BOTTOM_FIELD)
listX[l][k]->chroma_vector_adjustment = -2;
if(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;
}
}
}
}
// luma decoding **************************************************
// get prediction for INTRA_MB_16x16
if (IS_NEWINTRA (currMB))
{
intrapred_luma_16x16(img, currMB, PLANE_Y, currMB->i16mode);
ipmode_DPCM = currMB->i16mode; //For residual DPCM
// =============== 4x4 itrans ================
// -------------------------------------------
iMBtrans4x4(PLANE_Y, img, smb);
// chroma decoding *******************************************************
if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444))
{
intra_cr_decoding(currMB, yuv, img, smb);
}
}
else if (currMB->mb_type == I4MB)
{
itrans_4x4 = (!lossless_qpprime) ? itrans4x4 : Inv_Residual_trans_4x4;
for (block8x8 = 0; block8x8 < 4; block8x8++)
{
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);
joff = (j << 2);
i4 = img->block_x + i;
j4 = img->block_y + j;
j_pos = j4 * BLOCK_SIZE;
i_pos = i4 * BLOCK_SIZE;
// PREDICTION
//===== INTRA PREDICTION =====
if (intrapred(img, currMB, PLANE_Y, ioff,joff,i4,j4) == SEARCH_SYNC) /* make 4x4 prediction block mpr from given prediction img->mb_mode */
return SEARCH_SYNC; /* bit error */
// =============== 4x4 itrans ================
// -------------------------------------------
itrans_4x4 (img, (ColorPlane) LumaComp, ioff, joff); // use DCT transform and make 4x4 block m7 from prediction block mpr
for(jj=0;jj<BLOCK_SIZE;jj++)
{
cur_m7 = &img->mb_rres[0][jj + joff][ioff];
cur_line = &dec_picture->imgY[j_pos + jj][i_pos];
for(ii=0;ii<BLOCK_SIZE;ii++)
{
*(cur_line++) = (imgpel) (*cur_m7++); // construct picture from 4x4 blocks
}
}
}
}
// chroma decoding *******************************************************
if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444))
{
intra_cr_decoding(currMB, yuv, img, smb);
}
}
else if (currMB->mb_type == I8MB)
{
itrans_8x8 = (!lossless_qpprime) ? itrans8x8 : Inv_Residual_trans_8x8;
for (block8x8 = 0; block8x8 < 4; block8x8++)
{
//=========== 8x8 BLOCK TYPE ============
ioff = 8 * (block8x8 & 0x01);
joff = 8 * (block8x8 >> 1);
//PREDICTION
intrapred8x8(img, currMB, PLANE_Y, block8x8);
itrans_8x8(img, currMB, PLANE_Y, ioff,joff); // use DCT transform and make 8x8 block m7 from prediction block mpr
for(jj = joff; jj < joff + 8;jj++)
{
cur_m7 = &img->mb_rres[0][jj][ioff];
cur_line = &dec_picture->imgY[img->pix_y + jj][img->pix_x + ioff];
for(ii = 0; ii < 8; ii++)
{
*(cur_line++) = (imgpel) *(cur_m7++); // construct picture from 8x8 blocks
}
}
}
// chroma decoding *******************************************************
if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444))
{
intra_cr_decoding(currMB, yuv, img, smb);
}
}
else if ((img->type == P_SLICE) && (currMB->mb_type == PSKIP))
{
block_size_x = MB_BLOCK_SIZE;
block_size_y = MB_BLOCK_SIZE;
i = 0;
j = 0;
pred_dir = LIST_0;
perform_mc(PLANE_Y, dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
mpr = img->mb_pred[LumaComp];
curComp = &dec_picture->imgY[img->pix_y];
for(j = 0; j < img->mb_size[0][1]; j++)
{
memcpy(&(curComp[j][img->pix_x]), &(mpr[j][0]), img->mb_size[0][0] * sizeof(imgpel));
}
if ((dec_picture->chroma_format_idc != YUV400) && (dec_picture->chroma_format_idc != YUV444))
{
for(uv=0;uv<2;uv++)
{
curComp = &dec_picture->imgUV[uv][img->pix_c_y];
mpr = img->mb_pred[uv + 1];
for(jj = 0; jj < img->mb_size[1][1]; jj++)
memcpy(&(curComp[jj][img->pix_c_x]), &(mpr[jj][0]), img->mb_size[1][0] * sizeof(imgpel));
}
}
}
else if (currMB->mb_type == P16x16)
{
block_size_x = MB_BLOCK_SIZE;
block_size_y = MB_BLOCK_SIZE;
i = 0;
j = 0;
pred_dir = currMB->b8pdir[0];
perform_mc(PLANE_Y, dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
iTransform(img, currMB, PLANE_Y, need_4x4_transform, smb);
}
else if (currMB->mb_type == P16x8)
{
block_size_x = MB_BLOCK_SIZE;
block_size_y = 8;
for (block8x8 = 0; block8x8 < 4; block8x8 += 2)
{
i = 0;
j = block8x8;
pred_dir = currMB->b8pdir[block8x8];
perform_mc(PLANE_Y, dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
iTransform(img, currMB, PLANE_Y, need_4x4_transform, smb);
}
else if (currMB->mb_type == P8x16)
{
block_size_x = 8;
block_size_y = 16;
for (block8x8 = 0; block8x8 < 2; block8x8 ++)
{
i = block8x8<<1;
j = 0;
pred_dir = currMB->b8pdir[block8x8];
assert (pred_dir<=2);
perform_mc(PLANE_Y, dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
iTransform(img, currMB, PLANE_Y, need_4x4_transform, smb);
}
else
{
// prepare direct modes
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]))))
prepare_direct_params(currMB, dec_picture, img, pmvl0, pmvl1, &l0_rFrame, &l1_rFrame);
for (block8x8=0; block8x8<4; block8x8++)
{
mv_mode = currMB->b8mode[block8x8];
pred_dir = currMB->b8pdir[block8x8];
//if ( mv_mode == SMB8x8 || mv_mode == SMB8x4 || mv_mode == SMB4x8 || mv_mode == SMB4x4 )
if ( mv_mode != 0 )
{
int k_start = (block8x8 << 2);
int k_inc = (mv_mode == SMB8x4) ? 2 : 1;
int k_end = (mv_mode == SMB8x8) ? k_start + 1 : ((mv_mode == SMB4x4) ? k_start + 4 : k_start + k_inc + 1);
block_size_x = ( mv_mode == SMB8x4 || mv_mode == SMB8x8 ) ? SMB_BLOCK_SIZE : BLOCK_SIZE;
block_size_y = ( mv_mode == SMB4x8 || mv_mode == SMB8x8 ) ? SMB_BLOCK_SIZE : BLOCK_SIZE;
for (k = k_start; k < k_end; k += k_inc)
{
i = (decode_block_scan[k] & 3);
j = ((decode_block_scan[k] >> 2) & 3);
perform_mc(PLANE_Y, dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
}
else
{
int k_start = (block8x8 << 2);
int k_end = k_start;
if (active_sps->direct_8x8_inference_flag)
{
block_size_x = SMB_BLOCK_SIZE;
block_size_y = SMB_BLOCK_SIZE;
k_end ++;
}
else
{
block_size_x = BLOCK_SIZE;
block_size_y = BLOCK_SIZE;
k_end += BLOCK_MULTIPLE;
}
// Prepare mvs (needed for deblocking and mv prediction
if (img->direct_spatial_mv_pred_flag)
{
for (k = k_start; k < k_start + BLOCK_MULTIPLE; 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;
assert (pred_dir<=2);
j6 = img->block_y_aff + j;
//===== DIRECT PREDICTION =====
if (l0_rFrame >=0)
{
if (!l0_rFrame && ((!colocated->moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
{
dec_picture->motion.mv [LIST_0][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_0][j4][i4][1] = 0;
dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
}
else
{
dec_picture->motion.mv [LIST_0][j4][i4][0] = pmvl0[0];
dec_picture->motion.mv [LIST_0][j4][i4][1] = pmvl0[1];
dec_picture->motion.ref_idx[LIST_0][j4][i4] = l0_rFrame;
}
}
else
{
dec_picture->motion.ref_idx[LIST_0][j4][i4] = -1;
dec_picture->motion.mv [LIST_0][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_0][j4][i4][1] = 0;
}
if (l1_rFrame >=0)
{
if (l1_rFrame==0 && ((!colocated->moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
{
dec_picture->motion.mv [LIST_1][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_1][j4][i4][1] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = l1_rFrame;
}
else
{
dec_picture->motion.mv [LIST_1][j4][i4][0] = pmvl1[0];
dec_picture->motion.mv [LIST_1][j4][i4][1] = pmvl1[1];
dec_picture->motion.ref_idx[LIST_1][j4][i4] = l1_rFrame;
}
}
else
{
dec_picture->motion.mv [LIST_1][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_1][j4][i4][1] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = -1;
}
if (l0_rFrame < 0 && l1_rFrame < 0)
{
dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
}
if (dec_picture->motion.ref_idx[LIST_1][j4][i4]==-1)
{
direct_pdir = 0;
ref_idx = (dec_picture->motion.ref_idx[LIST_0][j4][i4] != -1) ? dec_picture->motion.ref_idx[LIST_0][j4][i4] : 0;
}
else if (dec_picture->motion.ref_idx[LIST_0][j4][i4]==-1)
{
direct_pdir = 1;
ref_idx = (dec_picture->motion.ref_idx[LIST_1][j4][i4] != -1) ? dec_picture->motion.ref_idx[LIST_1][j4][i4] : 0;
}
else
direct_pdir = 2;
pred_dir = direct_pdir;
dec_picture->motion.ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->motion.ref_idx[LIST_0][j4][i4]];
dec_picture->motion.ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->motion.ref_idx[LIST_1][j4][i4]];
}
}
else
{
for (k = k_start; k < k_start + BLOCK_MULTIPLE; 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;
assert (pred_dir<=2);
j6 = img->block_y_aff + j;
refList = (colocated->ref_idx[LIST_0][j6][i4]== -1 ? LIST_1 : LIST_0);
ref_idx = colocated->ref_idx[refList][j6][i4];
if(ref_idx==-1) // co-located is intra mode
{
memset( &dec_picture->motion.mv [LIST_0][j4][i4][0], 0, 2* sizeof(short));
memset( &dec_picture->motion.mv [LIST_1][j4][i4][0], 0, 2* sizeof(short));
dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = 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 colocated->ref_pic_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 == colocated->ref_pic_id[refList][j6][i4] || listX[0][iref]->bottom_poc*2 == colocated->ref_pic_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]==colocated->ref_pic_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);
}
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)
{
memcpy(&dec_picture->motion.mv [LIST_0][j4][i4][0], &colocated->mv[refList][j6][i4][0], 2 * sizeof(short));
memset(&dec_picture->motion.mv [LIST_1][j4][i4][0], 0, 2 * sizeof(short));
}
else
{
dec_picture->motion.mv [LIST_0][j4][i4][0]=(mv_scale * colocated->mv[refList][j6][i4][0] + 128 ) >> 8;
dec_picture->motion.mv [LIST_0][j4][i4][1]=(mv_scale * colocated->mv[refList][j6][i4][1] + 128 ) >> 8;
dec_picture->motion.mv [LIST_1][j4][i4][0]=dec_picture->motion.mv[LIST_0][j4][i4][0] - colocated->mv[refList][j6][i4][0] ;
dec_picture->motion.mv [LIST_1][j4][i4][1]=dec_picture->motion.mv[LIST_0][j4][i4][1] - colocated->mv[refList][j6][i4][1] ;
}
dec_picture->motion.ref_idx[LIST_0][j4][i4] = (char) mapped_idx; //listX[1][0]->ref_idx[refList][j4][i4];
dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
}
// store reference picture ID determined by direct mode
dec_picture->motion.ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->motion.ref_idx[LIST_0][j4][i4]];
dec_picture->motion.ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->motion.ref_idx[LIST_1][j4][i4]];
}
}
for (k = k_start; k < k_end; k ++)
{
i = (decode_block_scan[k] & 3);
j = ((decode_block_scan[k] >> 2) & 3);
perform_mc(PLANE_Y, dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
}
}
iTransform(img, currMB, PLANE_Y, need_4x4_transform, smb);
}
if ((active_sps->chroma_format_idc==YUV444)&&(!IS_INDEPENDENT(img)))
{
for (uv = 0; uv < 2; uv++ )
{
if (IS_NEWINTRA (currMB))
{
// =============== 4x4 itrans ================
// -------------------------------------------
if (uv==0)
{
intrapred_luma_16x16(img, currMB, PLANE_U, currMB->i16mode);
iMBtrans4x4(PLANE_U, img, smb);
}
else
{
intrapred_luma_16x16(img, currMB, PLANE_V, currMB->i16mode);
iMBtrans4x4(PLANE_V, img, smb);
}
}
else if (currMB->mb_type == I4MB)
{
itrans_4x4 = (!lossless_qpprime) ? itrans4x4 : Inv_Residual_trans_4x4;
for (block8x8 = 0; block8x8 < 4; block8x8++)
{
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);
joff = (j << 2);
i4 = img->block_x + i;
j4 = img->block_y + j;
j_pos = j4 * BLOCK_SIZE;
i_pos = i4 * BLOCK_SIZE;
// PREDICTION
//===== INTRA PREDICTION =====
if (intrapred(img, currMB, (ColorPlane) (uv + 1), ioff, joff, i4,j4)==SEARCH_SYNC) /* make 4x4 prediction block mpr from given prediction img->mb_mode */
return SEARCH_SYNC; /* bit error */
// =============== 4x4 itrans ================
// -------------------------------------------
itrans_4x4 (img, (ColorPlane) (uv + 1), ioff, joff);
for(jj=0;jj<BLOCK_SIZE;jj++)
{
for(ii=0;ii<BLOCK_SIZE;ii++)
{
dec_picture->imgUV[uv][j_pos + jj][i_pos + ii] = (imgpel) img->mb_rres[uv+1][jj + joff][ii + ioff]; // construct picture from 4x4 blocks
}
}
}
}
} //I4MB
else if (currMB->mb_type == I8MB)
{
itrans_8x8 = (!lossless_qpprime) ? itrans8x8 : Inv_Residual_trans_8x8;
for (block8x8 = 0; block8x8 < 4; block8x8++)
{
//=========== 8x8 BLOCK TYPE ============
ioff = 8 * (block8x8 & 0x01);
joff = 8 * (block8x8 >> 1);
//PREDICTION
intrapred8x8(img, currMB, (ColorPlane) (uv + 1), block8x8);
//For residual DPCM
itrans_8x8(img, currMB, (ColorPlane) (uv + 1), 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->imgUV[uv][img->pix_y + jj][img->pix_x + ii] = (imgpel) img->mb_rres[uv+1][jj][ii]; // construct picture from 4x4 blocks
}
}
}
} //I8MB
else if ((img->type == P_SLICE) && (currMB->mb_type == PSKIP))
{
block_size_x = MB_BLOCK_SIZE;
block_size_y = MB_BLOCK_SIZE;
i = 0;
j = 0;
pred_dir = LIST_0;
perform_mc((ColorPlane) (uv + 1), dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
mpr = img->mb_pred[uv+1];
curComp = dec_picture->imgUV[uv];
for(j = 0; j < img->mb_size[0][1]; j++)
{
memcpy(&(curComp[img->pix_y + j][img->pix_x]), &(mpr[j][0]), img->mb_size[0][0] * sizeof(imgpel));
}
} //PSKIP
else if (currMB->mb_type == P16x16)
{
block_size_x = MB_BLOCK_SIZE;
block_size_y = MB_BLOCK_SIZE;
i = 0;
j = 0;
pred_dir = currMB->b8pdir[0];
perform_mc((ColorPlane) (uv + 1), dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
iTransform(img, currMB, (ColorPlane) (uv + 1), need_4x4_transform, smb);
} //P16x16
else if (currMB->mb_type == P16x8)
{
block_size_x = MB_BLOCK_SIZE;
block_size_y = 8;
for (block8x8 = 0; block8x8 < 4; block8x8 += 2)
{
i = 0;
j = block8x8;
pred_dir = currMB->b8pdir[block8x8];
perform_mc((ColorPlane) (uv + 1), dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
iTransform(img, currMB, (ColorPlane) (uv + 1), need_4x4_transform, smb);
} //P16x8
else if (currMB->mb_type == P8x16)
{
block_size_x = 8;
block_size_y = 16;
for (block8x8 = 0; block8x8 < 2; block8x8 ++)
{
i = block8x8<<1;
j = 0;
pred_dir = currMB->b8pdir[block8x8];
assert (pred_dir<=2);
perform_mc((ColorPlane) (uv + 1), dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
iTransform(img, currMB, (ColorPlane) (uv + 1), need_4x4_transform, smb);
} //P8x16
else
{
// prepare direct modes
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]))))
prepare_direct_params(currMB, dec_picture, img, pmvl0, pmvl1, &l0_rFrame, &l1_rFrame);
for (block8x8=0; block8x8<4; block8x8++)
{
mv_mode = currMB->b8mode[block8x8];
pred_dir = currMB->b8pdir[block8x8];
//if ( mv_mode == SMB8x8 || mv_mode == SMB8x4 || mv_mode == SMB4x8 || mv_mode == SMB4x4 )
if ( mv_mode != 0 )
{
int k_start = (block8x8 << 2);
int k_inc = (mv_mode == SMB8x4) ? 2 : 1;
int k_end = (mv_mode == SMB8x8) ? k_start + 1 : ((mv_mode == SMB4x4) ? k_start + 4 : k_start + k_inc + 1);
block_size_x = ( mv_mode == SMB8x4 || mv_mode == SMB8x8 ) ? SMB_BLOCK_SIZE : BLOCK_SIZE;
block_size_y = ( mv_mode == SMB4x8 || mv_mode == SMB8x8 ) ? SMB_BLOCK_SIZE : BLOCK_SIZE;
for (k = k_start; k < k_end; k += k_inc)
{
i = (decode_block_scan[k] & 3);
j = ((decode_block_scan[k] >> 2) & 3);
perform_mc((ColorPlane) (uv + 1), dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
}
else
{
int k_start = (block8x8 << 2);
int k_end = k_start;
if (active_sps->direct_8x8_inference_flag)
{
block_size_x = SMB_BLOCK_SIZE;
block_size_y = SMB_BLOCK_SIZE;
k_end ++;
}
else
{
block_size_x = BLOCK_SIZE;
block_size_y = BLOCK_SIZE;
k_end += BLOCK_MULTIPLE;
}
// Prepare mvs (needed for deblocking and mv prediction
for (k = k_start; k < k_start + BLOCK_MULTIPLE; 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;
assert (pred_dir<=2);
if (img->direct_spatial_mv_pred_flag)
{
j6 = img->block_y_aff + j;
//===== DIRECT PREDICTION =====
if (l0_rFrame >=0)
{
if (!l0_rFrame && ((!colocated->moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
{
dec_picture->motion.mv [LIST_0][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_0][j4][i4][1] = 0;
dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
}
else
{
dec_picture->motion.mv [LIST_0][j4][i4][0] = pmvl0[0];
dec_picture->motion.mv [LIST_0][j4][i4][1] = pmvl0[1];
dec_picture->motion.ref_idx[LIST_0][j4][i4] = l0_rFrame;
}
}
else
{
dec_picture->motion.ref_idx[LIST_0][j4][i4] = -1;
dec_picture->motion.mv [LIST_0][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_0][j4][i4][1] = 0;
}
if (l1_rFrame >=0)
{
if (l1_rFrame==0 && ((!colocated->moving_block[j6][i4]) && (!listX[LIST_1 + list_offset][0]->is_long_term)))
{
dec_picture->motion.mv [LIST_1][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_1][j4][i4][1] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = l1_rFrame;
}
else
{
dec_picture->motion.mv [LIST_1][j4][i4][0] = pmvl1[0];
dec_picture->motion.mv [LIST_1][j4][i4][1] = pmvl1[1];
dec_picture->motion.ref_idx[LIST_1][j4][i4] = l1_rFrame;
}
}
else
{
dec_picture->motion.mv [LIST_1][j4][i4][0] = 0;
dec_picture->motion.mv [LIST_1][j4][i4][1] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = -1;
}
if (l0_rFrame < 0 && l1_rFrame < 0)
{
dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
}
if (dec_picture->motion.ref_idx[LIST_1][j4][i4]==-1)
{
direct_pdir = 0;
ref_idx = (dec_picture->motion.ref_idx[LIST_0][j4][i4] != -1) ? dec_picture->motion.ref_idx[LIST_0][j4][i4] : 0;
}
else if (dec_picture->motion.ref_idx[LIST_0][j4][i4]==-1)
{
direct_pdir = 1;
ref_idx = (dec_picture->motion.ref_idx[LIST_1][j4][i4] != -1) ? dec_picture->motion.ref_idx[LIST_1][j4][i4] : 0;
}
else
direct_pdir = 2;
pred_dir = direct_pdir;
}
else
{
j6= img->block_y_aff + j;
refList = (colocated->ref_idx[LIST_0][j6][i4]== -1 ? LIST_1 : LIST_0);
ref_idx = colocated->ref_idx[refList][j6][i4];
if(ref_idx==-1) // co-located is intra mode
{
for(hv=0; hv<2; hv++)
{
dec_picture->motion.mv [LIST_0][j4][i4][hv]=0;
dec_picture->motion.mv [LIST_1][j4][i4][hv]=0;
}
dec_picture->motion.ref_idx[LIST_0][j4][i4] = 0;
dec_picture->motion.ref_idx[LIST_1][j4][i4] = 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 colocated->ref_pic_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 == colocated->ref_pic_id[refList][j6][i4] || listX[0][iref]->bottom_poc*2 == colocated->ref_pic_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]==colocated->ref_pic_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);
}
}
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->motion.mv [LIST_0][j4][i4][0]=colocated->mv[refList][j6][i4][0];
dec_picture->motion.mv [LIST_0][j4][i4][1]=colocated->mv[refList][j6][i4][1];
dec_picture->motion.mv [LIST_1][j4][i4][0]=0;
dec_picture->motion.mv [LIST_1][j4][i4][1]=0;
}
else
{
dec_picture->motion.mv [LIST_0][j4][i4][0] = (short) ((mv_scale * colocated->mv[refList][j6][i4][0] + 128 ) >> 8);
dec_picture->motion.mv [LIST_0][j4][i4][1] = (short) ((mv_scale * colocated->mv[refList][j6][i4][1] + 128 ) >> 8);
dec_picture->motion.mv [LIST_1][j4][i4][0] = (short) (dec_picture->motion.mv[LIST_0][j4][i4][0] - colocated->mv[refList][j6][i4][0]);
dec_picture->motion.mv [LIST_1][j4][i4][1] = (short) (dec_picture->motion.mv[LIST_0][j4][i4][1] - colocated->mv[refList][j6][i4][1]);
}
dec_picture->motion.ref_idx[LIST_0][j4][i4] = (char) mapped_idx; //listX[1][0]->ref_idx[refList][j4][i4];
dec_picture->motion.ref_idx[LIST_1][j4][i4] = 0;
}
}
// store reference picture ID determined by direct mode
dec_picture->motion.ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->motion.ref_idx[LIST_0][j4][i4]];
dec_picture->motion.ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->motion.ref_idx[LIST_1][j4][i4]];
}
for (k = k_start; k < k_end; k ++)
{
i = (decode_block_scan[k] & 3);
j = ((decode_block_scan[k] >> 2) & 3);
perform_mc((ColorPlane) (uv + 1), dec_picture, img, pred_dir, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
}
}
iTransform(img, currMB, (ColorPlane) (uv + 1), need_4x4_transform, smb);
}
}
}
return 0;
}
/*!
************************************************************************
* \brief
* change target plane
* for 4:4:4 Independent mode
************************************************************************
*/
void change_plane_JV( int nplane )
{
img->colour_plane_id = nplane;
img->mb_data = img->mb_data_JV[nplane];
dec_picture = dec_picture_JV[nplane];
Co_located = Co_located_JV[nplane];
}
/*!
************************************************************************
* \brief
* make frame picture from each plane data
* for 4:4:4 Independent mode
************************************************************************
*/
void make_frame_picture_JV()
{
int uv, line;
int nsize;
int nplane;
dec_picture = dec_picture_JV[0];
// Copy Storable Params
for( nplane=0; nplane<MAX_PLANE; nplane++ )
{
copy_storable_param_JV( &dec_picture->JVmotion[nplane], &dec_picture_JV[nplane]->motion );
}
// This could be done with pointers and seems not necessary
for( uv=0; uv<2; uv++ )
{
for( line=0; line<img->height; line++ )
{
nsize = sizeof(imgpel) * img->width;
memcpy( dec_picture->imgUV[uv][line], dec_picture_JV[uv+1]->imgY[line], nsize );
}
free_storable_picture(dec_picture_JV[uv+1]);
}
}
|
|
|
The lossless mode is now set in the update_qp() function. This should fix the problem. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2008-12-02 15:37 | Eugeniy Belyaev | New Issue | |
| 2008-12-02 15:37 | Eugeniy Belyaev | File Added: macroblock.c | |
| 2008-12-15 15:09 | Karsten Suehring | Note Added: 0000263 | |
| 2008-12-15 15:09 | Karsten Suehring | Status | new => resolved |
| 2008-12-15 15:09 | Karsten Suehring | Fixed in Version | => JM 14.2-dev |
| 2008-12-15 15:09 | Karsten Suehring | Resolution | open => fixed |
| 2008-12-15 15:09 | Karsten Suehring | Assigned To | => Karsten Suehring |