Intra angular fixed, intra filtering. This version produces bit-perfect output.

This commit is contained in:
Marko Viitanen 2013-03-19 15:45:50 +02:00
parent 83b904e34d
commit 08cc0e97ab
3 changed files with 162 additions and 23 deletions

View file

@ -130,7 +130,7 @@
/* input init (ToDo: read from commandline / config) */ /* input init (ToDo: read from commandline / config) */
encoder->bitdepth = 8; encoder->bitdepth = 8;
encoder->frame = 0; encoder->frame = 0;
encoder->QP = 35; encoder->QP = 36;
encoder->in.video_format = FORMAT_420; encoder->in.video_format = FORMAT_420;
init_encoder_input(&encoder->in, input, cfg->width, cfg->height); init_encoder_input(&encoder->in, input, cfg->width, cfg->height);
@ -141,10 +141,13 @@
fread(encoder->in.cur_pic.yData, cfg->width*cfg->height,1,input); fread(encoder->in.cur_pic.yData, cfg->width*cfg->height,1,input);
fread(encoder->in.cur_pic.uData, cfg->width*cfg->height>>2,1,input); fread(encoder->in.cur_pic.uData, cfg->width*cfg->height>>2,1,input);
fread(encoder->in.cur_pic.vData, cfg->width*cfg->height>>2,1,input); fread(encoder->in.cur_pic.vData, cfg->width*cfg->height>>2,1,input);
/* Clear reconstruction buffers */
memset(encoder->in.cur_pic.yRecData, 0, cfg->width*cfg->height); memset(encoder->in.cur_pic.yRecData, 0, cfg->width*cfg->height);
memset(encoder->in.cur_pic.uRecData, 128, cfg->width*cfg->height>>2); memset(encoder->in.cur_pic.uRecData, 128, cfg->width*cfg->height>>2);
memset(encoder->in.cur_pic.vRecData, 128, cfg->width*cfg->height>>2); memset(encoder->in.cur_pic.vRecData, 128, cfg->width*cfg->height>>2);
/* /////////////THE ACTUAL CODING HAPPENDS HERE\\\\\\\\\\\\\\\\\\\ */
encode_one_frame(encoder); encode_one_frame(encoder);
#ifdef _DEBUG #ifdef _DEBUG

View file

@ -334,12 +334,29 @@ void encode_one_frame(encoder_control* encoder)
bitstream_clear_buffer(encoder->stream); bitstream_clear_buffer(encoder->stream);
*/ */
} }
#ifdef _DEBUG
/*
{
int x,y;
for(y = 0; y < encoder->in.height_in_LCU*2;y++)
{
for(x = 0;x < encoder->in.width_in_LCU*2;x++)
{
i = (x<<2)+(y<<2)*(encoder->in.width_in_LCU<<MAX_DEPTH);
printf("(%d,%d) Intramode: %d\n", x<<2, y<<2,encoder->in.cur_pic.CU[0][i].intra.mode);
}
}
}
*/
#endif
/* Clear prediction data */ /* Clear prediction data */
/* ToDo: store */ /* ToDo: store */
for(i=0; i < MAX_DEPTH+1; i++) for(i=0; i < MAX_DEPTH+1; i++)
{ {
memset(encoder->in.cur_pic.CU[i], 0, (encoder->in.height_in_LCU<<MAX_DEPTH)*(encoder->in.width_in_LCU<<MAX_DEPTH)*sizeof(CU_info)); memset(encoder->in.cur_pic.CU[i], 0, (encoder->in.height_in_LCU<<MAX_DEPTH)*(encoder->in.width_in_LCU<<MAX_DEPTH)*sizeof(CU_info));
} }
} }
void encode_pic_parameter_set(encoder_control* encoder) void encode_pic_parameter_set(encoder_control* encoder)
@ -745,7 +762,15 @@ void encode_coding_tree(encoder_control* encoder,uint16_t xCtb,uint16_t yCtb, ui
//int16_t dcpredV = intra_getDCPred(encoder->in.cur_pic.vRecData,encoder->in.width>>1, xCtb*(LCU_WIDTH>>(MAX_DEPTH+1)), yCtb*(LCU_WIDTH>>(MAX_DEPTH+1)), depth+1); //int16_t dcpredV = intra_getDCPred(encoder->in.cur_pic.vRecData,encoder->in.width>>1, xCtb*(LCU_WIDTH>>(MAX_DEPTH+1)), yCtb*(LCU_WIDTH>>(MAX_DEPTH+1)), depth+1);
cabac_encodeBinTrm(&cabac, 0); /* IPCMFlag == 0 */ cabac_encodeBinTrm(&cabac, 0); /* IPCMFlag == 0 */
/*
{
FILE *recout = fopen("blockrec.yuv", "wb");
fwrite(encoder->in.cur_pic.yRecData,encoder->cfg->width*encoder->cfg->height,1,recout);
fwrite(encoder->in.cur_pic.uRecData,encoder->cfg->width*encoder->cfg->height>>2,1,recout);
fwrite(encoder->in.cur_pic.vRecData,encoder->cfg->width*encoder->cfg->height>>2,1,recout);
fclose(recout);
}
*/
/* Build reconstructed block to use in prediction with extrapolated borders */ /* Build reconstructed block to use in prediction with extrapolated borders */
intra_buildReferenceBorder(&encoder->in.cur_pic, xCtb, yCtb,(LCU_WIDTH>>(depth))*2+8, rec, (LCU_WIDTH>>(depth))*2+8, 0); intra_buildReferenceBorder(&encoder->in.cur_pic, xCtb, yCtb,(LCU_WIDTH>>(depth))*2+8, rec, (LCU_WIDTH>>(depth))*2+8, 0);
@ -886,7 +911,7 @@ void encode_coding_tree(encoder_control* encoder,uint16_t xCtb,uint16_t yCtb, ui
} }
/* Transform and quant residual to coeffs */ /* Transform and quant residual to coeffs */
transform2d(block,pre_quant_coeff,LCU_WIDTH>>depth,0); transform2d(block,pre_quant_coeff,width,0);
quant(encoder,pre_quant_coeff,coeff, width, width, 0); quant(encoder,pre_quant_coeff,coeff, width, width, 0);
/* Check for non-zero coeffs */ /* Check for non-zero coeffs */
@ -906,7 +931,7 @@ void encode_coding_tree(encoder_control* encoder,uint16_t xCtb,uint16_t yCtb, ui
{ {
/* RECONSTRUCT for predictions */ /* RECONSTRUCT for predictions */
dequant(encoder,coeff,pre_quant_coeff,width, width,0); dequant(encoder,coeff,pre_quant_coeff,width, width,0);
itransform2d(block,pre_quant_coeff,LCU_WIDTH>>depth,0); itransform2d(block,pre_quant_coeff,width,0);
i = 0; i = 0;
for(y = 0; y < LCU_WIDTH>>depth; y++) for(y = 0; y < LCU_WIDTH>>depth; y++)

View file

@ -190,6 +190,69 @@ int8_t intra_getDirLumaPredictor(picture* pic,uint32_t xCtb, uint32_t yCtb, uint
return 1; return 1;
} }
void intra_filter(int16_t* ref, uint32_t stride,uint32_t width, int8_t mode)
{
#define FWIDTH (LCU_WIDTH+1)
int16_t filtered[FWIDTH*FWIDTH];
int16_t* filteredShift = &filtered[FWIDTH+1];
int x,y;
if(!mode)
{
//pF[ -1 ][ -1 ] = ( p[ -1 ][ 0 ] + 2 * p[ -1 ][ -1 ] + p[ 0 ][ -1 ] + 2 ) >> 2 (8 35)
filteredShift[-FWIDTH-1] = (ref[-1]+2*ref[-stride-1]+ref[-stride]+2) >> 2;
//pF[ -1 ][ y ] = ( p[ -1 ][ y + 1 ] + 2 * p[ -1 ][ y ] + p[ -1 ][ y - 1 ] + 2 ) >> 2 for y = 0..nTbS * 2 - 2 (8 36)
for(y = 0; y < width*2-1; y++)
{
filteredShift[y*FWIDTH-1] = (ref[(y+1)*stride-1] + 2*ref[y*stride-1] + ref[(y-1)*stride-1]+2) >> 2;
}
//pF[ -1 ][ nTbS * 2 - 1 ] = p[ -1 ][ nTbS * 2 - 1 ] (8 37)
filteredShift[(width*2-1)*FWIDTH-1] = ref[(width*2-1)*stride-1];
//pF[ x ][ -1 ] = ( p[ x - 1 ][ -1 ] + 2 * p[ x ][ -1 ] + p[ x + 1 ][ -1 ] + 2 ) >> 2 for x = 0..nTbS * 2 - 2 (8 38)
for(x = 0; x < width*2-1; x++)
{
filteredShift[x-FWIDTH] = (ref[x-1-stride] + 2*ref[x-stride] + ref[x+1-stride]+2) >> 2;
}
//pF[ nTbS * 2 - 1 ][ -1 ] = p[ nTbS * 2 - 1 ][ -1 ]
filteredShift[(width*2-1)-FWIDTH] = ref[(width*2-1)-stride];
for(x = -1; x < (int32_t)width*2; x++)
{
ref[x-stride] = filtered[x+1];
}
for(y = 0; y < width*2; y++)
{
ref[y*stride-1] = filtered[(y+1)*FWIDTH];
}
/*
{
FILE* test = fopen("blockoutF2.yuv","wb");
uint8_t outvalue;
for(y = 0; y < 72; y++)
{
for(x = 0; x < 72; x++)
{
outvalue = filtered[(x)+(y)*FWIDTH];
fwrite(&outvalue,1,1,test);
}
}
fclose(test);
}
*/
}
else
{
printf("UNHANDLED: %s: %d\r\n", __FILE__, __LINE__);
exit(1);
}
#undef FWIDTH
}
/*! \brief Function to test best intra prediction /*! \brief Function to test best intra prediction
\param orig original picture data \param orig original picture data
\param origstride original picture stride \param origstride original picture stride
@ -251,9 +314,7 @@ int16_t intra_prediction(uint8_t* orig,uint32_t origstride,int16_t* rec,uint32_t
} }
} }
/* Test planar */
intra_getPlanarPred(rec, recstride, xpos, ypos, width, pred, width);
CHECK_FOR_BEST(0);
/* Test DC */ /* Test DC */
x = intra_getDCPred(rec, recstride, xpos, ypos, width); x = intra_getDCPred(rec, recstride, xpos, ypos, width);
for(i = 0; i < width*width; i++) for(i = 0; i < width*width; i++)
@ -261,20 +322,62 @@ int16_t intra_prediction(uint8_t* orig,uint32_t origstride,int16_t* rec,uint32_t
pred[i] = x; pred[i] = x;
} }
CHECK_FOR_BEST(1); CHECK_FOR_BEST(1);
intra_getAngularPred(rec,recstride,pred, width,width,width,10, xpos?1:0, ypos?1:0, 0);
CHECK_FOR_BEST(10);
intra_getAngularPred(rec,recstride,pred, width,width,width,26, xpos?1:0, ypos?1:0, 0);
CHECK_FOR_BEST(26);
/*Apply filter*/
intra_filter(rec,recstride,width,0);
/*
{
FILE* test = fopen("blockoutF.yuv","wb");
uint8_t outvalue;
for(y = 0; y < recstride; y++)
{
for(x = 0; x < recstride; x++)
{
outvalue = rec[(x-1)+(y-1)*recstride];
fwrite(&outvalue,1,1,test);
}
}
fclose(test);
}
*/
/* Test planar */
intra_getPlanarPred(rec, recstride, xpos, ypos, width, pred, width);
CHECK_FOR_BEST(0);
/* Test directional predictions */ /* Test directional predictions */
/* ToDo: add conditions to skip some modes on borders */ /* ToDo: add conditions to skip some modes on borders */
//chroma can use only 26 and 10 //chroma can use only 26 and 10
//OK: 26 10
/* //if(xpos && ypos)
if(xpos && ypos)
//for(i = 2; i < 35; i++) //for(i = 2; i < 35; i++)
//for(i = 26; i < 35; i++) //for(i = 26; i < 35; i++)
for(i = 2; i < 35; i++) for(i = 2; i < 35; i++)
{
if(i != 10 && i != 26)
{ {
intra_getAngularPred(rec,recstride,pred, width,width,width,i, xpos?1:0, ypos?1:0, 0); intra_getAngularPred(rec,recstride,pred, width,width,width,i, xpos?1:0, ypos?1:0, 0);
CHECK_FOR_BEST(i); CHECK_FOR_BEST(i);
} }
}
/*
intra_getAngularPred(rec,recstride,pred, width,width,width,2, xpos?1:0, ypos?1:0, 0);
CHECK_FOR_BEST(2);
*/
/*
intra_getAngularPred(rec,recstride,pred, width,width,width,3, xpos?1:0, ypos?1:0, 0);
CHECK_FOR_BEST(3);
*/ */
*sad = bestSAD; *sad = bestSAD;
@ -316,6 +419,14 @@ void intra_recon(int16_t* rec,uint32_t recstride, uint32_t xpos, uint32_t ypos,u
COPY_PRED_TO_DST(); COPY_PRED_TO_DST();
} }
/*! \brief this functions build a reference block (only borders) used for intra predictions
\param pic picture to use as a source, should contain full CU-data
\param outwidth width of the prediction block
\param chroma signaling if chroma is used, 0 = luma, 1 = U and 2 = V
*/
void intra_buildReferenceBorder(picture* pic, int32_t xCtb, int32_t yCtb,int8_t outwidth, int16_t* dst, int32_t dststride, int8_t chroma) void intra_buildReferenceBorder(picture* pic, int32_t xCtb, int32_t yCtb,int8_t outwidth, int16_t* dst, int32_t dststride, int8_t chroma)
{ {
int32_t leftColumn; /*!< left column iterator */ int32_t leftColumn; /*!< left column iterator */
@ -330,7 +441,7 @@ void intra_buildReferenceBorder(picture* pic, int32_t xCtb, int32_t yCtb,int8_t
uint8_t* srcShifted = &srcPic[xCtb*SCU_width+(yCtb*SCU_width)*srcWidth]; /*!< input picture pointer shifted to start from the left-top corner of the current block */ uint8_t* srcShifted = &srcPic[xCtb*SCU_width+(yCtb*SCU_width)*srcWidth]; /*!< input picture pointer shifted to start from the left-top corner of the current block */
int32_t width_in_SCU = srcWidth/SCU_width; /*!< picture width in SCU */ int32_t width_in_SCU = srcWidth/SCU_width; /*!< picture width in SCU */
memset(dst,0,outwidth*outwidth*sizeof(int16_t)); //memset(dst,127,outwidth*outwidth*sizeof(int16_t));
/* Fill left column */ /* Fill left column */
if(xCtb) if(xCtb)
@ -405,7 +516,7 @@ void intra_buildReferenceBorder(picture* pic, int32_t xCtb, int32_t yCtb,int8_t
} }
/* Topleft corner */ /* Topleft corner */
dst[0] = (xCtb&&yCtb)?srcShifted[-srcWidth-1]:dst[dststride]; dst[0] = (xCtb&&yCtb)?srcShifted[-srcWidth-1]:dst[dststride];
/*
{ {
FILE* test = fopen("blockout.yuv","wb"); FILE* test = fopen("blockout.yuv","wb");
int x,y; int x,y;
@ -420,7 +531,7 @@ void intra_buildReferenceBorder(picture* pic, int32_t xCtb, int32_t yCtb,int8_t
} }
fclose(test); fclose(test);
} }
*/
} }
void intra_getAngularPred(uint16_t* pSrc, int32_t srcStride, int16_t* rpDst, int32_t dstStride, int32_t width, int32_t height, int32_t dirMode, int8_t leftAvail,int8_t topAvail, int8_t filter) void intra_getAngularPred(uint16_t* pSrc, int32_t srcStride, int16_t* rpDst, int32_t dstStride, int32_t width, int32_t height, int32_t dirMode, int8_t leftAvail,int8_t topAvail, int8_t filter)
@ -591,9 +702,9 @@ void intra_DCPredFiltering(uint8_t* pSrc, int32_t iSrcStride, uint8_t* rpDst, in
void intra_getPlanarPred(int16_t* src,int32_t srcstride, uint32_t xpos, uint32_t ypos,uint32_t width, int16_t* dst,int32_t dststride) void intra_getPlanarPred(int16_t* src,int32_t srcstride, uint32_t xpos, uint32_t ypos,uint32_t width, int16_t* dst,int32_t dststride)
{ {
int16_t pDcVal = 1<<(g_uiBitDepth-1); int16_t pDcVal = 1<<(g_uiBitDepth-1);
uint32_t k, l, bottomLeft, topRight; int32_t k, l, bottomLeft, topRight;
int32_t horPred; int32_t horPred;
int16_t leftColumn[LCU_WIDTH], topRow[LCU_WIDTH], bottomRow[LCU_WIDTH], rightColumn[LCU_WIDTH]; int32_t leftColumn[LCU_WIDTH], topRow[LCU_WIDTH], bottomRow[LCU_WIDTH], rightColumn[LCU_WIDTH];
uint32_t blkSize = width; uint32_t blkSize = width;
uint32_t offset2D = width; uint32_t offset2D = width;
uint32_t shift1D = g_aucConvertToBit[ width ] + 2; uint32_t shift1D = g_aucConvertToBit[ width ] + 2;