www.pudn.com > wm2.5.zip > picture.c
/* *********************************************************************** * COPYRIGHT AND WARRANTY INFORMATION * * Copyright 2004, Advanced Audio Video Coding Standard, Part II * * DISCLAIMER OF WARRANTY * * These software programs are available to the users without any * license fee or royalty on an "as is" basis. The AVS disclaims * any and all warranties, whether express, implied, or statutory, * including any implied warranties of merchantability or of fitness * for a particular purpose. In no event shall the contributors or * the AVS be liable for any incidental, punitive, or consequential * damages of any kind whatsoever arising from the use of this program. * * This disclaimer of warranty extends to the user of this program * and user's customers, employees, agents, transferees, successors, * and assigns. * * The AVS does not represent or warrant that the program furnished * hereunder are free of infringement of any third-party patents. * Commercial implementations of AVS, including shareware, may be * subject to royalty fees to patent holders. Information regarding * the AVS patent policy is available from the AVS Web site at * http://www.avs.org.cn * * THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. ************************************************************************ */ #include#include #include #include "global.h" #include "define.h" #include "macroblock.h" #include "block.h" #include "intrapred.h" #include "interpred.h" #include "picture.h" #include "vlc.h" #include "types.h" #include "block_const.h" #include "rdopt.h" #include "loopfilter.h" #include "nalu.h"//WJP FOR NAL #include "parset.h"//cbzhu 041221 #include "ratectl.h" // LX 0409 #define Clip(a, b, c) max (a, min (b, c)) extern void Form_RBSP(Bitstream *currBitStream); //! convert from H.263 QP to H.26L quant given by: quant=pow(2,QP/6) const int QP2QUANT[40]= { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,10,11,13,14, 16,18,20,23,25,29,32,36, 40,45,51,57,64,72,81,91 }; extern const int BITSMBTYPE[6]; //qwang 2004-3-24 const int Mv_Block_Size[4][2] = {{16,16},{16,8},{8,16},{8,8}}; //WJP FOR SLICE /******************************************************************** Created: 2004.9.18 Author : Jianpeng Wang Input : Output : Function: Encode Slice Header *********************************************************************/ void SliceHeader(int first_mb_nr_in_slice,int slice_qp)//WJP FOR SLICE_HEADER 050320 { /*WJP FOR SLICE_HEADER 050320 / *WJP FOR NAL u_v(24,"start code prefix",1);* / u_v(8,"Slice start code", Pos_Slice); first_mb_nr_in_slice = pgImage->current_mb_nr; */ int delta_qp; delta_qp = slice_qp - pgImage->qp; ue_linfo(first_mb_nr_in_slice); //WJP END if(!pgImage->fixed_picture_qp) { u_v(1,"fixed_slice_qp",1); // u_v(6,"slice_qp",slice_qp);WJP FOR SLICE_HEADER 050320 se_linfo(delta_qp); } //WJP FOR SLICE_DEBLOCK 050321 if(!active_pps->loop_filter_disable_flag) u_v(1, "disable_loop_filter_slice_flag", pgImage->disable_loop_filter_slice_flag); //WJP END 050321 } /******************************************************************** Created: 2004.9.18 Author : Jianpeng Wang Input : Output : Function: Terminate a Slice *********************************************************************/ void terminate_slice(int mb_x, int mb_y) { /*WJP FOR SLICE_HEADER 050320 assert (input.slice_parameter>0 && input.slice_parameter<=input.img_height/MB_BLOCK_SIZE); if((mb_x==input.img_width / MB_BLOCK_SIZE-1)&&!((mb_y+1)%input.slice_parameter)) */ assert (input.slice_parameter>0 && input.slice_parameter<=(input.img_height/MB_BLOCK_SIZE)*(input.img_width/MB_BLOCK_SIZE)); if(!(pgImage->current_mb_nr%input.slice_parameter) ||pgImage->current_mb_nr == input.img_height*input.img_width/MB_BLOCK_SIZE/MB_BLOCK_SIZE) //WJP END { pgImage->current_slice_nr++; Form_RBSP(pgcurrBitStream);//WJP FOR NAL } } //WJP END /******************************************************************** Created: 12:2:2004 Author : Siwei Ma Input : Output : Function: Encode I frame *********************************************************************/ void Encode_I_Frame(void) { int mb_x, mb_y; int img_x, img_y; int dummy; int mb_nr=0; pgImage->picture_code_type = INTRA_IMG; pgImage->p_pic_type = 0; if(!input.RCEnable) { pgMbData->lambda = QP2QUANT[max(0, pgImage->qp0 - 11)]; //qwang 2004-3-18 pgImage->qp0 - 11 pgMbData->lamda_mode = 0.85*pow(2, (pgImage->qp0 - 11)/4.0); } else { pgMbData->lambda = QP2QUANT[max(0, pgMbData->qp_mb - 11)]; // LX 0409 pgMbData->lamda_mode = 0.85*pow(2, (pgMbData->qp_mb - 11)/4.0); // LX 0409 } pgMbHeader->mb_type = I4MB; //write I picture header //I_Picture_Header(); write_PicHeader(picture_header_rbsp); //cbzhu 0412 pgImage->current_mb_nr=0; //WJP FOR SLICE pgImage->current_slice_nr=0; pgImage->disable_loop_filter_slice_flag = 1;//WJP FOR SLICE_DEBLOCK 050321 for(dummy=0;dummy qp_mb = pgImage->qp0; // LX 0409 for(mb_y=0, img_y=0; img_y img_height; img_y+=16, mb_y++) for(mb_x=0, img_x=0; img_x img_width ; img_x+=16, mb_x++) { pgMbData->mb_x = mb_x; pgMbData->mb_y = mb_y; //WJP FOR SLICE pgImage->mb_y = mb_y; pgImage->mb_x = mb_x; //WJP END Init_Macroblock(img_x, img_y); //WJP FOR SLICE if(input.slice) { if(pgImage->current_mb_nr==0 || ( pgImage->current_mb_nr>0 && (pgImage->current_slice_nr != pgImage->mb_data_forlf[pgImage->current_mb_nr-1].slice_nr) )) { //Form_RBSP(pgcurrBitStream);//WJP FOR NAL assert(pgImage->current_slice_nr current_slice_nr]=pgcurrBitStream->byte_pos; SliceHeader(pgImage->current_mb_nr,pgImage->qp0);//WJP FOR SLICE_HEADER 050320 } } //WJP END Intra_Luma_Prediction(&dummy); Intra_Chroma_Prediction(&dummy); //zhangnan //write one macroblock to bitstream write_one_macroblock (); Output_Macroblock(img_x, img_y); //write reconstructed image to memory mb_nr++; pgMbHeader->cbp_blk=0; pgImage->mb_headerdata[pgImage->current_mb_nr] = * pgMbHeader; pgImage->mb_data_forlf[pgImage->current_mb_nr] = * pgMbData; pgImage->current_mb_nr++; //WJP FOR SLICE if(input.slice) { terminate_slice(mb_x, mb_y); } //WJP END } DeblockFrame(pgImage , current_frame); } /******************************************************************** Created: 12:2:2004 Author : Siwei Ma Input : Output : Function: Encode P frame *********************************************************************/ void Encode_P_Frame(void) //qwang 2004-3-20 { int mb_x, mb_y; int img_x, img_y; int i, j; int min_cost_intra; int dummy; int min_cost_inter; int inter_mode; double validbits; // LX 0409 CurrentFrameLValidbits = 0; // LX 0409 //cbzhu 12-15 #ifdef _ISOLATED_REGION_ if(input.IREGEnable) { intrambcount=0; } #endif pgImage->current_mb_nr=0; //WJP FOR SLICE pgImage->current_slice_nr=0; pgImage->disable_loop_filter_slice_flag = 1;//WJP FOR SLICE_DEBLOCK 050321 for(i=0;i picture_code_type = INTER_IMG; if(input.spframe == 0) { pgImage->p_pic_type = 0; } else { pgImage->p_pic_type = 1 - pgImage->p_pic_type; } if(!input.RCEnable) { //pgMbData->lambda = QP2QUANT[max(0, pgImage->qpN - 11)]; //qwang 2004-3-18 -11 //pgMbData->lamda_mode = 0.85*pow(2, (pgImage->qpN - 11)/4.0); //Hou huiman 2004-10-28-----start //non reference P frame , accepted as M1445 //added by cbzhu , Nov 13 2004 /**/if(pgImage->p_pic_type==0/*1 dongjie(check) */) { pgMbData->lambda = QP2QUANT[max(0, pgImage->qpN - 11)]; //qwang 2004-3-18 -11 pgMbData->lamda_mode = 0.85*pow(2, (pgImage->qpN - 11)/4.0); //2.5 pgMbData->lamda_motion = sqrt(pgMbData->lamda_mode); pgMbData->qp_mb = pgImage->qpN; } else { pgMbData->lambda = QP2QUANT[max(0, pgImage->qpN - 11)]; //qwang 2004-3-18 -11 pgMbData->lamda_mode = 0.90/* dongjie(check) 0.80*/*pow(2, (pgImage->qpN - 11)/4.0); //0.6 pgMbData->lamda_motion = sqrt(pgMbData->lamda_mode); pgMbData->qp_mb = pgImage->qpN-1; } //Hou huiman-------end } else { pgMbData->lambda = QP2QUANT[max(0, pgMbData->qp_mb - 11)]; pgMbData->lamda_mode = 0.85*pow(2, (pgMbData->qp_mb - 11)/4.0); } pgMbData->lamda_motion = sqrt(pgMbData->lamda_mode); pgImage->cod_counter = 0; pgImage->half_pixel_mv_flag = pgImage->half_pixel_mv_enable_flag; //Yulejun 2004.Sep.04. //write out P picuture header //P_Picture_Header(); write_PicHeader(picture_header_rbsp); //cbzhu 0412 //if(!input.RCEnable) // LX 0409 // pgMbData->qp_mb = pgImage->qpN; // LX 0409 //deleted by Hou huiman for(mb_y=0, img_y=0; img_y img_height; img_y+=16, mb_y++) for(mb_x=0, img_x=0; img_x img_width ; img_x+=16, mb_x++) { pgMbData->mb_x = mb_x; pgMbData->mb_y = mb_y; pgImage->mb_y = mb_y; pgImage->mb_x = mb_x; Init_Macroblock(img_x, img_y); //WJP FOR SLICE if(input.slice) { if(pgImage->current_mb_nr==0 || ( pgImage->current_mb_nr>0 && (pgImage->current_slice_nr != pgImage->mb_data_forlf[pgImage->current_mb_nr-1].slice_nr) )) { //Form_RBSP(pgcurrBitStream); WJP FOR NAL assert(pgImage->current_slice_nr current_slice_nr]=pgcurrBitStream->byte_pos; SliceHeader(pgImage->current_mb_nr,pgImage->qpN);//WJP FOR SLICE_HEADER 050320 } } //WJP END min_cost_inter = Inter_Modes_Decision(); if(!input.rdopt) { pgMbHeader->mb_type = I4MB; min_cost_intra = Intra_Luma_Prediction(&dummy); min_cost_intra += MODE_COST(LAMBDA_FACTOR(pgMbData->lambda), BITSMBTYPE[I4MB]); //qwang 2004-3-24 //--- Update ref info ... delay one macroblock --- if(mb_x > 0) { pgMbData->up_row_ref[mb_x - 1] = pgMbData->left_ref; } else { // Update the last pos in the begin of next row pgMbData->up_row_ref[pgImage->img_width/16 - 1] = pgMbData->left_ref; } /////////////////////////////////////////////// // Mode decision //select INTRA inter_mode = (min_cost_inter <= min_cost_intra); if (!inter_mode) { pgMbHeader->mb_type = I4MB; pgMbData->left_ref = -1; for (j = 0; j < 4; j++) for (i = 0; i < 4; i++) { tmp_mv[0][pgMbData->mb_y*4+j][pgMbData->mb_x*4+i+4] = 0; tmp_mv[1][pgMbData->mb_y*4+j][pgMbData->mb_x*4+i+4] = 0; refFrArr [pgMbData->mb_y*4+j][pgMbData->mb_x*4+i ] = -1; } Intra_Chroma_Prediction(&dummy); //write one macroblock to bitstream write_one_macroblock (); } } else inter_mode = RD_Cost_Inter_Macrobock(); if(inter_mode) { Code_Inter_Macroblock(); } //cbzhu 12-15 #ifdef _ISOLATED_REGION_ if (input.IREGEnable) { if (pCurrFrmIREGMap[mb_y][mb_x] != 2) { for (j = 0; j < 4; j++) { for (i = 0; i < 4; i++) { ipredmode[mb_x * 4 + i + 1][mb_y * 4 + j + 1] = -1; } } } } #endif // _ISOLATED_REGION_ // LX 0409 validbits = 0; for ( j = 0; j < MB_BLOCK_SIZE; j++) for ( i = 0; i < MB_BLOCK_SIZE; i++) { if ( g_nbestDCTcoef[i][j] != 0 ) { // 除以最小量化间隔, 若小于 1 则不计算有效比特长 g_nbestDCTcoef[i][j] = g_nbestDCTcoef[i][j] * DCTscale[i%4][j%4] / 0.625; if (g_nbestDCTcoef[i][j] < 1) { continue; } else { validbits = log(absm(g_nbestDCTcoef[i][j]))/log(2) + 1; } } } CurrentFrameLValidbits += validbits; // LX 0409 //--- write reconstructed image to memory --- Output_Macroblock(img_x,img_y); //save for loopfilter cbzhu pgMbHeader->cbp_blk=0; pgImage->mb_headerdata[pgImage->current_mb_nr] = * pgMbHeader; pgImage->mb_data_forlf[pgImage->current_mb_nr] = * pgMbData; //if( pgImage->current_mb_nr == 17) // printf("%d \n" , pgMbHeader->mb_type); pgImage->current_mb_nr++; //WJP FOR SLICE if(input.slice) { terminate_slice(mb_x, mb_y); } //WJP END //printf("%d \n " , pgMbHeader->mb_type); } DeblockFrame(pgImage , current_frame); } /******************************************************************** Created: 13:2:2004 Author : Siwei Ma Input : Output : Function: *********************************************************************/ void Padding_IP_Frame(void) { int i, j; int ii, jj; for (j = -PAD_SIZE; j < pgImage->img_height + PAD_SIZE; j++) { for (i = -PAD_SIZE; i < pgImage->img_width + PAD_SIZE; i++) { jj = max (0, min (pgImage->img_height - 1, j)); ii = max (0, min (pgImage->img_width - 1, i)); //store 1/1 pixel value current_frame[0][j + PAD_SIZE][i + PAD_SIZE] = current_frame[0][jj + PAD_SIZE][ii + PAD_SIZE];// 1/1 pix pos } } } /******************************************************************** Created: 12:2:2004 Author : Siwei Ma Input : Output : Function: Interpolation Note : Aug 10, 2004, accept M1323(北京工业大学), added by yiwang *********************************************************************/ /* void Interpolate_IP_Frame(void) { int TapArr1_2[4] = { -1, 5, 5, -1}; int TapArr1_4a[3] = { 8, 7, 1}; int TapArr1_4b[3] = { 1, 7, 8}; int TapArr1_4c[3] = { 7, 7, 2}; int TapArr1_4d[3] = { 2, 7, 7}; int iWeight1_2 = 8; int iWeight1_4a = 16; int iWeight1_4b = 16; int iWeight1_4c = 16; int iWeight1_4d = 16; int is; int i, j;// j4; int ie2, je2; int maxy, maxx; int ii, jj, yy; int val; //Half pel interpolation to half-pel reference buffer //horizonal 1/2 interpolation maxx = pgImage->img_width + 2 * PAD_SIZE - 1; for (j = -PAD_SIZE; j < pgImage->img_height + PAD_SIZE; j++) { jj = j + PAD_SIZE; for (i = -PAD_SIZE; i < pgImage->img_width + PAD_SIZE; i++) { ii = i + PAD_SIZE; val = TapArr1_2[0] * current_frame[0][jj][Clip(0, maxx, ii - 1)] + TapArr1_2[1] * current_frame[0][jj][ii ] + TapArr1_2[2] * current_frame[0][jj][Clip(0, maxx, ii + 1)] + TapArr1_2[3] * current_frame[0][jj][Clip(0, maxx, ii + 2)]; //store 1/1 pixel value half_pel_frame_tmp[0][2 * jj][2 * ii] = current_frame[0][jj][Clip(0, maxx, ii)] * 1024;// 1/1 pix pos //store horizonal 1/2 pixel value half_pel_frame_tmp[0][2 * jj][2 * ii + 1] = val * 1024 / iWeight1_2;// 1/2 pix pos } } //vertical 1/2 interpolation maxy = 2 * (pgImage->img_height + 2 * PAD_SIZE) - 2; for (i = 0; i < (pgImage->img_width + 2 * PAD_SIZE) * 2; i++) { for (j = 0; j < pgImage->img_height + 2 * PAD_SIZE; j++) { is = ( TapArr1_2[0] * half_pel_frame_tmp[0][max(0, 2 * j - 2) ][i] + TapArr1_2[1] * half_pel_frame_tmp[0][min(maxy, 2 * j) ][i] + TapArr1_2[2] * half_pel_frame_tmp[0][min(maxy, 2 * j + 2)][i] + TapArr1_2[3] * half_pel_frame_tmp[0][min(maxy, 2 * j + 4)][i] ) / iWeight1_2; //vertical half pel yy = min(maxy, 2 * j); val = (int) ( ( half_pel_frame_tmp[0][yy][i] + 512 ) / 1024 ); reference_half_pel_frame[0][j * 2 ][i] = Clip(0, 255, val); val = (int) ( ( is + 512 ) / 1024 ); reference_half_pel_frame[0][j * 2 + 1][i] = Clip(0, 255, val); reference_quater_pel_frame[0][4 * j ][2 * i] = reference_half_pel_frame[0][j * 2][i]; reference_quater_pel_frame[0][4 * j + 2][2 * i] = reference_half_pel_frame[0][j * 2 + 1][i]; } } //Quater pel intepolation // 1/4 pix // luma ie2 = (pgImage->img_width + 2 * PAD_SIZE - 1) * 4; je2 = (pgImage->img_height + 2 * PAD_SIZE - 1) * 4; //horizonal 1/4 interpolation for (j = 0; j < je2 + 4; j += 2) { for (i = 0; i < ie2 + 3; i += 2) { // '-' if(j % 4 == 0) { if(i % 4 == 0) { val = (int) ( ( TapArr1_4a[0] * reference_quater_pel_frame[0][j][i ] + TapArr1_4a[1] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] + TapArr1_4a[2] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 4)] + iWeight1_4a / 2 ) ) / iWeight1_4a ; reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); }else{ val = (int) ( ( TapArr1_4b[0] * reference_quater_pel_frame[0][j][max(0, i - 2) ] + TapArr1_4b[1] * reference_quater_pel_frame[0][j][i ] + TapArr1_4b[2] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] + iWeight1_4b / 2 ) ) / iWeight1_4b ; reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); } }else{ if(i % 4 == 0) { val = (int) ( ( TapArr1_4c[0] * reference_quater_pel_frame[0][j][i ] + TapArr1_4c[1] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] + TapArr1_4c[2] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 4)] + iWeight1_4c / 2 ) ) / iWeight1_4c ; reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); }else{ val = (int) ( ( TapArr1_4d[0] * reference_quater_pel_frame[0][j][max(0, i - 2) ] + TapArr1_4d[1] * reference_quater_pel_frame[0][j][i ] + TapArr1_4d[2] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] + iWeight1_4d / 2 ) ) / iWeight1_4d ; reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); } } } } //vertical 1/4 interpolation for (i = 0; i < ie2 + 4; i++) { for (j = 0; j < je2 + 3; j += 2) { // '|' if (i % 4 == 0) { if(j % 4 == 0) { val = (int) ( ( TapArr1_4a[0] * reference_quater_pel_frame[0][j ][i] + TapArr1_4a[1] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] + TapArr1_4a[2] * reference_quater_pel_frame[0][min(je2 + 2, j + 4)][i] + iWeight1_4a / 2 ) / iWeight1_4a ); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); }else{ val = (int) ( ( TapArr1_4b[0] * reference_quater_pel_frame[0][max(0, j - 2) ][i] + TapArr1_4b[1] * reference_quater_pel_frame[0][j ][i] + TapArr1_4b[2] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] + iWeight1_4b / 2 ) / iWeight1_4b ); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } } else if(i % 4 == 2) { if(j % 4 == 0) { val = (int) ( ( TapArr1_4c[0] * reference_quater_pel_frame[0][j ][i] + TapArr1_4c[1] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] + TapArr1_4c[2] * reference_quater_pel_frame[0][min(je2 + 2, j + 4)][i] + iWeight1_4c / 2 ) / iWeight1_4c ); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); }else{ val = (int) ( ( TapArr1_4d[0] * reference_quater_pel_frame[0][max(0, j - 2) ][i] + TapArr1_4d[1] * reference_quater_pel_frame[0][j ][i] + TapArr1_4d[2] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] + iWeight1_4d / 2 ) / iWeight1_4d ); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } } else if (j % 4 == 0 && i % 4 == 1) { // '\' val = (int) ( ( reference_quater_pel_frame[0][j ][max(0, i - 1) ] + reference_quater_pel_frame[0][min(je2 + 2, j + 2)][min(ie2 + 2, i + 1)] + 1 ) / 2); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } else if(j % 4 == 2 && i % 4 == 3) { val = (int) ( ( reference_quater_pel_frame[0][j ][max(0, i - 1) ] + reference_quater_pel_frame[0][min(je2, j + 2)][min(ie2, i + 1)] + 1) / 2); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } else if(j % 4 == 0 && i % 4 == 3) { // '/' val = (int) ( ( reference_quater_pel_frame[0][j ][min(ie2, i + 1)] + reference_quater_pel_frame[0][min(je2 + 2, j + 2)][max(0, i - 1) ] + 1) / 2); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } else if(j % 4 == 2 && i % 4 == 1) { // '/' val = (int) ( ( reference_quater_pel_frame[0][j ][min(ie2 + 2, i + 1)] + reference_quater_pel_frame[0][min(je2, j + 2)][max(0, i - 1) ] + 1 ) / 2 ); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } }//for (j = 0; j < je2 + 3; j += 2) }//for (i = 0; i < ie2 + 4; i++) } */ /******************************************************************** Created: 12:2:2004 Author : Siwei Ma Input : Output : Function: Interpolation Note : Nov 13, 2004, accept M1466(北京工业大学), added by cbzhu *********************************************************************/ void Interpolate_IP_Frame(void) { int TapArr1_2_h[4][2] = { {41,20}, {-12,-4}, { 4, 0}, { -1, 0} }; int TapArr1_2_v[4][2] = { {5,20}, {-1,-4}, { 0, 0}, { 0, 0} }; int iWeight1_2_h = 64; int iWeight1_2_v = 8; int TapArr1_4[4] = { 0, 1, 1, 0}; int iWeight1_4 = 2; int is; int i, j;// j4; int ie2, je2; int maxy, maxx; int ii, jj, yy; int val; //Half pel interpolation to half-pel reference buffer //horizonal 1/2 interpolation maxx = pgImage->img_width + 2 * PAD_SIZE - 1; for (j = -PAD_SIZE; j < pgImage->img_height + PAD_SIZE; j++) { jj = j + PAD_SIZE; for (i = -PAD_SIZE; i < pgImage->img_width + PAD_SIZE; i++) { ii = i + PAD_SIZE; val =(int)( ( TapArr1_2_h[0][0] * ( current_frame[0][jj][ii ] + current_frame[0][jj][Clip(0, maxx, ii + 1)])+ TapArr1_2_h[1][0] * ( current_frame[0][jj][Clip(0, maxx, ii - 1)] + current_frame[0][jj][Clip(0, maxx, ii + 2)])+ TapArr1_2_h[2][0] * ( current_frame[0][jj][Clip(0, maxx, ii - 2)] + current_frame[0][jj][Clip(0, maxx, ii + 3)])+ TapArr1_2_h[3][0] * ( current_frame[0][jj][Clip(0, maxx, ii - 3)] + current_frame[0][jj][Clip(0, maxx, ii + 4)]) + iWeight1_2_h / 2) >>6 ); //store 1/1 pixel value half_pel_frame_tmp[0][2 * jj][2 * ii] = current_frame[0][jj][Clip(0, maxx, ii)];// 1/1 pix pos //store horizonal 1/2 pixel value half_pel_frame_tmp[0][2 * jj][2 * ii + 1] = Clip(0, 255, val);// 1/2 pix pos } } //vertical 1/2 interpolation maxy = 2 * (pgImage->img_height + 2 * PAD_SIZE) - 2; for (i = 0; i < (pgImage->img_width + 2 * PAD_SIZE) * 2; i++) { for (j = 0; j < pgImage->img_height + 2 * PAD_SIZE; j++) { is =(int)( ( TapArr1_2_v[0][0] * ( half_pel_frame_tmp[0][min(maxy, 2 * j) ][i] + half_pel_frame_tmp[0][min(maxy, 2 * j + 2)][i])+ TapArr1_2_v[1][0] * ( half_pel_frame_tmp[0][max(0, 2 * j - 2) ][i] + half_pel_frame_tmp[0][min(maxy, 2 * j + 4)][i])+ TapArr1_2_v[2][0] * ( half_pel_frame_tmp[0][max(0, 2 * j - 4) ][i] + half_pel_frame_tmp[0][min(maxy, 2 * j + 6)][i])+ TapArr1_2_v[3][0] * ( half_pel_frame_tmp[0][max(0, 2 * j - 6) ][i] + half_pel_frame_tmp[0][min(maxy, 2 * j + 8)][i]) + iWeight1_2_v / 2 ) >>3); //vertical half pel yy = min(maxy, 2 * j); reference_half_pel_frame[0][j * 2 ][i] = Clip(0, 255, half_pel_frame_tmp[0][yy][i]); reference_half_pel_frame[0][j * 2 + 1][i] = Clip(0, 255, is); reference_quater_pel_frame[0][4 * j ][2 * i] = reference_half_pel_frame[0][j * 2][i]; reference_quater_pel_frame[0][4 * j + 2][2 * i] = reference_half_pel_frame[0][j * 2 + 1][i]; } } //Quater pel intepolation // 1/4 pix // luma ie2 = (pgImage->img_width + 2 * PAD_SIZE - 1) * 4; je2 = (pgImage->img_height + 2 * PAD_SIZE - 1) * 4; //horizonal 1/4 interpolation for (j = 0; j < je2 + 4; j += 2) { for (i = 0; i < ie2 + 3; i += 2) { // '-' if(i % 4 == 0) { val = (int) ( ( TapArr1_4[0] * reference_quater_pel_frame[0][j][max(0, i - 2) ] + TapArr1_4[1] * reference_quater_pel_frame[0][j][i ] + TapArr1_4[2] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] + TapArr1_4[3] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 4)] + iWeight1_4 / 2 ) ) >>1 ; reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); }else{ val = (int) ( ( TapArr1_4[3] * reference_quater_pel_frame[0][j][max(0, i - 2) ] + TapArr1_4[2] * reference_quater_pel_frame[0][j][i ] + TapArr1_4[1] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] + TapArr1_4[0] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 4)] + iWeight1_4 / 2 ) ) >>1 ; reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); } } } //vertical 1/4 interpolation for (i = 0; i < ie2 + 4; i++) { for (j = 0; j < je2 + 3; j += 2) { // '|' if (i % 2 == 0) { if(j % 4 == 0) { val = (int) ( ( TapArr1_4[0] * reference_quater_pel_frame[0][max(0, j - 2) ][i] + TapArr1_4[1] * reference_quater_pel_frame[0][j ][i] + TapArr1_4[2] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] + TapArr1_4[3] * reference_quater_pel_frame[0][min(je2 + 2, j + 4)][i] + iWeight1_4 / 2 ) >>1); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); }else{ val = (int) ( ( TapArr1_4[3] * reference_quater_pel_frame[0][max(0, j - 2) ][i] + TapArr1_4[2] * reference_quater_pel_frame[0][j ][i] + TapArr1_4[1] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] + TapArr1_4[0] * reference_quater_pel_frame[0][min(je2 + 2, j + 4)][i] + iWeight1_4 / 2 ) >>1); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } } else if (j % 4 == 0 && i % 4 == 1) { // '\' val = (int) ( ( reference_quater_pel_frame[0][j ][max(0, i - 1) ] + reference_quater_pel_frame[0][min(je2 + 2, j + 2)][min(ie2 + 2, i + 1)] + 1 ) >>1); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } else if(j % 4 == 2 && i % 4 == 3) { val = (int) ( ( reference_quater_pel_frame[0][j ][max(0, i - 1) ] + reference_quater_pel_frame[0][min(je2 + 2, j + 2)][min(ie2 + 2, i + 1)] + 1) >>1); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } else if(j % 4 == 0 && i % 4 == 3) { // '/' val = (int) ( ( reference_quater_pel_frame[0][j ][min(ie2 + 2, i + 1)] + reference_quater_pel_frame[0][min(je2 + 2, j + 2)][max(0, i - 1) ] + 1) >>1); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } else if(j % 4 == 2 && i % 4 == 1) { // '/' val = (int) ( ( reference_quater_pel_frame[0][j ][min(ie2 + 2, i + 1)] + reference_quater_pel_frame[0][min(je2 + 2, j + 2)][max(0, i - 1) ] + 1 ) >>1 ); reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); } }//for (j = 0; j < je2 + 3; j += 2) }//for (i = 0; i < ie2 + 4; i++) }