changeset 1955:5dafb10e0252 libavcodec

reuse motion vectors/mb types/field select values of the source video, if the SSE for a macroblock which is predicted with these values is below me_threshold currently works only with mpeg1/2 source or some luck may need -sync 0 as otherwise framedrops could lead to extreemly long b frame sequences
author michael
date Fri, 23 Apr 2004 19:06:30 +0000
parents e943363932d9
children 0eb2947f56f6
files motion_est.c mpegvideo.c
diffstat 2 files changed, 162 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/motion_est.c	Thu Apr 22 23:15:24 2004 +0000
+++ b/motion_est.c	Fri Apr 23 19:06:30 2004 +0000
@@ -973,6 +973,119 @@
     }
 }
 
+static inline int check_input_motion(MpegEncContext * s, int mb_x, int mb_y, int p_type){
+    MotionEstContext * const c= &s->me;
+    Picture *p= s->current_picture_ptr;
+    int mb_xy= mb_x + mb_y*s->mb_stride;
+    int xy= 2*mb_x + 2*mb_y*s->b8_stride;
+    int mb_type= s->current_picture.mb_type[mb_xy];
+    int flags= c->flags;
+    int shift= (flags&FLAG_QPEL) + 1;
+    int mask= (1<<shift)-1;
+    int x, y;
+    int d=0;
+    me_cmp_func cmpf= s->dsp.sse[0];
+    me_cmp_func chroma_cmpf= s->dsp.sse[1];
+    
+    assert(p_type==0 || !USES_LIST(mb_type, 1));
+    assert(IS_INTRA(mb_type) || USES_LIST(mb_type,0) || USES_LIST(mb_type,1));
+    
+    if(IS_INTERLACED(mb_type)){
+        int xy2= xy  + s->b8_stride;
+        s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTRA;
+        c->stride<<=1;
+        c->uvstride<<=1;
+        c->ref[1][0] = c->ref[0][0] + s->linesize;
+        c->ref[3][0] = c->ref[2][0] + s->linesize;
+        c->src[1][0] = c->src[0][0] + s->linesize;
+        if(c->flags & FLAG_CHROMA){
+            c->ref[1][1] = c->ref[0][1] + s->uvlinesize;
+            c->ref[1][2] = c->ref[0][2] + s->uvlinesize;
+            c->ref[3][1] = c->ref[2][1] + s->uvlinesize;
+            c->ref[3][2] = c->ref[2][2] + s->uvlinesize;
+            c->src[1][1] = c->src[0][1] + s->uvlinesize;
+            c->src[1][2] = c->src[0][2] + s->uvlinesize;
+        }
+        if(USES_LIST(mb_type, 0)){
+            int field_select0= p->ref_index[0][xy ];
+            int field_select1= p->ref_index[0][xy2];
+            assert(field_select0==0 ||field_select0==1);
+            assert(field_select1==0 ||field_select1==1);
+            if(p_type){
+                s->p_field_select_table[0][mb_xy]= field_select0;
+                s->p_field_select_table[1][mb_xy]= field_select1;
+                *(uint32_t*)s->p_field_mv_table[0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[0][xy ];
+                *(uint32_t*)s->p_field_mv_table[1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[0][xy2];
+                s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER_I;
+            }else{
+                s->b_field_select_table[0][0][mb_xy]= field_select0;
+                s->b_field_select_table[0][1][mb_xy]= field_select1;
+                *(uint32_t*)s->b_field_mv_table[0][0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[0][xy ];
+                *(uint32_t*)s->b_field_mv_table[0][1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[0][xy2];
+                s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_FORWARD_I;
+            }
+
+            x= p->motion_val[0][xy ][0]; 
+            y= p->motion_val[0][xy ][1];
+            d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select0, 0, cmpf, chroma_cmpf, flags);
+            x= p->motion_val[0][xy2][0]; 
+            y= p->motion_val[0][xy2][1];
+            d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select1, 1, cmpf, chroma_cmpf, flags);
+        }
+        if(USES_LIST(mb_type, 1)){
+            int field_select0= p->ref_index[1][xy ];
+            int field_select1= p->ref_index[1][xy2];
+            assert(field_select0==0 ||field_select0==1);
+            assert(field_select1==0 ||field_select1==1);
+            s->b_field_select_table[1][0][mb_xy]= field_select0;
+            s->b_field_select_table[1][1][mb_xy]= field_select1;
+            *(uint32_t*)s->b_field_mv_table[1][0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[1][xy ];
+            *(uint32_t*)s->b_field_mv_table[1][1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[1][xy2];
+            if(USES_LIST(mb_type, 0)){
+                s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_BIDIR_I;
+            }else{
+                s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_BACKWARD_I;
+            }
+
+            x= p->motion_val[1][xy ][0]; 
+            y= p->motion_val[1][xy ][1];
+            d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select0+2, 0, cmpf, chroma_cmpf, flags);
+            x= p->motion_val[1][xy2][0]; 
+            y= p->motion_val[1][xy2][1];
+            d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select1+2, 1, cmpf, chroma_cmpf, flags);
+            //FIXME bidir scores
+        }
+        c->stride>>=1;
+        c->uvstride>>=1;
+    }else{
+        if(USES_LIST(mb_type, 0)){
+            if(p_type){
+                *(uint32_t*)s->p_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];
+                s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER;
+            }else if(USES_LIST(mb_type, 1)){
+                *(uint32_t*)s->b_bidir_forw_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];
+                *(uint32_t*)s->b_bidir_back_mv_table[mb_xy]= *(uint32_t*)p->motion_val[1][xy];
+                s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_BIDIR;
+            }else{
+                *(uint32_t*)s->b_forw_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];
+                s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_FORWARD;
+            }
+            x= p->motion_val[0][xy][0]; 
+            y= p->motion_val[0][xy][1];
+            d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 16, 0, 0, cmpf, chroma_cmpf, flags);
+        }else if(USES_LIST(mb_type, 1)){
+            *(uint32_t*)s->b_back_mv_table[mb_xy]= *(uint32_t*)p->motion_val[1][xy];
+            s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_BACKWARD;
+           
+            x= p->motion_val[1][xy][0]; 
+            y= p->motion_val[1][xy][1];
+            d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 16, 2, 0, cmpf, chroma_cmpf, flags);
+        }else
+            s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTRA;
+    }
+    return d;
+}
+
 void ff_estimate_p_frame_motion(MpegEncContext * s,
                                 int mb_x, int mb_y)
 {
@@ -999,6 +1112,28 @@
     get_limits(s, 16*mb_x, 16*mb_y);
     s->me.skip=0;
 
+    if(s->avctx->me_threshold){
+        vard= (check_input_motion(s, mb_x, mb_y, 1)+128)>>8;
+        
+        if(vard<s->avctx->me_threshold){
+            pix = c->src[0][0];
+            sum = s->dsp.pix_sum(pix, s->linesize);
+            varc = (s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)(sum*sum))>>8) + 500 + 128)>>8;
+        
+            pic->mb_var   [s->mb_stride * mb_y + mb_x] = varc;
+            pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = vard;
+            pic->mb_mean  [s->mb_stride * mb_y + mb_x] = (sum+128)>>8;
+            s->mb_var_sum_temp    += varc;
+            s->mc_mb_var_sum_temp += vard;
+            if (vard <= 64 || vard < varc) { //FIXME
+                s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
+            }else{
+                s->scene_change_score+= s->qscale;
+            }
+            return;
+        }
+    }
+
     switch(s->me_method) {
     case ME_ZERO:
     default:
@@ -1555,6 +1690,28 @@
     init_mc(s, 0, s->me.flags);
     
     s->me.skip=0;
+    if(s->avctx->me_threshold){
+        int vard= (check_input_motion(s, mb_x, mb_y, 0)+128)>>8;
+        
+        if(vard<s->avctx->me_threshold){
+//            pix = c->src[0][0];
+//            sum = s->dsp.pix_sum(pix, s->linesize);
+//            varc = (s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)(sum*sum))>>8) + 500 + 128)>>8;
+        
+//            pic->mb_var   [s->mb_stride * mb_y + mb_x] = varc;
+             s->current_picture.mc_mb_var[s->mb_stride * mb_y + mb_x] = vard;
+/*            pic->mb_mean  [s->mb_stride * mb_y + mb_x] = (sum+128)>>8;
+            s->mb_var_sum_temp    += varc;*/
+            s->mc_mb_var_sum_temp += vard;
+/*            if (vard <= 64 || vard < varc) {
+                s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
+            }else{
+                s->scene_change_score+= s->qscale;
+            }*/
+            return;
+        }
+    }
+
     if (s->codec_id == CODEC_ID_MPEG4)
         dmin= direct_search(s, mb_x, mb_y);
     else
--- a/mpegvideo.c	Thu Apr 22 23:15:24 2004 +0000
+++ b/mpegvideo.c	Fri Apr 23 19:06:30 2004 +0000
@@ -295,7 +295,8 @@
         if(!src->ref_index[0])
             av_log(s->avctx, AV_LOG_ERROR, "AVFrame.ref_index not set!\n");
         if(src->motion_subsample_log2 != dst->motion_subsample_log2)
-            av_log(s->avctx, AV_LOG_ERROR, "AVFrame.motion_subsample_log2 doesnt match!\n");
+            av_log(s->avctx, AV_LOG_ERROR, "AVFrame.motion_subsample_log2 doesnt match! (%d!=%d)\n",
+            src->motion_subsample_log2, dst->motion_subsample_log2);
 
         memcpy(dst->mb_type, src->mb_type, s->mb_stride * s->mb_height * sizeof(dst->mb_type[0]));
         
@@ -2055,11 +2056,12 @@
                 s->reordered_input_picture[0]->data[i]= NULL;
             s->reordered_input_picture[0]->type= 0;
             
-            copy_picture_attributes(s, (AVFrame*)pic, (AVFrame*)s->reordered_input_picture[0]);
             pic->reference              = s->reordered_input_picture[0]->reference;
             
             alloc_picture(s, pic, 0);
 
+            copy_picture_attributes(s, (AVFrame*)pic, (AVFrame*)s->reordered_input_picture[0]);
+
             s->current_picture_ptr= pic;
         }else{
             // input is not a shared pix -> reuse buffer for current_pix
@@ -4676,7 +4678,7 @@
     
     /* Estimate motion for every MB */
     if(s->pict_type != I_TYPE){
-        if(s->pict_type != B_TYPE){
+        if(s->pict_type != B_TYPE && s->avctx->me_threshold==0){
             if((s->avctx->pre_me && s->last_non_b_pict_type==I_TYPE) || s->avctx->pre_me==2){
                 s->avctx->execute(s->avctx, pre_estimate_motion_thread, (void**)&(s->thread_context[0]), NULL, s->avctx->thread_count);
             }