2 |
* |
* |
3 |
* Modifications: |
* Modifications: |
4 |
* |
* |
5 |
|
* 14.04.2002 added MotionEstimationBVOP() |
6 |
* 02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between |
* 02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between |
7 |
* EPZS and EPZS^2 |
* EPZS and EPZS^2 |
8 |
* 08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop |
* 08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop |
41 |
#include "../prediction/mbprediction.h" |
#include "../prediction/mbprediction.h" |
42 |
#include "../global.h" |
#include "../global.h" |
43 |
#include "../utils/timer.h" |
#include "../utils/timer.h" |
44 |
|
#include "motion.h" |
45 |
#include "sad.h" |
#include "sad.h" |
46 |
|
|
47 |
// very large value |
// very large value |
70 |
#define EVEN(A) (((A)<0?(A)+1:(A)) & ~1) |
#define EVEN(A) (((A)<0?(A)+1:(A)) & ~1) |
71 |
|
|
72 |
|
|
|
#define MIN(X, Y) ((X)<(Y)?(X):(Y)) |
|
|
#define MAX(X, Y) ((X)>(Y)?(X):(Y)) |
|
|
#define ABS(X) (((X)>0)?(X):-(X)) |
|
|
#define SIGN(X) (((X)>0)?1:-1) |
|
|
|
|
73 |
int32_t PMVfastSearch16( |
int32_t PMVfastSearch16( |
74 |
const uint8_t * const pRef, |
const uint8_t * const pRef, |
75 |
const uint8_t * const pRefH, |
const uint8_t * const pRefH, |
218 |
|
|
219 |
|
|
220 |
|
|
|
/* calculate the min/max range (in halfpixels) |
|
|
relative to the _MACROBLOCK_ position |
|
|
*/ |
|
|
|
|
|
static void __inline get_range( |
|
|
int32_t * const min_dx, int32_t * const max_dx, |
|
|
int32_t * const min_dy, int32_t * const max_dy, |
|
|
const uint32_t x, const uint32_t y, |
|
|
const uint32_t block_sz, // block dimension, 8 or 16 |
|
|
const uint32_t width, const uint32_t height, |
|
|
const uint32_t fcode) |
|
|
{ |
|
|
|
|
|
const int search_range = 32 << (fcode - 1); |
|
|
const int high = search_range - 1; |
|
|
const int low = -search_range; |
|
|
|
|
|
// convert full-pixel measurements to half pixel |
|
|
const int hp_width = 2 * width; |
|
|
const int hp_height = 2 * height; |
|
|
const int hp_edge = 2 * block_sz; |
|
|
const int hp_x = 2 * (x) * block_sz; // we need _right end_ of block, not x-coordinate |
|
|
const int hp_y = 2 * (y) * block_sz; // same for _bottom end_ |
|
|
|
|
|
*max_dx = MIN(high, hp_width - hp_x); |
|
|
*max_dy = MIN(high, hp_height - hp_y); |
|
|
*min_dx = MAX(low, -(hp_edge + hp_x)); |
|
|
*min_dy = MAX(low, -(hp_edge + hp_y)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
* getref: calculate reference image pointer |
|
|
* the decision to use interpolation h/v/hv or the normal image is |
|
|
* based on dx & dy. |
|
|
*/ |
|
|
|
|
|
static __inline const uint8_t * get_ref( |
|
|
const uint8_t * const refn, |
|
|
const uint8_t * const refh, |
|
|
const uint8_t * const refv, |
|
|
const uint8_t * const refhv, |
|
|
const uint32_t x, const uint32_t y, |
|
|
const uint32_t block, // block dimension, 8 or 16 |
|
|
const int32_t dx, const int32_t dy, |
|
|
const uint32_t stride) |
|
|
{ |
|
|
|
|
|
switch ( ((dx&1)<<1) + (dy&1) ) // ((dx%2)?2:0)+((dy%2)?1:0) |
|
|
{ |
|
|
case 0 : return refn + (x*block+dx/2) + (y*block+dy/2)*stride; |
|
|
case 1 : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride; |
|
|
case 2 : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride; |
|
|
default : |
|
|
case 3 : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride; |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* This is somehow a copy of get_ref, but with MV instead of X,Y */ |
|
|
|
|
|
static __inline const uint8_t * get_ref_mv( |
|
|
const uint8_t * const refn, |
|
|
const uint8_t * const refh, |
|
|
const uint8_t * const refv, |
|
|
const uint8_t * const refhv, |
|
|
const uint32_t x, const uint32_t y, |
|
|
const uint32_t block, // block dimension, 8 or 16 |
|
|
const VECTOR* mv, // measured in half-pel! |
|
|
const uint32_t stride) |
|
|
{ |
|
|
|
|
|
switch ( (((mv->x)&1)<<1) + ((mv->y)&1) ) |
|
|
{ |
|
|
case 0 : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride; |
|
|
case 1 : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride; |
|
|
case 2 : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride; |
|
|
default : |
|
|
case 3 : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride; |
|
|
} |
|
|
|
|
|
} |
|
221 |
|
|
222 |
#ifndef SEARCH16 |
#ifndef SEARCH16 |
223 |
#define SEARCH16 PMVfastSearch16 |
#define SEARCH16 PMVfastSearch16 |
1883 |
return iMinSAD; |
return iMinSAD; |
1884 |
} |
} |
1885 |
|
|
1886 |
|
|
1887 |
|
|
1888 |
|
|
1889 |
|
|
1890 |
|
/* *********************************************************** |
1891 |
|
bvop motion estimation |
1892 |
|
// TODO: need to incorporate prediction here (eg. sad += calc_delta_16) |
1893 |
|
***************************************************************/ |
1894 |
|
|
1895 |
|
/* |
1896 |
|
void MotionEstimationBVOP( |
1897 |
|
MBParam * const pParam, |
1898 |
|
FRAMEINFO * const frame, |
1899 |
|
|
1900 |
|
// forward (past) reference |
1901 |
|
const MACROBLOCK * const f_mbs, |
1902 |
|
const IMAGE * const f_ref, |
1903 |
|
const IMAGE * const f_refH, |
1904 |
|
const IMAGE * const f_refV, |
1905 |
|
const IMAGE * const f_refHV, |
1906 |
|
// backward (future) reference |
1907 |
|
const MACROBLOCK * const b_mbs, |
1908 |
|
const IMAGE * const b_ref, |
1909 |
|
const IMAGE * const b_refH, |
1910 |
|
const IMAGE * const b_refV, |
1911 |
|
const IMAGE * const b_refHV) |
1912 |
|
{ |
1913 |
|
const uint32_t mb_width = pParam->mb_width; |
1914 |
|
const uint32_t mb_height = pParam->mb_height; |
1915 |
|
const int32_t edged_width = pParam->edged_width; |
1916 |
|
|
1917 |
|
int32_t i,j; |
1918 |
|
|
1919 |
|
int32_t f_sad16; |
1920 |
|
int32_t b_sad16; |
1921 |
|
int32_t i_sad16; |
1922 |
|
int32_t d_sad16; |
1923 |
|
int32_t best_sad; |
1924 |
|
|
1925 |
|
VECTOR pmv_dontcare; |
1926 |
|
|
1927 |
|
// note: i==horizontal, j==vertical |
1928 |
|
for (j = 0; j < mb_height; j++) |
1929 |
|
{ |
1930 |
|
for (i = 0; i < mb_width; i++) |
1931 |
|
{ |
1932 |
|
MACROBLOCK *mb = &frame->mbs[i + j*mb_width]; |
1933 |
|
const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width]; |
1934 |
|
const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width]; |
1935 |
|
|
1936 |
|
if (b_mb->mode == MODE_INTER |
1937 |
|
&& b_mb->cbp == 0 |
1938 |
|
&& b_mb->mvs[0].x == 0 |
1939 |
|
&& b_mb->mvs[0].y == 0) |
1940 |
|
{ |
1941 |
|
mb->mode = MB_IGNORE; |
1942 |
|
mb->mvs[0].x = 0; |
1943 |
|
mb->mvs[0].y = 0; |
1944 |
|
mb->b_mvs[0].x = 0; |
1945 |
|
mb->b_mvs[0].y = 0; |
1946 |
|
continue; |
1947 |
|
} |
1948 |
|
|
1949 |
|
|
1950 |
|
// forward search |
1951 |
|
f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y, |
1952 |
|
&frame->image, |
1953 |
|
i, j, |
1954 |
|
frame->motion_flags, frame->quant, frame->fcode, |
1955 |
|
pParam, |
1956 |
|
f_mbs, |
1957 |
|
&mb->mvs[0], &pmv_dontcare); // ignore pmv |
1958 |
|
|
1959 |
|
// backward search |
1960 |
|
b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y, |
1961 |
|
&frame->image, |
1962 |
|
i, j, |
1963 |
|
frame->motion_flags, frame->quant, frame->bcode, |
1964 |
|
pParam, |
1965 |
|
b_mbs, |
1966 |
|
&mb->b_mvs[0], &pmv_dontcare); // ignore pmv |
1967 |
|
|
1968 |
|
// interpolate search (simple, but effective) |
1969 |
|
i_sad16 = sad16bi_c( |
1970 |
|
frame->image.y + i*16 + j*16*edged_width, |
1971 |
|
get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y, |
1972 |
|
i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width), |
1973 |
|
get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y, |
1974 |
|
i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width), |
1975 |
|
edged_width); |
1976 |
|
|
1977 |
|
// TODO: direct search |
1978 |
|
// predictor + range of [-32,32] |
1979 |
|
d_sad16 = 65535; |
1980 |
|
|
1981 |
|
|
1982 |
|
if (f_sad16 < b_sad16) |
1983 |
|
{ |
1984 |
|
best_sad = f_sad16; |
1985 |
|
mb->mode = MB_FORWARD; |
1986 |
|
} |
1987 |
|
else |
1988 |
|
{ |
1989 |
|
best_sad = b_sad16; |
1990 |
|
mb->mode = MB_BACKWARD; |
1991 |
|
} |
1992 |
|
|
1993 |
|
if (i_sad16 < best_sad) |
1994 |
|
{ |
1995 |
|
best_sad = i_sad16; |
1996 |
|
mb->mode = MB_INTERPOLATE; |
1997 |
|
} |
1998 |
|
|
1999 |
|
if (d_sad16 < best_sad) |
2000 |
|
{ |
2001 |
|
best_sad = d_sad16; |
2002 |
|
mb->mode = MB_DIRECT; |
2003 |
|
} |
2004 |
|
|
2005 |
|
} |
2006 |
|
} |
2007 |
|
} |
2008 |
|
|
2009 |
|
*/ |