📄 motion_est.c
字号:
}else{ if(l<=r){ if(t+l<=b+r){ CHECK_HALF_MV(xy2, -1, -1) ptr+= s->linesize; }else{ ptr+= s->linesize; CHECK_HALF_MV(xy2, +1, +1) } CHECK_HALF_MV(x2 , -1, 0) CHECK_HALF_MV(xy2, -1, +1) }else{ if(t+r<=b+l){ CHECK_HALF_MV(xy2, +1, -1) ptr+= s->linesize; }else{ ptr+= s->linesize; CHECK_HALF_MV(xy2, -1, +1) } CHECK_HALF_MV(x2 , +1, 0) CHECK_HALF_MV(xy2, +1, +1) } CHECK_HALF_MV(y2 , 0, +1) } mx+=dx; my+=dy; }else{ mx<<=1; my<<=1; } *mx_ptr = mx; *my_ptr = my; return dminh;}static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my, int mv4){ const int xy= s->mb_x + 1 + (s->mb_y + 1)*(s->mb_width + 2); s->p_mv_table[xy][0] = mx; s->p_mv_table[xy][1] = my; /* has allready been set to the 4 MV if 4MV is done */ if(mv4){ int mot_xy= s->block_index[0]; s->motion_val[mot_xy ][0]= mx; s->motion_val[mot_xy ][1]= my; s->motion_val[mot_xy+1][0]= mx; s->motion_val[mot_xy+1][1]= my; mot_xy += s->block_wrap[0]; s->motion_val[mot_xy ][0]= mx; s->motion_val[mot_xy ][1]= my; s->motion_val[mot_xy+1][0]= mx; s->motion_val[mot_xy+1][1]= my; }}static inline void get_limits(MpegEncContext *s, int *range, int *xmin, int *ymin, int *xmax, int *ymax, int f_code){ *range = 8 * (1 << (f_code - 1)); /* XXX: temporary kludge to avoid overflow for msmpeg4 */ if (s->out_format == FMT_H263 && !s->h263_msmpeg4) *range *= 2; if (s->unrestricted_mv) { *xmin = -16; *ymin = -16; if (s->h263_plus) *range *= 2; if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){ *xmax = s->mb_width*16; *ymax = s->mb_height*16; }else { /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise (cuz the drawn edge isnt large enough))*/ *xmax = s->width; *ymax = s->height; } } else { *xmin = 0; *ymin = 0; *xmax = s->mb_width*16 - 16; *ymax = s->mb_height*16 - 16; }}static inline int mv4_search(MpegEncContext *s, int xmin, int ymin, int xmax, int ymax, int mx, int my, int shift){ int block; int P[10][2]; uint8_t *ref_picture= s->last_picture[0]; int dmin_sum=0; for(block=0; block<4; block++){ int mx4, my4; int pred_x4, pred_y4; int dmin4; static const int off[4]= {2, 1, 1, -1}; const int mot_stride = s->block_wrap[0]; const int mot_xy = s->block_index[block];// const int block_x= (block&1);// const int block_y= (block>>1);#if 1 // this saves us a bit of cliping work and shouldnt affect compression in a negative way const int rel_xmin4= xmin; const int rel_xmax4= xmax; const int rel_ymin4= ymin; const int rel_ymax4= ymax;#else const int rel_xmin4= xmin - block_x*8; const int rel_xmax4= xmax - block_x*8 + 8; const int rel_ymin4= ymin - block_y*8; const int rel_ymax4= ymax - block_y*8 + 8;#endif P_LAST[0] = s->motion_val[mot_xy ][0]; P_LAST[1] = s->motion_val[mot_xy ][1]; P_LEFT[0] = s->motion_val[mot_xy - 1][0]; P_LEFT[1] = s->motion_val[mot_xy - 1][1]; P_LAST_RIGHT[0] = s->motion_val[mot_xy + 1][0]; P_LAST_RIGHT[1] = s->motion_val[mot_xy + 1][1]; P_LAST_BOTTOM[0]= s->motion_val[mot_xy + 1*mot_stride][0]; P_LAST_BOTTOM[1]= s->motion_val[mot_xy + 1*mot_stride][1]; if(P_LEFT[0] > (rel_xmax4<<shift)) P_LEFT[0] = (rel_xmax4<<shift); if(P_LAST_RIGHT[0] < (rel_xmin4<<shift)) P_LAST_RIGHT[0] = (rel_xmin4<<shift); if(P_LAST_BOTTOM[1]< (rel_ymin4<<shift)) P_LAST_BOTTOM[1]= (rel_ymin4<<shift); /* special case for first line */ if ((s->mb_y == 0 || s->first_slice_line) && block<2) { pred_x4= P_LEFT[0]; pred_y4= P_LEFT[1]; } else { P_TOP[0] = s->motion_val[mot_xy - mot_stride ][0]; P_TOP[1] = s->motion_val[mot_xy - mot_stride ][1]; P_TOPRIGHT[0] = s->motion_val[mot_xy - mot_stride + off[block]][0]; P_TOPRIGHT[1] = s->motion_val[mot_xy - mot_stride + off[block]][1]; if(P_TOP[1] > (rel_ymax4<<shift)) P_TOP[1] = (rel_ymax4<<shift); if(P_TOPRIGHT[0] < (rel_xmin4<<shift)) P_TOPRIGHT[0]= (rel_xmin4<<shift); if(P_TOPRIGHT[0] > (rel_xmax4<<shift)) P_TOPRIGHT[0]= (rel_xmax4<<shift); if(P_TOPRIGHT[1] > (rel_ymax4<<shift)) P_TOPRIGHT[1]= (rel_ymax4<<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]); if(s->out_format == FMT_H263){ pred_x4 = P_MEDIAN[0]; pred_y4 = P_MEDIAN[1]; }else { /* mpeg1 at least */ pred_x4= P_LEFT[0]; pred_y4= P_LEFT[1]; } } P_MV1[0]= mx; P_MV1[1]= my; dmin4 = epzs_motion_search4(s, block, &mx4, &my4, P, pred_x4, pred_y4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, ref_picture); dmin4= fast_halfpel_motion_search(s, &mx4, &my4, dmin4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, pred_x4, pred_y4, ref_picture, s->dsp.pix_abs8x8_x2, s->dsp.pix_abs8x8_y2, s->dsp.pix_abs8x8_xy2, block); s->motion_val[ s->block_index[block] ][0]= mx4; s->motion_val[ s->block_index[block] ][1]= my4; dmin_sum+= dmin4; } return dmin_sum;}void ff_estimate_p_frame_motion(MpegEncContext * s, int mb_x, int mb_y){ UINT8 *pix, *ppix; int sum, varc, vard, mx, my, range, dmin, xx, yy; int xmin, ymin, xmax, ymax; int rel_xmin, rel_ymin, rel_xmax, rel_ymax; int pred_x=0, pred_y=0; int P[10][2]; const int shift= 1+s->quarter_sample; int mb_type=0; uint8_t *ref_picture= s->last_picture[0]; get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, s->f_code); rel_xmin= xmin - mb_x*16; rel_xmax= xmax - mb_x*16; rel_ymin= ymin - mb_y*16; rel_ymax= ymax - mb_y*16; s->skip_me=0; switch(s->me_method) { case ME_ZERO: default: no_motion_search(s, &mx, &my); mx-= mb_x*16; my-= mb_y*16; dmin = 0; break; case ME_FULL: dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture); mx-= mb_x*16; my-= mb_y*16; break; case ME_LOG: dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture); mx-= mb_x*16; my-= mb_y*16; break; case ME_PHODS: dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture); mx-= mb_x*16; my-= mb_y*16; break; case ME_X1: case ME_EPZS: { const int mot_stride = s->block_wrap[0]; const int mot_xy = s->block_index[0]; P_LAST[0] = s->motion_val[mot_xy ][0]; P_LAST[1] = s->motion_val[mot_xy ][1]; P_LEFT[0] = s->motion_val[mot_xy - 1][0]; P_LEFT[1] = s->motion_val[mot_xy - 1][1]; P_LAST_RIGHT[0] = s->motion_val[mot_xy + 2][0]; P_LAST_RIGHT[1] = s->motion_val[mot_xy + 2][1]; P_LAST_BOTTOM[0]= s->motion_val[mot_xy + 2*mot_stride][0]; P_LAST_BOTTOM[1]= s->motion_val[mot_xy + 2*mot_stride][1]; if(P_LEFT[0] > (rel_xmax<<shift)) P_LEFT[0] = (rel_xmax<<shift); if(P_LAST_RIGHT[0] < (rel_xmin<<shift)) P_LAST_RIGHT[0] = (rel_xmin<<shift); if(P_LAST_BOTTOM[1]< (rel_ymin<<shift)) P_LAST_BOTTOM[1]= (rel_ymin<<shift); /* special case for first line */ if ((mb_y == 0 || s->first_slice_line)) { pred_x= P_LEFT[0]; pred_y= P_LEFT[1]; } else { P_TOP[0] = s->motion_val[mot_xy - mot_stride ][0]; P_TOP[1] = s->motion_val[mot_xy - mot_stride ][1]; P_TOPRIGHT[0] = s->motion_val[mot_xy - mot_stride + 2][0]; P_TOPRIGHT[1] = s->motion_val[mot_xy - mot_stride + 2][1]; if(P_TOP[1] > (rel_ymax<<shift)) P_TOP[1] = (rel_ymax<<shift); 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]); if(s->out_format == FMT_H263){ pred_x = P_MEDIAN[0]; pred_y = P_MEDIAN[1]; }else { /* mpeg1 at least */ pred_x= P_LEFT[0]; pred_y= P_LEFT[1]; } } } dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, ref_picture); break; } /* intra / predictive decision */ xx = mb_x * 16; yy = mb_y * 16; pix = s->new_picture[0] + (yy * s->linesize) + xx; /* At this point (mx,my) are full-pell and the relative displacement */ ppix = ref_picture + ((yy+my) * s->linesize) + (xx+mx); sum = s->dsp.pix_sum(pix, s->linesize); varc = (s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)(sum*sum))>>8) + 500 + 128)>>8; // FIXME: MMX OPTIMIZE vard = (pix_norm(pix, ppix, s->linesize)+128)>>8;//printf("%d %d %d %X %X %X\n", s->mb_width, mb_x, mb_y,(int)s, (int)s->mb_var, (int)s->mc_mb_var); fflush(stdout); s->mb_var [s->mb_width * mb_y + mb_x] = varc; s->mc_mb_var[s->mb_width * mb_y + mb_x] = vard; s->mb_mean [s->mb_width * mb_y + mb_x] = (sum+128)>>8; s->mb_var_sum += varc; s->mc_mb_var_sum += vard;//printf("E%d %d %d %X %X %X\n", s->mb_width, mb_x, mb_y,(int)s, (int)s->mb_var, (int)s->mc_mb_var); fflush(stdout); #if 0 printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n", varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);#endif if(s->flags&CODEC_FLAG_HQ){ if (vard <= 64 || vard < varc) s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc); else s->scene_change_score+= 20; if (vard*2 + 200 > varc) mb_type|= MB_TYPE_INTRA; if (varc*2 + 200 > vard){ mb_type|= MB_TYPE_INTER; if(s->me_method >= ME_EPZS) fast_halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax, pred_x, pred_y, ref_picture, s->dsp.pix_abs16x16_x2, s->dsp.pix_abs16x16_y2, s->dsp.pix_abs16x16_xy2, 0); else halfpel_motion_search( s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax, pred_x, pred_y, ref_picture, s->dsp.pix_abs16x16_x2, s->dsp.pix_abs16x16_y2, s->dsp.pix_abs16x16_xy2, 0); }else{ mx <<=1; my <<=1; } if((s->flags&CODEC_FLAG_4MV) && !s->skip_me && varc>50 && vard>10){ mv4_search(s, rel_xmin, rel_ymin, rel_xmax, rel_ymax, mx, my, shift); mb_type|=MB_TYPE_INTER4V; set_p_mv_tables(s, mx, my, 0); }else set_p_mv_tables(s, mx, my, 1); }else{ if (vard <= 64 || vard < varc) { s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc); mb_type|= MB_TYPE_INTER; if (s->me_method != ME_ZERO) { if(s->me_method >= ME_EPZS) dmin= fast_halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax, pred_x, pred_y, ref_picture, s->dsp.pix_abs16x16_x2, s->dsp.pix_abs16x16_y2, s->dsp.pix_abs16x16_xy2, 0); else dmin= halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax, pred_x, pred_y, ref_picture, s->dsp.pix_abs16x16_x2, s->dsp.pix_abs16x16_y2, s->dsp.pix_abs16x16_xy2, 0); if((s->flags&CODEC_FLAG_4MV) && !s->skip_me && varc>50 && vard>10){ int dmin4= mv4_search(s, rel_xmin, rel_ymin, rel_xmax, rel_ymax, mx, my, shift); if(dmin4 + 128 <dmin) mb_type= MB_TYPE_INTER4V; } set_p_mv_tables(s, mx, my, mb_type!=MB_TYPE_INTER4V); } else { mx <<=1; my <<=1; }#if 0 if (vard < 10) { skip++; fprintf(stderr,"\nEarly skip: %d vard: %2d varc: %5d dmin: %d", skip, vard, varc, dmin); }#endif }else{ s->scene_change_score+= 20; mb_type|= MB_TYPE_INTRA; mx = 0; my = 0; } } s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;}int ff_estimate_motion_b(MpegEncContext * s, int mb_x, int mb_y, int16_t (*mv_table)[2], uint8_t *ref_picture, int f_code){ int mx, my, range, dmin; int xmin, ymin, xmax, ymax; int rel_xmin, rel_ymin, rel_xmax, rel_ymax; int pred_x=0, pred_y=0; int P[10][2]; const int shift= 1+s->quarter_sample; const int mot_stride = s->mb_width + 2; const int mot_xy = (mb_y + 1)*mot_stride + mb_x + 1; get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, f_code); rel_xmin= xmin - mb_x*16; rel_xmax= xmax - mb_x*16; rel_ymin= ymin - mb_y*16; rel_ymax= ymax - mb_y*16; switch(s->me_method) { case ME_ZERO: default: no_motion_search(s, &mx, &my); dmin = 0; mx-= mb_x*16; my-= mb_y*16; break; case ME_FULL: dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture); mx-= mb_x*16; my-= mb_y*16; break; case ME_LOG: dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture); mx-= mb_x*16; my-= mb_y*16; break; case ME_PHODS: dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture); mx-= mb_x*16; my-= mb_y*16; break; case ME_X1: case ME_EPZS: { P_LAST[0] = mv_table[mot_xy ][0]; P_LAST[1] = mv_table[mot_xy ][1]; P_LEFT[0] = mv_table[mot_xy - 1][0]; P_LEFT[1] = mv_table[mot_xy - 1][1]; P_LAST_RIGHT[0] = mv_table[mot_xy + 1][0]; P_LAST_RIGHT[1] = mv_table[mot_xy + 1][1]; P_LAST_BOTTOM[0] = mv_table[mot_xy + mot_stride][0]; P_LAST_BOTTOM[1] = mv_table[mot_xy + mot_stride][1]; if(P_LEFT[0] > (rel_xmax<<shift)) P_LEFT[0] = (rel_xmax<<shift); if(P_LAST_RIGHT[0] < (rel_xmin<<shift)) P_LAST_RIGHT[0] = (rel_xmin<<shift); if(P_LAST_BOTTOM[1]< (rel_ymin<<shift)) P_LAST_BOTTOM[1]= (rel_ymin<<shift); /* special case for first line */ if ((mb_y == 0 || s->first_slice_line)) { } else { P_TOP[0] = mv_table[mot_xy - mot_stride ][0]; P_TOP[1] = mv_table[mot_xy - mot_stride ][1]; P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1 ][0]; P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1 ][1]; if(P_TOP[1] > (rel_ymax<<shift)) P_TOP[1]= (rel_ymax<<shift); 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]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -