32 |
#include <stdio.h> |
#include <stdio.h> |
33 |
#include <stdlib.h> |
#include <stdlib.h> |
34 |
#include <string.h> // memcpy |
#include <string.h> // memcpy |
35 |
|
#include <math.h> // lrint |
36 |
|
|
37 |
#include "../encoder.h" |
#include "../encoder.h" |
38 |
#include "../utils/mbfunctions.h" |
#include "../utils/mbfunctions.h" |
753 |
Data.iFcode = current->fcode; |
Data.iFcode = current->fcode; |
754 |
Data.rounding = pParam->m_rounding_type; |
Data.rounding = pParam->m_rounding_type; |
755 |
Data.qpel = pParam->m_quarterpel; |
Data.qpel = pParam->m_quarterpel; |
756 |
Data.chroma = current->global_flags & XVID_ME_COLOUR; |
Data.chroma = current->global_flags & ( PMV_CHROMA16 | PMV_CHROMA8 ); |
757 |
Data.rrv = current->global_flags & XVID_REDUCED; |
Data.rrv = current->global_flags & XVID_REDUCED; |
758 |
|
|
759 |
if ((current->global_flags & XVID_REDUCED)) { |
if ((current->global_flags & XVID_REDUCED)) { |
802 |
|
|
803 |
//initial skip decision |
//initial skip decision |
804 |
/* no early skip for GMC (global vector = skip vector is unknown!) */ |
/* no early skip for GMC (global vector = skip vector is unknown!) */ |
805 |
if (current->coding_type == P_VOP) { /* no fast SKIP for S(GMC)-VOPs */ |
if (!(current->global_flags & XVID_GMC)) { /* no fast SKIP for S(GMC)-VOPs */ |
806 |
if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH * (Data.rrv ? 4:1) ) |
if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH * (Data.rrv ? 4:1) ) |
807 |
if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) { |
if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) { |
808 |
SkipMacroblockP(pMB, sad00); |
SkipMacroblockP(pMB, sad00); |
816 |
current->global_flags & XVID_INTER4V, pMB); |
current->global_flags & XVID_INTER4V, pMB); |
817 |
|
|
818 |
/* final skip decision, a.k.a. "the vector you found, really that good?" */ |
/* final skip decision, a.k.a. "the vector you found, really that good?" */ |
819 |
if (current->coding_type == P_VOP) { |
if (!(current->global_flags & XVID_GMC)) { |
820 |
if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP) |
if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP) |
821 |
&& ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH * (Data.rrv ? 4:1)) ) |
&& ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH * (Data.rrv ? 4:1)) ) |
822 |
if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) { |
if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) { |
856 |
} |
} |
857 |
} |
} |
858 |
|
|
859 |
if (current->coding_type == S_VOP) /* first GMC step only for S(GMC)-VOPs */ |
if (current->global_flags & XVID_GMC ) /* first GMC step only for S(GMC)-VOPs */ |
860 |
current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode ); |
{ |
861 |
else |
current->warp = GlobalMotionEst( pMBs, pParam, current, reference, pRefH, pRefV, pRefHV); |
862 |
current->GMC_MV = zeroMV; |
} |
863 |
|
|
864 |
return 0; |
return 0; |
865 |
} |
} |
1914 |
|
|
1915 |
} |
} |
1916 |
|
|
1917 |
static void |
|
1918 |
CheckGMC(int x, int y, const int dir, int * iDirection, |
static WARPPOINTS |
1919 |
const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC, |
GlobalMotionEst(const MACROBLOCK * const pMBs, |
1920 |
const MBParam * const pParam) |
const MBParam * const pParam, |
1921 |
|
const FRAMEINFO * const current, |
1922 |
|
const FRAMEINFO * const reference, |
1923 |
|
const IMAGE * const pRefH, |
1924 |
|
const IMAGE * const pRefV, |
1925 |
|
const IMAGE * const pRefHV ) |
1926 |
{ |
{ |
|
uint32_t mx, my, a, count = 0; |
|
1927 |
|
|
1928 |
for (my = 1; my < pParam->mb_height-1; my++) |
const int deltax=8; // upper bound for difference between a MV and it's neighbour MVs |
1929 |
for (mx = 1; mx < pParam->mb_width-1; mx++) { |
const int deltay=8; |
1930 |
VECTOR mv; |
const int grad=512; // lower bound for deviation in MB |
1931 |
const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width]; |
|
1932 |
if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue; |
WARPPOINTS gmc; |
1933 |
mv = pMB->mvs[0]; |
|
1934 |
a = ABS(mv.x - x) + ABS(mv.y - y); |
uint32_t mx, my; |
|
if (a < 6) count += 6 - a; |
|
|
} |
|
1935 |
|
|
1936 |
if (count > *bestcount) { |
int MBh = pParam->mb_height; |
1937 |
*bestcount = count; |
int MBw = pParam->mb_width; |
1938 |
*iDirection = dir; |
|
1939 |
GMC->x = x; GMC->y = y; |
int *MBmask= calloc(MBh*MBw,sizeof(int)); |
1940 |
|
double DtimesF[4] = { 0.,0., 0., 0. }; |
1941 |
|
double sol[4] = { 0., 0., 0., 0. }; |
1942 |
|
double a,b,c,n,denom; |
1943 |
|
double meanx,meany; |
1944 |
|
int num,oldnum; |
1945 |
|
|
1946 |
|
if (!MBmask) { fprintf(stderr,"Mem error\n"); return gmc;} |
1947 |
|
|
1948 |
|
// filter mask of all blocks |
1949 |
|
|
1950 |
|
for (my = 1; my < MBh-1; my++) |
1951 |
|
for (mx = 1; mx < MBw-1; mx++) |
1952 |
|
{ |
1953 |
|
const int mbnum = mx + my * MBw; |
1954 |
|
const MACROBLOCK *pMB = &pMBs[mbnum]; |
1955 |
|
const VECTOR mv = pMB->mvs[0]; |
1956 |
|
|
1957 |
|
if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) |
1958 |
|
continue; |
1959 |
|
|
1960 |
|
if ( ( (ABS(mv.x - (pMB-1)->mvs[0].x) < deltax) && (ABS(mv.y - (pMB-1)->mvs[0].y) < deltay) ) |
1961 |
|
&& ( (ABS(mv.x - (pMB+1)->mvs[0].x) < deltax) && (ABS(mv.y - (pMB+1)->mvs[0].y) < deltay) ) |
1962 |
|
&& ( (ABS(mv.x - (pMB-MBw)->mvs[0].x) < deltax) && (ABS(mv.y - (pMB-MBw)->mvs[0].y) < deltay) ) |
1963 |
|
&& ( (ABS(mv.x - (pMB+MBw)->mvs[0].x) < deltax) && (ABS(mv.y - (pMB+MBw)->mvs[0].y) < deltay) ) ) |
1964 |
|
MBmask[mbnum]=1; |
1965 |
} |
} |
1966 |
|
|
1967 |
|
for (my = 1; my < MBh-1; my++) |
1968 |
|
for (mx = 1; mx < MBw-1; mx++) |
1969 |
|
{ |
1970 |
|
const uint8_t *const pCur = current->image.y + 16*my*pParam->edged_width + 16*mx; |
1971 |
|
|
1972 |
|
const int mbnum = mx + my * MBw; |
1973 |
|
if (!MBmask[mbnum]) |
1974 |
|
continue; |
1975 |
|
|
1976 |
|
if (sad16 ( pCur, pCur+1 , pParam->edged_width, 65536) <= grad ) |
1977 |
|
MBmask[mbnum] = 0; |
1978 |
|
if (sad16 ( pCur, pCur+pParam->edged_width, pParam->edged_width, 65536) <= grad ) |
1979 |
|
MBmask[mbnum] = 0; |
1980 |
|
|
1981 |
} |
} |
1982 |
|
|
1983 |
|
emms(); |
1984 |
|
|
1985 |
static VECTOR |
do { /* until convergence */ |
|
GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode) |
|
|
{ |
|
1986 |
|
|
1987 |
uint32_t count, bestcount = 0; |
a = b = c = n = 0; |
1988 |
int x, y; |
DtimesF[0] = DtimesF[1] = DtimesF[2] = DtimesF[3] = 0.; |
1989 |
VECTOR gmc = {0,0}; |
for (my = 0; my < MBh; my++) |
1990 |
int step, min_x, max_x, min_y, max_y; |
for (mx = 0; mx < MBw; mx++) |
1991 |
uint32_t mx, my; |
{ |
1992 |
int iDirection, bDirection; |
const int mbnum = mx + my * MBw; |
1993 |
|
const MACROBLOCK *pMB = &pMBs[mbnum]; |
1994 |
|
const VECTOR mv = pMB->mvs[0]; |
1995 |
|
|
1996 |
min_x = min_y = -32<<iFcode; |
if (!MBmask[mbnum]) |
1997 |
max_x = max_y = 32<<iFcode; |
continue; |
1998 |
|
|
1999 |
//step1: let's find a rough camera panning |
n++; |
2000 |
for (step = 32; step >= 2; step /= 2) { |
a += 16*mx+8; |
2001 |
bestcount = 0; |
b += 16*my+8; |
2002 |
for (y = min_y; y <= max_y; y += step) |
c += (16*mx+8)*(16*mx+8)+(16*my+8)*(16*my+8); |
2003 |
for (x = min_x ; x <= max_x; x += step) { |
|
2004 |
count = 0; |
DtimesF[0] += (double)mv.x; |
2005 |
//for all macroblocks |
DtimesF[1] += (double)mv.x*(16*mx+8) + (double)mv.y*(16*my+8); |
2006 |
for (my = 1; my < pParam->mb_height-1; my++) |
DtimesF[2] += (double)mv.x*(16*my+8) - (double)mv.y*(16*mx+8); |
2007 |
for (mx = 1; mx < pParam->mb_width-1; mx++) { |
DtimesF[3] += (double)mv.y; |
2008 |
const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width]; |
} |
2009 |
VECTOR mv; |
|
2010 |
|
denom = a*a+b*b-c*n; |
2011 |
|
|
2012 |
|
/* Solve the system: sol = (D'*E*D)^{-1} D'*E*F */ |
2013 |
|
/* D'*E*F has been calculated in the same loop as matrix */ |
2014 |
|
|
2015 |
|
sol[0] = -c*DtimesF[0] + a*DtimesF[1] + b*DtimesF[2]; |
2016 |
|
sol[1] = a*DtimesF[0] - n*DtimesF[1] + b*DtimesF[3]; |
2017 |
|
sol[2] = b*DtimesF[0] - n*DtimesF[2] - a*DtimesF[3]; |
2018 |
|
sol[3] = b*DtimesF[1] - a*DtimesF[2] - c*DtimesF[3]; |
2019 |
|
|
2020 |
|
sol[0] /= denom; |
2021 |
|
sol[1] /= denom; |
2022 |
|
sol[2] /= denom; |
2023 |
|
sol[3] /= denom; |
2024 |
|
|
2025 |
|
meanx = meany = 0.; |
2026 |
|
oldnum = 0; |
2027 |
|
for (my = 0; my < MBh; my++) |
2028 |
|
for (mx = 0; mx < MBw; mx++) |
2029 |
|
{ |
2030 |
|
const int mbnum = mx + my * MBw; |
2031 |
|
const MACROBLOCK *pMB = &pMBs[mbnum]; |
2032 |
|
const VECTOR mv = pMB->mvs[0]; |
2033 |
|
|
2034 |
if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) |
if (!MBmask[mbnum]) |
2035 |
continue; |
continue; |
2036 |
|
|
2037 |
mv = pMB->mvs[0]; |
oldnum++; |
2038 |
if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step ) /* GMC translation is always halfpel-res */ |
meanx += ABS(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x ); |
2039 |
count++; |
meany += ABS(( sol[3] + (16*my+8)*sol[1] - (16*mx+8)*sol[2] ) - mv.y ); |
2040 |
} |
|
|
if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; } |
|
2041 |
} |
} |
2042 |
min_x = gmc.x - step; |
|
2043 |
max_x = gmc.x + step; |
if (2*meanx > oldnum) /* mittlere Abweichung von Ebene */ |
2044 |
min_y = gmc.y - step; |
meanx /= oldnum; |
2045 |
max_y = gmc.y + step; |
else |
2046 |
|
meanx = 0.5; |
2047 |
|
if (2*meany > oldnum) |
2048 |
|
meany /= oldnum; |
2049 |
|
else |
2050 |
|
meanx = 0.5; |
2051 |
|
|
2052 |
|
// fprintf(stderr,"meanx = %8.5f meany = %8.5f %d\n",meanx,meany, oldnum); |
2053 |
|
|
2054 |
|
num = 0; |
2055 |
|
for (my = 0; my < MBh; my++) |
2056 |
|
for (mx = 0; mx < MBw; mx++) |
2057 |
|
{ |
2058 |
|
const int mbnum = mx + my * MBw; |
2059 |
|
const MACROBLOCK *pMB = &pMBs[mbnum]; |
2060 |
|
const VECTOR mv = pMB->mvs[0]; |
2061 |
|
|
2062 |
|
if (!MBmask[mbnum]) |
2063 |
|
continue; |
2064 |
|
|
2065 |
|
if ( ( ABS(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x ) > meanx ) |
2066 |
|
|| ( ABS(( sol[3] + (16*my+8)*sol[1] - (16*mx+8)*sol[2] ) - mv.y ) > meany ) ) |
2067 |
|
MBmask[mbnum]=0; |
2068 |
|
else |
2069 |
|
num++; |
2070 |
} |
} |
2071 |
|
|
2072 |
if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10) |
} while ( (oldnum != num) && (num>=4) ); |
|
gmc.x = gmc.y = 0; //no camara pan, no GMC |
|
2073 |
|
|
2074 |
// step2: let's refine camera panning using gradiend-descent approach |
if (num < 4) |
2075 |
// TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond) |
{ |
2076 |
bestcount = 0; |
gmc.duv[0].x= gmc.duv[0].y= gmc.duv[1].x= gmc.duv[1].y= gmc.duv[2].x= gmc.duv[2].y=0; |
2077 |
CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam); |
} else { |
|
do { |
|
|
x = gmc.x; y = gmc.y; |
|
|
bDirection = iDirection; iDirection = 0; |
|
|
if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam); |
|
|
if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam); |
|
|
if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam); |
|
|
if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam); |
|
2078 |
|
|
2079 |
} while (iDirection); |
gmc.duv[0].x=(int)(sol[0]+0.5); |
2080 |
|
gmc.duv[0].y=(int)(sol[3]+0.5); |
2081 |
|
|
2082 |
if (pParam->m_quarterpel) { |
gmc.duv[1].x=(int)(sol[1]*pParam->width+0.5); |
2083 |
gmc.x *= 2; |
gmc.duv[1].y=(int)(-sol[2]*pParam->width+0.5); |
2084 |
gmc.y *= 2; /* we store the halfpel value as pseudo-qpel to make comparison easier */ |
|
2085 |
|
gmc.duv[2].x=0; |
2086 |
|
gmc.duv[2].y=0; |
2087 |
} |
} |
2088 |
|
// fprintf(stderr,"wp1 = ( %4d, %4d) wp2 = ( %4d, %4d) \n", gmc.duv[0].x, gmc.duv[0].y, gmc.duv[1].x, gmc.duv[1].y); |
2089 |
|
|
2090 |
|
free(MBmask); |
2091 |
|
|
2092 |
return gmc; |
return gmc; |
2093 |
} |
} |