📄 motionest.cc
字号:
* bestfld: location and distance of best field prediction * best8u: location of best 16x8 pred. for upper half of mb * best8lp: location of best 16x8 pred. for lower half of mb * bdestsp: location and distance of best same parity field * prediction (needed for dual prime, only valid if * ipflag==0) */static void field_estimate ( const Picture &picture, uint8_t *toporg, uint8_t *topref, uint8_t *botorg, uint8_t *botref, SubSampledImg *ssmb, int i, int j, int sx, int sy, MotionCand *bestfld, MotionCand *best8u, MotionCand *best8l, MotionCand *bestsp){ const EncoderParams &eparams = picture.encparams; MotionCand topfld_mc; MotionCand botfld_mc; int dt, db; int notop, nobot; SubSampledImg botssmb; botssmb.mb = ssmb->mb+eparams.phy_width; botssmb.umb = ssmb->umb+(eparams.phy_width>>1); botssmb.vmb = ssmb->vmb+(eparams.phy_width>>1); botssmb.fmb = ssmb->fmb+(eparams.phy_width>>1); botssmb.qmb = ssmb->qmb+(eparams.phy_width>>2); /* if ipflag is set, predict from field of opposite parity only */ notop = picture.ipflag && (picture.pict_struct==TOP_FIELD); nobot = picture.ipflag && (picture.pict_struct==BOTTOM_FIELD); /* field prediction */ /* predict current field from top field */ if (notop) topfld_mc.sad = dt = 65536; /* infinity */ else mb_me_search(eparams, toporg,topref,0,ssmb, eparams.phy_width<<1, i,j,sx,sy>>1,16, eparams.enc_width,eparams.enc_height>>1, &topfld_mc); dt = topfld_mc.sad; /* predict current field from bottom field */ if (nobot) botfld_mc.sad = db = 65536; /* infinity */ else mb_me_search(eparams, botorg,botref,eparams.phy_width,ssmb, eparams.phy_width<<1, i,j,sx,sy>>1,16, eparams.enc_width,eparams.enc_height>>1, &botfld_mc); db = botfld_mc.sad; /* Set correct field selectors */ topfld_mc.fieldsel = 0; botfld_mc.fieldsel = 1; topfld_mc.fieldoff = 0; botfld_mc.fieldoff = eparams.phy_width; /* same parity prediction (only valid if ipflag==0) */ if (picture.pict_struct==TOP_FIELD) { *bestsp = topfld_mc; } else { *bestsp = botfld_mc; } /* select field prediction */ if (dt<=db) { *bestfld = topfld_mc; } else { *bestfld = botfld_mc; } /* 16x8 motion estimation */ /* predict upper half field from top field */ if (notop) topfld_mc.sad = dt = 65536; else mb_me_search(eparams, toporg,topref,0,ssmb, eparams.phy_width<<1, i,j,sx,sy>>1,8, eparams.enc_width,eparams.enc_height>>1,&topfld_mc); dt = topfld_mc.sad; /* predict upper half field from bottom field */ if (nobot) botfld_mc.sad = db = 65536; else mb_me_search(eparams, botorg,botref,eparams.phy_width,ssmb, eparams.phy_width<<1, i,j,sx,sy>>1,8, eparams.enc_width, eparams.enc_height>>1,&botfld_mc); db = botfld_mc.sad; /* Set correct field selectors */ topfld_mc.fieldsel = 0; botfld_mc.fieldsel = 1; topfld_mc.fieldoff = 0; botfld_mc.fieldoff = eparams.phy_width; /* select prediction for upper half field */ if (dt<=db) { *best8u = topfld_mc; } else { *best8u = botfld_mc; } /* predict lower half field from top field */ /* N.b. For interlaced data width<<4 (width*16) takes us 8 rows down in the same field. Thus for the fast motion data (2*2 sub-sampled) we need to go 4 rows down in the same field. This requires adding width*4 = (width<<2). For the 4*4 sub-sampled motion data we need to go down 2 rows. This requires adding width = width */ if (notop) topfld_mc.sad = dt = 65536; else mb_me_search(eparams, toporg,topref,0,&botssmb, eparams.phy_width<<1, i,j+8,sx,sy>>1,8, eparams.enc_width,eparams.enc_height>>1, &topfld_mc); dt = topfld_mc.sad; /* predict lower half field from bottom field */ if (nobot) botfld_mc.sad = db = 65536; else mb_me_search(eparams, botorg,botref,eparams.phy_width,&botssmb, eparams.phy_width<<1,i,j+8,sx,sy>>1,8, eparams.enc_width,eparams.enc_height>>1, &botfld_mc); db = botfld_mc.sad; /* Set correct field selectors */ topfld_mc.fieldsel = 0; botfld_mc.fieldsel = 1; topfld_mc.fieldoff = 0; botfld_mc.fieldoff = eparams.phy_width; /* select prediction for lower half field */ if (dt<=db) { *best8l = topfld_mc; } else { *best8l = botfld_mc; }} /* Hierarchical block matching motion estimation search * * A.Stevens 2000: This is now a big misnomer. The search is now a * hierarchical/sub-sampling search not a full search. However, * experiments have shown it is always close to optimal and almost * always very close or optimal. * * org: top left pel of source reference frame * ref: top left pel of reconstructed reference frame * fieldoff - Offset to top left pel relevant field in org and ref * if we're doing by-field matching * ssblk: top-left element of macro block to be motion compensated * at 1*1,2*2 and 4*4 subsampling * lx: distance (in bytes) of vertically adjacent pels in ref,blk * This is twice the physical line length if we're doing by-field * matching otherwise the physical line length * i0,j0: center of search window * sx,sy: half widths of search window * h: height of macro block * xmax,ymax: right/bottom limits of search area for macro block * res: pointers to where the result is stored * N.b. as in the original code result is given as * half pel offset from ref(0,0) not the position relative to i0 j0 * as will actually be used. * * TODO: SHould use half-pel co-ordinates relative to i0,j0 for motion vectors * throughout the motion estimation code but this would be damn fiddly to * do without introducing lots of tricky-to-find bugs. * */ #ifdef DEBUG_MOTION_ESTstatic void log_result_set( me_result_set *rs ){ int i; for( i = 0; i < rs->len; ++i ) printf( "%03d: %6d %3d %3d\n", i, rs->mests[i].weight, 2*rs->mests[i].x, 2*rs->mests[i].y );}static int hash( uint8_t *blk, int stride ){ int i,j; int sum = 0; for( j= 0; j <16; ++j ) for( i = 0; i <16 ; ++i) sum += *(blk+i+j*stride); return sum;}static int dump( uint8_t *blk, int stride ){ int i,j; int sum = 0; for( j= 0; j <16; ++j ) { for( i = 0; i <16 ; ++i) printf( "%02x ", *(blk+i+j*stride) ); if( j & 1 ) printf( "\n" ); } return sum;}#endifstatic void mb_me_search( const EncoderParams &eparams, uint8_t *org, uint8_t *ref, int fieldoff, SubSampledImg *ssblk, int lx, int i0, int j0, int sx, int sy, int h, int xmax, int ymax, MotionCand *res ){ me_result_s best; int i,j,ilow,ihigh,jlow,jhigh; int x,y; int d; /* NOTE: Surprisingly, the initial motion estimation search works better when the original image not the reference (reconstructed) image is used. */ uint8_t *s22org = (uint8_t*)(org+eparams.fsubsample_offset+(fieldoff>>1)); uint8_t *s44org = (uint8_t*)(org+eparams.qsubsample_offset+(fieldoff>>2)); uint8_t *orgblk; uint8_t *reffld = ref+fieldoff; int flx = lx >> 1; int qlx = lx >> 2; int fh = h >> 1; int qh = h >> 2; me_result_set sub44set; me_result_set sub22set; /* xmax and ymax into more useful form... */ xmax -= 16; ymax -= h; /* The search radii are *always* multiples of 4 to avoid messiness in the initial 4*4 pel search. This is handled by the parameter checking/processing code in readparmfile() */ /* Create a distance-order mests of possible motion estimations based on the fast estimation data - 4*4 pel sums (4*4 sub-sampled) rather than actual pel's. 1/16 the size... */ jlow = j0-sy; jlow = jlow < 0 ? 0 : jlow; jhigh = j0+(sy-1); jhigh = jhigh > ymax ? ymax : jhigh; ilow = i0-sx; ilow = ilow < 0 ? 0 : ilow; ihigh = i0+(sx-1); ihigh = ihigh > xmax ? xmax : ihigh; /* Very rarely this may fail to find matchs due to all the good looking ones being over threshold. hence we make sure we fall back to a 0 motion estimation in this case. The sad for the 0 motion estimation is also very useful as a basis for setting thresholds for rejecting really dud 4*4 and 2*2 sub-sampled matches. */ best.weight = psad_00(reffld+i0+j0*lx,ssblk->mb,lx,h,INT_MAX); best.x = 0; best.y = 0; /* Generate the best matches at 4*4 sub-sampling. The precise fraction of the matches included is controlled by eparams.44_red Note: we use the original picture here for the match... */ pbuild_sub44_mests( &sub44set, ilow, jlow, ihigh, jhigh, i0, j0, best.weight, s44org, ssblk->qmb, qlx, qh, eparams.me44_red); #ifdef DEBUG_MOTION_EST if( trace_me ) log_result_set( &sub44set );#endif /* Generate the best 2*2 sub-sampling matches from the immediate 2*2 neighbourhoods of the 4*4 sub-sampling matches. The precise fraction of the matches included is controlled by eparams.22_red. Note: we use the original picture here for the match... */ pbuild_sub22_mests( &sub44set, &sub22set, i0, j0, ihigh, jhigh, best.weight, s22org, ssblk->fmb, flx, fh, eparams.me22_red);#ifdef DEBUG_MOTION_EST if( trace_me ) log_result_set( &sub22set );#endif /* Now choose best 1-pel match from the 2*2 neighbourhoods of the best 2*2 sub-sampled matches. Note that here we start using the reference picture not the original. */ pfind_best_one_pel( &sub22set, reffld, ssblk->mb, i0, j0, ihigh, jhigh, lx, h, &best );#ifdef DEBUG_MOTION_EST if( trace_me ) { printf( "BST: %6d %3d %3d @ %6d %7d (%7d)\n", best.weight, 2*best.x, 2*best.y, (i0+best.x)+lx*(j0+best.y), hash(reffld+(i0+best.x)+lx*(j0+best.y), lx), hash(ssblk->mb, lx) ); dump( reffld+(i0+best.x)+lx*(j0+best.y), lx ); };#endif /* Final polish: half-pel search of best 1*1 against reconstructed image. */ res->sad = INT_MAX; x = (i0+best.x)<<1; y = (j0+best.y)<<1; /* Narrow search box to half-pel's around best 1-pel match - half-pel units....*/ ilow = x - (x>(ilow<<1)); ihigh = x + (x<((ihigh)<<1)); jlow = y - (y>(jlow<<1)); jhigh = y+ (y<((jhigh)<<1)); for (j=jlow; j<=jhigh; j++) { for (i=ilow; i<=ihigh; i++) { orgblk = reffld+(i>>1)+((j>>1)*lx); if( i&1 ) { if( j & 1 ) d = psad_11(orgblk,ssblk->mb,lx,h); else d = psad_01(orgblk,ssblk->mb,lx,h); } else { if( j & 1 ) d = psad_10(orgblk,ssblk->mb,lx,h); else d = psad_00(orgblk,ssblk->mb,lx,h,res->sad); } // TODO: Mismatches motionsearch...#ifdef DEBUG_MOTION_EST if( trace_me ) printf( "BSS: %6d %3d %3d @ %6d %7d\n", d, i, j, orgblk-reffld, hash(orgblk, lx) );#endif d += mv_coding_penalty(i-(i0<<1),j-(j0<<1)); if (d<res->sad) { res->sad = d; res->pos.x = i; res->pos.y = j; res->blk = orgblk; res->hx = i&1; res->hy = j&1; } } } res->var = psumsq(res->blk, ssblk->mb, lx, res->hx, res->hy, h);}/* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -