📄 motion_est.c
字号:
P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]); } 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; } 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);//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 direct mode penalty UINT16 *mv_penalty= s->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; fbmin = (mv_penalty[motion_fx-pred_fx] + mv_penalty[motion_fy-pred_fy])*s->qscale; dxy = ((motion_fy & 1) << 1) | (motion_fx & 1); src_x = mb_x * 16 + (motion_fx >> 1); src_y = mb_y * 16 + (motion_fy >> 1); src_x = clip(src_x, -16, s->width); if (src_x == s->width) dxy&= 2; src_y = clip(src_y, -16, s->height); if (src_y == s->height) dxy&= 1; ptr = s->last_picture[0] + (src_y * s->linesize) + src_x; s->dsp.put_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16); fbmin += (mv_penalty[motion_bx-pred_bx] + mv_penalty[motion_by-pred_by])*s->qscale; dxy = ((motion_by & 1) << 1) | (motion_bx & 1); src_x = mb_x * 16 + (motion_bx >> 1); src_y = mb_y * 16 + (motion_by >> 1); src_x = clip(src_x, -16, s->width); if (src_x == s->width) dxy&= 2; src_y = clip(src_y, -16, s->height); if (src_y == s->height) dxy&= 1; ptr = s->next_picture[0] + (src_y * s->linesize) + src_x; s->dsp.avg_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16); fbmin += s->dsp.pix_abs16x16(s->new_picture[0] + mb_x*16 + mb_y*16*s->linesize, dest_y, s->linesize); 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_width + 2; const int xy = (mb_y + 1)*mot_stride + mb_x + 1; 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_width + 2; const int mot_xy = (mb_y + 1)*mot_stride + mb_x + 1; int dmin, dmin2; int motion_fx, motion_fy, motion_bx, motion_by, motion_bx0, motion_by0; int motion_dx, motion_dy; const int motion_px= s->p_mv_table[mot_xy][0]; const int motion_py= s->p_mv_table[mot_xy][1]; const int time_pp= s->pp_time; const int time_pb= s->pb_time; const int time_bp= time_pp - time_pb; int bx, by; int mx, my, mx2, my2; uint8_t *ref_picture= s->me_scratchpad - (mb_x - 1 + (mb_y - 1)*s->linesize)*16; int16_t (*mv_table)[2]= s->b_direct_mv_table;/* uint16_t *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; */ // f_code of the prev frame /* thanks to iso-mpeg the rounding is different for the zero vector, so we need to handle that ... */ motion_fx= (motion_px*time_pb)/time_pp; motion_fy= (motion_py*time_pb)/time_pp; motion_bx0= (-motion_px*time_bp)/time_pp; motion_by0= (-motion_py*time_bp)/time_pp; motion_dx= motion_dy=0; dmin2= check_bidir_mv(s, mb_x, mb_y, motion_fx, motion_fy, motion_bx0, motion_by0, motion_fx, motion_fy, motion_bx0, motion_by0) - s->qscale; motion_bx= motion_fx - motion_px; motion_by= motion_fy - motion_py; for(by=-1; by<2; by++){ for(bx=-1; bx<2; bx++){ uint8_t *dest_y = s->me_scratchpad + (by+1)*s->linesize*16 + (bx+1)*16; uint8_t *ptr; int dxy; int src_x, src_y; const int width= s->width; const int height= s->height; dxy = ((motion_fy & 1) << 1) | (motion_fx & 1); src_x = (mb_x + bx) * 16 + (motion_fx >> 1); src_y = (mb_y + by) * 16 + (motion_fy >> 1); src_x = clip(src_x, -16, width); if (src_x == width) dxy &= ~1; src_y = clip(src_y, -16, height); if (src_y == height) dxy &= ~2; ptr = s->last_picture[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 + bx) * 16 + (motion_bx >> 1); src_y = (mb_y + by) * 16 + (motion_by >> 1); src_x = clip(src_x, -16, width); if (src_x == width) dxy &= ~1; src_y = clip(src_y, -16, height); if (src_y == height) dxy &= ~2; s->dsp.avg_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16); } } 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]; 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]); } dmin = epzs_motion_search(s, &mx, &my, P, 0, 0, -16, -16, 15, 15, ref_picture); if(mx==0 && my==0) dmin=99999999; // not representable, due to rounding stuff if(dmin2<dmin){ dmin= dmin2; mx=0; my=0; }#if 1 mx2= mx= mx*2; my2= my= my*2; for(by=-1; by<2; by++){ if(my2+by < -32) continue; for(bx=-1; bx<2; bx++){ if(bx==0 && by==0) continue; if(mx2+bx < -32) continue; dmin2= check_bidir_mv(s, mb_x, mb_y, mx2+bx+motion_fx, my2+by+motion_fy, mx2+bx+motion_bx, my2+by+motion_by, mx2+bx+motion_fx, my2+by+motion_fy, motion_bx, motion_by) - s->qscale; if(dmin2<dmin){ dmin=dmin2; mx= mx2 + bx; my= my2 + by; } } }#else mx*=2; my*=2;#endif if(mx==0 && my==0){ motion_bx= motion_bx0; motion_by= motion_by0; } s->b_direct_mv_table[mot_xy][0]= mx; s->b_direct_mv_table[mot_xy][1]= my; s->b_direct_forw_mv_table[mot_xy][0]= motion_fx + mx; s->b_direct_forw_mv_table[mot_xy][1]= motion_fy + my; s->b_direct_back_mv_table[mot_xy][0]= motion_bx + mx; s->b_direct_back_mv_table[mot_xy][1]= motion_by + my; return dmin;}void ff_estimate_b_frame_motion(MpegEncContext * s, int mb_x, int mb_y){ const int quant= s->qscale; int fmin, bmin, dmin, fbmin; int type=0; dmin= direct_search(s, mb_x, mb_y); fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, s->last_picture[0], s->f_code); bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, s->next_picture[0], s->b_code) - quant;//printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]); fbmin= bidir_refine(s, mb_x, mb_y); { int score= dmin; type=MB_TYPE_DIRECT; if(fmin<score){ score=fmin; type= MB_TYPE_FORWARD; } 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->mc_mb_var_sum += score; s->mc_mb_var[mb_y*s->mb_width + mb_x] = score; //FIXME use SSD } if(s->flags&CODEC_FLAG_HQ){ type= MB_TYPE_FORWARD | MB_TYPE_BACKWARD | MB_TYPE_BIDIR | MB_TYPE_DIRECT; //FIXME something smarter }/*{static int count=0;static int sum=0;if(type==MB_TYPE_DIRECT){ int diff= ABS(s->b_forw_mv_table)}}*/ s->mb_type[mb_y*s->mb_width + mb_x]= type;/* if(mb_y==0 && mb_x==0) printf("\n"); if(mb_x==0) printf("\n"); printf("%d", av_log2(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 * 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); //FIXME *2 and all other too so its the same but nicer for(y=0; y<s->mb_height; y++){ int x; int xy= (y+1)* (s->mb_width+2) + 1; i= y*s->mb_width; for(x=0; x<s->mb_width; x++){ if(s->mb_type[i] & 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->mc_mb_var[i] < s->mb_var[i]) score[j]-= 170; } } i++; 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; UINT8 * fcode_tab= s->fcode_tab;//int clip=0;//int noclip=0; /* clip / convert to intra 16x16 type MVs */ for(y=0; y<s->mb_height; y++){ int x; int xy= (y+1)* (s->mb_width+2)+1; int i= y*s->mb_width; for(x=0; x<s->mb_width; x++){ if(s->mb_type[i]&MB_TYPE_INTER){ if( fcode_tab[s->p_mv_table[xy][0] + MAX_MV] > f_code || fcode_tab[s->p_mv_table[xy][0] + MAX_MV] == 0 || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] > f_code || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] == 0 ){ s->mb_type[i] &= ~MB_TYPE_INTER; s->mb_type[i] |= MB_TYPE_INTRA; s->p_mv_table[xy][0] = 0; s->p_mv_table[xy][1] = 0;//clip++; }//else// noclip++; } xy++; i++; } }//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_width; 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( fcode_tab[mx + MAX_MV] > f_code || fcode_tab[mx + MAX_MV] == 0 || fcode_tab[my + MAX_MV] > f_code || fcode_tab[my + MAX_MV] == 0 ){ 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; UINT8 * fcode_tab= s->fcode_tab; /* clip / convert to intra 16x16 type MVs */ for(y=0; y<s->mb_height; y++){ int x; int xy= (y+1)* (s->mb_width+2)+1; int i= y*s->mb_width; for(x=0; x<s->mb_width; x++){ if( fcode_tab[mv_table[xy][0] + MAX_MV] > f_code || fcode_tab[mv_table[xy][0] + MAX_MV] == 0){ if(mv_table[xy][0]>0) mv_table[xy][0]= (16<<f_code)-1; else mv_table[xy][0]= -(16<<f_code); } if( fcode_tab[mv_table[xy][1] + MAX_MV] > f_code || fcode_tab[mv_table[xy][1] + MAX_MV] == 0){ if(mv_table[xy][1]>0) mv_table[xy][1]= (16<<f_code)-1; else mv_table[xy][1]= -(16<<f_code); } xy++; i++; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -