changeset 519:55b4e2248a45 libavcodec

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
author michaelni
date Sun, 07 Jul 2002 08:34:46 +0000
parents 70113647b50d
children 19a5e2a81e1a
files mpegvideo.h msmpeg4.c msmpeg4data.h
diffstat 3 files changed, 163 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- 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 */
--- 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;
--- 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}
+};
+