Mercurial > libavcodec.hg
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); }