# HG changeset patch # User michaelni # Date 1017979744 0 # Node ID 764aeec1320ebbfae5be0b7f9e766138af9346de # Parent ebfd518cbbbf05763adabba008d75df3690cbf8d msmpeg4v2 decoding (no encoding yet) diff -r ebfd518cbbbf -r 764aeec1320e avcodec.h --- a/avcodec.h Thu Apr 04 20:04:10 2002 +0000 +++ b/avcodec.h Fri Apr 05 04:09:04 2002 +0000 @@ -14,7 +14,9 @@ CODEC_ID_MJPEG, CODEC_ID_MPEG4, CODEC_ID_RAWVIDEO, - CODEC_ID_MSMPEG4, + CODEC_ID_MSMPEG4V1, + CODEC_ID_MSMPEG4V2, + CODEC_ID_MSMPEG4V3, CODEC_ID_H263P, CODEC_ID_H263I, @@ -28,6 +30,7 @@ CODEC_ID_PCM_MULAW, CODEC_ID_PCM_ALAW, }; +#define CODEC_ID_MSMPEG4 CODEC_ID_MSMPEG4V3 enum CodecType { CODEC_TYPE_VIDEO, @@ -200,11 +203,15 @@ extern AVCodec rv10_encoder; extern AVCodec mjpeg_encoder; extern AVCodec mpeg4_encoder; -extern AVCodec msmpeg4_encoder; +extern AVCodec msmpeg4v1_encoder; +extern AVCodec msmpeg4v2_encoder; +extern AVCodec msmpeg4v3_encoder; extern AVCodec h263_decoder; extern AVCodec mpeg4_decoder; -extern AVCodec msmpeg4_decoder; +extern AVCodec msmpeg4v1_decoder; +extern AVCodec msmpeg4v2_decoder; +extern AVCodec msmpeg4v3_decoder; extern AVCodec mpeg_decoder; extern AVCodec h263i_decoder; extern AVCodec rv10_decoder; diff -r ebfd518cbbbf -r 764aeec1320e h263data.h --- a/h263data.h Thu Apr 04 20:04:10 2002 +0000 +++ b/h263data.h Fri Apr 05 04:09:04 2002 +0000 @@ -40,13 +40,13 @@ 3, 7, 7, 8, };*/ -static const UINT8 cbpy_tab[16][2] = +const UINT8 cbpy_tab[16][2] = { {3,4}, {5,5}, {4,5}, {9,4}, {3,5}, {7,4}, {2,6}, {11,4}, {2,5}, {3,6}, {5,4}, {10,4}, {4,4}, {8,4}, {6,4}, {3,2} }; -static const UINT8 mvtab[33][2] = +const UINT8 mvtab[33][2] = { {1,1}, {1,2}, {1,3}, {1,4}, {3,6}, {5,7}, {4,7}, {3,7}, {11,9}, {10,9}, {9,9}, {17,10}, {16,10}, {15,10}, {14,10}, {13,10}, diff -r ebfd518cbbbf -r 764aeec1320e h263dec.c --- a/h263dec.c Thu Apr 04 20:04:10 2002 +0000 +++ b/h263dec.c Fri Apr 05 04:09:04 2002 +0000 @@ -47,9 +47,20 @@ s->h263_pred = 1; s->has_b_frames = 1; break; - case CODEC_ID_MSMPEG4: + case CODEC_ID_MSMPEG4V1: s->h263_msmpeg4 = 1; s->h263_pred = 1; + s->msmpeg4_version=1; + break; + case CODEC_ID_MSMPEG4V2: + s->h263_msmpeg4 = 1; + s->h263_pred = 1; + s->msmpeg4_version=2; + break; + case CODEC_ID_MSMPEG4V3: + s->h263_msmpeg4 = 1; + s->h263_pred = 1; + s->msmpeg4_version=3; break; case CODEC_ID_H263I: s->h263_intel = 1; @@ -269,10 +280,34 @@ CODEC_CAP_DRAW_HORIZ_BAND, }; -AVCodec msmpeg4_decoder = { +AVCodec msmpeg4v1_decoder = { + "msmpeg4v1", + CODEC_TYPE_VIDEO, + CODEC_ID_MSMPEG4V1, + sizeof(MpegEncContext), + h263_decode_init, + NULL, + h263_decode_end, + h263_decode_frame, + CODEC_CAP_DRAW_HORIZ_BAND, +}; + +AVCodec msmpeg4v2_decoder = { + "msmpeg4v2", + CODEC_TYPE_VIDEO, + CODEC_ID_MSMPEG4V2, + sizeof(MpegEncContext), + h263_decode_init, + NULL, + h263_decode_end, + h263_decode_frame, + CODEC_CAP_DRAW_HORIZ_BAND, +}; + +AVCodec msmpeg4v3_decoder = { "msmpeg4", CODEC_TYPE_VIDEO, - CODEC_ID_MSMPEG4, + CODEC_ID_MSMPEG4V3, sizeof(MpegEncContext), h263_decode_init, NULL, diff -r ebfd518cbbbf -r 764aeec1320e mpeg4data.h --- a/mpeg4data.h Thu Apr 04 20:04:10 2002 +0000 +++ b/mpeg4data.h Fri Apr 05 04:09:04 2002 +0000 @@ -12,13 +12,13 @@ #define GMC_SPRITE 2 /* dc encoding for mpeg4 */ -static const UINT8 DCtab_lum[13][2] = +const UINT8 DCtab_lum[13][2] = { {3,3}, {3,2}, {2,2}, {2,3}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7}, {1,8}, {1,9}, {1,10}, {1,11}, }; -static const UINT8 DCtab_chrom[13][2] = +const UINT8 DCtab_chrom[13][2] = { {3,2}, {2,2}, {1,2}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7}, {1,8}, {1,9}, {1,10}, {1,11}, {1,12}, @@ -103,3 +103,22 @@ static const UINT8 mb_type_b_tab[4][2] = { {1, 1}, {1, 2}, {1, 3}, {1, 4}, }; + +static const UINT16 pixel_aspect[16][2]={ + {0, 0}, + {1, 1}, + {12, 11}, + {10, 11}, + {16, 11}, + {40, 33}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, +}; diff -r ebfd518cbbbf -r 764aeec1320e mpegvideo.c --- a/mpegvideo.c Thu Apr 04 20:04:10 2002 +0000 +++ b/mpegvideo.c Fri Apr 05 04:09:04 2002 +0000 @@ -355,11 +355,26 @@ s->h263_pred = 1; s->unrestricted_mv = 1; break; - case CODEC_ID_MSMPEG4: + case CODEC_ID_MSMPEG4V1: s->out_format = FMT_H263; s->h263_msmpeg4 = 1; s->h263_pred = 1; s->unrestricted_mv = 1; + s->msmpeg4_version= 1; + break; + case CODEC_ID_MSMPEG4V2: + s->out_format = FMT_H263; + s->h263_msmpeg4 = 1; + s->h263_pred = 1; + s->unrestricted_mv = 1; + s->msmpeg4_version= 2; + break; + case CODEC_ID_MSMPEG4V3: + s->out_format = FMT_H263; + s->h263_msmpeg4 = 1; + s->h263_pred = 1; + s->unrestricted_mv = 1; + s->msmpeg4_version= 3; break; default: return -1; @@ -2117,12 +2132,32 @@ MPV_encode_end, }; -AVCodec msmpeg4_encoder = { - "msmpeg4", +AVCodec msmpeg4v1_encoder = { + "msmpeg4v1", CODEC_TYPE_VIDEO, - CODEC_ID_MSMPEG4, + CODEC_ID_MSMPEG4V1, sizeof(MpegEncContext), MPV_encode_init, MPV_encode_picture, MPV_encode_end, }; + +AVCodec msmpeg4v2_encoder = { + "msmpeg4v2", + CODEC_TYPE_VIDEO, + CODEC_ID_MSMPEG4V2, + sizeof(MpegEncContext), + MPV_encode_init, + MPV_encode_picture, + MPV_encode_end, +}; + +AVCodec msmpeg4v3_encoder = { + "msmpeg4", + CODEC_TYPE_VIDEO, + CODEC_ID_MSMPEG4V3, + sizeof(MpegEncContext), + MPV_encode_init, + MPV_encode_picture, + MPV_encode_end, +}; diff -r ebfd518cbbbf -r 764aeec1320e mpegvideo.h --- a/mpegvideo.h Thu Apr 04 20:04:10 2002 +0000 +++ b/mpegvideo.h Fri Apr 05 04:09:04 2002 +0000 @@ -267,6 +267,7 @@ int first_slice_line; /* used in mpeg4 too to handle resync markers */ int flipflop_rounding; int bitrate; + int msmpeg4_version; /* 1=mp41, 2=mp42, 3=mp43/divx3 */ /* decompression specific */ GetBitContext gb; diff -r ebfd518cbbbf -r 764aeec1320e msmpeg4.c --- a/msmpeg4.c Thu Apr 04 20:04:10 2002 +0000 +++ b/msmpeg4.c Fri Apr 05 04:09:04 2002 +0000 @@ -29,7 +29,6 @@ * TODO: * - (encoding) select best mv table (two choices) * - (encoding) select best vlc/dc table - * - (decoding) handle slice indication */ //#define DEBUG @@ -44,6 +43,9 @@ VLC vlc; /* decoding: vlc */ } MVTable; +static UINT32 v2_dc_lum_table[512][2]; +static UINT32 v2_dc_chroma_table[512][2]; + static void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n); static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block, int n, int coded); @@ -620,6 +622,72 @@ static VLC mb_intra_vlc; static VLC dc_lum_vlc[2]; static VLC dc_chroma_vlc[2]; +static VLC v2_dc_lum_vlc; +static VLC v2_dc_chroma_vlc; +static VLC cbpy_vlc; +static VLC v2_intra_cbpc_vlc; +static VLC v2_mb_type_vlc; +static VLC v2_mv_vlc; + +/* this table is practically identical to the one from h263 except that its inverted */ +static void init_h263_dc_for_msmpeg4() +{ + static int inited=0; + + if(!inited){ + int level, uni_code, uni_len; + inited=1; + + for(level=-255; level<256; level++){ + int size, v, l; + /* find number of bits */ + size = 0; + v = abs(level); + while (v) { + v >>= 1; + size++; + } + + if (level < 0) + l= (-level) ^ ((1 << size) - 1); + else + l= level; + + /* luminance h263 */ + uni_code= DCtab_lum[size][0]; + uni_len = DCtab_lum[size][1]; + uni_code ^= (1< 0) { + uni_code<<=size; uni_code|=l; + uni_len+=size; + if (size > 8){ + uni_code<<=1; uni_code|=1; + uni_len++; + } + } + v2_dc_lum_table[level+256][0]= uni_code; + v2_dc_lum_table[level+256][1]= uni_len; + + /* chrominance h263 */ + uni_code= DCtab_chrom[size][0]; + uni_len = DCtab_chrom[size][1]; + uni_code ^= (1< 0) { + uni_code<<=size; uni_code|=l; + uni_len+=size; + if (size > 8){ + uni_code<<=1; uni_code|=1; + uni_len++; + } + } + v2_dc_chroma_table[level+256][0]= uni_code; + v2_dc_chroma_table[level+256][1]= uni_len; + + } + } +} /* init all vlc decoding tables */ int msmpeg4_decode_init_vlc(MpegEncContext *s) @@ -650,6 +718,27 @@ init_vlc(&dc_chroma_vlc[1], 9, 120, &table1_dc_chroma[0][1], 8, 4, &table1_dc_chroma[0][0], 8, 4); + + init_h263_dc_for_msmpeg4(); + init_vlc(&v2_dc_lum_vlc, 9, 512, + &v2_dc_lum_table[0][1], 8, 4, + &v2_dc_lum_table[0][0], 8, 4); + init_vlc(&v2_dc_chroma_vlc, 9, 512, + &v2_dc_chroma_table[0][1], 8, 4, + &v2_dc_chroma_table[0][0], 8, 4); + + init_vlc(&cbpy_vlc, 6, 16, + &cbpy_tab[0][1], 2, 1, + &cbpy_tab[0][0], 2, 1); + init_vlc(&v2_intra_cbpc_vlc, 3, 4, + &v2_intra_cbpc[0][1], 2, 1, + &v2_intra_cbpc[0][0], 2, 1); + init_vlc(&v2_mb_type_vlc, 5, 8, + &v2_mb_type[0][1], 2, 1, + &v2_mb_type[0][0], 2, 1); + init_vlc(&v2_mv_vlc, 9, 33, + &mvtab[0][1], 2, 1, + &mvtab[0][0], 2, 1); init_vlc(&mb_non_intra_vlc, 9, 128, &table_mb_non_intra[0][1], 8, 4, @@ -670,7 +759,7 @@ return get_bits1(gb) + 1; } -int msmpeg4v2_decode_picture_header(MpegEncContext * s) +int msmpeg4_decode_picture_header(MpegEncContext * s) { int code; @@ -683,72 +772,21 @@ if (s->pict_type == I_TYPE) { code = get_bits(&s->gb, 5); - /* 0x17: one slice, 0x18: three slices */ - /* XXX: implement it */ - //printf("%d %d %d\n", code, s->slice_height, s->first_slice_line); + /* 0x17: one slice, 0x18: two slices */ if (code < 0x17) return -1; s->slice_height = s->mb_height / (code - 0x16); -/* s->rl_chroma_table_index = decode012(&s->gb); - s->rl_table_index = decode012(&s->gb); - - s->dc_table_index = get_bits1(&s->gb);*/ - s->no_rounding = 1; - } else { - s->use_skip_mb_code = get_bits1(&s->gb); - -/* s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; - - s->dc_table_index = get_bits1(&s->gb); - - s->mv_table_index = get_bits1(&s->gb);*/ - if(s->flipflop_rounding){ - s->no_rounding ^= 1; - }else{ - s->no_rounding = 0; - } -// printf("%d", s->no_rounding); - } - -printf("%s q:%d s:%X ", s->pict_type == I_TYPE ? "I" : "P" , s->qscale, - s->pict_type == I_TYPE ? code : s->use_skip_mb_code); - - return 0; -} + if(s->msmpeg4_version==2){ + s->rl_chroma_table_index = 2; + s->rl_table_index = 2; -int msmpeg4_decode_picture_header(MpegEncContext * s) -{ - int code; -#if 0 -{ -int i; -msmpeg4v2_decode_picture_header(s); -for(i=0; igb.size*8; i++) - printf("%d", get_bits1(&s->gb)); -printf("END\n"); -return -1; -} -#endif - s->pict_type = get_bits(&s->gb, 2) + 1; - if (s->pict_type != I_TYPE && - s->pict_type != P_TYPE) - return -1; + s->dc_table_index = 0; //not used + }else{ + s->rl_chroma_table_index = decode012(&s->gb); + s->rl_table_index = decode012(&s->gb); - s->qscale = get_bits(&s->gb, 5); - - if (s->pict_type == I_TYPE) { - code = get_bits(&s->gb, 5); - /* 0x17: one slice, 0x18: three slices */ - /* XXX: implement it */ - //printf("%d %d %d\n", code, s->slice_height, s->first_slice_line); - if (code < 0x17) - return -1; - s->slice_height = s->mb_height / (code - 0x16); - s->rl_chroma_table_index = decode012(&s->gb); - s->rl_table_index = decode012(&s->gb); - - s->dc_table_index = get_bits1(&s->gb); + s->dc_table_index = get_bits1(&s->gb); + } s->no_rounding = 1; /* printf(" %d %d %d %d \n", s->qscale, @@ -758,12 +796,21 @@ } else { s->use_skip_mb_code = get_bits1(&s->gb); - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; + if(s->msmpeg4_version==2){ + s->rl_table_index = 2; + s->rl_chroma_table_index = s->rl_table_index; + + s->dc_table_index = 0; //not used - s->dc_table_index = get_bits1(&s->gb); + s->mv_table_index = 0; + }else{ + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; - s->mv_table_index = get_bits1(&s->gb); + s->dc_table_index = get_bits1(&s->gb); + + s->mv_table_index = get_bits1(&s->gb); + } /* printf(" %d %d %d %d %d \n", s->use_skip_mb_code, s->rl_table_index, @@ -778,7 +825,20 @@ // printf("%d", s->no_rounding); } - +#if 0 +if(s->msmpeg4_version==2) +{ +int i; +printf("%s q:%d s:%X ", s->pict_type == I_TYPE ? "I" : "P" , s->qscale, + s->pict_type == I_TYPE ? code : s->use_skip_mb_code); +for(i=0; igb.size*8; i++) +// printf("%d", get_bits1(&s->gb)); + get_bits1(&s->gb); +printf("END\n"); +return -1; +} +#endif + #ifdef DEBUG printf("*****frame %d:\n", frame_count++); #endif @@ -814,6 +874,103 @@ tab[i] = val; } +/* this is identical to h263 except that its range is multiplied by 2 */ +static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code) +{ + int code, val, sign, shift; + + code = get_vlc(&s->gb, &v2_mv_vlc); + if (code < 0) + return 0xffff; + + if (code == 0) + return pred; + sign = get_bits1(&s->gb); + shift = f_code - 1; + val = (code - 1) << shift; + if (shift > 0) + val |= get_bits(&s->gb, shift); + val++; + if (sign) + val = -val; + val += pred; + + if (val <= -64) + val += 64; + else if (val >= 64) + val -= 64; + + return val; +} + + +int msmpeg4v2_decode_mb(MpegEncContext *s, + DCTELEM block[6][64]) +{ + int cbp, code, i; +//printf("M"); +//fflush(stderr); fflush(stdout); + if (s->pict_type == P_TYPE) { + if (s->use_skip_mb_code) { + if (get_bits1(&s->gb)) { + /* skip mb */ + s->mb_intra = 0; + for(i=0;i<6;i++) + s->block_last_index[i] = -1; + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->mb_skiped = 1; + return 0; + } + } + + code = get_vlc(&s->gb, &v2_mb_type_vlc); + s->mb_intra = code >>2; + + cbp = code & 0x3; + } else { + s->mb_intra = 1; +//printf("%X ", show_bits(&s->gb, 24)); + cbp= get_vlc(&s->gb, &v2_intra_cbpc_vlc); +//printf("%X ", show_bits(&s->gb, 24)); +//printf("CBP: %X ",cbp); + } + + if (!s->mb_intra) { + int mx, my; + + cbp|= get_vlc(&s->gb, &cbpy_vlc)<<2; + if((cbp&3) != 3) cbp^= 0x3C; + + h263_pred_motion(s, 0, &mx, &my); + mx= msmpeg4v2_decode_motion(s, mx, 1); + my= msmpeg4v2_decode_motion(s, my, 1); + + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = mx; + s->mv[0][0][1] = my; + } else { +//if(s->pict_type == P_TYPE) printf("intra cbp: %X", cbp); + s->ac_pred = get_bits1(&s->gb); +//printf("AC: %d ",s->ac_pred); + cbp|= get_vlc(&s->gb, &cbpy_vlc)<<2; +//printf("cbp: %X ",cbp); + } + + for (i = 0; i < 6; i++) { + if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1) < 0) + { +//fflush(stderr); fflush(stdout); + fprintf(stderr,"\nIgnoring error while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); + return -1; + } + } + return 0; +} + int msmpeg4_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) { @@ -850,6 +1007,8 @@ } } + if(s->msmpeg4_version==2) return msmpeg4v2_decode_mb(s, block); //FIXME merge if possible + if (s->pict_type == P_TYPE) { set_stat(ST_INTER_MB); if (s->use_skip_mb_code) { @@ -962,7 +1121,12 @@ qadd = (s->qscale - 1) | 1; i = 0; rl = &rl_table[3 + s->rl_table_index]; - run_diff = 1; + + if(s->msmpeg4_version==2) + run_diff = 0; + else + run_diff = 1; + if (!coded) { s->block_last_index[n] = i - 1; return 0; @@ -1046,21 +1210,33 @@ int level, pred; INT16 *dc_val; - if (n < 4) { - level = get_vlc(&s->gb, &dc_lum_vlc[s->dc_table_index]); - } else { - level = get_vlc(&s->gb, &dc_chroma_vlc[s->dc_table_index]); - } - if (level < 0) - return -1; + if(s->msmpeg4_version==2){ + if (n < 4) { + level = get_vlc(&s->gb, &v2_dc_lum_vlc); + } else { + level = get_vlc(&s->gb, &v2_dc_chroma_vlc); + } + if (level < 0) + return -1; - if (level == DC_MAX) { - level = get_bits(&s->gb, 8); - if (get_bits1(&s->gb)) - level = -level; - } else if (level != 0) { - if (get_bits1(&s->gb)) - level = -level; + level-=256; + }else{ //FIXME optimize use unified tables & index + if (n < 4) { + level = get_vlc(&s->gb, &dc_lum_vlc[s->dc_table_index]); + } else { + level = get_vlc(&s->gb, &dc_chroma_vlc[s->dc_table_index]); + } + if (level < 0) + return -1; + + if (level == DC_MAX) { + level = get_bits(&s->gb, 8); + if (get_bits1(&s->gb)) + level = -level; + } else if (level != 0) { + if (get_bits1(&s->gb)) + level = -level; + } } pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr); diff -r ebfd518cbbbf -r 764aeec1320e msmpeg4data.h --- a/msmpeg4data.h Thu Apr 04 20:04:10 2002 +0000 +++ b/msmpeg4data.h Fri Apr 05 04:09:04 2002 +0000 @@ -569,6 +569,13 @@ extern const INT8 intra_level[102]; extern const INT8 intra_run[102]; +extern const UINT8 DCtab_lum[13][2]; +extern const UINT8 DCtab_chrom[13][2]; + +extern const UINT8 cbpy_tab[16][2]; +extern const UINT8 mvtab[33][2]; + + #define NB_RL_TABLES 6 static RLTable rl_table[NB_RL_TABLES] = { @@ -1765,3 +1772,12 @@ table1_mvy, } }; + +static const UINT8 v2_mb_type[8][2] = { + {1, 1}, {0 , 2}, {3 , 3}, {9 , 5}, + {5, 4}, {0x21, 7}, {0x20, 7}, {0x11, 6}, +}; + +static const UINT8 v2_intra_cbpc[4][2] = { + {1, 1}, {0, 3}, {1, 3}, {1, 2}, +}; diff -r ebfd518cbbbf -r 764aeec1320e utils.c --- a/utils.c Thu Apr 04 20:04:10 2002 +0000 +++ b/utils.c Fri Apr 05 04:09:04 2002 +0000 @@ -416,7 +416,9 @@ register_avcodec(&rv10_encoder); register_avcodec(&mjpeg_encoder); register_avcodec(&mpeg4_encoder); - register_avcodec(&msmpeg4_encoder); + register_avcodec(&msmpeg4v1_encoder); + register_avcodec(&msmpeg4v2_encoder); + register_avcodec(&msmpeg4v3_encoder); #endif /* CONFIG_ENCODERS */ register_avcodec(&rawvideo_codec); @@ -424,7 +426,9 @@ #ifdef CONFIG_DECODERS register_avcodec(&h263_decoder); register_avcodec(&mpeg4_decoder); - register_avcodec(&msmpeg4_decoder); + register_avcodec(&msmpeg4v1_decoder); + register_avcodec(&msmpeg4v2_decoder); + register_avcodec(&msmpeg4v3_decoder); register_avcodec(&mpeg_decoder); register_avcodec(&h263i_decoder); register_avcodec(&rv10_decoder);