📄 motion_est.c
字号:
ptr = ref_data[0] + (src_y * stride) + src_x; s->dsp.put_qpel_pixels_tab[0][dxy](dest_y , ptr , stride); dxy = ((motion_by & 3) << 2) | (motion_bx & 3); src_x = motion_bx >> 2; src_y = motion_by >> 2; ptr = ref_data[3] + (src_y * stride) + src_x; s->dsp.avg_qpel_pixels_tab[size][dxy](dest_y , ptr , stride); }else{ dxy = ((motion_fy & 1) << 1) | (motion_fx & 1); src_x = motion_fx >> 1; src_y = motion_fy >> 1; ptr = ref_data[0] + (src_y * stride) + src_x; s->dsp.put_pixels_tab[size][dxy](dest_y , ptr , stride, h); dxy = ((motion_by & 1) << 1) | (motion_bx & 1); src_x = motion_bx >> 1; src_y = motion_by >> 1; ptr = ref_data[3] + (src_y * stride) + src_x; s->dsp.avg_pixels_tab[size][dxy](dest_y , ptr , stride, h); } 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[size](s, src_data[0], dest_y, stride, h); //FIXME new_pic 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, uint8_t *src_data[3], uint8_t *ref_data[6], int stride, int uvstride, 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, src_data, ref_data, stride, uvstride, motion_fx, motion_fy, motion_bx, motion_by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16); return fbmin;}static inline int direct_search(MpegEncContext * s, uint8_t *src_data[3], uint8_t *ref_data[6], int stride, int uvstride, 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->next_picture.motion_val[0][index][0]; s->me.co_located_mv[i][1]= s->next_picture.motion_val[0][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+= 16*mb_x + 1; // +-1 is for the simpler rounding min+= 16*mb_x - 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+= 16*mb_y + 1; // +-1 is for the simpler rounding min+= 16*mb_y - 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; } s->me.xmin= xmin; s->me.ymin= ymin; s->me.xmax= xmax; s->me.ymax= ymax; 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 (!s->first_slice_line) { //FIXME maybe allow this over thread boundary as its cliped 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, &mx, &my, P, 0, 0, src_data, ref_data, stride, uvstride, mv_table, 1<<14, mv_penalty); dmin = simple_direct_qpel_qpel_motion_search(s, &mx, &my, dmin, 0, 0, src_data, ref_data, stride, uvstride, 0, 16, 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, src_data, ref_data, stride, uvstride, mv_penalty); }else{ dmin = simple_direct_hpel_epzs_motion_search(s, &mx, &my, P, 0, 0, src_data, ref_data, stride, uvstride, mv_table, 1<<15, mv_penalty); dmin = simple_direct_hpel_hpel_motion_search(s, &mx, &my, dmin, 0, 0, src_data, ref_data, stride, uvstride, 0, 16, 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, src_data, ref_data, stride, uvstride, mv_penalty); } get_limits(s, 16*mb_x, 16*mb_y); //restore s->me.?min/max, maybe not needed 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, bimin, fimin; int type=0; const int stride= s->linesize; const int uvstride= s->uvlinesize; uint8_t *src_data[3]= { s->new_picture.data[0] + 16*(s->mb_x + stride*s->mb_y), s->new_picture.data[1] + 8*(s->mb_x + uvstride*s->mb_y), s->new_picture.data[2] + 8*(s->mb_x + uvstride*s->mb_y) }; uint8_t *ref_data[6]= { s->last_picture.data[0] + 16*(s->mb_x + stride*s->mb_y), s->last_picture.data[1] + 8*(s->mb_x + uvstride*s->mb_y), s->last_picture.data[2] + 8*(s->mb_x + uvstride*s->mb_y), s->next_picture.data[0] + 16*(s->mb_x + stride*s->mb_y), s->next_picture.data[1] + 8*(s->mb_x + uvstride*s->mb_y), s->next_picture.data[2] + 8*(s->mb_x + uvstride*s->mb_y) }; s->me.skip=0; if (s->codec_id == CODEC_ID_MPEG4) dmin= direct_search(s, src_data, ref_data, stride, uvstride, mb_x, mb_y); else dmin= INT_MAX;//FIXME penalty stuff for non mpeg4 s->me.skip=0; fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, src_data, ref_data, stride, uvstride, 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, src_data, ref_data+3, stride, uvstride, 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, src_data, ref_data, stride, uvstride, mb_x, mb_y) + penalty_factor;//printf("%d %d %d %d\n", dmin, fmin, bmin, fbmin); if(s->flags & CODEC_FLAG_INTERLACED_ME){ const int xy = mb_y*s->mb_stride + mb_x;//FIXME mb type penalty s->me.skip=0; fimin= interlaced_search(s, src_data, ref_data , s->b_field_mv_table[0], s->b_field_select_table[0], s->f_code, s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]); bimin= interlaced_search(s, src_data, ref_data+3, s->b_field_mv_table[1], s->b_field_select_table[1], s->b_code, s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1]); }else fimin= bimin= INT_MAX; { int score= fmin; type = CANDIDATE_MB_TYPE_FORWARD; if (dmin <= score){ score = dmin; type = CANDIDATE_MB_TYPE_DIRECT; } if(bmin<score){ score=bmin; type= CANDIDATE_MB_TYPE_BACKWARD; } if(fbmin<score){ score=fbmin; type= CANDIDATE_MB_TYPE_BIDIR; } if(fimin<score){ score=fimin; type= CANDIDATE_MB_TYPE_FORWARD_I; } if(bimin<score){ score=bimin; type= CANDIDATE_MB_TYPE_BACKWARD_I; } score= ((unsigned)(score*score + 128*256))>>16; s->mc_mb_var_sum_temp += 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= CANDIDATE_MB_TYPE_FORWARD | CANDIDATE_MB_TYPE_BACKWARD | CANDIDATE_MB_TYPE_BIDIR | CANDIDATE_MB_TYPE_DIRECT; if(fimin < INT_MAX) type |= CANDIDATE_MB_TYPE_FORWARD_I; if(bimin < INT_MAX) type |= CANDIDATE_MB_TYPE_BACKWARD_I; if(fimin < INT_MAX && bimin < INT_MAX){ type |= CANDIDATE_MB_TYPE_BIDIR_I; } //FIXME something smarter if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT; //dont try direct mode if its invalid for this MB#if 0 if(s->out_format == FMT_MPEG1) type |= CANDIDATE_MB_TYPE_INTRA;#endif } 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; //printf("%d no:%d %d//\n", clip, noclip, f_code); if(s->flags&CODEC_FLAG_4MV){ const int wrap= s->b8_stride; /* clip / convert to intra 8x8 type MVs */ for(y=0; y<s->mb_height; y++){ int xy= y*2*wrap; int i= y*s->mb_stride; int x; for(x=0; x<s->mb_width; x++){ if(s->mb_type[i]&CANDIDATE_MB_TYPE_INTER4V){ int block; for(block=0; block<4; block++){ int off= (block& 1) + (block>>1)*wrap; int mx= s->current_picture.motion_val[0][ xy + off ][0]; int my= s->current_picture.motion_val[0][ xy + off ][1]; if( mx >=range || mx <-range || my >=range || my <-range){ s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V; s->mb_type[i] |= CANDIDATE_MB_TYPE_INTRA; s->current_picture.mb_type[i]= CANDIDATE_MB_TYPE_INTRA; } } } x
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -