changeset 78:92ed1c4f94fa libavcodec

Added support to Unrestricted Motion Vectors (UMV) on H.263+ encoding/decoding. According to Annex D. Now MV on H.263+ are 32x32 long.
author pulento
date Tue, 28 Aug 2001 23:32:34 +0000
parents 9e8ae8222ddc
children 82e579c37bc3
files h263.c mpegvideo.c
diffstat 2 files changed, 182 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/h263.c	Mon Aug 20 16:01:35 2001 +0000
+++ b/h263.c	Tue Aug 28 23:32:34 2001 +0000
@@ -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
@@ -28,14 +28,21 @@
 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 @@
 
 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 @@
     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 @@
         /* 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 @@
         /* 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 @@
     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]);
+   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 {
+	   /* 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 @@
     }
 }
 
+/* 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 @@
             /* 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 @@
     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 @@
     } else {
         s->h263_plus = 1;
         /* H.263v2 */
-        if (get_bits(&s->gb, 3) != 1)
+        /* OPPTYPE */
+     
+        if (get_bits(&s->gb, 3) != 1) /* Update Full Extended PTYPE */
             return -1;
-        if (get_bits(&s->gb, 3) != 6) /* custom source format */
-            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 */
--- a/mpegvideo.c	Mon Aug 20 16:01:35 2001 +0000
+++ b/mpegvideo.c	Tue Aug 28 23:32:34 2001 +0000
@@ -277,7 +277,7 @@
     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;