diff msmpeg4.c @ 457:583dcee270d2 libavcodec

msmpeg4v1 decoding
author michaelni
date Sun, 02 Jun 2002 12:22:30 +0000
parents 000aeeac27a2
children 1e23eae32087
line wrap: on
line diff
--- a/msmpeg4.c	Sun Jun 02 12:20:39 2002 +0000
+++ b/msmpeg4.c	Sun Jun 02 12:22:30 2002 +0000
@@ -16,7 +16,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * msmpeg4v2 stuff by Michael Niedermayer <michaelni@gmx.at>
+ * msmpeg4v1 & v2 stuff by Michael Niedermayer <michaelni@gmx.at>
  */
 #include "avcodec.h"
 #include "dsputil.h"
@@ -159,7 +159,7 @@
     }
 }
 
-/* write MSMPEG4 V3 compatible frame header */
+/* write MSMPEG4 compatible frame header */
 void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
 {
     int i;
@@ -171,7 +171,7 @@
     put_bits(&s->pb, 5, s->qscale);
 
     s->rl_table_index = 2;
-    if(s->msmpeg4_version==2)
+    if(s->msmpeg4_version<=2)
         s->rl_chroma_table_index = 2; /* only for I frame */
     else
         s->rl_chroma_table_index = 1; /* only for I frame */
@@ -183,7 +183,7 @@
     if (s->pict_type == I_TYPE) {
         put_bits(&s->pb, 5, 0x17); /* indicate only one "slice" */
 
-        if(s->msmpeg4_version!=2){
+        if(s->msmpeg4_version>2){
             code012(&s->pb, s->rl_chroma_table_index);
             code012(&s->pb, s->rl_table_index);
 
@@ -194,7 +194,7 @@
         put_bits(&s->pb, 1, s->use_skip_mb_code);
         
         s->rl_chroma_table_index = s->rl_table_index;
-        if(s->msmpeg4_version!=2){
+        if(s->msmpeg4_version>2){
             code012(&s->pb, s->rl_table_index);
 
             put_bits(&s->pb, 1, s->dc_table_index);
@@ -228,14 +228,16 @@
 
 void msmpeg4_encode_ext_header(MpegEncContext * s)
 {
-        s->flipflop_rounding=1;
-        s->bitrate= 910; // FIXME
-
         put_bits(&s->pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29
 
-	put_bits(&s->pb, 11, s->bitrate);
+	put_bits(&s->pb, 11, MIN(s->bit_rate, 2047));
 
-	put_bits(&s->pb, 1, s->flipflop_rounding);
+        if(s->msmpeg4_version<3)
+            s->flipflop_rounding=0;
+        else{
+            s->flipflop_rounding=1;
+            put_bits(&s->pb, 1, s->flipflop_rounding);
+        }
 }
 
 /* predict coded block */
@@ -328,7 +330,7 @@
         if (s->use_skip_mb_code)
             put_bits(&s->pb, 1, 0);	/* mb coded */
         
-        if(s->msmpeg4_version==2){
+        if(s->msmpeg4_version<=2){
             put_bits(&s->pb, 
                      v2_mb_type[cbp&3][1], 
                      v2_mb_type[cbp&3][0]);
@@ -373,7 +375,7 @@
             printf("cbp=%x %x\n", cbp, coded_cbp);
 #endif
 
-        if(s->msmpeg4_version==2){
+        if(s->msmpeg4_version<=2){
             if (s->pict_type == I_TYPE) {
                 put_bits(&s->pb, 
                          v2_intra_cbpc[cbp&3][1], v2_intra_cbpc[cbp&3][0]);
@@ -425,6 +427,21 @@
     }
 }
 
+static int msmpeg4v1_pred_dc(MpegEncContext * s, int n, 
+                           INT32 **dc_val_ptr)
+{
+    int i;
+
+    if (n < 4) {
+        i= 0;
+    } else {
+        i= n-3;
+    }
+    
+    *dc_val_ptr= &s->last_dc[i];
+    return s->last_dc[i]; 
+}
+
 /* dir = 0: left, dir = 1: top prediction */
 static int msmpeg4_pred_dc(MpegEncContext * s, int n, 
                            INT16 **dc_val_ptr, int *dir_ptr)
@@ -438,6 +455,7 @@
     } else {
 	scale = s->c_dc_scale;
     }
+    
     wrap = s->block_wrap[n];
     dc_val= s->dc_val[0] + s->block_index[n];
 
@@ -507,21 +525,29 @@
 {
     int sign, code;
     int pred;
-    INT16 *dc_val;
-
-    pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
 
-    /* update predictor */
-    if (n < 4) {
-        *dc_val = level * s->y_dc_scale;
-    } else {
-        *dc_val = level * s->c_dc_scale;
+    if(s->msmpeg4_version==1){
+        INT32 *dc_val;
+        pred = msmpeg4v1_pred_dc(s, n, &dc_val);
+        
+        /* update predictor */
+        *dc_val= level;
+    }else{
+        INT16 *dc_val;
+        pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
+
+        /* update predictor */
+        if (n < 4) {
+            *dc_val = level * s->y_dc_scale;
+        } else {
+            *dc_val = level * s->c_dc_scale;
+        }
     }
 
     /* do the prediction */
     level -= pred;
 
-    if(s->msmpeg4_version==2){
+    if(s->msmpeg4_version<=2){
         if (n < 4) {
             put_bits(&s->pb, 
                      v2_dc_lum_table[level+256][1],
@@ -588,7 +614,7 @@
     } else {
         i = 0;
         rl = &rl_table[3 + s->rl_table_index];
-        if(s->msmpeg4_version==2)
+        if(s->msmpeg4_version<=2)
             run_diff = 0;
         else
             run_diff = 1;
@@ -668,6 +694,8 @@
 static VLC v2_intra_cbpc_vlc;
 static VLC v2_mb_type_vlc;
 static VLC v2_mv_vlc;
+static VLC v1_intra_cbpc_vlc;
+static VLC v1_inter_cbpc_vlc;
 
 /* this table is practically identical to the one from h263 except that its inverted */
 static void init_h263_dc_for_msmpeg4()
@@ -786,6 +814,14 @@
     init_vlc(&mb_intra_vlc, 9, 64, 
              &table_mb_intra[0][1], 4, 2,
              &table_mb_intra[0][0], 4, 2);
+        
+    init_vlc(&v1_intra_cbpc_vlc, 6, 8, 
+             intra_MCBPC_bits, 1, 1,
+             intra_MCBPC_code, 1, 1);
+    init_vlc(&v1_inter_cbpc_vlc, 6, 25, 
+             inter_MCBPC_bits, 1, 1,
+             inter_MCBPC_code, 1, 1);
+
     return 0;
 }
 
@@ -813,21 +849,46 @@
 return -1;
 }
 #endif
+
+    if(s->msmpeg4_version==1){
+        int start_code, num;
+        start_code = (get_bits(&s->gb, 16)<<16) | get_bits(&s->gb, 16);
+        if(start_code!=0x00000100){
+            fprintf(stderr, "invalid startcode\n");
+            return -1;
+        }
+
+        num= get_bits(&s->gb, 5); // frame number */
+    }
+
     s->pict_type = get_bits(&s->gb, 2) + 1;
     if (s->pict_type != I_TYPE &&
-        s->pict_type != P_TYPE)
+        s->pict_type != P_TYPE){
+        fprintf(stderr, "invalid picture type\n");
         return -1;
+    }
 
     s->qscale = get_bits(&s->gb, 5);
 
     if (s->pict_type == I_TYPE) {
         code = get_bits(&s->gb, 5); 
-        /* 0x17: one slice, 0x18: two slices */
-        if (code < 0x17)
-            return -1;
-        s->slice_height = s->mb_height / (code - 0x16);
+        if(s->msmpeg4_version==1){
+            if(code==0 || code>s->mb_height){
+                fprintf(stderr, "invalid slice height %d\n", code);
+                return -1;
+            }
+
+            s->slice_height = code;
+        }else{
+            /* 0x17: one slice, 0x18: two slices, ... */
+            if (code < 0x17)
+                return -1;
+
+            s->slice_height = s->mb_height / (code - 0x16);
+        }
 
         switch(s->msmpeg4_version){
+        case 1:
         case 2:
             s->rl_chroma_table_index = 2;
             s->rl_table_index = 2;
@@ -862,22 +923,28 @@
 		s->rl_table_index, 
 		s->dc_table_index);*/
     } else {
-        s->use_skip_mb_code = get_bits1(&s->gb);
         
-        if(s->msmpeg4_version==2){
+        switch(s->msmpeg4_version){
+        case 1:
+        case 2:
+            if(s->msmpeg4_version==1)
+                s->use_skip_mb_code = 1;
+            else
+                s->use_skip_mb_code = get_bits1(&s->gb);
             s->rl_table_index = 2;
             s->rl_chroma_table_index = s->rl_table_index;
-
             s->dc_table_index = 0; //not used
-
             s->mv_table_index = 0;
-        }else{
+            break;
+        case 3:
+            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);
+            break;
         }
 /*	printf(" %d %d %d %d %d     \n", 
 		s->use_skip_mb_code, 
@@ -914,21 +981,30 @@
 
 int msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size)
 {
+    int left= buf_size*8 - get_bits_count(&s->gb);
+    int length= s->msmpeg4_version>=3 ? 17 : 16;
     /* the alt_bitstream reader could read over the end so we need to check it */
-    if(get_bits_count(&s->gb) + 16 < buf_size*8)
+    if(left>=length && left<length+8)
     {
         int fps;
 
         fps= get_bits(&s->gb, 5);
-        s->bitrate= get_bits(&s->gb, 11);
-        s->flipflop_rounding= get_bits1(&s->gb);
+        s->bit_rate= get_bits(&s->gb, 11);
+        if(s->msmpeg4_version>=3)
+            s->flipflop_rounding= get_bits1(&s->gb);
+        else
+            s->flipflop_rounding= 0;
 
-//        printf("fps:%2d bps:%2d roundingType:%1d\n", fps, s->bitrate, s->flipflop_rounding);
+//        printf("fps:%2d bps:%2d roundingType:%1d\n", fps, s->bit_rate, s->flipflop_rounding);
+    }
+    else if(left<length+8)
+    {
+        s->flipflop_rounding= 0;
+        printf("ext header missing, %d left\n", left);
     }
     else
     {
-        s->flipflop_rounding= 0;
-        s->bitrate= 0;
+        fprintf(stderr, "I frame too long, ignoring ext header\n");
     }
 
     return 0;
@@ -980,6 +1056,7 @@
     int code, val, sign, shift;
 
     code = get_vlc(&s->gb, &v2_mv_vlc);
+//     printf("MV code %d at %d %d pred: %d\n", code, s->mb_x,s->mb_y, pred);
     if (code < 0)
         return 0xffff;
 
@@ -993,8 +1070,8 @@
     val++;
     if (sign)
         val = -val;
+
     val += pred;
-
     if (val <= -64)
         val += 64;
     else if (val >= 64)
@@ -1004,7 +1081,7 @@
 }
 
 
-int msmpeg4v2_decode_mb(MpegEncContext *s, 
+static int msmpeg4v12_decode_mb(MpegEncContext *s, 
                       DCTELEM block[6][64])
 {
     int cbp, code, i;
@@ -1024,20 +1101,41 @@
             }
         }
 
-        code = get_vlc(&s->gb, &v2_mb_type_vlc);
+        if(s->msmpeg4_version==2)
+            code = get_vlc(&s->gb, &v2_mb_type_vlc);
+        else
+            code = get_vlc(&s->gb, &v1_inter_cbpc_vlc);
+        if(code<0 || code>7){
+            fprintf(stderr, "cbpc %d invalid at %d %d\n", code, s->mb_x, s->mb_y);
+            return -1;
+        }
+
         s->mb_intra = code >>2;
     
         cbp = code & 0x3;
     } else {
         s->mb_intra = 1;
-        cbp= get_vlc(&s->gb, &v2_intra_cbpc_vlc);
+        if(s->msmpeg4_version==2)
+            cbp= get_vlc(&s->gb, &v2_intra_cbpc_vlc);
+        else
+            cbp= get_vlc(&s->gb, &v1_intra_cbpc_vlc);
+        if(cbp<0 || cbp>3){
+            fprintf(stderr, "cbpc %d invalid at %d %d\n", cbp, s->mb_x, s->mb_y);
+            return -1;
+        }
     }
 
     if (!s->mb_intra) {
-        int mx, my;
+        int mx, my, cbpy;
+        
+        cbpy= get_vlc(&s->gb, &cbpy_vlc);
+        if(cbpy<0){
+            fprintf(stderr, "cbpy %d invalid at %d %d\n", cbp, s->mb_x, s->mb_y);
+            return -1;
+        }
 
-        cbp|= get_vlc(&s->gb, &cbpy_vlc)<<2;
-        if((cbp&3) != 3) cbp^= 0x3C;
+        cbp|= cbpy<<2;
+        if(s->msmpeg4_version==1 || (cbp&3) != 3) cbp^= 0x3C;
         
         h263_pred_motion(s, 0, &mx, &my);
         mx= msmpeg4v2_decode_motion(s, mx, 1);
@@ -1048,14 +1146,20 @@
         s->mv[0][0][0] = mx;
         s->mv[0][0][1] = my;
     } else {
-        s->ac_pred = get_bits1(&s->gb);
-        cbp|= get_vlc(&s->gb, &cbpy_vlc)<<2;
+        if(s->msmpeg4_version==2){
+            s->ac_pred = get_bits1(&s->gb);
+            cbp|= get_vlc(&s->gb, &cbpy_vlc)<<2; //FIXME check errors
+        } else{
+            s->ac_pred = 0;
+            cbp|= get_vlc(&s->gb, &cbpy_vlc)<<2; //FIXME check errors
+            if(s->pict_type==P_TYPE) cbp^=0x3C;
+        }
     }
 
     for (i = 0; i < 6; i++) {
         if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1) < 0)
 	{
-             fprintf(stderr,"\nIgnoring error while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);
+             fprintf(stderr,"\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);
              return -1;
 	}
     }
@@ -1098,7 +1202,7 @@
         }
     }
 
-    if(s->msmpeg4_version==2) return msmpeg4v2_decode_mb(s, block); //FIXME merge if possible
+    if(s->msmpeg4_version<=2) return msmpeg4v12_decode_mb(s, block); //FIXME export function & call from outside perhaps
     
     if (s->pict_type == P_TYPE) {
         set_stat(ST_INTER_MB);
@@ -1161,10 +1265,11 @@
     for (i = 0; i < 6; i++) {
         if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1) < 0)
 	{
-	    fprintf(stderr,"\nIgnoring error while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);
-	    // return -1;
+	    fprintf(stderr,"\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);
+	    return -1;
 	}
     }
+
     return 0;
 }
 
@@ -1184,14 +1289,24 @@
 	/* DC coef */
         set_stat(ST_DC);
         level = msmpeg4_decode_dc(s, n, &dc_pred_dir);
-        if (level < 0)
+        if (level < 0){
+            fprintf(stderr, "dc overflow-\n");
             return -1;
-        block[0] = level;
+        }
         if (n < 4) {
             rl = &rl_table[s->rl_table_index];
+            if(level > 256*s->y_dc_scale){
+                fprintf(stderr, "dc overflow+\n");
+                return -1;
+            }
         } else {
             rl = &rl_table[3 + s->rl_chroma_table_index];
+            if(level > 256*s->c_dc_scale){
+                fprintf(stderr, "dc overflow+\n");
+                return -1;
+            }
         }
+        block[0] = level;
 
         run_diff = 0;
 	i = 1;
@@ -1232,16 +1347,42 @@
             return -1;
         if (code == rl->n) {
             /* escape */
-            if (get_bits1(&s->gb) == 0) {
-                if (get_bits1(&s->gb) == 0) {
+            if (s->msmpeg4_version==1 || get_bits1(&s->gb) == 0) {
+                if (s->msmpeg4_version==1 || get_bits1(&s->gb) == 0) {
                     /* third escape */
                     last = get_bits1(&s->gb);
                     run = get_bits(&s->gb, 6);
                     level = get_bits(&s->gb, 8);
                     level = (level << 24) >> 24; /* sign extend */
+#if 0 // waste of time / this will detect very few errors
+                    {
+                        const int abs_level= ABS(level);
+                        const int run1= run - rl->max_run[last][abs_level] - run_diff;
+                        if(abs_level<=MAX_LEVEL && run<=MAX_RUN){
+                            if(abs_level <= rl->max_level[last][run]){
+                                fprintf(stderr, "illegal 3. esc, vlc encoding possible\n");
+                                return DECODING_AC_LOST;
+                            }
+                            if(abs_level <= rl->max_level[last][run]*2){
+                                fprintf(stderr, "illegal 3. esc, esc 1 encoding possible\n");
+                                return DECODING_AC_LOST;
+                            }
+                            if(abs_level <= rl->max_level[last][run1] && 0){
+                                fprintf(stderr, "illegal 3. esc, esc 2 encoding possible\n");
+                                return DECODING_AC_LOST;
+                            }
+                        }
+                    }
+#endif
 		    //level = level * qmul + (level>0) * qadd - (level<=0) * qadd ;
 		    if (level>0) level= level * qmul + qadd;
-                    else        level= level * qmul - qadd;
+                    else         level= level * qmul - qadd;
+#if 0 // waste of time too :(
+                    if(level>2048 || level<-2048){
+                        fprintf(stderr, "|level| overflow in 3. esc\n");
+                        return DECODING_AC_LOST;
+                    }
+#endif
                 } else {
                     /* second escape */
                     code = get_vlc(&s->gb, &rl->vlc);
@@ -1278,7 +1419,7 @@
         i += run;
         if (i >= 64)
             return -1;
-//printf("RL:%d %d %d ", run, level, last);
+
 	j = scan_table[i];
         block[j] = level;
         i++;
@@ -1300,9 +1441,8 @@
 static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr)
 {
     int level, pred;
-    INT16 *dc_val;
 
-    if(s->msmpeg4_version==2){
+    if(s->msmpeg4_version<=2){
         if (n < 4) {
             level = get_vlc(&s->gb, &v2_dc_lum_vlc);
         } else {
@@ -1317,8 +1457,10 @@
         } else {
             level = get_vlc(&s->gb, &dc_chroma_vlc[s->dc_table_index]);
         }
-        if (level < 0)
+        if (level < 0){
+            fprintf(stderr, "illegal dc vlc\n");
             return -1;
+        }
 
         if (level == DC_MAX) {
             level = get_bits(&s->gb, 8);
@@ -1330,14 +1472,24 @@
         }
     }
 
-    pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
-    level += pred;
+    if(s->msmpeg4_version==1){
+        INT32 *dc_val;
+        pred = msmpeg4v1_pred_dc(s, n, &dc_val);
+        level += pred;
+        
+        /* update predictor */
+        *dc_val= level;
+    }else{
+        INT16 *dc_val;
+        pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
+        level += pred;
 
-    /* update predictor */
-    if (n < 4) {
-        *dc_val = level * s->y_dc_scale;
-    } else {
-        *dc_val = level * s->c_dc_scale;
+        /* update predictor */
+        if (n < 4) {
+            *dc_val = level * s->y_dc_scale;
+        } else {
+            *dc_val = level * s->c_dc_scale;
+        }
     }
 
     return level;