Added support to Unrestricted Motion Vectors (UMV)
authorJuanjo <pulento@users.sourceforge.net>
Tue, 28 Aug 2001 23:32:34 +0000 (23:32 +0000)
committerJuanjo <pulento@users.sourceforge.net>
Tue, 28 Aug 2001 23:32:34 +0000 (23:32 +0000)
on H.263+ encoding/decoding. According to Annex D.
Now MV on H.263+ are 32x32 long.

Originally committed as revision 113 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/h263.c
libavcodec/mpegvideo.c

index 12f14db..3f74d9e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * H263/MPEG4 backend for ffmpeg encoder and decoder
  * Copyright (c) 2000,2001 Gerard Lantau.
- * H263+ support for custom picture format.
+ * H263+ support.
  * Copyright (c) 2001 Juan J. Sierralta P.
  *
  * This program is free software; you can redistribute it and/or modify
 static void h263_encode_block(MpegEncContext * s, DCTELEM * block,
                              int n);
 static void h263_encode_motion(MpegEncContext * s, int val);
+static void h263p_encode_umotion(MpegEncContext * s, int val);
 static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block,
                               int n);
 static int h263_decode_motion(MpegEncContext * s, int pred);
+static int h263p_decode_umotion(MpegEncContext * s, int pred);
 static int h263_decode_block(MpegEncContext * s, DCTELEM * block,
                              int n, int coded);
 static int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
                               int n, int coded);
 
+/* This are for H.263+ UMV */
+/* Shouldn't be here */
+static int umvplus = 0;
+static int umvplus_dec = 0;
+
 int h263_get_picture_format(int width, int height)
 {
     int format;
@@ -57,7 +64,7 @@ int h263_get_picture_format(int width, int height)
 
 void h263_encode_picture_header(MpegEncContext * s, int picture_number)
 {
-    int format, umvplus;
+    int format;
 
     align_put_bits(&s->pb);
     put_bits(&s->pb, 22, 0x20);
@@ -69,10 +76,10 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
     put_bits(&s->pb, 1, 0);    /* split screen off */
     put_bits(&s->pb, 1, 0);    /* camera  off */
     put_bits(&s->pb, 1, 0);    /* freeze picture release off */
-
+    
+    format = h263_get_picture_format(s->width, s->height);
     if (!s->h263_plus) {
         /* H.263v1 */
-        format = h263_get_picture_format(s->width, s->height);
         put_bits(&s->pb, 3, format);
         put_bits(&s->pb, 1, (s->pict_type == P_TYPE));
         /* By now UMV IS DISABLED ON H.263v1, since the restrictions
@@ -89,7 +96,11 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
         /* H.263 Plus PTYPE */
         put_bits(&s->pb, 3, 7);
         put_bits(&s->pb,3,1); /* Update Full Extended PTYPE */
-        put_bits(&s->pb,3,6); /* Custom Source Format */
+        if (format == 7)
+            put_bits(&s->pb,3,6); /* Custom Source Format */
+        else
+            put_bits(&s->pb, 3, format);
+            
         put_bits(&s->pb,1,0); /* Custom PCF: off */
         umvplus = (s->pict_type == P_TYPE) && s->unrestricted_mv;
         put_bits(&s->pb, 1, umvplus); /* Unrestricted Motion Vector */
@@ -116,12 +127,15 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
         /* This should be here if PLUSPTYPE */
         put_bits(&s->pb, 1, 0);        /* Continuous Presence Multipoint mode: off */
                
-        /* Custom Picture Format (CPFMT) */
+               if (format == 7) {
+            /* Custom Picture Format (CPFMT) */
                
-        put_bits(&s->pb,4,2); /* Aspect ratio: CIF 12:11 (4:3) picture */
-        put_bits(&s->pb,9,(s->width >> 2) - 1);
-        put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */
-        put_bits(&s->pb,9,(s->height >> 2));
+            put_bits(&s->pb,4,2); /* Aspect ratio: CIF 12:11 (4:3) picture */
+            put_bits(&s->pb,9,(s->width >> 2) - 1);
+            put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */
+            put_bits(&s->pb,9,(s->height >> 2));
+        }
+        
         /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */
         if (umvplus)
             put_bits(&s->pb,1,1); /* Limited according tables of Annex D */
@@ -138,33 +152,42 @@ void h263_encode_mb(MpegEncContext * s,
     int cbpc, cbpy, i, cbp, pred_x, pred_y;
 
     //    printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
-    if (!s->mb_intra) {
-       /* compute cbp */
-       cbp = 0;
-       for (i = 0; i < 6; i++) {
-           if (s->block_last_index[i] >= 0)
-               cbp |= 1 << (5 - i);
-       }
-       if ((cbp | motion_x | motion_y) == 0) {
-           /* skip macroblock */
-           put_bits(&s->pb, 1, 1);
-           return;
-       }
-       put_bits(&s->pb, 1, 0); /* mb coded */
-       cbpc = cbp & 3;
-       put_bits(&s->pb,
-                inter_MCBPC_bits[cbpc],
-                inter_MCBPC_code[cbpc]);
-       cbpy = cbp >> 2;
-       cbpy ^= 0xf;
-       put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]);
-
-       /* motion vectors: 16x16 mode only now */
-        h263_pred_motion(s, 0, &pred_x, &pred_y);
-        
-        h263_encode_motion(s, motion_x - pred_x);
-        h263_encode_motion(s, motion_y - pred_y);
-    } else {
+   if (!s->mb_intra) {
+          /* compute cbp */
+          cbp = 0;
+          for (i = 0; i < 6; i++) {
+             if (s->block_last_index[i] >= 0)
+                  cbp |= 1 << (5 - i);
+          }
+          if ((cbp | motion_x | motion_y) == 0) {
+             /* skip macroblock */
+             put_bits(&s->pb, 1, 1);
+             return;
+          }
+          put_bits(&s->pb, 1, 0);      /* mb coded */
+          cbpc = cbp & 3;
+          put_bits(&s->pb,
+               inter_MCBPC_bits[cbpc],
+               inter_MCBPC_code[cbpc]);
+          cbpy = cbp >> 2;
+          cbpy ^= 0xf;
+          put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]);
+
+          /* motion vectors: 16x16 mode only now */
+      h263_pred_motion(s, 0, &pred_x, &pred_y);
+      
+      if (!umvplus) {  
+         h263_encode_motion(s, motion_x - pred_x);
+         h263_encode_motion(s, motion_y - pred_y);
+      }
+      else {
+         h263p_encode_umotion(s, motion_x - pred_x);
+         h263p_encode_umotion(s, motion_y - pred_y);
+         if (((motion_x - pred_x) == 1) && ((motion_y - pred_y) == 1))
+            /* To prevent Start Code emulation */
+            put_bits(&s->pb,1,1);
+      }
+   } else {
        /* compute cbp */
        cbp = 0;
        for (i = 0; i < 6; i++) {
@@ -305,6 +328,45 @@ static void h263_encode_motion(MpegEncContext * s, int val)
     }
 }
 
+/* Encode MV differences on H.263+ with Unrestricted MV mode */
+static void h263p_encode_umotion(MpegEncContext * s, int val)
+{
+    short sval = 0; 
+    short i = 0;
+    short n_bits = 0;
+    short temp_val;
+    int code = 0;
+    int tcode;
+    
+    if ( val == 0)
+        put_bits(&s->pb, 1, 1);
+    else if (val == 1)
+        put_bits(&s->pb, 3, 0);
+    else if (val == -1)
+        put_bits(&s->pb, 3, 2);
+    else {
+        
+        sval = ((val < 0) ? (short)(-val):(short)val);
+        temp_val = sval;
+        
+        while (temp_val != 0) {
+            temp_val = temp_val >> 1;
+            n_bits++;
+        }
+        
+        i = n_bits - 1;
+        while (i > 0) {
+            tcode = (sval & (1 << (i-1))) >> (i-1);
+            tcode = (tcode << 1) | 1;
+            code = (code << 2) | tcode;
+            i--;
+        }
+        code = ((code << 1) | (val < 0)) << 1;
+        put_bits(&s->pb, (2*n_bits)+1, code);
+        //printf("\nVal = %d\tCode = %d", sval, code);
+    }
+}
+
 void h263_encode_init_vlc(MpegEncContext *s)
 {
     static int done = 0;
@@ -763,26 +825,45 @@ int h263_decode_mb(MpegEncContext *s,
             /* 16x16 motion prediction */
             s->mv_type = MV_TYPE_16X16;
             h263_pred_motion(s, 0, &pred_x, &pred_y);
-            mx = h263_decode_motion(s, pred_x);
+            if (umvplus_dec)
+               mx = h263p_decode_umotion(s, pred_x);
+            else
+               mx = h263_decode_motion(s, pred_x);
             if (mx >= 0xffff)
                 return -1;
-            my = h263_decode_motion(s, pred_y);
+            
+            if (umvplus_dec)
+               my = h263p_decode_umotion(s, pred_y);
+            else    
+               my = h263_decode_motion(s, pred_y);
             if (my >= 0xffff)
                 return -1;
             s->mv[0][0][0] = mx;
             s->mv[0][0][1] = my;
+            if (umvplus_dec && (mx - pred_x) == 1 && (my - pred_y) == 1)
+               skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */
+                           
         } else {
             s->mv_type = MV_TYPE_8X8;
             for(i=0;i<4;i++) {
                 mot_val = h263_pred_motion(s, i, &pred_x, &pred_y);
-                mx = h263_decode_motion(s, pred_x);
+                if (umvplus_dec)
+                  mx = h263p_decode_umotion(s, pred_x);
+                else
+                  mx = h263_decode_motion(s, pred_x);
                 if (mx >= 0xffff)
                     return -1;
-                my = h263_decode_motion(s, pred_y);
+                
+                if (umvplus_dec)
+                  my = h263p_decode_umotion(s, pred_y);
+                else    
+                  my = h263_decode_motion(s, pred_y);
                 if (my >= 0xffff)
                     return -1;
                 s->mv[0][i][0] = mx;
                 s->mv[0][i][1] = my;
+                if (umvplus_dec && (mx - pred_x) == 1 && (my - pred_y) == 1)
+                  skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */
                 mot_val[0] = mx;
                 mot_val[1] = my;
             }
@@ -857,6 +938,32 @@ static int h263_decode_motion(MpegEncContext * s, int pred)
     return val;
 }
 
+/* Decodes RVLC of H.263+ UMV */
+static int h263p_decode_umotion(MpegEncContext * s, int pred)
+{
+   int code = 0, sign;
+   
+   if (get_bits1(&s->gb)) /* Motion difference = 0 */
+      return pred;
+   
+   code = 2 + get_bits1(&s->gb);
+   
+   while (get_bits1(&s->gb))
+   {
+      code <<= 1;
+      code += get_bits1(&s->gb);
+   }
+   sign = code & 1;
+   code >>= 1;
+   
+   code = (sign) ? (pred - code) : (pred + code);
+#ifdef DEBUG
+   fprintf(stderr,"H.263+ UMV Motion = %d\n", code);
+#endif
+   return code;   
+
+}
+
 static int h263_decode_block(MpegEncContext * s, DCTELEM * block,
                              int n, int coded)
 {
@@ -1108,23 +1215,47 @@ int h263_decode_picture_header(MpegEncContext *s)
     } else {
         s->h263_plus = 1;
         /* H.263v2 */
-        if (get_bits(&s->gb, 3) != 1)
-            return -1;
-        if (get_bits(&s->gb, 3) != 6) /* custom source format */
+        /* OPPTYPE */
+     
+        if (get_bits(&s->gb, 3) != 1) /* Update Full Extended PTYPE */
             return -1;
-        skip_bits(&s->gb, 12);
-        skip_bits(&s->gb, 3);
+        format = get_bits(&s->gb, 3);
+                
+        skip_bits(&s->gb,1); /* Custom PCF */
+        umvplus_dec = get_bits(&s->gb, 1); /* Unrestricted Motion Vector */
+        skip_bits(&s->gb, 10);
+        skip_bits(&s->gb, 3); /* Reserved */
+        
+        /* MPPTYPE */
         s->pict_type = get_bits(&s->gb, 3) + 1;
         if (s->pict_type != I_TYPE &&
             s->pict_type != P_TYPE)
             return -1;
         skip_bits(&s->gb, 7);
-        skip_bits(&s->gb, 4); /* aspect ratio */
-        width = (get_bits(&s->gb, 9) + 1) * 4;
-        skip_bits1(&s->gb);
-        height = get_bits(&s->gb, 9) * 4;
-        if (height == 0)
+        
+        /* Get the picture dimensions */
+        if (format == 6) {
+            /* Custom Picture Format (CPFMT) */
+            skip_bits(&s->gb, 4); /* aspect ratio */
+            width = (get_bits(&s->gb, 9) + 1) * 4;
+            skip_bits1(&s->gb);
+            height = get_bits(&s->gb, 9) * 4;
+#ifdef DEBUG 
+            fprintf(stderr,"\nH.263+ Custom picture: %dx%d\n",width,height);
+#endif            
+        }
+        else {
+            width = h263_format[format][0];
+            height = h263_format[format][1];
+        }
+        
+        if ((width == 0) || (height == 0))
             return -1;
+            
+        if (umvplus_dec) {
+            skip_bits1(&s->gb); /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */
+        }
+            
         s->qscale = get_bits(&s->gb, 5);
     }
     /* PEI */
index ea7979b..6fd2a01 100644 (file)
@@ -277,7 +277,7 @@ int MPV_encode_init(AVCodecContext *avctx)
     case CODEC_ID_H263P:
         s->out_format = FMT_H263;
         s->h263_plus = 1;
-        /* XXX: not unrectricted mv yet */
+        s->unrestricted_mv = 1;
         break;
     case CODEC_ID_RV10:
         s->out_format = FMT_H263;