changeset 281:1fc96b02142e libavcodec

mpeg4 aspect_ratio_info in AVCodecContext (requested by alex) experimental (& faster) motion estimation squished a dirty uninitialized var bug mpeg1 fcode>1 support
author michaelni
date Fri, 22 Mar 2002 23:22:08 +0000
parents 3dc1ca4ba717
children 5c7fdbecfa97
files avcodec.h h263.c h263dec.c motion_est.c mpeg12.c mpegvideo.c mpegvideo.h
diffstat 7 files changed, 173 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/avcodec.h	Fri Mar 22 16:51:44 2002 +0000
+++ b/avcodec.h	Fri Mar 22 23:22:08 2002 +0000
@@ -81,6 +81,7 @@
     /* video only */
     int frame_rate; /* frames per sec multiplied by FRAME_RATE_BASE */
     int width, height;
+    int aspect_ratio_info;
     int gop_size; /* 0 = intra only */
     int pix_fmt;  /* pixel format, see PIX_FMT_xxx */
 
--- a/h263.c	Fri Mar 22 16:51:44 2002 +0000
+++ b/h263.c	Fri Mar 22 23:22:08 2002 +0000
@@ -781,7 +781,10 @@
     put_bits(&s->pb, 1, 1);		/* is obj layer id= yes */
       put_bits(&s->pb, 4, vo_ver_id);	/* is obj layer ver id */
       put_bits(&s->pb, 3, 1);		/* is obj layer priority */
-    put_bits(&s->pb, 4, 1);		/* aspect ratio info= sqare pixel */ //FIXME real aspect
+    if(s->aspect_ratio_info) 
+        put_bits(&s->pb, 4, s->aspect_ratio_info);/* aspect ratio info */
+    else
+        put_bits(&s->pb, 4, 1);		/* aspect ratio info= sqare pixel */
     put_bits(&s->pb, 1, 0);		/* vol control parameters= no */
     put_bits(&s->pb, 2, RECT_SHAPE);	/* vol shape= rectangle */
     put_bits(&s->pb, 1, 1);		/* marker bit */
@@ -2149,6 +2152,7 @@
             skip_bits(&s->gb, 8); //par_width
             skip_bits(&s->gb, 8); // par_height
         }
+
         if(get_bits1(&s->gb)){ /* vol control parameter */
             printf("vol control parameter not supported\n");
             return -1;   
@@ -2388,7 +2392,6 @@
 //printf("b-code %d\n", s->b_code);
          }
 //printf("quant:%d fcode:%d\n", s->qscale, s->f_code);
-
          if(!s->scalability){
              if (s->shape!=RECT_SHAPE && s->pict_type!=I_TYPE) {
                  skip_bits1(&s->gb); // vop shape coding type
--- a/h263dec.c	Fri Mar 22 16:51:44 2002 +0000
+++ b/h263dec.c	Fri Mar 22 23:22:08 2002 +0000
@@ -123,6 +123,7 @@
     if (!s->context_initialized) {
         avctx->width = s->width;
         avctx->height = s->height;
+        avctx->aspect_ratio_info= s->aspect_ratio_info;
         if (MPV_common_init(s) < 0)
             return -1;
     } else if (s->width != avctx->width || s->height != avctx->height) {
--- a/motion_est.c	Fri Mar 22 16:51:44 2002 +0000
+++ b/motion_est.c	Fri Mar 22 23:22:08 2002 +0000
@@ -335,13 +335,15 @@
 #define Z_THRESHOLD 256
 
 #define CHECK_MV(x,y)\
+{\
     d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
     d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
     if(d<dmin){\
         best[0]=x;\
         best[1]=y;\
         dmin=d;\
-    }
+    }\
+}
 
 #define CHECK_MV_DIR(x,y,new_dir)\
 {\
@@ -355,6 +357,13 @@
     }\
 }
 
+#define check(x,y,S,v)\
+if( (x)<(xmin<<(S)) ) printf("%d %d %d %d xmin" #v, (x), (y), s->mb_x, s->mb_y);\
+if( (x)>(xmax<<(S)) ) printf("%d %d %d %d xmax" #v, (x), (y), s->mb_x, s->mb_y);\
+if( (y)<(ymin<<(S)) ) printf("%d %d %d %d ymin" #v, (x), (y), s->mb_x, s->mb_y);\
+if( (y)>(ymax<<(S)) ) printf("%d %d %d %d ymax" #v, (x), (y), s->mb_x, s->mb_y);\
+
+
 static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
                                        UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
                                        int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
@@ -379,6 +388,91 @@
             return dmin;
         }
     }
+
+/*    for(;;){
+        int d;
+        const int x= best[0];
+        const int y= best[1];
+        const int last_min=dmin;
+        if(x>xmin) CHECK_MV(x-1, y  )
+        if(y>xmin) CHECK_MV(x  , y-1)
+        if(x<xmax) CHECK_MV(x+1, y  )
+        if(y<xmax) CHECK_MV(x  , y+1)
+        if(x>xmin && y>ymin) CHECK_MV(x-1, y-1)
+        if(x>xmin && y<ymax) CHECK_MV(x-1, y+1)
+        if(x<xmax && y>ymin) CHECK_MV(x+1, y-1)
+        if(x<xmax && y<ymax) CHECK_MV(x+1, y+1)
+        if(x-1>xmin) CHECK_MV(x-2, y  )
+        if(y-1>xmin) CHECK_MV(x  , y-2)
+        if(x+1<xmax) CHECK_MV(x+2, y  )
+        if(y+1<xmax) CHECK_MV(x  , y+2)
+        if(x-1>xmin && y-1>ymin) CHECK_MV(x-2, y-2)
+        if(x-1>xmin && y+1<ymax) CHECK_MV(x-2, y+2)
+        if(x+1<xmax && y-1>ymin) CHECK_MV(x+2, y-2)
+        if(x+1<xmax && y+1<ymax) CHECK_MV(x+2, y+2)
+        if(dmin==last_min) return dmin;
+    }
+    */
+}
+
+static inline int snake_search(MpegEncContext * s, int *best, int dmin,
+                                       UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
+                                       int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
+                                       int xmin, int ymin, int xmax, int ymax, int shift)
+{
+    int dir=0;
+    int c=1;
+    static int x_dir[8]= {1,1,0,-1,-1,-1, 0, 1};
+    static int y_dir[8]= {0,1,1, 1, 0,-1,-1,-1};
+    int fails=0;
+    int last_d[2]={dmin, dmin};
+
+/*static int good=0;
+static int bad=0;
+static int point=0;
+
+point++;
+if(256*256*256*64%point==0)
+{
+    printf("%d %d %d\n", good, bad, point);
+}*/
+
+    for(;;){
+        int x= best[0];
+        int y= best[1];
+        int d;
+        x+=x_dir[dir];
+        y+=y_dir[dir];
+        if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){
+            d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);
+            d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;
+        }else{
+            d = dmin + 10000; //FIXME smarter boundary handling
+        }
+        if(d<dmin){
+            best[0]=x;
+            best[1]=y;
+            dmin=d;
+
+            if(last_d[1] - last_d[0] > last_d[0] - d) c= -c;
+            dir+=c;
+
+            fails=0;
+//good++;
+            last_d[1]=last_d[0];
+            last_d[0]=d;
+        }else{
+//bad++;
+            if(fails){
+                if(fails>=3) return dmin;
+            }else{
+                c= -c;
+            }
+            dir+=c*2;
+            fails++;
+        }
+        dir&=7;
+    }
 }
 
 static int epzs_motion_search(MpegEncContext * s,
@@ -397,8 +491,7 @@
 
     new_pic = s->new_picture[0] + pic_xy;
     old_pic = s->last_picture[0] + pic_xy;
-//printf("%d %d %d %d\n", xmin, ymin, xmax, ymax);
-    
+   
     dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16);
     if(dmin<Z_THRESHOLD){
         *mx_ptr= 0;
@@ -424,13 +517,18 @@
     }
     CHECK_MV(P[0][0]>>shift, P[0][1]>>shift)
 
-    dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, 
-                               pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
+//check(best[0],best[1],0, b0)
+    if(s->full_search==ME_EPZS)
+        dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, 
+                                   pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
+    else
+        dmin=         snake_search(s, best, dmin, new_pic, old_pic, pic_stride, 
+                                   pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
+//check(best[0],best[1],0, b1)
     *mx_ptr= best[0];
     *my_ptr= best[1];    
 
 //    printf("%d %d %d \n", best[0], best[1], dmin);
-
     return dmin;
 }
 
@@ -563,8 +661,8 @@
         rel_ymax= ymax - s->mb_y*16;
         if(s->out_format == FMT_H263){
             static const int off[4]= {2, 1, 1, -1};
-            const int mot_stride = s->block_wrap[0];
-            const int mot_xy = s->block_index[0];
+            const int mot_stride = s->mb_width*2 + 2;
+            const int mot_xy = (s->mb_y*2 + 1)*mot_stride + s->mb_x*2 + 1;
          
             P[0][0] = s->motion_val[mot_xy    ][0];
             P[0][1] = s->motion_val[mot_xy    ][1];
@@ -618,7 +716,8 @@
                 P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]);
             }
         }
-	dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax);
+        dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax);
+ 
         mx+= s->mb_x*16;
         my+= s->mb_y*16;
         break;
@@ -654,6 +753,8 @@
             mx -= 16 * s->mb_x;
             my -= 16 * s->mb_y;
         }
+//        check(mx + 32*s->mb_x, my + 32*s->mb_y, 1, end)
+        
 	*mx_ptr = mx;
 	*my_ptr = my;
 	return 0;
--- a/mpeg12.c	Fri Mar 22 16:51:44 2002 +0000
+++ b/mpeg12.c	Fri Mar 22 23:22:08 2002 +0000
@@ -51,6 +51,9 @@
                                     int n);
 static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred);
 
+static UINT16 mv_penalty[MAX_FCODE][MAX_MV*2+1];
+static UINT8 fcode_tab[MAX_MV*2+1];
+
 static void put_header(MpegEncContext *s, int header)
 {
     align_put_bits(&s->pb);
@@ -353,6 +356,53 @@
     }
 }
 
+void mpeg1_encode_init(MpegEncContext *s)
+{
+    static int done=0;
+    if(!done){
+        int f_code;
+        int mv;
+
+        done=1;
+        for(f_code=1; f_code<=MAX_FCODE; f_code++){
+            for(mv=-MAX_MV; mv<=MAX_MV; mv++){
+                int len;
+
+                if(mv==0) len= mbMotionVectorTable[0][1];
+                else{
+                    int val, bit_size, range, code;
+
+                    bit_size = s->f_code - 1;
+                    range = 1 << bit_size;
+
+                    val=mv;
+                    if (val < 0) 
+                        val = -val;
+                    val--;
+                    code = (val >> bit_size) + 1;
+                    if(code<17){
+                        len= mbMotionVectorTable[code][1] + 1 + bit_size;
+                    }else{
+                        len= mbMotionVectorTable[16][1] + 2 + bit_size;
+                    }
+                }
+
+                mv_penalty[f_code][mv+MAX_MV]= len;
+            }
+        }
+        
+
+        for(f_code=MAX_FCODE; f_code>0; f_code--){
+            for(mv=-(8<<f_code); mv<(8<<f_code); mv++){
+                fcode_tab[mv+MAX_MV]= f_code;
+            }
+        }
+    }
+    s->mv_penalty= mv_penalty;
+    
+    s->fcode_tab= fcode_tab;
+}
+ 
 static inline void encode_dc(MpegEncContext *s, int diff, int component)
 {
     if (component == 0) {
--- a/mpegvideo.c	Fri Mar 22 16:51:44 2002 +0000
+++ b/mpegvideo.c	Fri Mar 22 23:22:08 2002 +0000
@@ -294,6 +294,7 @@
     s->qcompress= avctx->qcompress;
     s->qblur= avctx->qblur;
     s->avctx = avctx;
+    s->aspect_ratio_info= avctx->aspect_ratio_info;
     
     if (s->gop_size <= 1) {
         s->intra_only = 1;
@@ -377,6 +378,8 @@
 
     if (s->out_format == FMT_H263)
         h263_encode_init(s);
+    else if (s->out_format == FMT_MPEG1)
+        mpeg1_encode_init(s);
 
     s->encoding = 1;
 
@@ -1075,7 +1078,6 @@
     /* Reset the average MB variance */
     s->avg_mb_var = 0;
     s->mc_mb_var = 0;
-
     /* Estimate motion for every MB */
     for(mb_y=0; mb_y < s->mb_height; mb_y++) {
         for(mb_x=0; mb_x < s->mb_width; mb_x++) {
@@ -1132,12 +1134,13 @@
 
         for(i=MAX_FCODE; i>1; i--){
             loose+= mv_num[i];
-            if(loose > 4) break;
+            if(loose > 4) break; //FIXME this is pretty ineffective
         }
         s->f_code= i;
     }else{
         s->f_code= 1;
     }
+
 //printf("f_code %d ///\n", s->f_code);
     /* convert MBs with too long MVs to I-Blocks */
     if(s->pict_type==P_TYPE){
--- a/mpegvideo.h	Fri Mar 22 16:51:44 2002 +0000
+++ b/mpegvideo.h	Fri Mar 22 23:22:08 2002 +0000
@@ -309,6 +309,7 @@
 void mpeg1_encode_mb(MpegEncContext *s,
                      DCTELEM block[6][64],
                      int motion_x, int motion_y);
+void mpeg1_encode_init(MpegEncContext *s);
 
 /* h263enc.c */