mot_est_mb.c
来自「实现在linux下的mpeg4编解码」· C语言 代码 · 共 846 行 · 第 1/2 页
C
846 行
/************************************************************************** * * * This code is developed by Adam Li. This software is an * * implementation of a part of one or more MPEG-4 Video tools as * * specified in ISO/IEC 14496-2 standard. Those intending to use this * * software module in hardware or software products are advised that its * * use may infringe existing patents or copyrights, and any such use * * would be at such party's own risk. The original developer of this * * software module and his/her company, and subsequent editors and their * * companies (including Project Mayo), will have no liability for use of * * this software or modifications or derivatives thereof. * * * * Project Mayo gives users of the Codec a license to this software * * module or modifications thereof for use in hardware or software * * products claiming conformance to the MPEG-4 Video Standard as * * described in the Open DivX license. * * * * The complete Open DivX license can be found at * * http://www.projectmayo.com/opendivx/license.php . * * * **************************************************************************//************************************************************************** * * mot_est_mb.c * * Copyright (C) 2001 Project Mayo * * Adam Li * * DivX Advance Research Center <darc@projectmayo.com> * **************************************************************************//* This file contains some functions to do motion estimation and *//* for one MacroBlock in one pass. *//* Some codes of this project come from MoMuSys MPEG-4 implementation. *//* Please see seperate acknowledgement file for a list of contributors. */#include "mot_util.h"/* Obtaining if two floating point values are equal*/#define ABSDOUBLE(x) (((x) > 0.0001) ? (x) : (((x) < -0.0001) ? -(x): 0.0 ))#define ARE_EQUAL(x,y) ( (ABSDOUBLE((Float)(x)-(y))>0.1)?(0):(1) )/* auxiliar define for indexing in MBMotionEstimation */#define INDEX_BIG(x,y) ((x)+(y)*(vop_width))#define INDEX_NOR(x,y) ((x)+(y)*(MB_SIZE))/* ------------------------------------------------------------------------- *//***********************************************************CommentBegin****** * * -- RangeInSearchArea -- computes the range of the search area * * Purpose : * computes the range of the search area for the predicted MV's * INSIDE the overlapped zone between reference and current vops * ***********************************************************CommentEnd********/static VoidRangeInSearchArea(Int i, /* <-- horizontal MBcoordinate in pixels */Int j, /* <-- vertical MB coordinate in pixels */Int block, /* <-- block position (0 16x16; 1-2-3-4 8x8) */Int prev_x, /* <-- absolute horizontal position of the previous vop*/Int prev_y, /* <-- absolute vertical position of the previous vop */Int vop_width, /* <-- horizontal vop dimension */Int vop_height, /* <-- vertical vop dimension */Int br_x, /* <-- absolute horizontal position of the current vop */Int br_y, /* <-- absolute vertical position of the current vop */Int edge, /* <-- edge arround the reference vop */Int f_code, /* <- MV search range 1/2 (or 1/4) pel: (0=16,) 1=32,2=64,...,7=2048 */Float *mv_x_min, /* <-- min horizontal range */Float *mv_x_max, /* <-- max horizontal range */Float *mv_y_min, /* <-- min vertical range */Float *mv_y_max, /* <-- max vertical range */Int *out /* --> the search area does not exist (the reference */ /* and current BB does not overlap) */){ Int dim_curr_x_max, dim_curr_y_max, dim_curr_x_min, dim_curr_y_min; Int dim_prev_x_max, dim_prev_y_max, dim_prev_x_min, dim_prev_y_min; Int mb_b_size, block_x, block_y; *out=0; switch (block) { case 0: /* 8x8 or 16x16 block search */ block_x=0; /*****************************/ block_y=0; /** 1 2 ******** 0 *********/ mb_b_size=MB_SIZE; /** 3 4 ******** *********/ break; /*****************************/ case 1: block_x=0; block_y=0; mb_b_size=B_SIZE; break; case 2: block_x=B_SIZE; block_y=0; mb_b_size=B_SIZE; break; case 3: block_x=0; block_y=B_SIZE; mb_b_size=B_SIZE; break; case 4: block_x=B_SIZE; block_y=B_SIZE; mb_b_size=B_SIZE; break; default: return; } /* min x/y */ dim_curr_x_min=(Int)(br_x+i*MB_SIZE+*mv_x_min+block_x); dim_curr_y_min=(Int)(br_y+j*MB_SIZE+*mv_y_min+block_y); dim_prev_x_min=prev_x/*-edge*/; dim_prev_y_min=prev_y/*-edge*/; /* max x/y */ /*the MB right-pixels inside */ dim_curr_x_max=(Int)(br_x+i*MB_SIZE+*mv_x_max+mb_b_size+block_x); /*the MB bottom-pixels inside */ dim_curr_y_max=(Int)(br_y+j*MB_SIZE+*mv_y_max+mb_b_size+block_y); dim_prev_x_max=prev_x+vop_width /*+edge*/; dim_prev_y_max=prev_y+vop_height/*+edge*/; /* range x/y min */ if (dim_curr_x_min > dim_prev_x_max) { *out=1; } else if(dim_curr_x_min < dim_prev_x_min) { *mv_x_min = *mv_x_min + ( dim_prev_x_min - dim_curr_x_min ) ; } if(!(*out)) { if (dim_curr_y_min > dim_prev_y_max) { *out=1; } else if(dim_curr_y_min < dim_prev_y_min) { *mv_y_min = *mv_y_min + ( dim_prev_y_min - dim_curr_y_min ) ; } } /* range x/y max */ if(!(*out)) { if(dim_curr_x_max < dim_prev_x_min) { *out=1; } if ((!(*out))&&(dim_curr_x_max > dim_prev_x_max)) { *mv_x_max = *mv_x_max - ( dim_curr_x_max - dim_prev_x_max) ; } } if(!(*out)) { if(dim_curr_y_max < dim_prev_y_min) { *out=1; /* already set */ } if ((!(*out))&&(dim_curr_y_max > dim_prev_y_max)) { *mv_y_max = *mv_y_max - ( dim_curr_y_max - dim_prev_y_max) ; } } if(*mv_x_min>*mv_x_max) { *out=1; } if ( (!(*out)) && (*mv_y_min>*mv_y_max)) { *out=1; } return;}/***********************************************************CommentBegin****** * * -- Obtain_Range -- computes the range of the search area * * Purpose : * computes the range of the search area for the predicted MV's * (it can be outside the overlapped zone between the reference * and current vops) * * Return values : * 1 on success, 0 on error * ***********************************************************CommentEnd********/static IntObtain_Range(Int f_code, /* <-- MV search range 1/2 (or 1/4 pel): (0=16,) 1=32,2=64,...,7=2048 */Int sr, /* <-- Serach range (radius) */Int type, /* <-- MBM_INTER16==16x16 search; MBM_INTER8==8x8 search */Float pmv_x, /* <-- predicted horizontal motion vector */Float pmv_y, /* <-- predicted horizontal motion vector */Float *mv_x_min, /* --> min horizontal range */Float *mv_x_max, /* --> max horizontal range */Float *mv_y_min, /* --> min vertical range */Float *mv_y_max, /* --> max vertical range */Int quarter_pel /* <-- quarter pel flag (to allow f_code==0 without sprite) */){ Int error; Float aux_x_min, aux_y_min, aux_x_max, aux_y_max; Float range; error=0; if ((f_code==0) && (!quarter_pel)) /* for Low Latency Sprite */ { *mv_x_min=0; *mv_x_max=0; *mv_y_min=0; *mv_y_max=0; } else { range = sr; *mv_x_min=-range; *mv_x_max= range - 0.5f; *mv_y_min=-range; *mv_y_max= range - 0.5f; } if (type==MBM_INTER8) { aux_x_min=pmv_x - DEFAULT_8_WIN; aux_y_min=pmv_y - DEFAULT_8_WIN; aux_x_max=pmv_x + DEFAULT_8_WIN; aux_y_max=pmv_y + DEFAULT_8_WIN; if(*mv_x_min < aux_x_min) *mv_x_min = aux_x_min; if(*mv_y_min < aux_y_min) *mv_y_min = aux_y_min; if(*mv_x_max > aux_x_max) *mv_x_max = aux_x_max; if(*mv_y_max > aux_y_max) *mv_y_max = aux_y_max; } if (error==1) return(0); else return(1);}/***********************************************************CommentBegin****** * * -- MBMotionEstimation -- Computes INTEGER PRECISION MV's for a MB * * Purpose : * Computes INTEGER PRECISION MV's for a MB. Also returns * prediction errors. Requires the whole MVs data images to * obtain prediction for the current MV, which determines search * range * ***********************************************************CommentEnd********/VoidMBMotionEstimation(SInt *curr, /* <-- Current vop pointer */SInt *prev, /* <-- extended reference picture */Int br_x, /* <-- horizontal bounding rectangle coordinate */Int br_y, /* <-- vertical bounding rectangle coordinate */Int br_width, /* <-- bounding rectangule width */Int i, /* <-- horizontal MBcoordinate in pixels */Int j, /* <-- vertical MB coordinate in pixels */Int prev_x, /* <-- absolute horiz. position of previous vop */Int prev_y, /* <-- absolute verti. position of previous vop */Int vop_width, /* <-- horizontal vop dimension */Int vop_height, /* <-- vertical vop dimension */Int enable_8x8_mv, /* <-- 8x8 MV (=1) or only 16x16 MV (=0) */Int edge, /* <-- edge */Int f_code, /* <-- MV search range 1/2 (or 1/4) pel: (0=16,) 1=32,2=64,...,7=2048*/Int sr, /* <-- search range (corresponds to f_code) UB 990215*/Float hint_mv_w, /* <-- hint seed for horizontal MV */Float hint_mv_h, /* <-- hint seed for vertical MV */Float *mv16_w, /* --> predicted horizontal 16x16 MV(if approp.) */Float *mv16_h, /* --> predicted vertical 16x16 MV (if approp.) */Float *mv8_w, /* --> predicted horizontal 8x8 MV (if approp.) */Float *mv8_h, /* --> predicted vertical 8x8 MV (if approp.) */Int *min_error, /* --> Minimum prediction error */SInt *flags){ Int x, y; Int sad, sad_min=MV_MAX_ERROR; Int mv_x, mv_y; Int block; Float pmv_x, pmv_y; SInt act_block[MB_SIZE*MB_SIZE]; Float mv_x_min, mv_x_max, mv_y_min, mv_y_max; Int int_mv_x_min=0, int_mv_x_max=0, int_mv_y_min=0, int_mv_y_max=0; Int pos16, pos8; Int mvm_width = br_width/MB_SIZE; Int x_curr = i*MB_SIZE, y_curr = j*MB_SIZE; Int hb,vb; Int out; Int rel_ori_x; Int rel_ori_y; Int min_error16, min_error8 = 0;// SInt *curr = (SInt *)GetImageData(GetVopY(curr_vop)); #ifndef _FULL_SEARCH_ /* PIH (NTU) Fast ME 08/08/99 */ typedef struct { Int x; Int y; SInt start_nmbr; } DPoint; typedef struct { DPoint point[8]; } Diamond; SInt d_type=1,stop_flag=0,pt_nmbr=0,check_pts,total_check_pts=8,mot_dirn=0; Int d_centre_x=0,d_centre_y=0,check_pt_x,check_pt_y; Diamond diamond[2]= { { { {0,1,0}, {1,0,0}, {0,-1,0}, {-1,0,0} } } , { { {0,2,6}, {1,1,0}, {2,0,0}, {1,-1,2}, {0,-2,2}, {-1,-1,4}, {-2,0,4}, {-1,1,6} } } }; #endif d_centre_x = (int)hint_mv_w; d_centre_y = (int)hint_mv_h; rel_ori_x=br_x-prev_x; rel_ori_y=br_y-prev_y; /* Load act_block */ LoadArea(curr, x_curr,y_curr,MB_SIZE,MB_SIZE,br_width, act_block); /* Compute 16x16 integer MVs */ /* Obtain range */ Obtain_Range (f_code, sr, MBM_INTER16, /* UB 990215 added search range */ 0.0, 0.0, &mv_x_min, &mv_x_max, /*UB 990215 added quarter pel support */ &mv_y_min, &mv_y_max, 0/*GetVopQuarterPel(curr_vop)*/); RangeInSearchArea (i,j,0, prev_x, prev_y, vop_width, vop_height, br_x, br_y, edge,f_code, &mv_x_min, &mv_x_max, /*UB 990215 added quarter pel support */ &mv_y_min, &mv_y_max,&out); /* Compute */ 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[0]=ARE_EQUAL(int_mv_x_min,mv_x_min); flags[1]=ARE_EQUAL(int_mv_x_max,mv_x_max); flags[2]=ARE_EQUAL(int_mv_y_min,mv_y_min); flags[3]=ARE_EQUAL(int_mv_y_max,mv_y_max); sad_min=MV_MAX_ERROR; mv_x = mv_y = 2000; /* A very large MV */ #ifdef _FULL_SEARCH_ /* PIH (NTU) 08/08/99 */ for (y=int_mv_y_min; y<=int_mv_y_max; y++) for (x=int_mv_x_min; x<=int_mv_x_max; x++) { if (x==0 && y==0) 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); else sad=SAD_Macroblock(prev+INDEX_BIG(x_curr+x+rel_ori_x,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?