Commit 8d8c0294 authored by Michael Niedermayer's avatar Michael Niedermayer

ac prediction cleanup

rate distorted optimal ac prediction for mpeg4

Originally committed as revision 2325 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 2fdf638b
......@@ -15,7 +15,7 @@ extern "C" {
#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 @@ typedef struct RcOverride{
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 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG,
#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 */
......
......@@ -69,8 +69,6 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
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 @@ int h263_encode_gob_header(MpegEncContext * s, int mb_line)
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(j<block_last_index) rate+= s->intra_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 @@ static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int d
/* 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 @@ static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int d
/* 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 @@ static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int d
/* 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 @@ static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int d
/* 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 score0 > score1 ? 1 : 0;
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 ];
}
}
}
}
/**
......@@ -939,23 +992,10 @@ void mpeg4_encode_mb(MpegEncContext * s,
}
}
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 @@ void mpeg4_encode_mb(MpegEncContext * s,
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 @@ void mpeg4_pred_ac(MpegEncContext * s, DCTELEM *block, int n,
#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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment