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[6][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); switch(s->me_method) { case ME_ZERO: default: no_motion_search(s, &mx, &my); dmin = 0; break; case ME_FULL: dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture); break; case ME_LOG: dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture); break; case ME_PHODS: dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture); break; case ME_X1: case ME_EPZS: { const int mot_stride = s->block_wrap[0]; const int mot_xy = s->block_index[0]; rel_xmin= xmin - mb_x*16; rel_xmax= xmax - mb_x*16; rel_ymin= ymin - mb_y*16; rel_ymax= ymax - mb_y*16; P[0][0] = s->motion_val[mot_xy ][0]; P[0][1] = s->motion_val[mot_xy ][1]; P[1][0] = s->motion_val[mot_xy - 1][0]; P[1][1] = s->motion_val[mot_xy - 1][1]; if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift); /* special case for first line */ if ((mb_y == 0 || s->first_slice_line || s->first_gob_line)) { P[4][0] = P[1][0]; P[4][1] = P[1][1]; } else { P[2][0] = s->motion_val[mot_xy - mot_stride ][0]; P[2][1] = s->motion_val[mot_xy - mot_stride ][1]; P[3][0] = s->motion_val[mot_xy - mot_stride + 2 ][0]; P[3][1] = s->motion_val[mot_xy - mot_stride + 2 ][1]; if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift); if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift); if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift); P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]); P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]); } if(s->out_format == FMT_H263){ pred_x = P[4][0]; pred_y = P[4][1]; }else { /* mpeg1 at least */ pred_x= P[1][0]; pred_y= P[1][1]; } } dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, ref_picture); mx+= mb_x*16; my+= mb_y*16; break; } if(s->flags&CODEC_FLAG_4MV){ int block; mb_type|= MB_TYPE_INTER4V; 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= mb_x*2 + (block&1); const int block_y= mb_y*2 + (block>>1); 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; P[0][0] = s->motion_val[mot_xy ][0]; P[0][1] = s->motion_val[mot_xy ][1]; P[1][0] = s->motion_val[mot_xy - 1][0]; P[1][1] = s->motion_val[mot_xy - 1][1]; if(P[1][0] > (rel_xmax4<<shift)) P[1][0]= (rel_xmax4<<shift); /* special case for first line */ if ((mb_y == 0 || s->first_slice_line || s->first_gob_line) && block<2) { P[4][0] = P[1][0]; P[4][1] = P[1][1]; } else { P[2][0] = s->motion_val[mot_xy - mot_stride ][0]; P[2][1] = s->motion_val[mot_xy - mot_stride ][1]; P[3][0] = s->motion_val[mot_xy - mot_stride + off[block]][0]; P[3][1] = s->motion_val[mot_xy - mot_stride + off[block]][1]; if(P[2][1] > (rel_ymax4<<shift)) P[2][1]= (rel_ymax4<<shift); if(P[3][0] < (rel_xmin4<<shift)) P[3][0]= (rel_xmin4<<shift); if(P[3][0] > (rel_xmax4<<shift)) P[3][0]= (rel_xmax4<<shift); if(P[3][1] > (rel_ymax4<<shift)) P[3][1]= (rel_ymax4<<shift); P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]); P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]); } if(s->out_format == FMT_H263){ pred_x4 = P[4][0]; pred_y4 = P[4][1]; }else { /* mpeg1 at least */ pred_x4= P[1][0]; pred_y4= P[1][1]; } P[5][0]= mx - mb_x*16; P[5][1]= my - mb_y*16; dmin4 = epzs_motion_search4(s, block, &mx4, &my4, P, pred_x4, pred_y4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, ref_picture); halfpel_motion_search4(s, &mx4, &my4, dmin4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, pred_x4, pred_y4, block_x, block_y, ref_picture); s->motion_val[ s->block_index[block] ][0]= mx4; s->motion_val[ s->block_index[block] ][1]= my4; } } /* 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 absolute displacement */ ppix = ref_picture + (my * s->linesize) + mx; sum = pix_sum(pix, s->linesize); #if 0 varc = pix_dev(pix, s->linesize, (sum+128)>>8) + INTER_BIAS; vard = pix_abs16x16(pix, ppix, s->linesize); #else sum= (sum+8)>>4; varc = ((pix_norm1(pix, s->linesize) - sum*sum + 128 + 500)>>8); vard = (pix_norm(pix, ppix, s->linesize)+128)>>8; #endif s->mb_var[s->mb_width * mb_y + mb_x] = varc; s->avg_mb_var+= varc; s->mc_mb_var += vard; #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*2 + 200 > varc) mb_type|= MB_TYPE_INTRA; if (varc*2 + 200 > vard){ mb_type|= MB_TYPE_INTER; halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y, ref_picture); }else{ mx = mx*2 - mb_x*32; my = my*2 - mb_y*32; } }else{ if (vard <= 64 || vard < varc) { mb_type|= MB_TYPE_INTER; if (s->me_method != ME_ZERO) { halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y, ref_picture); } else { mx -= 16 * mb_x; my -= 16 * mb_y; } #if 0 if (vard < 10) { skip++; fprintf(stderr,"\nEarly skip: %d vard: %2d varc: %5d dmin: %d", skip, vard, varc, dmin); } #endif }else{ mb_type|= MB_TYPE_INTRA; mx = 0;//mx*2 - 32 * mb_x; my = 0;//my*2 - 32 * mb_y; } } s->mb_type[mb_y*s->mb_width + mb_x]= mb_type; set_p_mv_tables(s, mx, my); }