motion estimation pre pass
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 2 Jan 2003 01:29:35 +0000 (01:29 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 2 Jan 2003 01:29:35 +0000 (01:29 +0000)
Originally committed as revision 1389 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/avcodec.h
libavcodec/motion_est.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h

index 9ad87aedd464c99e3f15b816d4ef73a3f35d90ff..783374126855caeef72e1f04364b7823cd504d6d 100644 (file)
@@ -5,8 +5,8 @@
 
 #define LIBAVCODEC_VERSION_INT 0x000406
 #define LIBAVCODEC_VERSION     "0.4.6"
-#define LIBAVCODEC_BUILD       4649
-#define LIBAVCODEC_BUILD_STR   "4649"
+#define LIBAVCODEC_BUILD       4650
+#define LIBAVCODEC_BUILD_STR   "4650"
 
 enum CodecID {
     CODEC_ID_NONE, 
@@ -894,6 +894,13 @@ typedef struct AVCodecContext {
      * decoding: unused
      */
     int last_predictor_count;
+    
+    /**
+     * pre pass for motion estimation
+     * encoding: set by user.
+     * decoding: unused
+     */
+    int pre_me;
 
 } AVCodecContext;
 
index 10e4bb51c48410387ce2bc21a95d2f606a84687b..58128ea928d2423ee94b3d183bbf3cd8f26bb946 100644 (file)
@@ -754,12 +754,10 @@ static inline void get_limits(MpegEncContext *s, int *range, int *xmin, int *ymi
         *ymin = -16;
         if (s->h263_plus)
             *range *= 2;
-        if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){
+        if(s->avctx->codec->id!=CODEC_ID_MPEG4){
             *xmax = s->mb_width*16;
             *ymax = s->mb_height*16;
         }else {
-            /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise 
-                   (cuz the drawn edge isnt large enough))*/
             *xmax = s->width;
             *ymax = s->height;
         }
@@ -1024,6 +1022,68 @@ void ff_estimate_p_frame_motion(MpegEncContext * s,
     s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
 }
 
+int ff_pre_estimate_p_frame_motion(MpegEncContext * s,
+                                    int mb_x, int mb_y)
+{
+    int mx, my, range, dmin;
+    int xmin, ymin, xmax, ymax;
+    int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
+    int pred_x=0, pred_y=0;
+    int P[10][2];
+    const int shift= 1+s->quarter_sample;
+    uint16_t * const mv_penalty= s->me.mv_penalty[s->f_code] + MAX_MV;
+    const int mv_stride= s->mb_width + 2;
+    const int xy= mb_x + 1 + (mb_y + 1)*mv_stride;
+    
+    assert(s->quarter_sample==0 || s->quarter_sample==1);
+
+    s->me.penalty_factor    = get_penalty_factor(s, s->avctx->me_cmp);
+
+    get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, s->f_code);
+    rel_xmin= xmin - mb_x*16;
+    rel_xmax= xmax - mb_x*16;
+    rel_ymin= ymin - mb_y*16;
+    rel_ymax= ymax - mb_y*16;
+    s->me.skip=0;
+
+    P_LEFT[0]       = s->p_mv_table[xy + 1][0];
+    P_LEFT[1]       = s->p_mv_table[xy + 1][1];
+
+    if(P_LEFT[0]       < (rel_xmin<<shift)) P_LEFT[0]       = (rel_xmin<<shift);
+
+    /* special case for first line */
+    if (mb_y == s->mb_height-1) {
+        pred_x= P_LEFT[0];
+        pred_y= P_LEFT[1];
+    } else {
+        P_TOP[0]      = s->p_mv_table[xy + mv_stride    ][0];
+        P_TOP[1]      = s->p_mv_table[xy + mv_stride    ][1];
+        P_TOPRIGHT[0] = s->p_mv_table[xy + mv_stride - 1][0];
+        P_TOPRIGHT[1] = s->p_mv_table[xy + mv_stride - 1][1];
+        if(P_TOP[1]      < (rel_ymin<<shift)) P_TOP[1]     = (rel_ymin<<shift);
+        if(P_TOPRIGHT[0] > (rel_xmax<<shift)) P_TOPRIGHT[0]= (rel_xmax<<shift);
+        if(P_TOPRIGHT[1] < (rel_ymin<<shift)) P_TOPRIGHT[1]= (rel_ymin<<shift);
+    
+        P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
+        P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
+
+        if(s->out_format == FMT_H263){
+            pred_x = P_MEDIAN[0];
+            pred_y = P_MEDIAN[1];
+        }else { /* mpeg1 at least */
+            pred_x= P_LEFT[0];
+            pred_y= P_LEFT[1];
+        }
+    }
+    dmin = s->me.motion_search[0](s, 0, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, 
+                                  &s->last_picture, s->p_mv_table, (1<<16)>>shift, mv_penalty);
+        
+    s->p_mv_table[xy][0] = mx<<shift;
+    s->p_mv_table[xy][1] = my<<shift;
+    
+    return dmin;
+}
+
 int ff_estimate_motion_b(MpegEncContext * s,
                        int mb_x, int mb_y, int16_t (*mv_table)[2], Picture *picture, int f_code)
 {
index 139688f794fa14db8b14b64f86821cb1cc37f0e1..f773d9f306c21a81ff45c0f66c2f21121336754d 100644 (file)
@@ -2789,6 +2789,19 @@ static void encode_picture(MpegEncContext *s, int picture_number)
 
     /* Estimate motion for every MB */
     if(s->pict_type != I_TYPE){
+
+        if(s->pict_type != B_TYPE){
+            if((s->avctx->pre_me && s->last_non_b_pict_type==I_TYPE) || s->avctx->pre_me==2){
+                for(mb_y=s->mb_height-1; mb_y >=0 ; mb_y--) {
+                    for(mb_x=s->mb_width-1; mb_x >=0 ; mb_x--) {
+                        s->mb_x = mb_x;
+                        s->mb_y = mb_y;
+                        ff_pre_estimate_p_frame_motion(s, mb_x, mb_y);
+                    }
+                }
+            }
+        }
+
         for(mb_y=0; mb_y < s->mb_height; mb_y++) {
             s->block_index[0]= s->block_wrap[0]*(mb_y*2 + 1) - 1;
             s->block_index[1]= s->block_wrap[0]*(mb_y*2 + 1);
index 51370bab5a715d3fb53b123ae34fb14030f9dc14..1356e75c6022c6820030dc3471a76a509582a6fc 100644 (file)
@@ -620,6 +620,7 @@ int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type);
 void ff_fix_long_p_mvs(MpegEncContext * s);
 void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type);
 void ff_init_me(MpegEncContext *s);
+int ff_pre_estimate_p_frame_motion(MpegEncContext * s, int mb_x, int mb_y);
 
 
 /* mpeg12.c */