📄 motion_est.c
字号:
if(P_TOPRIGHT[0] < (rel_xmin<<shift)) P_TOPRIGHT[0]= (rel_xmin<<shift); if(P_TOPRIGHT[1] > (rel_ymax<<shift)) P_TOPRIGHT[1]= (rel_ymax<<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]); } pred_x= P_LEFT[0]; pred_y= P_LEFT[1]; } if(mv_table == s->b_forw_mv_table){ mv_scale= (s->pb_time<<16) / (s->pp_time<<shift); }else{ mv_scale= ((s->pb_time - s->pp_time)<<16) / (s->pp_time<<shift); } dmin = s->me.motion_search[0](s, 0, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, picture, s->p_mv_table, mv_scale, mv_penalty); break; } dmin= s->me.sub_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax, pred_x, pred_y, picture, 0, 0, mv_penalty); if(s->avctx->me_sub_cmp != s->avctx->mb_cmp && !s->me.skip) dmin= s->me.get_mb_score(s, mx, my, pred_x, pred_y, picture, mv_penalty);//printf("%d %d %d %d//", s->mb_x, s->mb_y, mx, my);// s->mb_type[mb_y*s->mb_width + mb_x]= mb_type; mv_table[mot_xy][0]= mx; mv_table[mot_xy][1]= my; return dmin;}static inline int check_bidir_mv(MpegEncContext * s, int mb_x, int mb_y, int motion_fx, int motion_fy, int motion_bx, int motion_by, int pred_fx, int pred_fy, int pred_bx, int pred_by){ //FIXME optimize? //FIXME move into template? //FIXME better f_code prediction (max mv & distance) uint8_t * const mv_penalty= s->me.mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame uint8_t *dest_y = s->me.scratchpad; uint8_t *ptr; int dxy; int src_x, src_y; int fbmin; if(s->quarter_sample){ dxy = ((motion_fy & 3) << 2) | (motion_fx & 3); src_x = mb_x * 16 + (motion_fx >> 2); src_y = mb_y * 16 + (motion_fy >> 2); assert(src_x >=-16 && src_x<=s->h_edge_pos); assert(src_y >=-16 && src_y<=s->v_edge_pos); ptr = s->last_picture.data[0] + (src_y * s->linesize) + src_x; s->dsp.put_qpel_pixels_tab[0][dxy](dest_y , ptr , s->linesize); dxy = ((motion_by & 3) << 2) | (motion_bx & 3); src_x = mb_x * 16 + (motion_bx >> 2); src_y = mb_y * 16 + (motion_by >> 2); assert(src_x >=-16 && src_x<=s->h_edge_pos); assert(src_y >=-16 && src_y<=s->v_edge_pos); ptr = s->next_picture.data[0] + (src_y * s->linesize) + src_x; s->dsp.avg_qpel_pixels_tab[0][dxy](dest_y , ptr , s->linesize); }else{ dxy = ((motion_fy & 1) << 1) | (motion_fx & 1); src_x = mb_x * 16 + (motion_fx >> 1); src_y = mb_y * 16 + (motion_fy >> 1); assert(src_x >=-16 && src_x<=s->h_edge_pos); assert(src_y >=-16 && src_y<=s->v_edge_pos); ptr = s->last_picture.data[0] + (src_y * s->linesize) + src_x; s->dsp.put_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16); dxy = ((motion_by & 1) << 1) | (motion_bx & 1); src_x = mb_x * 16 + (motion_bx >> 1); src_y = mb_y * 16 + (motion_by >> 1); assert(src_x >=-16 && src_x<=s->h_edge_pos); assert(src_y >=-16 && src_y<=s->v_edge_pos); ptr = s->next_picture.data[0] + (src_y * s->linesize) + src_x; s->dsp.avg_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16); } fbmin = (mv_penalty[motion_fx-pred_fx] + mv_penalty[motion_fy-pred_fy])*s->me.mb_penalty_factor +(mv_penalty[motion_bx-pred_bx] + mv_penalty[motion_by-pred_by])*s->me.mb_penalty_factor + s->dsp.mb_cmp[0](s, s->new_picture.data[0] + mb_x*16 + mb_y*16*s->linesize, dest_y, s->linesize); if(s->avctx->mb_cmp&FF_CMP_CHROMA){ } //FIXME CHROMA !!! return fbmin;}/* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y){ const int mot_stride = s->mb_stride; const int xy = mb_y *mot_stride + mb_x; int fbmin; int pred_fx= s->b_bidir_forw_mv_table[xy-1][0]; int pred_fy= s->b_bidir_forw_mv_table[xy-1][1]; int pred_bx= s->b_bidir_back_mv_table[xy-1][0]; int pred_by= s->b_bidir_back_mv_table[xy-1][1]; int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0]; int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1]; int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0]; int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1]; //FIXME do refinement and add flag fbmin= check_bidir_mv(s, mb_x, mb_y, motion_fx, motion_fy, motion_bx, motion_by, pred_fx, pred_fy, pred_bx, pred_by); return fbmin;}static inline int direct_search(MpegEncContext * s, int mb_x, int mb_y){ int P[10][2]; const int mot_stride = s->mb_stride; const int mot_xy = mb_y*mot_stride + mb_x; const int shift= 1+s->quarter_sample; int dmin, i; const int time_pp= s->pp_time; const int time_pb= s->pb_time; int mx, my, xmin, xmax, ymin, ymax; int16_t (*mv_table)[2]= s->b_direct_mv_table; uint8_t * const mv_penalty= s->me.mv_penalty[1] + MAX_MV; ymin= xmin=(-32)>>shift; ymax= xmax= 31>>shift; if(IS_8X8(s->next_picture.mb_type[mot_xy])){ s->mv_type= MV_TYPE_8X8; }else{ s->mv_type= MV_TYPE_16X16; } for(i=0; i<4; i++){ int index= s->block_index[i]; int min, max; s->me.co_located_mv[i][0]= s->motion_val[index][0]; s->me.co_located_mv[i][1]= s->motion_val[index][1]; s->me.direct_basis_mv[i][0]= s->me.co_located_mv[i][0]*time_pb/time_pp + ((i& 1)<<(shift+3)); s->me.direct_basis_mv[i][1]= s->me.co_located_mv[i][1]*time_pb/time_pp + ((i>>1)<<(shift+3));// s->me.direct_basis_mv[1][i][0]= s->me.co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3);// s->me.direct_basis_mv[1][i][1]= s->me.co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3); max= FFMAX(s->me.direct_basis_mv[i][0], s->me.direct_basis_mv[i][0] - s->me.co_located_mv[i][0])>>shift; min= FFMIN(s->me.direct_basis_mv[i][0], s->me.direct_basis_mv[i][0] - s->me.co_located_mv[i][0])>>shift; max+= (2*mb_x + (i& 1))*8 + 1; // +-1 is for the simpler rounding min+= (2*mb_x + (i& 1))*8 - 1; xmax= FFMIN(xmax, s->width - max); xmin= FFMAX(xmin, - 16 - min); max= FFMAX(s->me.direct_basis_mv[i][1], s->me.direct_basis_mv[i][1] - s->me.co_located_mv[i][1])>>shift; min= FFMIN(s->me.direct_basis_mv[i][1], s->me.direct_basis_mv[i][1] - s->me.co_located_mv[i][1])>>shift; max+= (2*mb_y + (i>>1))*8 + 1; // +-1 is for the simpler rounding min+= (2*mb_y + (i>>1))*8 - 1; ymax= FFMIN(ymax, s->height - max); ymin= FFMAX(ymin, - 16 - min); if(s->mv_type == MV_TYPE_16X16) break; } assert(xmax <= 15 && ymax <= 15 && xmin >= -16 && ymin >= -16); if(xmax < 0 || xmin >0 || ymax < 0 || ymin > 0){ s->b_direct_mv_table[mot_xy][0]= 0; s->b_direct_mv_table[mot_xy][1]= 0; return 256*256*256*64; } P_LEFT[0] = clip(mv_table[mot_xy - 1][0], xmin<<shift, xmax<<shift); P_LEFT[1] = clip(mv_table[mot_xy - 1][1], ymin<<shift, ymax<<shift); /* special case for first line */ if (mb_y) { P_TOP[0] = clip(mv_table[mot_xy - mot_stride ][0], xmin<<shift, xmax<<shift); P_TOP[1] = clip(mv_table[mot_xy - mot_stride ][1], ymin<<shift, ymax<<shift); P_TOPRIGHT[0] = clip(mv_table[mot_xy - mot_stride + 1 ][0], xmin<<shift, xmax<<shift); P_TOPRIGHT[1] = clip(mv_table[mot_xy - mot_stride + 1 ][1], ymin<<shift, ymax<<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]); } //FIXME direct_search ptr in context!!! (needed for chroma anyway or this will get messy) if(s->flags&CODEC_FLAG_QPEL){ dmin = simple_direct_qpel_epzs_motion_search(s, 0, &mx, &my, P, 0, 0, xmin, ymin, xmax, ymax, &s->last_picture, mv_table, 1<<14, mv_penalty); dmin = simple_direct_qpel_qpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, 0, 0, &s->last_picture, 0, 0, mv_penalty); if(s->avctx->me_sub_cmp != s->avctx->mb_cmp && !s->me.skip) dmin= simple_direct_qpel_qpel_get_mb_score(s, mx, my, 0, 0, &s->last_picture, mv_penalty); }else{ dmin = simple_direct_hpel_epzs_motion_search(s, 0, &mx, &my, P, 0, 0, xmin, ymin, xmax, ymax, &s->last_picture, mv_table, 1<<15, mv_penalty); dmin = simple_direct_hpel_hpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, 0, 0, &s->last_picture, 0, 0, mv_penalty); if(s->avctx->me_sub_cmp != s->avctx->mb_cmp && !s->me.skip) dmin= simple_direct_hpel_hpel_get_mb_score(s, mx, my, 0, 0, &s->last_picture, mv_penalty); } s->b_direct_mv_table[mot_xy][0]= mx; s->b_direct_mv_table[mot_xy][1]= my; return dmin;}void ff_estimate_b_frame_motion(MpegEncContext * s, int mb_x, int mb_y){ const int penalty_factor= s->me.mb_penalty_factor; int fmin, bmin, dmin, fbmin; int type=0; s->me.skip=0; if (s->codec_id == CODEC_ID_MPEG4) dmin= direct_search(s, mb_x, mb_y); else dmin= INT_MAX; s->me.skip=0; fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, &s->last_picture, s->f_code) + 3*penalty_factor; s->me.skip=0; bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, &s->next_picture, s->b_code) + 2*penalty_factor;//printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]); s->me.skip=0; fbmin= bidir_refine(s, mb_x, mb_y) + penalty_factor;//printf("%d %d %d %d\n", dmin, fmin, bmin, fbmin); { int score= fmin; type = MB_TYPE_FORWARD; if (dmin <= score){ score = dmin; type = MB_TYPE_DIRECT; } if(bmin<score){ score=bmin; type= MB_TYPE_BACKWARD; } if(fbmin<score){ score=fbmin; type= MB_TYPE_BIDIR; } score= ((unsigned)(score*score + 128*256))>>16; s->current_picture.mc_mb_var_sum += score; s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score; //FIXME use SSE } if(s->avctx->mb_decision > FF_MB_DECISION_SIMPLE){ type= MB_TYPE_FORWARD | MB_TYPE_BACKWARD | MB_TYPE_BIDIR | MB_TYPE_DIRECT; //FIXME something smarter if(dmin>256*256*16) type&= ~MB_TYPE_DIRECT; //dont try direct mode if its invalid for this MB } s->mb_type[mb_y*s->mb_stride + mb_x]= type;}/* find best f_code for ME which do unlimited searches */int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type){ if(s->me_method>=ME_EPZS){ int score[8]; int i, y; uint8_t * fcode_tab= s->fcode_tab; int best_fcode=-1; int best_score=-10000000; for(i=0; i<8; i++) score[i]= s->mb_num*(8-i); for(y=0; y<s->mb_height; y++){ int x; int xy= y*s->mb_stride; for(x=0; x<s->mb_width; x++){ if(s->mb_type[xy] & type){ int fcode= FFMAX(fcode_tab[mv_table[xy][0] + MAX_MV], fcode_tab[mv_table[xy][1] + MAX_MV]); int j; for(j=0; j<fcode && j<8; j++){ if(s->pict_type==B_TYPE || s->current_picture.mc_mb_var[xy] < s->current_picture.mb_var[xy]) score[j]-= 170; } } xy++; } } for(i=1; i<8; i++){ if(score[i] > best_score){ best_score= score[i]; best_fcode= i; }// printf("%d %d\n", i, score[i]); }// printf("fcode: %d type: %d\n", i, s->pict_type); return best_fcode;/* for(i=0; i<=MAX_FCODE; i++){ printf("%d ", mv_num[i]); } printf("\n");*/ }else{ return 1; }}void ff_fix_long_p_mvs(MpegEncContext * s){ const int f_code= s->f_code; int y, range; assert(s->pict_type==P_TYPE); range = (((s->out_format == FMT_MPEG1) ? 8 : 16) << f_code); if(s->msmpeg4_version) range= 16; if(s->avctx->me_range && range > s->avctx->me_range) range= s->avctx->me_range; /* clip / convert to intra 16x16 type MVs */ for(y=0; y<s->mb_height; y++){ int x; int xy= y*s->mb_stride; for(x=0; x<s->mb_width; x++){ if(s->mb_type[xy]&MB_TYPE_INTER){ if( s->p_mv_table[xy][0] >=range || s->p_mv_table[xy][0] <-range || s->p_mv_table[xy][1] >=range || s->p_mv_table[xy][1] <-range){ s->mb_type[xy] &= ~MB_TYPE_INTER; s->mb_type[xy] |= MB_TYPE_INTRA; s->p_mv_table[xy][0] = 0; s->p_mv_table[xy][1] = 0; } } xy++; } }//printf("%d no:%d %d//\n", clip, noclip, f_code); if(s->flags&CODEC_FLAG_4MV){ const int wrap= 2+ s->mb_width*2; /* clip / convert to intra 8x8 type MVs */ for(y=0; y<s->mb_height; y++){ int xy= (y*2 + 1)*wrap + 1; int i= y*s->mb_stride; int x; for(x=0; x<s->mb_width; x++){ if(s->mb_type[i]&MB_TYPE_INTER4V){ int block; for(block=0; block<4; block++){ int off= (block& 1) + (block>>1)*wrap; int mx= s->motion_val[ xy + off ][0]; int my= s->motion_val[ xy + off ][1]; if( mx >=range || mx <-range || my >=range || my <-range){ s->mb_type[i] &= ~MB_TYPE_INTER4V; s->mb_type[i] |= MB_TYPE_INTRA; } } } xy+=2; i++; } } }}void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type){ int y; // RAL: 8 in MPEG-1, 16 in MPEG-4 int range = (((s->out_format == FMT_MPEG1) ? 8 : 16) << f_code); if(s->avctx->me_range && range > s->avctx->me_range) range= s->avctx->me_range; /* clip / convert to intra 16x16 type MVs */ for(y=0; y<s->mb_height; y++){ int x; int xy= y*s->mb_stride; for(x=0; x<s->mb_width; x++){ if (s->mb_type[xy] & type){ // RAL: "type" test added... if( mv_table[xy][0] >=range || mv_table[xy][0] <-range || mv_table[xy][1] >=range || mv_table[xy][1] <-range){ if(s->codec_id == CODEC_ID_MPEG1VIDEO && 0){ }else{ if (mv_table[xy][0] > range-1) mv_table[xy][0]= range-1; else if(mv_table[xy][0] < -range ) mv_table[xy][0]= -range; if (mv_table[xy][1] > range-1) mv_table[xy][1]= range-1; else if(mv_table[xy][1] < -range ) mv_table[xy][1]= -range; } } } xy++; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -