# HG changeset patch # User michaelni # Date 1065022896 0 # Node ID 3518325146fcd747dad8f66517bc22ee6b1801e0 # Parent 222643544cf127552a05941fe66b669a041102f8 ac prediction cleanup rate distorted optimal ac prediction for mpeg4 diff -r 222643544cf1 -r 3518325146fc avcodec.h --- a/avcodec.h Wed Oct 01 04:39:38 2003 +0000 +++ b/avcodec.h Wed Oct 01 15:41:36 2003 +0000 @@ -15,7 +15,7 @@ #define FFMPEG_VERSION_INT 0x000408 #define FFMPEG_VERSION "0.4.8" -#define LIBAVCODEC_BUILD 4681 +#define LIBAVCODEC_BUILD 4682 #define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT #define LIBAVCODEC_VERSION FFMPEG_VERSION @@ -199,6 +199,7 @@ extern int motion_estimation_method; /* ME algos sorted by quality */ +//FIXME remove IMHO static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG, ME_X1, ME_EPZS, ME_FULL }; @@ -234,7 +235,8 @@ #define CODEC_FLAG_GLOBAL_HEADER 0x00400000 ///< place global headers in extradata instead of every keyframe #define CODEC_FLAG_BITEXACT 0x00800000 ///< use only bitexact stuff (except (i)dct) /* Fx : Flag for h263+ extra options */ -#define CODEC_FLAG_H263P_AIC 0x01000000 ///< Advanced intra coding +#define CODEC_FLAG_H263P_AIC 0x01000000 ///< H263 Advanced intra coding / MPEG4 AC prediction (remove this) +#define CODEC_FLAG_AC_PRED 0x01000000 ///< H263 Advanced intra coding / MPEG4 AC prediction #define CODEC_FLAG_H263P_UMV 0x02000000 ///< Unlimited motion vector #define CODEC_FLAG_CBP_RD 0x04000000 ///< use rate distortion optimization for cbp /* For advanced prediction mode, we reuse the 4MV flag */ diff -r 222643544cf1 -r 3518325146fc h263.c --- a/h263.c Wed Oct 01 04:39:38 2003 +0000 +++ b/h263.c Wed Oct 01 15:41:36 2003 +0000 @@ -69,8 +69,6 @@ int n, int coded, int intra, int rvlc); static int h263_pred_dc(MpegEncContext * s, int n, uint16_t **dc_val_ptr); #ifdef CONFIG_ENCODERS -static void mpeg4_inv_pred_ac(MpegEncContext * s, DCTELEM *block, int n, - int dir); static void mpeg4_encode_visual_object_header(MpegEncContext * s); static void mpeg4_encode_vol_header(MpegEncContext * s, int vo_number, int vol_number); #endif //CONFIG_ENCODERS @@ -325,14 +323,42 @@ return 0; } -static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int dir[6]) +static inline int get_block_rate(MpegEncContext * s, DCTELEM block[64], int block_last_index, uint8_t scantable[64]){ + int last=0; + int j; + int rate=0; + + for(j=1; j<=block_last_index; j++){ + const int index= scantable[j]; + int level= block[index]; + if(level){ + level+= 64; + if((level&(~127)) == 0){ + if(jintra_ac_vlc_length [UNI_AC_ENC_INDEX(j-last-1, level)]; + else rate+= s->intra_ac_vlc_last_length[UNI_AC_ENC_INDEX(j-last-1, level)]; + }else + rate += s->ac_esc_length; + level-= 64; + + last= j; + } + } + + return rate; +} + +static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int dir[6], uint8_t *st[6], int zigzag_last_index[6]) { - int score0=0, score1=0; + int score= 0; int i, n; int8_t * const qscale_table= s->current_picture.qscale_table; + memcpy(zigzag_last_index, s->block_last_index, sizeof(int)*6); + for(n=0; n<6; n++){ int16_t *ac_val, *ac_val1; + + score -= get_block_rate(s, block[n], s->block_last_index[n], s->intra_scantable.permutated); ac_val = s->ac_val[0][0] + s->block_index[n] * 16; ac_val1= ac_val; @@ -344,8 +370,7 @@ /* same qscale */ for(i=1; i<8; i++){ const int level= block[n][s->dsp.idct_permutation[i ]]; - score0+= ABS(level); - score1+= ABS(level - ac_val[i+8]); + block[n][s->dsp.idct_permutation[i ]] = level - ac_val[i+8]; ac_val1[i ]= block[n][s->dsp.idct_permutation[i<<3]]; ac_val1[i+8]= level; } @@ -353,12 +378,12 @@ /* different qscale, we must rescale */ for(i=1; i<8; i++){ const int level= block[n][s->dsp.idct_permutation[i ]]; - score0+= ABS(level); - score1+= ABS(level - ROUNDED_DIV(ac_val[i + 8]*qscale_table[xy], s->qscale)); + block[n][s->dsp.idct_permutation[i ]] = level - ROUNDED_DIV(ac_val[i + 8]*qscale_table[xy], s->qscale); ac_val1[i ]= block[n][s->dsp.idct_permutation[i<<3]]; ac_val1[i+8]= level; } } + st[n]= s->intra_h_scantable.permutated; }else{ const int xy= s->mb_x-1 + s->mb_y*s->mb_stride; /* left prediction */ @@ -367,8 +392,7 @@ /* same qscale */ for(i=1; i<8; i++){ const int level= block[n][s->dsp.idct_permutation[i<<3]]; - score0+= ABS(level); - score1+= ABS(level - ac_val[i]); + block[n][s->dsp.idct_permutation[i<<3]]= level - ac_val[i]; ac_val1[i ]= level; ac_val1[i+8]= block[n][s->dsp.idct_permutation[i ]]; } @@ -376,16 +400,45 @@ /* different qscale, we must rescale */ for(i=1; i<8; i++){ const int level= block[n][s->dsp.idct_permutation[i<<3]]; - score0+= ABS(level); - score1+= ABS(level - ROUNDED_DIV(ac_val[i]*qscale_table[xy], s->qscale)); + block[n][s->dsp.idct_permutation[i<<3]]= level - ROUNDED_DIV(ac_val[i]*qscale_table[xy], s->qscale); ac_val1[i ]= level; ac_val1[i+8]= block[n][s->dsp.idct_permutation[i ]]; } } + st[n]= s->intra_v_scantable.permutated; + } + + for(i=63; i>0; i--) //FIXME optimize + if(block[n][ st[n][i] ]) break; + s->block_last_index[n]= i; + + score += get_block_rate(s, block[n], s->block_last_index[n], st[n]); + } + + return score < 0; +} + +static inline void restore_ac_coeffs(MpegEncContext * s, DCTELEM block[6][64], int dir[6], uint8_t *st[6], int zigzag_last_index[6]) +{ + int i, n; + memcpy(s->block_last_index, zigzag_last_index, sizeof(int)*6); + + for(n=0; n<6; n++){ + int16_t *ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + + st[n]= s->intra_scantable.permutated; + if(dir[n]){ + /* top prediction */ + for(i=1; i<8; i++){ + block[n][s->dsp.idct_permutation[i ]] = ac_val[i+8]; + } + }else{ + /* left prediction */ + for(i=1; i<8; i++){ + block[n][s->dsp.idct_permutation[i<<3]]= ac_val[i ]; + } } } - - return score0 > score1 ? 1 : 0; } /** @@ -939,23 +992,10 @@ } } - s->ac_pred= decide_ac_pred(s, block, dir); - - if(s->ac_pred){ - for(i=0; i<6; i++){ - uint8_t *st; - int last_index; - - mpeg4_inv_pred_ac(s, block[i], i, dir[i]); - if (dir[i]==0) st = s->intra_v_scantable.permutated; /* left */ - else st = s->intra_h_scantable.permutated; /* top */ - - for(last_index=63; last_index>=0; last_index--) //FIXME optimize - if(block[i][st[last_index]]) break; - zigzag_last_index[i]= s->block_last_index[i]; - s->block_last_index[i]= last_index; - scan_table[i]= st; - } + if(s->flags & CODEC_FLAG_AC_PRED){ + s->ac_pred= decide_ac_pred(s, block, dir, scan_table, zigzag_last_index); + if(!s->ac_pred) + restore_ac_coeffs(s, block, dir, scan_table, zigzag_last_index); }else{ for(i=0; i<6; i++) scan_table[i]= s->intra_scantable.permutated; @@ -1006,23 +1046,8 @@ s->i_count++; /* restore ac coeffs & last_index stuff if we messed them up with the prediction */ - if(s->ac_pred){ - for(i=0; i<6; i++){ - int j; - int16_t *ac_val; - - ac_val = s->ac_val[0][0] + s->block_index[i] * 16; - - if(dir[i]){ - for(j=1; j<8; j++) - block[i][s->dsp.idct_permutation[j ]]= ac_val[j+8]; - }else{ - for(j=1; j<8; j++) - block[i][s->dsp.idct_permutation[j<<3]]= ac_val[j ]; - } - s->block_last_index[i]= zigzag_last_index[i]; - } - } + if(s->ac_pred) + restore_ac_coeffs(s, block, dir, scan_table, zigzag_last_index); } } @@ -2195,49 +2220,6 @@ #ifdef CONFIG_ENCODERS -static void mpeg4_inv_pred_ac(MpegEncContext * s, DCTELEM *block, int n, - int dir) -{ - int i; - int16_t *ac_val; - int8_t * const qscale_table= s->current_picture.qscale_table; - - /* find prediction */ - ac_val = s->ac_val[0][0] + s->block_index[n] * 16; - - if (dir == 0) { - const int xy= s->mb_x-1 + s->mb_y*s->mb_stride; - /* left prediction */ - ac_val -= 16; - if(s->mb_x==0 || s->qscale == qscale_table[xy] || n==1 || n==3){ - /* same qscale */ - for(i=1;i<8;i++) { - block[s->dsp.idct_permutation[i<<3]] -= ac_val[i]; - } - }else{ - /* different qscale, we must rescale */ - for(i=1;i<8;i++) { - block[s->dsp.idct_permutation[i<<3]] -= ROUNDED_DIV(ac_val[i]*qscale_table[xy], s->qscale); - } - } - } else { - const int xy= s->mb_x + s->mb_y*s->mb_stride - s->mb_stride; - /* top prediction */ - ac_val -= 16 * s->block_wrap[n]; - if(s->mb_y==0 || s->qscale == qscale_table[xy] || n==2 || n==3){ - /* same qscale */ - for(i=1;i<8;i++) { - block[s->dsp.idct_permutation[i]] -= ac_val[i + 8]; - } - }else{ - /* different qscale, we must rescale */ - for(i=1;i<8;i++) { - block[s->dsp.idct_permutation[i]] -= ROUNDED_DIV(ac_val[i + 8]*qscale_table[xy], s->qscale); - } - } - } -} - /** * encodes the dc value. * @param n block index (0-3 are luma, 4-5 are chroma)