📄 mv-search.c
字号:
/************************************************************************* COPYRIGHT AND WARRANTY INFORMATION** Copyright 2001, International Telecommunications Union, Geneva** DISCLAIMER OF WARRANTY** These software programs are available to the user without any* license fee or royalty on an "as is" basis. The ITU disclaims* any and all warranties, whether express, implied, or* statutory, including any implied warranties of merchantability* or of fitness for a particular purpose. In no event shall the* contributor or the ITU be liable for any incidental, punitive, or* consequential damages of any kind whatsoever arising from the* use of these programs.** This disclaimer of warranty extends to the user of these programs* and user's customers, employees, agents, transferees, successors,* and assigns.** The ITU does not represent or warrant that the programs furnished* hereunder are free of infringement of any third-party patents.* Commercial implementations of ITU-T Recommendations, including* shareware, may be subject to royalty fees to patent holders.* Information regarding the ITU-T patent policy is available from* the ITU Web site at http://www.itu.int.** THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE ITU-T PATENT POLICY.*************************************************************************//*! ************************************************************************************* * \file mv-search.c * * \brief * Motion Vector Search, unified for B and P Pictures * * \author * Main contributors (see contributors.h for copyright, address and affiliation details) * - Stephan Wenger <stewe@cs.tu-berlin.de> * - Inge Lille-Lang鴜 <inge.lille-langoy@telenor.com> * - Rickard Sjoberg <rickard.sjoberg@era.ericsson.se> * - Stephan Wenger <stewe@cs.tu-berlin.de> * - Jani Lainema <jani.lainema@nokia.com> * - Detlev Marpe <marpe@hhi.de> * - Thomas Wedi <wedi@tnt.uni-hannover.de> * - Heiko Schwarz <hschwarz@hhi.de> * ************************************************************************************* * \todo * 6. Unite the 1/2, 1/4 and1/8th pel search routines into a single routine \n * 7. Clean up parameters, use sensemaking variable names \n * 9. Implement fast leaky search, such as UBCs Diamond search * **************************************************************************************/#include "contributors.h"#include <math.h>#include <stdlib.h>#include <assert.h>#include "global.h"#include "mv-search.h"#include "refbuf.h"// Local function declarations__inline int ByteAbs (int foo);// These procedure pointers are used by motion_search() and one_eigthpel()static pel_t (*PelY_18) (pel_t**, int, int);static pel_t (*PelY_14) (pel_t**, int, int);static pel_t *(*PelYline_11) (pel_t *, int, int);//! The Spiral for spiral searchstatic int SpiralX[6561];static int SpiralY[6561];/*! The bit usage for MVs (currently lives in img-> mv_bituse and is used by b_frame.c, but should move one day to a more appropriate place */static int *MVBitUse;// Statistics, temporary/*! *********************************************************************** * \brief * MV Cost returns the initial penalty for the motion vector representation. * Used by the various MV search routines for MV RD optimization * * \param ParameterResolution * the resolution of the vector parameter, 1, 2, 4, 8, eg 4 means 1/4 pel * \param BitstreamResolution * the resolyution in which the bitstream is coded * \param ParameterResolution * TargetResolution * \param pred_x, pred_y * Predicted vector in BitstreamResolution * \param Candidate_x, Candidate_y * Candidate vector in Parameter Resolution *********************************************************************** */static int MVCost (int ParameterResolution, int BitstreamResolution, int Blocktype, int qp, int Pred_x, int Pred_y, int Candidate_x, int Candidate_y){ int Factor = BitstreamResolution/ParameterResolution; int Penalty; int len_x, len_y; len_x = Candidate_x * Factor - Pred_x; len_y = Candidate_y * Factor - Pred_y; Penalty = (QP2QUANT[qp] * ( MVBitUse[absm (len_x)]+MVBitUse[absm(len_y)]) ); if (img->type != B_IMG && Blocktype == 1 && Candidate_x == 0 && Candidate_y == 0) // 16x16 and no motion Penalty -= QP2QUANT [qp] * 16; return Penalty;}/*! *********************************************************************** * \brief * motion vector cost for rate-distortion optimization *********************************************************************** */static int MVCostLambda (int shift, double lambda, int pred_x, int pred_y, int cand_x, int cand_y){ return (int)(lambda * (MVBitUse[absm((cand_x << shift) - pred_x)] + MVBitUse[absm((cand_y << shift) - pred_y)] ));}/*! *********************************************************************** * \brief * setting the motion vector predictor *********************************************************************** */voidSetMotionVectorPredictor (int pred[2], int **refFrArr, int ***tmp_mv, int ref_frame, int mb_x, int mb_y, int blockshape_x, int blockshape_y){ int block_x = mb_x/BLOCK_SIZE; int block_y = mb_y/BLOCK_SIZE; int pic_block_x = img->block_x + block_x; int pic_block_y = img->block_y + block_y; int mb_nr = img->current_mb_nr; int mb_width = img->width/16; int mb_available_up = (img->mb_y == 0) ? 0 : (img->slice_numbers[mb_nr] == img->slice_numbers[mb_nr-mb_width]); int mb_available_left = (img->mb_x == 0) ? 0 : (img->slice_numbers[mb_nr] == img->slice_numbers[mb_nr-1]); int mb_available_upleft = (img->mb_x == 0 || img->mb_y == 0) ? 0 : (img->slice_numbers[mb_nr] == img->slice_numbers[mb_nr-mb_width-1]); int mb_available_upright = (img->mb_x >= mb_width-1 || img->mb_y == 0) ? 0 : (img->slice_numbers[mb_nr] == img->slice_numbers[mb_nr-mb_width+1]); int block_available_up, block_available_left, block_available_upright, block_available_upleft; int mv_a, mv_b, mv_c, mv_d, pred_vec=0; int mvPredType, rFrameL, rFrameU, rFrameUR; int hv; // D B C // A X // 1 A, B, D are set to 0 if unavailable // 2 If C is not available it is replaced by D block_available_up = mb_available_up || (mb_y > 0); block_available_left = mb_available_left || (mb_x > 0); if (mb_y > 0) block_available_upright = mb_x+blockshape_x != MB_BLOCK_SIZE ? 1 : 0; else if (mb_x+blockshape_x != MB_BLOCK_SIZE) block_available_upright = block_available_up; else block_available_upright = mb_available_upright; if (mb_x > 0) block_available_upleft = mb_y > 0 ? 1 : block_available_up; else if (mb_y > 0) block_available_upleft = block_available_left; else block_available_upleft = mb_available_upleft; mvPredType = MVPRED_MEDIAN; rFrameL = block_available_left ? refFrArr[pic_block_y][pic_block_x-1] : -1; rFrameU = block_available_up ? refFrArr[pic_block_y-1][pic_block_x] : -1; rFrameUR = block_available_upright ? refFrArr[pic_block_y-1][pic_block_x+blockshape_x/4] : block_available_upleft ? refFrArr[pic_block_y-1][pic_block_x-1] : -1; /* Prediction if only one of the neighbors uses the reference frame * we are checking */ if(rFrameL == ref_frame && rFrameU != ref_frame && rFrameUR != ref_frame) mvPredType = MVPRED_L; else if(rFrameL != ref_frame && rFrameU == ref_frame && rFrameUR != ref_frame) mvPredType = MVPRED_U; else if(rFrameL != ref_frame && rFrameU != ref_frame && rFrameUR == ref_frame) mvPredType = MVPRED_UR; // Directional predictions else if(blockshape_x == 8 && blockshape_y == 16) { if(mb_x == 0) { if(rFrameL == ref_frame) mvPredType = MVPRED_L; } else { if(rFrameUR == ref_frame) mvPredType = MVPRED_UR; } } else if(blockshape_x == 16 && blockshape_y == 8) { if(mb_y == 0) { if(rFrameU == ref_frame) mvPredType = MVPRED_U; } else { if(rFrameL == ref_frame) mvPredType = MVPRED_L; } } else if(blockshape_x == 8 && blockshape_y == 4 && mb_x == 8) mvPredType = MVPRED_L; else if(blockshape_x == 4 && blockshape_y == 8 && mb_y == 8) mvPredType = MVPRED_U; for (hv=0; hv < 2; hv++) { mv_a = block_available_left ? tmp_mv[hv][pic_block_y][pic_block_x-1+4] : 0; mv_b = block_available_up ? tmp_mv[hv][pic_block_y-1][pic_block_x+4] : 0; mv_d = block_available_upleft ? tmp_mv[hv][pic_block_y-1][pic_block_x-1+4] : 0; mv_c = block_available_upright ? tmp_mv[hv][pic_block_y-1][pic_block_x+blockshape_x/4+4] : mv_d; switch (mvPredType) { case MVPRED_MEDIAN: if(!(block_available_upleft || block_available_up || block_available_upright)) pred_vec = mv_a; else pred_vec = mv_a+mv_b+mv_c-min(mv_a,min(mv_b,mv_c))-max(mv_a,max(mv_b,mv_c)); break; case MVPRED_L: pred_vec = mv_a; break; case MVPRED_U: pred_vec = mv_b; break; case MVPRED_UR: pred_vec = mv_c; break; default: break; } pred[hv] = pred_vec; }}#ifdef _FAST_FULL_ME_/***** ***** static variables for fast integer motion estimation ***** */static int *search_setup_done; //!< flag if all block SAD's have been calculated yetstatic int *search_center_x; //!< absolute search center for fast full motion searchstatic int *search_center_y; //!< absolute search center for fast full motion searchstatic int *pos_00; //!< position of (0,0) vectorstatic int ****BlockSAD; //!< SAD for all blocksize, ref. frames and motion vectors/*! *********************************************************************** * \brief * function creating arrays for fast integer motion estimation *********************************************************************** */voidInitializeFastFullIntegerSearch (int search_range){ int i, j, k; int max_pos = (2*search_range+1) * (2*search_range+1); if ((BlockSAD = (int****)malloc ((img->buf_cycle+1) * sizeof(int***))) == NULL) no_mem_exit ("InitializeFastFullIntegerSearch: BlockSAD"); for (i = 0; i <= img->buf_cycle; i++) { if ((BlockSAD[i] = (int***)malloc (8 * sizeof(int**))) == NULL) no_mem_exit ("InitializeFastFullIntegerSearch: BlockSAD"); for (j = 1; j < 8; j++) { if ((BlockSAD[i][j] = (int**)malloc (16 * sizeof(int*))) == NULL) no_mem_exit ("InitializeFastFullIntegerSearch: BlockSAD"); for (k = 0; k < 16; k++) { if ((BlockSAD[i][j][k] = (int*)malloc (max_pos * sizeof(int))) == NULL) no_mem_exit ("InitializeFastFullIntegerSearch: BlockSAD"); } } } if ((search_setup_done = (int*)malloc ((img->buf_cycle+1)*sizeof(int)))==NULL) no_mem_exit ("InitializeFastFullIntegerSearch: search_setup_done"); if ((search_center_x = (int*)malloc ((img->buf_cycle+1)*sizeof(int)))==NULL) no_mem_exit ("InitializeFastFullIntegerSearch: search_center_x"); if ((search_center_y = (int*)malloc ((img->buf_cycle+1)*sizeof(int)))==NULL) no_mem_exit ("InitializeFastFullIntegerSearch: search_center_y"); if ((pos_00 = (int*)malloc ((img->buf_cycle+1)*sizeof(int)))==NULL) no_mem_exit ("InitializeFastFullIntegerSearch: pos_00");}/*! *********************************************************************** * \brief * function for deleting the arrays for fast integer motion estimation *********************************************************************** */voidClearFastFullIntegerSearch (){ int i, j, k; for (i = 0; i <= img->buf_cycle; i++) { for (j = 1; j < 8; j++) { for (k = 0; k < 16; k++) { free (BlockSAD[i][j][k]); } free (BlockSAD[i][j]); } free (BlockSAD[i]); } free (BlockSAD); free (search_setup_done); free (search_center_x); free (search_center_y); free (pos_00);}/*! *********************************************************************** * \brief * function resetting flags for fast integer motion estimation * (have to be called in start_macroblock()) *********************************************************************** */voidResetFastFullIntegerSearch (){ int i; for (i = 0; i <= img->buf_cycle; i++) search_setup_done [i] = 0;}/*! *********************************************************************** * \brief * calculation of SAD for larger blocks on the basis of 4x4 blocks *********************************************************************** */voidSetupLargerBlocks (int refindex, int max_pos){#define ADD_UP_BLOCKS() _o=*_bo; _i=*_bi; _j=*_bj; for(pos=0;pos<max_pos;pos++) *_o++ = *_i++ + *_j++;#define INCREMENT(inc) _bo+=inc; _bi+=inc; _bj+=inc; int pos, **_bo, **_bi, **_bj; register int *_o, *_i, *_j; //--- blocktype 6 --- _bo = BlockSAD[refindex][6]; _bi = BlockSAD[refindex][7]; _bj = _bi + 4; ADD_UP_BLOCKS(); INCREMENT(1); ADD_UP_BLOCKS(); INCREMENT(1); ADD_UP_BLOCKS(); INCREMENT(1); ADD_UP_BLOCKS(); INCREMENT(5); ADD_UP_BLOCKS(); INCREMENT(1); ADD_UP_BLOCKS(); INCREMENT(1); ADD_UP_BLOCKS(); INCREMENT(1); ADD_UP_BLOCKS(); //--- blocktype 5 --- _bo = BlockSAD[refindex][5]; _bi = BlockSAD[refindex][7]; _bj = _bi + 1; ADD_UP_BLOCKS(); INCREMENT(2); ADD_UP_BLOCKS(); INCREMENT(2); ADD_UP_BLOCKS(); INCREMENT(2); ADD_UP_BLOCKS(); INCREMENT(2); ADD_UP_BLOCKS(); INCREMENT(2); ADD_UP_BLOCKS(); INCREMENT(2); ADD_UP_BLOCKS(); INCREMENT(2); ADD_UP_BLOCKS(); //--- blocktype 4 --- _bo = BlockSAD[refindex][4]; _bi = BlockSAD[refindex][6]; _bj = _bi + 1; ADD_UP_BLOCKS(); INCREMENT(2); ADD_UP_BLOCKS(); INCREMENT(6); ADD_UP_BLOCKS(); INCREMENT(2); ADD_UP_BLOCKS(); //--- blocktype 3 ---
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -