📄 me_epzs.c
字号:
/*!
*************************************************************************************
* \file me_epzs.c
*
* \brief
* Motion Estimation using EPZS
*
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
* - Alexis Michael Tourapis <alexismt@ieee.org>
* - Athanasios Leontaris <aleon@dolby.com>
*
*************************************************************************************
*/
#include "contributors.h"
#include <limits.h>
#include "global.h"
#include "image.h"
#include "memalloc.h"
#include "mb_access.h"
#include "refbuf.h"
#include "me_distortion.h"
#include "me_epzs.h"
#include "mv-search.h"
#define EPZSREF 1
// Define Global Parameters
static const short blk_parent[8] = {1, 1, 1, 1, 2, 4, 4, 5}; //!< {skip, 16x16, 16x8, 8x16, 8x8, 8x4, 4x8, 4x4}
//static const short blk_child[8] = {1, 2, 4, 4, 5, 7, 7, 7}; //!< {skip, 16x16, 16x8, 8x16, 8x8, 8x4, 4x8, 4x4}
static const int minthres_base[8] = {0, 64, 32, 32, 16, 8, 8, 4};
static const int medthres_base[8] = {0, 256, 128, 128, 64, 32, 32, 16};
static const int maxthres_base[8] = {0, 768, 384, 384, 192, 96, 96, 48};
static const short search_point_hp[10][2] = {{0,0},{-2,0}, {0,2}, {2,0}, {0,-2}, {-2,2}, {2,2}, {2,-2}, {-2,-2}, {-2,2}};
static const short search_point_qp[10][2] = {{0,0},{-1,0}, {0,1}, {1,0}, {0,-1}, {-1,1}, {1,1}, {1,-1}, {-1,-1}, {-1,1}};
//static const int next_subpel_pos_start[5][5] = {};
//static const int next_subpel_pos_end [5][5] = {};
static int (*computePred)(imgpel* , int , int , int , int , int );
static short EPZSBlkCount;
static int searcharray;
static int mv_rescale;
//! Define EPZS Refinement patterns
static int pattern_data[5][12][4] =
{
{ // Small Diamond pattern
{ 0, 4, 3, 3 }, { 4, 0, 0, 3 }, { 0, -4, 1, 3 }, { -4, 0, 2, 3 }
},
{ // Square pattern
{ 0, 4, 7, 3 }, { 4, 4, 7, 5 }, { 4, 0, 1, 3 }, { 4, -4, 1, 5 },
{ 0, -4, 3, 3 }, { -4, -4, 3, 5 }, { -4, 0, 5, 3 }, { -4, 4, 5, 5 }
},
{ // Enhanced Diamond pattern
{ -4, 4, 10, 5 }, { 0, 8, 10, 8 }, { 0, 4, 10, 7 }, { 4, 4, 1, 5 },
{ 8, 0, 1, 8 }, { 4, 0, 1, 7 }, { 4, -4, 4, 5 }, { 0, -8, 4, 8 },
{ 0, -4, 4, 7 }, { -4, -4, 7, 5 }, { -8, 0, 7, 8 }, { -4, 0, 7, 7 }
},
{ // Large Diamond pattern
{ 0, 8, 6, 5 }, { 4, 4, 0, 3 }, { 8, 0, 0, 5 }, { 4, -4, 2, 3 },
{ 0, -8, 2, 5 }, { -4, -4, 4, 3 }, { -8, 0, 4, 5 }, { -4, 4, 6, 3 }
},
{ // Extended Subpixel pattern
{ 0, 8, 6, 12 }, { 4, 4, 0, 12 }, { 8, 0, 0, 12 }, { 4, -4, 2, 12 },
{ 0, -8, 2, 12 }, { -4, -4, 4, 12 }, { -8, 0, 4, 12 }, { -4, 4, 6, 12 },
{ 0, 2, 6, 12 }, { 2, 0, 0, 12 }, { 0, -2, 2, 12 }, { -2, 0, 4, 12 }
}
};
// Other definitions
static const char c_EPZSPattern[6][20] = { "Diamond", "Square", "Extended Diamond", "Large Diamond", "SBP Large Diamond", "PMVFAST"};
static const char c_EPZSDualPattern[7][20] = { "Disabled","Diamond", "Square", "Extended Diamond", "Large Diamond", "SBP Large Diamond", "PMVFAST"};
static const char c_EPZSFixed[3][20] = { "Disabled","All P", "All P + B"};
static const char c_EPZSOther[2][20] = { "Disabled","Enabled"};
static int medthres[8];
static int maxthres[8];
static int minthres[8];
static int subthres[8];
static int mv_scale[6][MAX_REFERENCE_PICTURES][MAX_REFERENCE_PICTURES];
static short **EPZSMap; //!< Memory Map definition
int ***EPZSDistortion; //!< Array for storing SAD Values
int ***EPZSBiDistortion; //!< Array for storing SAD Values
#if EPZSREF
MotionVector *****EPZS_Motion; //!< Array for storing Motion Vectors
short ******EPZSMotion; //!< Array for storing Motion Vectors
#else
MotionVector ****EPZS_Motion; //!< Array for storing Motion Vectors
short *****EPZSMotion; //!< Array for storing Motion Vectors
#endif
//
EPZSStructure *searchPattern,*searchPatternD, *predictor;
EPZSStructure *window_predictor, *window_predictor_extended;
EPZSStructure *sdiamond,*square,*ediamond,*ldiamond, *sbdiamond, *pmvfast;
EPZSColocParams *EPZSCo_located;
// Functions
/*!
*************************************************************************************
* \brief
* Determine stop criterion for EPZS
*************************************************************************************
*/
static int EPZSDetermineStopCriterion(int* prevSad, PixelPos *block_a, PixelPos *block_b, PixelPos *block_c, int pic_pix_x2, int blocktype, int blockshape_x)
{
int sadA, sadB, sadC, stopCriterion;
sadA = block_a->available ? prevSad[pic_pix_x2 - blockshape_x] : INT_MAX;
sadB = block_b->available ? prevSad[pic_pix_x2] : INT_MAX;
sadC = block_c->available ? prevSad[pic_pix_x2 + blockshape_x] : INT_MAX;
stopCriterion = imin(sadA,imin(sadB,sadC));
stopCriterion = imax(stopCriterion,minthres[blocktype]);
stopCriterion = imin(stopCriterion,maxthres[blocktype]);
stopCriterion = (9 * imax (medthres[blocktype], stopCriterion) + 2 * medthres[blocktype]) >> 3;
return stopCriterion;
}
/*!
************************************************************************
* \brief
* Allocate co-located memory
*
* \param size_x
* horizontal luma size
* \param size_y
* vertical luma size
* \param mb_adaptive_frame_field_flag
* flag that indicates macroblock adaptive frame/field coding
*
* \return
* the allocated EPZSColocParams structure
************************************************************************
*/
static EPZSColocParams* allocEPZScolocated(int size_x, int size_y, int mb_adaptive_frame_field_flag)
{
EPZSColocParams *s;
s = calloc(1, sizeof(EPZSColocParams));
if (NULL == s)
no_mem_exit("alloc_EPZScolocated: s");
s->size_x = size_x;
s->size_y = size_y;
get_mem3Dmv(&(s->frame), 2, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
if (mb_adaptive_frame_field_flag)
{
get_mem3Dmv(&(s->top), 2, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
get_mem3Dmv(&(s->bot), 2, size_y / (BLOCK_SIZE * 2), size_x / BLOCK_SIZE);
}
s->mb_adaptive_frame_field_flag = mb_adaptive_frame_field_flag;
return s;
}
/*!
************************************************************************
* \brief
* Free co-located memory.
*
* \param p
* structure to be freed
*
************************************************************************
*/
static void freeEPZScolocated(EPZSColocParams* p)
{
if (p)
{
free_mem3Dmv (p->frame);
if (p->mb_adaptive_frame_field_flag)
{
free_mem3Dmv (p->top);
free_mem3Dmv (p->bot);
}
free(p);
p=NULL;
}
}
/*!
************************************************************************
* \brief
* Allocate EPZS pattern memory
*
* \param searchpoints
* number of searchpoints to allocate
*
* \return
* the allocated EPZSStructure structure
************************************************************************
*/
static EPZSStructure* allocEPZSpattern(int searchpoints)
{
EPZSStructure *s;
s = calloc(1, sizeof(EPZSStructure));
if (NULL == s)
no_mem_exit("alloc_EPZSpattern: s");
s->searchPoints = searchpoints;
s->point = (SPoint*) calloc(searchpoints, sizeof(SPoint));
return s;
}
/*!
************************************************************************
* \brief
* Free EPZS pattern memory.
*
* \param p
* structure to be freed
*
************************************************************************
*/
static void freeEPZSpattern(EPZSStructure* p)
{
if (p)
{
free ( (SPoint*) p->point);
free(p);
p=NULL;
}
}
static void assignEPZSpattern(EPZSStructure *pattern,int type, int stopSearch, int nextLast, EPZSStructure *nextpattern)
{
int i;
for (i = 0; i < pattern->searchPoints; i++)
{
pattern->point[i].motion.mv_x = pattern_data[type][i][0] >> mv_rescale;
pattern->point[i].motion.mv_y = pattern_data[type][i][1] >> mv_rescale;
pattern->point[i].start_nmbr = pattern_data[type][i][2];
pattern->point[i].next_points = pattern_data[type][i][3];
}
pattern->stopSearch = stopSearch;
pattern->nextLast = nextLast;
pattern->nextpattern = nextpattern;
}
/*!
************************************************************************
* \brief
* calculate RoundLog2(uiVal)
************************************************************************
*/
static int RoundLog2 (int iValue)
{
int iRet = 0;
int iValue_square = iValue * iValue;
while ((1 << (iRet + 1)) <= iValue_square)
iRet++;
iRet = (iRet + 1) >> 1;
return iRet;
}
/*!
***********************************************************************
* \brief
* Add Predictor function
*
***********************************************************************
*/
static inline int add_predictor(MotionVector *cur_mv, MotionVector prd_mv, int mvScale, int shift_mv)
{
*cur_mv = prd_mv;
cur_mv->mv_x = rshift_rnd_sf((mvScale * cur_mv->mv_x), shift_mv);
cur_mv->mv_y = rshift_rnd_sf((mvScale * cur_mv->mv_y), shift_mv);
return (*((int*) cur_mv) != 0);
}
/*!
************************************************************************
* \brief
* EPZS Search Window Predictor Initialization
************************************************************************
*/
static void EPZSWindowPredictorInit (short search_range, EPZSStructure * predictor, short mode)
{
int pos;
int searchpos, fieldsearchpos;
int prednum = 0;
int i;
int search_range_qpel = params->EPZSSubPelGrid ? 2 : 0;
if (mode == 0)
{
for (pos = RoundLog2 (search_range) - 2; pos > -1; pos--)
{
searchpos = ((search_range << search_range_qpel)>> pos);
for (i=1; i>=-1; i-=2)
{
predictor->point[prednum ].motion.mv_x = i * searchpos;
predictor->point[prednum++].motion.mv_y = 0;
predictor->point[prednum ].motion.mv_x = i * searchpos;
predictor->point[prednum++].motion.mv_y = i * searchpos;
predictor->point[prednum ].motion.mv_x = 0;
predictor->point[prednum++].motion.mv_y = i * searchpos;
predictor->point[prednum ].motion.mv_x = -i * searchpos;
predictor->point[prednum++].motion.mv_y = i * searchpos;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -