📄 motion_est_template.c
字号:
const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
// if(l < r && l < t && l < b && l < tl && l < bl && l < tr && l < br && bl < tl){
if(tl<br){
// nx= FFMAX(4*mx - bx, bx - 4*mx);
// ny= FFMAX(4*my - by, by - 4*my);
static int stats[7][7], count;
count++;
stats[4*mx - bx + 3][4*my - by + 3]++;
if(256*256*256*64 % count ==0){
for(i=0; i<49; i++){
if((i%7)==0) printf("\n");
printf("%6d ", stats[0][i]);
}
printf("\n");
}
}
#endif
#else
CHECK_QUARTER_MV(2, 2, mx-1, my-1)
CHECK_QUARTER_MV(0, 2, mx , my-1)
CHECK_QUARTER_MV(2, 2, mx , my-1)
CHECK_QUARTER_MV(2, 0, mx , my )
CHECK_QUARTER_MV(2, 2, mx , my )
CHECK_QUARTER_MV(0, 2, mx , my )
CHECK_QUARTER_MV(2, 2, mx-1, my )
CHECK_QUARTER_MV(2, 0, mx-1, my )
nx= bx;
ny= by;
for(i=0; i<8; i++){
int ox[8]= {0, 1, 1, 1, 0,-1,-1,-1};
int oy[8]= {1, 1, 0,-1,-1,-1, 0, 1};
CHECK_QUARTER_MV((nx + ox[i])&3, (ny + oy[i])&3, (nx + ox[i])>>2, (ny + oy[i])>>2)
}
#endif
#if 0
//outer ring
CHECK_QUARTER_MV(1, 3, mx-1, my-1)
CHECK_QUARTER_MV(1, 2, mx-1, my-1)
CHECK_QUARTER_MV(1, 1, mx-1, my-1)
CHECK_QUARTER_MV(2, 1, mx-1, my-1)
CHECK_QUARTER_MV(3, 1, mx-1, my-1)
CHECK_QUARTER_MV(0, 1, mx , my-1)
CHECK_QUARTER_MV(1, 1, mx , my-1)
CHECK_QUARTER_MV(2, 1, mx , my-1)
CHECK_QUARTER_MV(3, 1, mx , my-1)
CHECK_QUARTER_MV(3, 2, mx , my-1)
CHECK_QUARTER_MV(3, 3, mx , my-1)
CHECK_QUARTER_MV(3, 0, mx , my )
CHECK_QUARTER_MV(3, 1, mx , my )
CHECK_QUARTER_MV(3, 2, mx , my )
CHECK_QUARTER_MV(3, 3, mx , my )
CHECK_QUARTER_MV(2, 3, mx , my )
CHECK_QUARTER_MV(1, 3, mx , my )
CHECK_QUARTER_MV(0, 3, mx , my )
CHECK_QUARTER_MV(3, 3, mx-1, my )
CHECK_QUARTER_MV(2, 3, mx-1, my )
CHECK_QUARTER_MV(1, 3, mx-1, my )
CHECK_QUARTER_MV(1, 2, mx-1, my )
CHECK_QUARTER_MV(1, 1, mx-1, my )
CHECK_QUARTER_MV(1, 0, mx-1, my )
#endif
assert(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);
*mx_ptr = bx;
*my_ptr = by;
}else{
*mx_ptr =4*mx;
*my_ptr =4*my;
}
return dmin;
}
#define CHECK_MV(x,y)\
{\
const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
assert((x) >= xmin);\
assert((x) <= xmax);\
assert((y) >= ymin);\
assert((y) <= ymax);\
/*printf("check_mv %d %d\n", x, y);*/\
if(map[index]!=key){\
d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
map[index]= key;\
score_map[index]= d;\
d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
/*printf("score:%d\n", d);*/\
COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
}\
}
#define CHECK_CLIPPED_MV(ax,ay)\
{\
const int Lx= ax;\
const int Ly= ay;\
const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\
const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\
CHECK_MV(Lx2, Ly2)\
}
#define CHECK_MV_DIR(x,y,new_dir)\
{\
const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
/*printf("check_mv_dir %d %d %d\n", x, y, new_dir);*/\
if(map[index]!=key){\
d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
map[index]= key;\
score_map[index]= d;\
d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
/*printf("score:%d\n", d);*/\
if(d<dmin){\
best[0]=x;\
best[1]=y;\
dmin=d;\
next_dir= new_dir;\
}\
}\
}
#define check(x,y,S,v)\
if( (x)<(xmin<<(S)) ) printf("%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
if( (x)>(xmax<<(S)) ) printf("%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
if( (y)<(ymin<<(S)) ) printf("%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
if( (y)>(ymax<<(S)) ) printf("%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\
#define LOAD_COMMON2\
uint32_t *map= c->map;\
const int qpel= flags&FLAG_QPEL;\
const int shift= 1+qpel;\
static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
int src_index, int ref_index, int const penalty_factor,
int size, int h, int flags)
{
MotionEstContext * const c= &s->me;
me_cmp_func cmpf, chroma_cmpf;
int next_dir=-1;
LOAD_COMMON
LOAD_COMMON2
int map_generation= c->map_generation;
cmpf= s->dsp.me_cmp[size];
chroma_cmpf= s->dsp.me_cmp[size+1];
{ /* ensure that the best point is in the MAP as h/qpel refinement needs it */
const int key= (best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
const int index= ((best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1);
if(map[index]!=key){ //this will be executed only very rarey
score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
map[index]= key;
}
}
for(;;){
int d;
const int dir= next_dir;
const int x= best[0];
const int y= best[1];
next_dir=-1;
//printf("%d", dir);
if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0)
if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1)
if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2)
if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
if(next_dir==-1){
return dmin;
}
}
}
static int funny_diamond_search(MpegEncContext * s, int *best, int dmin,
int src_index, int ref_index, int const penalty_factor,
int size, int h, int flags)
{
MotionEstContext * const c= &s->me;
me_cmp_func cmpf, chroma_cmpf;
int dia_size;
LOAD_COMMON
LOAD_COMMON2
int map_generation= c->map_generation;
cmpf= s->dsp.me_cmp[size];
chroma_cmpf= s->dsp.me_cmp[size+1];
for(dia_size=1; dia_size<=4; dia_size++){
int dir;
const int x= best[0];
const int y= best[1];
if(dia_size&(dia_size-1)) continue;
if( x + dia_size > xmax
|| x - dia_size < xmin
|| y + dia_size > ymax
|| y - dia_size < ymin)
continue;
for(dir= 0; dir<dia_size; dir+=2){
int d;
CHECK_MV(x + dir , y + dia_size - dir);
CHECK_MV(x + dia_size - dir, y - dir );
CHECK_MV(x - dir , y - dia_size + dir);
CHECK_MV(x - dia_size + dir, y + dir );
}
if(x!=best[0] || y!=best[1])
dia_size=0;
#if 0
{
int dx, dy, i;
static int stats[8*8];
dx= FFABS(x-best[0]);
dy= FFABS(y-best[1]);
if(dy>dx){
dx^=dy; dy^=dx; dx^=dy;
}
stats[dy*8 + dx] ++;
if(256*256*256*64 % (stats[0]+1)==0){
for(i=0; i<64; i++){
if((i&7)==0) printf("\n");
printf("%8d ", stats[i]);
}
printf("\n");
}
}
#endif
}
return dmin;
}
static int hex_search(MpegEncContext * s, int *best, int dmin,
int src_index, int ref_index, int const penalty_factor,
int size, int h, int flags, int dia_size)
{
MotionEstContext * const c= &s->me;
me_cmp_func cmpf, chroma_cmpf;
LOAD_COMMON
LOAD_COMMON2
int map_generation= c->map_generation;
int x,y,d;
const int dec= dia_size & (dia_size-1);
cmpf= s->dsp.me_cmp[size];
chroma_cmpf= s->dsp.me_cmp[size+1];
for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
do{
x= best[0];
y= best[1];
CHECK_CLIPPED_MV(x -dia_size , y);
CHECK_CLIPPED_MV(x+ dia_size , y);
CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size);
CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size);
if(dia_size>1){
CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size);
CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size);
}
}while(best[0] != x || best[1] != y);
}
return dmin;
}
static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
int src_index, int ref_index, int const penalty_factor,
int size, int h, int flags)
{
MotionEstContext * const c= &s->me;
me_cmp_func cmpf, chroma_cmpf;
LOAD_COMMON
LOAD_COMMON2
int map_generation= c->map_generation;
int x,y,i,d;
int dia_size= c->dia_size&0xFF;
const int dec= dia_size & (dia_size-1);
static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1},
{ 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};
cmpf= s->dsp.me_cmp[size];
chroma_cmpf= s->dsp.me_cmp[size+1];
for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
do{
x= best[0];
y= best[1];
for(i=0; i<8; i++){
CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size);
}
}while(best[0] != x || best[1] != y);
}
x= best[0];
y= best[1];
CHECK_CLIPPED_MV(x+1, y);
CHECK_CLIPPED_MV(x, y+1);
CHECK_CLIPPED_MV(x-1, y);
CHECK_CLIPPED_MV(x, y-1);
return dmin;
}
static int umh_search(MpegEncContext * s, int *best, int dmin,
int src_index, int ref_index, int const penalty_factor,
int size, int h, int flags)
{
MotionEstContext * const c= &s->me;
me_cmp_func cmpf, chroma_cmpf;
LOAD_COMMON
LOAD_COMMON2
int map_generation= c->map_generation;
int x,y,x2,y2, i, j, d;
const int dia_size= c->dia_size&0xFE;
static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2},
{ 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
{-2, 3}, { 0, 4}, { 2, 3},
{-2,-3}, { 0,-4}, { 2,-3},};
cmpf= s->dsp.me_cmp[size];
chroma_cmpf= s->dsp.me_cmp[size+1];
x= best[0];
y= best[1];
for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){
CHECK_MV(x2, y);
}
for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){
CHECK_MV(x, y2);
}
x= best[0];
y= best[1];
for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){
for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){
CHECK_MV(x2, y2);
}
}
//FIXME prevent the CLIP stuff
for(j=1; j<=dia_size/4; j++){
for(i=0; i<16; i++){
CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j);
}
}
return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2);
}
#define SAB_CHECK_MV(ax,ay)\
{\
const int key= ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
/*printf("sab check %d %d\n", ax, ay);*/\
if(map[index]!=key){\
d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
map[index]= key;\
score_map[index]= d;\
d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
/*printf("score: %d\n", d);*/\
if(d < minima[minima_count-1].height){\
int j=0;\
\
while(d >= minima[j].height) j++;\
\
memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\
\
minima[j].checked= 0;\
minima[j].height= d;\
minima[j].x= ax;\
minima[j].y= ay;\
\
i=-1;\
continue;\
}\
}\
}
#define MAX_SAB_SIZE ME_MAP_SIZE
static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
int src_index, int ref_index, int const penalty_factor,
int size, int h, int flags)
{
MotionEstContext * const c= &s->me;
me_cmp_func cmpf, chroma_cmpf;
Minima minima[MAX_SAB_SIZE];
const int minima_count= FFABS(c->dia_size);
int i, j;
LOAD_COMMON
LOAD_COMMON2
int map_generation= c->map_generation;
cmpf= s->dsp.me_cmp[size];
chroma_cmpf= s->dsp.me_cmp[size+1];
/*Note j<MAX_SAB_SIZE is needed if MAX_SAB_SIZE < ME_MAP_SIZE as j can
become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map
*/
for(j=i=0; i<ME_MAP_SIZE && j<MAX_SAB_SIZE; i++){
uint32_t key= map[i];
key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -