aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/motion_est.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2004-04-23 19:06:30 +0000
committerMichael Niedermayer <michaelni@gmx.at>2004-04-23 19:06:30 +0000
commitf4f3223ffd87e330910a49c45741920f25101285 (patch)
treec5dc7e3eeae5f133b80993c51dfee35978fb54c6 /libavcodec/motion_est.c
parent10f3005f51c4aed49abad7d882e1488225f1c674 (diff)
downloadffmpeg-f4f3223ffd87e330910a49c45741920f25101285.tar.gz
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 Originally committed as revision 3042 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/motion_est.c')
-rw-r--r--libavcodec/motion_est.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c
index 59ffc31756..65b21b0248 100644
--- a/libavcodec/motion_est.c
+++ b/libavcodec/motion_est.c
@@ -973,6 +973,119 @@ static int interlaced_search(MpegEncContext *s, int ref_index,
}
}
+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 @@ void ff_estimate_p_frame_motion(MpegEncContext * s,
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 @@ void ff_estimate_b_frame_motion(MpegEncContext * s,
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