mot_est_mb.c
来自「实现在linux下的mpeg4编解码」· C语言 代码 · 共 846 行 · 第 1/2 页
C
846 行
y_curr+y+rel_ori_y), act_block, (vop_width/*+2*edge*/), sad_min); if (sad<sad_min) { sad_min=sad; mv_x=x; mv_y=y; } else if (sad==sad_min) if((ABS(x)+ABS(y)) < (ABS(mv_x)+ABS(mv_y))) { sad_min=sad; mv_x=x; mv_y=y; } } /*for*/ #else /* PIH (NTU) Fast ME 08/08/99 */ sad = SAD_Macroblock(prev+INDEX_BIG(x_curr+rel_ori_x, y_curr+rel_ori_y), act_block, (vop_width/*+2*edge*/), MV_MAX_ERROR) - (128 + 1); if (sad<sad_min) { sad_min=sad; mv_x = mv_y = 0; } do { check_pts=total_check_pts; do { check_pt_x = diamond[d_type].point[pt_nmbr].x + d_centre_x; check_pt_y = diamond[d_type].point[pt_nmbr].y + d_centre_y; /* Restrict the search to the searching window ; Note: This constraint can be removed */ if ( check_pt_x < int_mv_x_min || check_pt_x > int_mv_x_max || check_pt_y < int_mv_y_min || check_pt_y > int_mv_y_max) { sad = MV_MAX_ERROR; } else { sad=SAD_Macroblock(prev+INDEX_BIG(x_curr+check_pt_x+rel_ori_x, y_curr+check_pt_y+rel_ori_y), act_block, (vop_width/*+2*edge*/), sad_min); #ifdef _SAD_EXHAUS_ fprintf(stdout,"+o+ [%2d,%2d] sad16(%3d,%3d)=%4d\n",i,j,x,y,sad); #endif } if (sad<sad_min) { sad_min=sad; mv_x=check_pt_x; mv_y=check_pt_y; mot_dirn=pt_nmbr; } else if (sad==sad_min) if((ABS(check_pt_x)+ABS(check_pt_y)) < (ABS(mv_x)+ABS(mv_y))) { sad_min=sad; mv_x=check_pt_x; mv_y=check_pt_y; mot_dirn=pt_nmbr; } pt_nmbr+=1; if((pt_nmbr)>= 8) pt_nmbr-=8; check_pts-=1; } while(check_pts>0); if( d_type == 0) { stop_flag = 1; } else { if( (mv_x == d_centre_x) && (mv_y == d_centre_y) ) { d_type=0; pt_nmbr=0; total_check_pts = 4; } else { if((mv_x==d_centre_x) ||(mv_y==d_centre_y)) total_check_pts=5; else total_check_pts=3; pt_nmbr=diamond[d_type].point[mot_dirn].start_nmbr; d_centre_x = mv_x; d_centre_y = mv_y; } } } while(stop_flag!=1); #endif flags[0]=flags[0] && (mv_x==int_mv_x_min); flags[1]=flags[1] && (mv_x==int_mv_x_max); flags[2]=flags[2] && (mv_y==int_mv_y_min); flags[3]=flags[3] && (mv_y==int_mv_y_max); } else { mv_x=mv_y=0; sad_min=MV_MAX_ERROR; } /* Store result */ out |=((mv_x==2000)||(mv_y==2000)); if(out) { mv_x=mv_y=0; sad_min=MV_MAX_ERROR; } pos16=2*j*2*mvm_width + 2*i; mv16_w[pos16]= mv_x; mv16_h[pos16]= mv_y; mv16_w[pos16+1]= mv_x; mv16_h[pos16+1]= mv_y; pos16+=2*mvm_width; mv16_w[pos16]= mv_x; mv16_h[pos16]= mv_y; mv16_w[pos16+1]= mv_x; mv16_h[pos16+1]= mv_y; min_error16 = sad_min; *min_error = min_error16; /* Compute 8x8 MVs */ if(enable_8x8_mv==1) { if(!out) { for (block=0;block<4;block++) { /* Obtain range */ if(block==0) { hb=vb=0; } else if (block==1) { hb=1;vb=0; } else if (block==2) { hb=0;vb=1; } else { hb=vb=1; } /* VM 2.*: restrict the search range based on the current 16x16 MV * inside a window around it */ pmv_x=mv16_w[pos16]; pmv_y=mv16_h[pos16]; /* UB 990215 added search range */ Obtain_Range(f_code, sr, MBM_INTER8, pmv_x, pmv_y, &mv_x_min, /*UB 990215 added quarter pel support */ &mv_x_max, &mv_y_min, &mv_y_max, 0 /*GetVopQuarterPel(curr_vop)*/); RangeInSearchArea(i,j, block+1, prev_x, prev_y, vop_width, vop_height, br_x, br_y, edge,f_code, /*UB 990215 added quarter pel support */ &mv_x_min, &mv_x_max, &mv_y_min,&mv_y_max,&out); if(!out) { int_mv_x_min=(int)ceil((double)mv_x_min); int_mv_y_min=(int)ceil((double)mv_y_min); int_mv_x_max=(int)floor((double)mv_x_max); int_mv_y_max=(int)floor((double)mv_y_max); flags[4+block*4]=ARE_EQUAL(int_mv_x_min,mv_x_min); flags[4+block*4+1]=ARE_EQUAL(int_mv_x_max,mv_x_max); flags[4+block*4+2]=ARE_EQUAL(int_mv_y_min,mv_y_min); flags[4+block*4+3]=ARE_EQUAL(int_mv_y_max,mv_y_max); sad_min=MV_MAX_ERROR; mv_x = mv_y = 2000; /* A very large MV */ for (y=int_mv_y_min; y<=int_mv_y_max; y++) for (x=int_mv_x_min; x<=int_mv_x_max; x++) { sad=SAD_Block(prev+ INDEX_BIG(x_curr + x + 8*(block==1||block==3)+rel_ori_x, y_curr + y + 8*(block==2||block==3)+rel_ori_y), act_block+INDEX_NOR(8*(block==1||block==3), 8*(block==2||block==3)), (vop_width /*+2*edge*/), sad_min); if (sad<sad_min) { sad_min=sad; mv_x=x; mv_y=y; } else if (sad==sad_min) if((ABS(x)+ABS(y)) < (ABS(mv_x)+ABS(mv_y))) { sad_min=sad; mv_x=x; mv_y=y; } } /*for*/ flags[4+block*4] = flags[4+block*4] && (mv_x==int_mv_x_min); flags[4+block*4+1] = flags[4+block*4+1] && (mv_x==int_mv_x_max); flags[4+block*4+2] = flags[4+block*4+2] && (mv_y==int_mv_y_min); flags[4+block*4+3] = flags[4+block*4+3] && (mv_y==int_mv_y_max); } else { mv_x=mv_y=0; sad_min=MV_MAX_ERROR; /* punish the OUTER blocks with MV_MAX_ERROR in order to be INTRA CODED */ } /* Store result */ if(block==0) { pos8=2*j*2*mvm_width + 2*i; min_error8 += sad_min; } else if (block==1) { pos8=2*j*2*mvm_width + 2*i+1; min_error8 += sad_min; } else if (block==2) { pos8=(2*j+1)*2*mvm_width + 2*i; min_error8 += sad_min; } else { pos8=(2*j+1)*2*mvm_width + 2*i+1; min_error8 += sad_min; } /* Store result: absolute coordinates (note that in restricted mode pmv is (0,0)) */ mv8_w[pos8]=mv_x; mv8_h[pos8]=mv_y; } /*for block*/ if (min_error8 < *min_error) *min_error = min_error8; } else { /* all the four blocks are out */ pos8=2*j*2*mvm_width + 2*i; mv8_w[pos8]=mv8_h[pos8]=0.0; pos8=2*j*2*mvm_width + 2*i+1; mv8_w[pos8]=mv8_h[pos8]=0.0; pos8=(2*j+1)*2*mvm_width + 2*i; mv8_w[pos8]=mv8_h[pos8]=0.0; pos8=(2*j+1)*2*mvm_width + 2*i+1;mv8_w[pos8]=mv8_h[pos8]=0.0; min_error8 = MV_MAX_ERROR; } } /* enable_8x8_mv*/}/***********************************************************CommentBegin****** * * -- FindSubPel -- Computes MV with half-pixel accurary * * Purpose : * Computes MV with sub-pixel accurary for a 16x16 or 8x8 block * * Description : * 1) The preference for the 16x16 null motion vector must be applied * again (now, the SAD is recomputed for the recontructed interpolated * reference) * ***********************************************************CommentEnd********/VoidFindSubPel(Int x, /* <-- horizontal block coordinate in pixels */Int y, /* <-- vertical blocl coordinate in pixels */SInt *prev, /* <-- interpolated reference vop */SInt *curr, /* <-- current block */ Int bs_x, /* <-- hor. block size (8/16) */Int bs_y, /* <-- vert. block size (8/16) */Int comp, /* <-- block position in MB (0,1,2,3) */Int rel_x, /* <-- relative horiz. position between curr & prev vops*/Int rel_y, /* <-- relative verti. position between curr & prev vops*/Int pels, /* <-- vop width */Int lines, /* <-- vop height */Int edge, /* <-- edge */SInt *flags, /* <-- flags */SInt *curr_comp_mb, /* <-> motion compensated current mb */Float *mvx, /* <-> horizontal motion vector */Float *mvy, /* <-> vertical motion vector */Int *min_error /* --> prediction error */){ static PixPoint search[9] = { {0, 0}, {-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1} }; /* searching map 1 2 3 4 0 5 6 7 8 */ Int i, m, n; Int new_x, new_y, lx, size_x; /* MW QPEL 07-JUL-1998 */ Int min_pos; Int AE, AE_min; Int flag_pos; SInt *pRef, *pComp; int flag_search[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; Int SubDimension = 2; lx = 2*(pels /*+ 2*edge*/); new_x = (Int)((x + *mvx + rel_x)*(SubDimension)); new_y = (Int)((y + *mvy + rel_y)*(SubDimension)); new_x += ((comp&1)<<3)*SubDimension; new_y += ((comp&2)<<2)*SubDimension; size_x=16; /** in 1-pixel search we check if we are inside the range; so don't check it again **/ /* avoids trying outside the reference image */ /* we also check with flags if we are inside */ /* search range (1==don't make 1/x search by */ /* this side */ if (bs_x==8) flag_pos=4+comp*4; else /* ==16*/ flag_pos=0; if (((new_x/SubDimension) <= 0/*-edge*/) || *(flags+flag_pos)) { flag_search[1] = flag_search[4] = flag_search[6] = 0; } else if (((new_x/SubDimension) >= (pels - bs_x /*+ edge*/)) || *(flags+flag_pos+1)) { flag_search[3] = flag_search[5] = flag_search[8] = 0; }; if (((new_y/SubDimension) <= 0/*-edge*/) || *(flags+flag_pos+2)) { flag_search[1] = flag_search[2] = flag_search[3] = 0; } else if (((new_y/SubDimension) >= (lines- bs_y /*+ edge*/)) || *(flags+flag_pos+3)) { flag_search[6] = flag_search[7] = flag_search[8] = 0; }; AE_min = MV_MAX_ERROR; min_pos = 0; for (i = 0; i < 9; i++) { if (flag_search[i]) { AE = 0; /* estimate on the already interpolated half-pel image */ pRef = prev + new_x + search[i].x + (new_y + search[i].y) * lx; pComp = curr; n = bs_y; while (n--) { m = bs_x; while (m--) { AE += abs((Int)*pRef - (Int)*pComp); pRef += 2; pComp ++; } pRef += 2 * lx - 2 * bs_x; pComp += size_x - bs_x; } if (i==0 && bs_y==16 && *mvx==0 && *mvy==0) AE -= (128 + 1); if (AE < AE_min) { AE_min = AE; min_pos = i; } } /* else don't look outside the reference */ } /* Store optimal values */ *min_error = AE_min; *mvx += ((Float)search[min_pos].x)/(Float)(SubDimension); *mvy += ((Float)search[min_pos].y)/(Float)(SubDimension); // generate comp mb data for the minimum point pRef = prev + new_x + search[min_pos].x + (new_y + search[min_pos].y) * lx; pComp = curr_comp_mb; n = bs_y; while (n--) { m = bs_x; while (m--) { *(pComp ++) = *pRef; pRef += 2; } pRef += 2 * lx - 2 * bs_x; pComp += 16 - bs_x; } return;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?