# HG changeset patch # User michaelni # Date 1026030886 0 # Node ID 55b4e2248a4555cd37087c610418459913db44a5 # Parent 70113647b50d428af977fc6270e77f45c565dada wmv1 slice_height != mb_height support encoding of slice_height != mb_height 1bit shorter wmv1 headers if bit_rate<50 !? ROTFL M$ is even more stupid than i thought using dc of non intra blocks for dc prediction of wmv1 if bitrate < 129 && res < 320x240 diff -r 70113647b50d -r 55b4e2248a45 mpegvideo.h --- a/mpegvideo.h Fri Jul 05 19:16:26 2002 +0000 +++ b/mpegvideo.h Sun Jul 07 08:34:46 2002 +0000 @@ -392,6 +392,7 @@ UINT8 *intra_h_scantable; /* [mb_intra][isChroma][level][run][last] */ int ac_stats[2][2][MAX_LEVEL+1][MAX_RUN+1][2]; + int inter_intra_pred; /* decompression specific */ diff -r 70113647b50d -r 55b4e2248a45 msmpeg4.c --- a/msmpeg4.c Fri Jul 05 19:16:26 2002 +0000 +++ b/msmpeg4.c Sun Jul 07 08:34:46 2002 +0000 @@ -43,6 +43,8 @@ int *mx_ptr, int *my_ptr); static void msmpeg4v2_encode_motion(MpegEncContext * s, int val); static void init_h263_dc_for_msmpeg4(void); +static inline void msmpeg4_memsetw(short *tab, int val, int n); + extern UINT32 inverse[256]; @@ -345,14 +347,17 @@ s->mv_table_index = 1; /* only if P frame */ s->use_skip_mb_code = 1; /* only if P frame */ s->per_mb_rl_table = 0; + s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=128 && s->pict_type==P_TYPE); if (s->pict_type == I_TYPE) { s->no_rounding = 1; - put_bits(&s->pb, 5, 0x17); /* indicate only one "slice" */ + s->slice_height= s->mb_height/1; + put_bits(&s->pb, 5, 0x16 + s->mb_height/s->slice_height); if(s->msmpeg4_version==4){ msmpeg4_encode_ext_header(s); - put_bits(&s->pb, 1, s->per_mb_rl_table); + if(s->bit_rate>50) + put_bits(&s->pb, 1, s->per_mb_rl_table); } if(s->msmpeg4_version>2){ @@ -366,7 +371,7 @@ } else { put_bits(&s->pb, 1, s->use_skip_mb_code); - if(s->msmpeg4_version==4) + if(s->msmpeg4_version==4 && s->bit_rate>50) put_bits(&s->pb, 1, s->per_mb_rl_table); if(s->msmpeg4_version>2){ @@ -398,7 +403,7 @@ { put_bits(&s->pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29 - put_bits(&s->pb, 11, MIN(s->bit_rate, 2047)); + put_bits(&s->pb, 11, MIN(s->bit_rate, 2047)); if(s->msmpeg4_version<3) s->flipflop_rounding=0; @@ -474,6 +479,38 @@ } } +static inline void handle_slices(MpegEncContext *s){ + if (s->mb_x == 0) { + if (s->slice_height && (s->mb_y % s->slice_height) == 0) { + if(s->msmpeg4_version != 4){ + int wrap; + /* reset DC pred (set previous line to 1024) */ + wrap = 2 * s->mb_width + 2; + msmpeg4_memsetw(&s->dc_val[0][(1) + (2 * s->mb_y) * wrap], + 1024, 2 * s->mb_width); + wrap = s->mb_width + 2; + msmpeg4_memsetw(&s->dc_val[1][(1) + (s->mb_y) * wrap], + 1024, s->mb_width); + msmpeg4_memsetw(&s->dc_val[2][(1) + (s->mb_y) * wrap], + 1024, s->mb_width); + + /* reset AC pred (set previous line to 0) */ + wrap = s->mb_width * 2 + 2; + msmpeg4_memsetw(s->ac_val[0][0] + (1 + (2 * s->mb_y) * wrap)*16, + 0, 2 * s->mb_width*16); + wrap = s->mb_width + 2; + msmpeg4_memsetw(s->ac_val[1][0] + (1 + (s->mb_y) * wrap)*16, + 0, s->mb_width*16); + msmpeg4_memsetw(s->ac_val[2][0] + (1 + (s->mb_y) * wrap)*16, + 0, s->mb_width*16); + } + s->first_slice_line = 1; + } else { + s->first_slice_line = 0; + } + } +} + void msmpeg4_encode_mb(MpegEncContext * s, DCTELEM block[6][64], int motion_x, int motion_y) @@ -482,6 +519,8 @@ int pred_x, pred_y; UINT8 *coded_block; + handle_slices(s); + if (!s->mb_intra) { /* compute cbp */ set_stat(ST_INTER_MB); @@ -610,6 +649,19 @@ return s->last_dc[i]; } +static int get_dc(uint8_t *src, int stride, int scale) +{ + int y; + int sum=0; + for(y=0; y<8; y++){ + int x; + for(x=0; x<8; x++){ + sum+=src[x + y*stride]; + } + } + return (sum + (scale>>1))/scale; +} + /* dir = 0: left, dir = 1: top prediction */ static inline int msmpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr) @@ -675,12 +727,69 @@ /* XXX: WARNING: they did not choose the same test as MPEG4. This is very important ! */ if(s->msmpeg4_version>3){ - if (abs(a - b) < abs(b - c)) { - pred = c; - *dir_ptr = 1; - } else { - pred = a; - *dir_ptr = 0; + if(s->inter_intra_pred){ + uint8_t *dest; + int wrap; + + if(n==1){ + pred=a; + *dir_ptr = 0; + }else if(n==2){ + pred=c; + *dir_ptr = 1; + }else if(n==3){ + if (abs(a - b) < abs(b - c)) { + pred = c; + *dir_ptr = 1; + } else { + pred = a; + *dir_ptr = 0; + } + }else{ + if(n<4){ + wrap= s->linesize; + dest= s->current_picture[0] + (((n>>1) + 2*s->mb_y) * 8* wrap ) + ((n&1) + 2*s->mb_x) * 8; + }else{ + wrap= s->linesize>>1; + dest= s->current_picture[n-3] + (s->mb_y * 8 * wrap) + s->mb_x * 8; + } + if(s->mb_x==0) a= (1024 + (scale>>1))/scale; + else a= get_dc(dest-8, wrap, scale*8); + if(s->mb_y==0) c= (1024 + (scale>>1))/scale; + else c= get_dc(dest-8*wrap, wrap, scale*8); + + if (s->h263_aic_dir==0) { + pred= a; + *dir_ptr = 0; + }else if (s->h263_aic_dir==1) { + if(n==0){ + pred= c; + *dir_ptr = 1; + }else{ + pred= a; + *dir_ptr = 0; + } + }else if (s->h263_aic_dir==2) { + if(n==0){ + pred= a; + *dir_ptr = 0; + }else{ + pred= c; + *dir_ptr = 1; + } + } else { + pred= c; + *dir_ptr = 1; + } + } + }else{ + if (abs(a - b) < abs(b - c)) { + pred = c; + *dir_ptr = 1; + } else { + pred = a; + *dir_ptr = 0; + } } }else{ if (abs(a - b) <= abs(b - c)) { @@ -904,6 +1013,7 @@ static VLC v2_mv_vlc; static VLC v1_intra_cbpc_vlc; static VLC v1_inter_cbpc_vlc; +static VLC inter_intra_vlc; /* this table is practically identical to the one from h263 except that its inverted */ static void init_h263_dc_for_msmpeg4(void) @@ -1029,6 +1139,10 @@ init_vlc(&v1_inter_cbpc_vlc, 6, 25, inter_MCBPC_bits, 1, 1, inter_MCBPC_code, 1, 1); + + init_vlc(&inter_intra_vlc, 3, 4, + &table_inter_intra[0][1], 2, 1, + &table_inter_intra[0][0], 2, 1); } return 0; } @@ -1075,7 +1189,13 @@ fprintf(stderr, "invalid picture type\n"); return -1; } - +#if 0 +{ + static int had_i=0; + if(s->pict_type == I_TYPE) had_i=1; + if(!had_i) return -1; +} +#endif s->qscale = get_bits(&s->gb, 5); if (s->pict_type == I_TYPE) { @@ -1089,8 +1209,10 @@ s->slice_height = code; }else{ /* 0x17: one slice, 0x18: two slices, ... */ - if (code < 0x17) + if (code < 0x17){ + fprintf(stderr, "error, slice code was %X\n", code); return -1; + } s->slice_height = s->mb_height / (code - 0x16); } @@ -1112,24 +1234,27 @@ case 4: msmpeg4_decode_ext_header(s, (2+5+5+17+7)/8); - s->per_mb_rl_table= get_bits1(&s->gb); + if(s->bit_rate > 50) s->per_mb_rl_table= get_bits1(&s->gb); + else s->per_mb_rl_table= 0; + if(!s->per_mb_rl_table){ s->rl_chroma_table_index = decode012(&s->gb); s->rl_table_index = decode012(&s->gb); } s->dc_table_index = get_bits1(&s->gb); + s->inter_intra_pred= 0; break; } s->no_rounding = 1; -/* printf(" %d %d %d %d %d \n", +/* printf("qscale:%d rlc:%d rl:%d dc:%d mbrl:%d slice:%d \n", s->qscale, s->rl_chroma_table_index, s->rl_table_index, s->dc_table_index, - s->per_mb_rl_table);*/ + s->per_mb_rl_table, + s->slice_height);*/ } else { - switch(s->msmpeg4_version){ case 1: case 2: @@ -1153,7 +1278,10 @@ break; case 4: s->use_skip_mb_code = get_bits1(&s->gb); - s->per_mb_rl_table= get_bits1(&s->gb); + + if(s->bit_rate > 50) s->per_mb_rl_table= get_bits1(&s->gb); + else s->per_mb_rl_table= 0; + if(!s->per_mb_rl_table){ s->rl_table_index = decode012(&s->gb); s->rl_chroma_table_index = s->rl_table_index; @@ -1162,15 +1290,17 @@ s->dc_table_index = get_bits1(&s->gb); s->mv_table_index = get_bits1(&s->gb); + s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=128); break; } -/* printf(" %d %d %d %d %d %d \n", +/* printf("skip:%d rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d \n", s->use_skip_mb_code, s->rl_table_index, s->rl_chroma_table_index, s->dc_table_index, s->mv_table_index, - s->per_mb_rl_table);*/ + s->per_mb_rl_table, + s->qscale);*/ if(s->flipflop_rounding){ s->no_rounding ^= 1; }else{ @@ -1387,34 +1517,7 @@ } #endif /* special slice handling */ - if (s->mb_x == 0) { - if (s->slice_height && (s->mb_y % s->slice_height) == 0) { - int wrap; - /* reset DC pred (set previous line to 1024) */ - wrap = 2 * s->mb_width + 2; - msmpeg4_memsetw(&s->dc_val[0][(1) + (2 * s->mb_y) * wrap], - 1024, 2 * s->mb_width); - wrap = s->mb_width + 2; - msmpeg4_memsetw(&s->dc_val[1][(1) + (s->mb_y) * wrap], - 1024, s->mb_width); - msmpeg4_memsetw(&s->dc_val[2][(1) + (s->mb_y) * wrap], - 1024, s->mb_width); - - /* reset AC pred (set previous line to 0) */ - wrap = s->mb_width * 2 + 2; - msmpeg4_memsetw(s->ac_val[0][0] + (1 + (2 * s->mb_y) * wrap)*16, - 0, 2 * s->mb_width*16); - wrap = s->mb_width + 2; - msmpeg4_memsetw(s->ac_val[1][0] + (1 + (s->mb_y) * wrap)*16, - 0, s->mb_width*16); - msmpeg4_memsetw(s->ac_val[2][0] + (1 + (s->mb_y) * wrap)*16, - 0, s->mb_width*16); - - s->first_slice_line = 1; - } else { - s->first_slice_line = 0; - } - } + handle_slices(s); if(s->msmpeg4_version<=2) return msmpeg4v12_decode_mb(s, block); //FIXME export function & call from outside perhaps @@ -1489,6 +1592,10 @@ #ifdef PRINT_MB printf("%c", s->ac_pred ? 'A' : 'I'); #endif + if(s->inter_intra_pred){ + s->h263_aic_dir= get_vlc(&s->gb, &inter_intra_vlc); +// printf("%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y); + } if(s->per_mb_rl_table && cbp){ s->rl_table_index = decode012(&s->gb); s->rl_chroma_table_index = s->rl_table_index; @@ -1532,19 +1639,20 @@ #endif if (level < 0){ fprintf(stderr, "dc overflow- block: %d qscale: %d//\n", n, s->qscale); - return -1; + if(s->inter_intra_pred) level=0; + else return -1; } if (n < 4) { rl = &rl_table[s->rl_table_index]; if(level > 256*s->y_dc_scale){ fprintf(stderr, "dc overflow+ L qscale: %d//\n", s->qscale); - return -1; + if(!s->inter_intra_pred) return -1; } } else { rl = &rl_table[3 + s->rl_chroma_table_index]; if(level > 256*s->c_dc_scale){ fprintf(stderr, "dc overflow+ C qscale: %d//\n", s->qscale); - return -1; + if(!s->inter_intra_pred) return -1; } } block[0] = level; diff -r 70113647b50d -r 55b4e2248a45 msmpeg4data.h --- a/msmpeg4data.h Fri Jul 05 19:16:26 2002 +0000 +++ b/msmpeg4data.h Sun Jul 07 08:34:46 2002 +0000 @@ -1867,3 +1867,7 @@ wmv1_scantable03, }; +static UINT8 table_inter_intra[4][2]={ + {0,1},{2,2},{6,3},{7,3} +}; +