From d140623fc44c67e8955c56c7cf74c56c94c0f064 Mon Sep 17 00:00:00 2001 From: Juanjo Date: Mon, 18 Feb 2002 19:33:27 +0000 Subject: [PATCH] - H.263+ decoder support for Advanded INTRA Coding (buggy) Originally committed as revision 310 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/h263.c | 148 ++++++++++++++++++++++++++++++-- libavcodec/h263data.h | 41 +++++++++ libavcodec/h263dec.c | 3 + libavcodec/i386/mpegvideo_mmx.c | 5 +- libavcodec/mpegvideo.c | 30 +++++-- libavcodec/mpegvideo.h | 4 +- 6 files changed, 214 insertions(+), 17 deletions(-) diff --git a/libavcodec/h263.c b/libavcodec/h263.c index dade959adb..e0b234bbd4 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -273,6 +273,97 @@ void h263_encode_mb(MpegEncContext * s, } } +static int h263_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr) +{ + int a, c, x, y, wrap, pred, scale; + UINT16 *dc_val; + + /* find prediction */ + if (n < 4) { + x = 2 * s->mb_x + 1 + (n & 1); + y = 2 * s->mb_y + 1 + ((n & 2) >> 1); + wrap = s->mb_width * 2 + 2; + dc_val = s->dc_val[0]; + scale = s->y_dc_scale; + } else { + x = s->mb_x + 1; + y = s->mb_y + 1; + wrap = s->mb_width + 2; + dc_val = s->dc_val[n - 4 + 1]; + scale = s->c_dc_scale; + } + + /* B C + * A X + */ + a = dc_val[(x - 1) + (y) * wrap]; + c = dc_val[(x) + (y - 1) * wrap]; + + if (s->ac_pred) { + if (s->h263_aic_dir) + pred = a; + else + pred = c; + } else if (a != 1024 && c != 1024) + pred = (a + c) >> 1; + else if (a != 1024) + pred = a; + else + pred = c; + + + /* we assume pred is positive */ + pred = (pred) / scale; + + /* prepare address for prediction update */ + *dc_val_ptr = &dc_val[(x) + (y) * wrap]; + + return pred; +} + +void h263_pred_ac(MpegEncContext * s, INT16 *block, int n) +{ + int x, y, wrap, i; + INT16 *ac_val, *ac_val1; + + /* find prediction */ + if (n < 4) { + x = 2 * s->mb_x + 1 + (n & 1); + y = 2 * s->mb_y + 1 + ((n & 2) >> 1); + wrap = s->mb_width * 2 + 2; + ac_val = s->ac_val[0][0]; + } else { + x = s->mb_x + 1; + y = s->mb_y + 1; + wrap = s->mb_width + 2; + ac_val = s->ac_val[n - 4 + 1][0]; + } + ac_val += ((y) * wrap + (x)) * 16; + ac_val1 = ac_val; + + if (s->ac_pred) { + if (s->h263_aic_dir) { + /* left prediction */ + ac_val -= 16; + for(i=1;i<8;i++) { + block[block_permute_op(i*8)] += ac_val[i]; + } + } else { + /* top prediction */ + ac_val -= 16 * wrap; + for(i=1;i<8;i++) { + block[block_permute_op(i)] += ac_val[i + 8]; + } + } + } + /* left copy */ + for(i=1;i<8;i++) + ac_val1[i] = block[block_permute_op(i * 8)]; + /* top copy */ + for(i=1;i<8;i++) + ac_val1[8 + i] = block[block_permute_op(i)]; +} + static inline int mid_pred(int a, int b, int c) { int vmin, vmax; @@ -821,8 +912,10 @@ void h263_decode_init_vlc(MpegEncContext *s) &mvtab[0][0], 2, 1); init_rl(&rl_inter); init_rl(&rl_intra); + init_rl(&rl_intra_aic); init_vlc_rl(&rl_inter); init_vlc_rl(&rl_intra); + init_vlc_rl(&rl_intra_aic); init_vlc(&dc_lum, 9, 13, &DCtab_lum[0][1], 2, 1, &DCtab_lum[0][0], 2, 1); @@ -959,8 +1052,10 @@ int h263_decode_mb(MpegEncContext *s, } } else { s->ac_pred = 0; - if (s->h263_pred) { + if (s->h263_pred || s->h263_aic) { s->ac_pred = get_bits1(&s->gb); + if (s->ac_pred && s->h263_aic) + s->h263_aic_dir = get_bits1(&s->gb); } cbpy = get_vlc(&s->gb, &cbpy_vlc); cbp = (cbpc & 3) | (cbpy << 2); @@ -1059,9 +1154,21 @@ static int h263_decode_block(MpegEncContext * s, DCTELEM * block, { int code, level, i, j, last, run; RLTable *rl = &rl_inter; + UINT16 *dc_val; + const UINT8 *scan_table; - if (s->mb_intra) { - /* DC coef */ + scan_table = zigzag_direct; + if (s->h263_aic) { + rl = &rl_intra_aic; + i = 0; + if (s->ac_pred) { + if (s->h263_aic_dir) + scan_table = ff_alternate_vertical_scan; /* left */ + else + scan_table = ff_alternate_horizontal_scan; /* top */ + } + } else if (s->mb_intra) { + /* DC coef */ if (s->h263_rv10 && s->rv10_version == 3 && s->pict_type == I_TYPE) { int component, diff; component = (n <= 3 ? 0 : n - 4 + 1); @@ -1082,11 +1189,21 @@ static int h263_decode_block(MpegEncContext * s, DCTELEM * block, level = 128; } block[0] = level; - i = 1; + i = 1; } else { - i = 0; + i = 0; } if (!coded) { + if (s->mb_intra && s->h263_aic) { + level = h263_pred_dc(s, n, &dc_val); + if (level < 0) + level = 0; + *dc_val = level * s->y_dc_scale; + block[0] = level; + h263_pred_ac(s, block, n); + i = 64; + //i = 1; + } s->block_last_index[n] = i - 1; return 0; } @@ -1112,15 +1229,29 @@ static int h263_decode_block(MpegEncContext * s, DCTELEM * block, if (get_bits1(&s->gb)) level = -level; } + if (!i && s->h263_aic) { + level += h263_pred_dc(s, n, &dc_val); + if (level < 0) + level = 0; + else if (level & 1) + level++; + *dc_val = level * s->y_dc_scale; + + } i += run; if (i >= 64) return -1; - j = zigzag_direct[i]; + j = scan_table[i]; block[j] = level; if (last) break; i++; } + + if (s->h263_aic) { + h263_pred_ac(s, block, n); + i = 64; + } s->block_last_index[n] = i; return 0; } @@ -1325,7 +1456,10 @@ int h263_decode_picture_header(MpegEncContext *s) if (get_bits1(&s->gb) != 0) { s->mv_type = MV_TYPE_8X8; /* Advanced prediction mode */ } - skip_bits(&s->gb, 8); + if (get_bits1(&s->gb) != 0) { /* Advanced Intra Coding (AIC) */ + s->h263_aic = 1; + } + skip_bits(&s->gb, 7); skip_bits(&s->gb, 3); /* Reserved */ } else if (ufep != 0) return -1; diff --git a/libavcodec/h263data.h b/libavcodec/h263data.h index d41996a3bc..88e456ba26 100644 --- a/libavcodec/h263data.h +++ b/libavcodec/h263data.h @@ -125,6 +125,47 @@ static RLTable rl_inter = { inter_level, }; +/* table used for Advanced INTRA Coding, just RUN and LEVEL change */ +const INT8 inter_level_aic[102] = { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 2, 1, 2, 2, 4, 5, + 6, 7, 3, 2, 3, 4, 5, 2, + 3, 4, 2, 3, 1, 2, 25, 1, + 2, 24, 8, 2, 7, 4, 6, 1, + 9, 23, 2, 3, 1, 10, 12, 11, + 18, 17, 16, 15, 14, 13, 20, 19, + 22, 21, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 4, 1, 1, + 1, 1, 2, 2, 6, 5, 2, 2, + 3, 7, 3, 4, 9, 8, 1, 1, + 1, 2, 2, 2, 3, 10, +}; + +const INT8 inter_run_aic[102] = { + 0, 1, 3, 5, 7, 8, 9, 10, + 11, 4, 9, 13, 0, 1, 1, 1, + 1, 1, 0, 3, 2, 3, 0, 4, + 3, 0, 5, 5, 2, 6, 0, 4, + 7, 0, 0, 8, 0, 2, 0, 12, + 0, 0, 2, 1, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14, 20, 1, 19, 2, + 3, 0, 5, 6, 4, 0, 9, 10, + 11, 12, 13, 8, 7, 0, 17, 18, + 16, 15, 2, 1, 0, 0, 4, 3, + 1, 0, 2, 1, 0, 0, 21, 22, + 23, 7, 6, 5, 3, 0, +}; + +static RLTable rl_intra_aic = { + 102, + 58, + inter_vlc, + inter_run_aic, + inter_level_aic, +}; + static const UINT16 h263_format[8][2] = { { 0, 0 }, { 128, 96 }, diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index ea628bf127..e0a5f671a3 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -156,6 +156,9 @@ static int h263_decode_frame(AVCodecContext *avctx, msmpeg4_dc_scale(s); } else if (s->h263_pred) { h263_dc_scale(s); + } else if (s->h263_aic) { + s->y_dc_scale = s->qscale; + s->c_dc_scale = s->qscale; } else { /* default quantization values */ s->y_dc_scale = 8; diff --git a/libavcodec/i386/mpegvideo_mmx.c b/libavcodec/i386/mpegvideo_mmx.c index 3ca40ca047..542d2d819c 100644 --- a/libavcodec/i386/mpegvideo_mmx.c +++ b/libavcodec/i386/mpegvideo_mmx.c @@ -83,7 +83,10 @@ static void dct_unquantize_h263_mmx(MpegEncContext *s, int i, level, qmul, qadd, nCoeffs; qmul = s->qscale << 1; - qadd = (s->qscale - 1) | 1; + if (s->h263_aic && s->mb_intra) + qadd = 0; + else + qadd = (s->qscale - 1) | 1; if (s->mb_intra) { if (n < 4) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index a8e19073ec..d67dffe67a 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -181,7 +181,7 @@ int MPV_common_init(MpegEncContext *s) memset(s->motion_val, 0, size * 2 * sizeof(INT16)); } - if (s->h263_pred) { + if (s->h263_pred || s->h263_plus) { int y_size, c_size, i, size; /* dc values */ @@ -1062,10 +1062,20 @@ static void encode_picture(MpegEncContext *s, int picture_number) sub_pixels_2(s->block[5], ptr, s->linesize >> 1, dxy); } emms_c(); - //if (s->avg_mb_var) - // printf("\nqscale=%2d dquant=%2d var=%4d avgvar=%4d", s->qscale, - // s->qscale*(s->mb_var[s->mb_width*mb_y+mb_x]/s->avg_mb_var), - // s->mb_var[s->mb_width*mb_y+mb_x], s->avg_mb_var); + +#if 0 + { + float adap_parm; + + adap_parm = ((s->avg_mb_var << 1) + s->mb_var[s->mb_width*mb_y+mb_x] + 1.0) / + ((s->mb_var[s->mb_width*mb_y+mb_x] << 1) + s->avg_mb_var + 1.0); + + printf("\ntype=%c qscale=%2d adap=%0.2f dquant=%4.2f var=%4d avgvar=%4d", + (s->mb_type[s->mb_width*mb_y+mb_x] > 0) ? 'I' : 'P', + s->qscale, adap_parm, s->qscale*adap_parm, + s->mb_var[s->mb_width*mb_y+mb_x], s->avg_mb_var); + } +#endif /* DCT & quantize */ if (s->h263_msmpeg4) { msmpeg4_dc_scale(s); @@ -1331,7 +1341,10 @@ static void dct_unquantize_h263_c(MpegEncContext *s, } qmul = s->qscale << 1; - qadd = (s->qscale - 1) | 1; + if (s->h263_aic && s->mb_intra) + qadd = 0; + else + qadd = (s->qscale - 1) | 1; for(;ipicture_number, (double)total_bits, + (double)s->wanted_bits, (float)s->frame_rate / FRAME_RATE_BASE * total_bits / s->picture_number, - diff, q); + (int)diff, q); #endif return qscale; } diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index acbb1230d1..8b39746b8e 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -146,10 +146,12 @@ typedef struct MpegEncContext { int gob_number; int gob_index; int first_gob_line; - + /* H.263+ specific */ int umvplus; int umvplus_dec; + int h263_aic; /* Advanded INTRA Coding (AIC) */ + int h263_aic_dir; /* AIC direction: 0 = left, 1 = top */ /* mpeg4 specific */ int time_increment_bits;