Merge remote branch 'internal/upstream' into HEAD
This commit is contained in:
Коммит
848c18e9be
|
@ -831,7 +831,9 @@ int vp8_hex_search
|
|||
)
|
||||
{
|
||||
MV hex[6] = { { -1, -2}, {1, -2}, {2, 0}, {1, 2}, { -1, 2}, { -2, 0} } ;
|
||||
MV neighbors[8] = { { -1, -1}, {0, -1}, {1, -1}, { -1, 0}, {1, 0}, { -1, 1}, {0, 1}, {1, 1} } ;
|
||||
//MV neighbors[8] = { { -1, -1}, {0, -1}, {1, -1}, { -1, 0}, {1, 0}, { -1, 1}, {0, 1}, {1, 1} } ;
|
||||
MV neighbors[4] = {{0, -1}, { -1, 0}, {1, 0}, {0, 1}} ;
|
||||
|
||||
int i, j;
|
||||
unsigned char *src = (*(b->base_src) + b->src);
|
||||
int src_stride = b->src_stride;
|
||||
|
@ -918,24 +920,31 @@ int vp8_hex_search
|
|||
break;
|
||||
}
|
||||
|
||||
// check 8 1 away neighbors
|
||||
// check 4 1-away neighbors
|
||||
cal_neighbors:
|
||||
tr = br;
|
||||
tc = bc;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
for (j = 0; j < 32; j++)
|
||||
{
|
||||
int nr = tr + neighbors[i].row, nc = tc + neighbors[i].col;
|
||||
tr = br;
|
||||
tc = bc;
|
||||
|
||||
if (nc < x->mv_col_min) continue;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
int nr = tr + neighbors[i].row, nc = tc + neighbors[i].col;
|
||||
|
||||
if (nc > x->mv_col_max) continue;
|
||||
if (nc < x->mv_col_min) continue;
|
||||
|
||||
if (nr < x->mv_row_min) continue;
|
||||
if (nc > x->mv_col_max) continue;
|
||||
|
||||
if (nr > x->mv_row_max) continue;
|
||||
if (nr < x->mv_row_min) continue;
|
||||
|
||||
CHECK_BETTER(thiserr, nr, nc);
|
||||
if (nr > x->mv_row_max) continue;
|
||||
|
||||
CHECK_BETTER(thiserr, nr, nc);
|
||||
}
|
||||
|
||||
if (tr == br && tc == bc)
|
||||
break;
|
||||
}
|
||||
|
||||
best_mv->row = br;
|
||||
|
|
|
@ -95,7 +95,8 @@ extern double vp8_calc_ssimg
|
|||
YV12_BUFFER_CONFIG *dest,
|
||||
double *ssim_y,
|
||||
double *ssim_u,
|
||||
double *ssim_v
|
||||
double *ssim_v,
|
||||
const vp8_variance_rtcd_vtable_t *rtcd
|
||||
);
|
||||
|
||||
|
||||
|
@ -5022,7 +5023,8 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
|
|||
if (cpi->b_calculate_ssimg)
|
||||
{
|
||||
double y, u, v, frame_all;
|
||||
frame_all = vp8_calc_ssimg(cpi->Source, cm->frame_to_show, &y, &u, &v);
|
||||
frame_all = vp8_calc_ssimg(cpi->Source, cm->frame_to_show,
|
||||
&y, &u, &v, IF_RTCD(&cpi->rtcd.variance));
|
||||
cpi->total_ssimg_y += y;
|
||||
cpi->total_ssimg_u += u;
|
||||
cpi->total_ssimg_v += v;
|
||||
|
|
|
@ -18,223 +18,6 @@
|
|||
#else
|
||||
#define IF_RTCD(x) NULL
|
||||
#endif
|
||||
// Google version of SSIM
|
||||
// SSIM
|
||||
#define KERNEL 3
|
||||
#define KERNEL_SIZE (2 * KERNEL + 1)
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
static const int K[KERNEL_SIZE] =
|
||||
{
|
||||
1, 4, 11, 16, 11, 4, 1 // 16 * exp(-0.3 * i * i)
|
||||
};
|
||||
static const double ki_w = 1. / 2304.; // 1 / sum(i:0..6, j..6) K[i]*K[j]
|
||||
double get_ssimg(const uint8 *org, const uint8 *rec,
|
||||
int xo, int yo, int W, int H,
|
||||
const int stride1, const int stride2
|
||||
)
|
||||
{
|
||||
// TODO(skal): use summed tables
|
||||
int y, x;
|
||||
|
||||
const int ymin = (yo - KERNEL < 0) ? 0 : yo - KERNEL;
|
||||
const int ymax = (yo + KERNEL > H - 1) ? H - 1 : yo + KERNEL;
|
||||
const int xmin = (xo - KERNEL < 0) ? 0 : xo - KERNEL;
|
||||
const int xmax = (xo + KERNEL > W - 1) ? W - 1 : xo + KERNEL;
|
||||
// worst case of accumulation is a weight of 48 = 16 + 2 * (11 + 4 + 1)
|
||||
// with a diff of 255, squares. That would a max error of 0x8ee0900,
|
||||
// which fits into 32 bits integers.
|
||||
uint32 w = 0, xm = 0, ym = 0, xxm = 0, xym = 0, yym = 0;
|
||||
org += ymin * stride1;
|
||||
rec += ymin * stride2;
|
||||
|
||||
for (y = ymin; y <= ymax; ++y, org += stride1, rec += stride2)
|
||||
{
|
||||
const int Wy = K[KERNEL + y - yo];
|
||||
|
||||
for (x = xmin; x <= xmax; ++x)
|
||||
{
|
||||
const int Wxy = Wy * K[KERNEL + x - xo];
|
||||
// TODO(skal): inlined assembly
|
||||
w += Wxy;
|
||||
xm += Wxy * org[x];
|
||||
ym += Wxy * rec[x];
|
||||
xxm += Wxy * org[x] * org[x];
|
||||
xym += Wxy * org[x] * rec[x];
|
||||
yym += Wxy * rec[x] * rec[x];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const double iw = 1. / w;
|
||||
const double iwx = xm * iw;
|
||||
const double iwy = ym * iw;
|
||||
double sxx = xxm * iw - iwx * iwx;
|
||||
double syy = yym * iw - iwy * iwy;
|
||||
|
||||
// small errors are possible, due to rounding. Clamp to zero.
|
||||
if (sxx < 0.) sxx = 0.;
|
||||
|
||||
if (syy < 0.) syy = 0.;
|
||||
|
||||
{
|
||||
const double sxsy = sqrt(sxx * syy);
|
||||
const double sxy = xym * iw - iwx * iwy;
|
||||
static const double C11 = (0.01 * 0.01) * (255 * 255);
|
||||
static const double C22 = (0.03 * 0.03) * (255 * 255);
|
||||
static const double C33 = (0.015 * 0.015) * (255 * 255);
|
||||
const double l = (2. * iwx * iwy + C11) / (iwx * iwx + iwy * iwy + C11);
|
||||
const double c = (2. * sxsy + C22) / (sxx + syy + C22);
|
||||
|
||||
const double s = (sxy + C33) / (sxsy + C33);
|
||||
return l * c * s;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double get_ssimfull_kernelg(const uint8 *org, const uint8 *rec,
|
||||
int xo, int yo, int W, int H,
|
||||
const int stride1, const int stride2)
|
||||
{
|
||||
// TODO(skal): use summed tables
|
||||
// worst case of accumulation is a weight of 48 = 16 + 2 * (11 + 4 + 1)
|
||||
// with a diff of 255, squares. That would a max error of 0x8ee0900,
|
||||
// which fits into 32 bits integers.
|
||||
int y_, x_;
|
||||
uint32 xm = 0, ym = 0, xxm = 0, xym = 0, yym = 0;
|
||||
org += (yo - KERNEL) * stride1;
|
||||
org += (xo - KERNEL);
|
||||
rec += (yo - KERNEL) * stride2;
|
||||
rec += (xo - KERNEL);
|
||||
|
||||
for (y_ = 0; y_ < KERNEL_SIZE; ++y_, org += stride1, rec += stride2)
|
||||
{
|
||||
const int Wy = K[y_];
|
||||
|
||||
for (x_ = 0; x_ < KERNEL_SIZE; ++x_)
|
||||
{
|
||||
const int Wxy = Wy * K[x_];
|
||||
// TODO(skal): inlined assembly
|
||||
const int org_x = org[x_];
|
||||
const int rec_x = rec[x_];
|
||||
xm += Wxy * org_x;
|
||||
ym += Wxy * rec_x;
|
||||
xxm += Wxy * org_x * org_x;
|
||||
xym += Wxy * org_x * rec_x;
|
||||
yym += Wxy * rec_x * rec_x;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const double iw = ki_w;
|
||||
const double iwx = xm * iw;
|
||||
const double iwy = ym * iw;
|
||||
double sxx = xxm * iw - iwx * iwx;
|
||||
double syy = yym * iw - iwy * iwy;
|
||||
|
||||
// small errors are possible, due to rounding. Clamp to zero.
|
||||
if (sxx < 0.) sxx = 0.;
|
||||
|
||||
if (syy < 0.) syy = 0.;
|
||||
|
||||
{
|
||||
const double sxsy = sqrt(sxx * syy);
|
||||
const double sxy = xym * iw - iwx * iwy;
|
||||
static const double C11 = (0.01 * 0.01) * (255 * 255);
|
||||
static const double C22 = (0.03 * 0.03) * (255 * 255);
|
||||
static const double C33 = (0.015 * 0.015) * (255 * 255);
|
||||
const double l = (2. * iwx * iwy + C11) / (iwx * iwx + iwy * iwy + C11);
|
||||
const double c = (2. * sxsy + C22) / (sxx + syy + C22);
|
||||
const double s = (sxy + C33) / (sxsy + C33);
|
||||
return l * c * s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double calc_ssimg(const uint8 *org, const uint8 *rec,
|
||||
const int image_width, const int image_height,
|
||||
const int stride1, const int stride2
|
||||
)
|
||||
{
|
||||
int j, i;
|
||||
double SSIM = 0.;
|
||||
|
||||
for (j = 0; j < KERNEL; ++j)
|
||||
{
|
||||
for (i = 0; i < image_width; ++i)
|
||||
{
|
||||
SSIM += get_ssimg(org, rec, i, j, image_width, image_height, stride1, stride2);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = KERNEL; j < image_height - KERNEL; ++j)
|
||||
{
|
||||
for (i = 0; i < KERNEL; ++i)
|
||||
{
|
||||
SSIM += get_ssimg(org, rec, i, j, image_width, image_height, stride1, stride2);
|
||||
}
|
||||
|
||||
for (i = KERNEL; i < image_width - KERNEL; ++i)
|
||||
{
|
||||
SSIM += get_ssimfull_kernelg(org, rec, i, j,
|
||||
image_width, image_height, stride1, stride2);
|
||||
}
|
||||
|
||||
for (i = image_width - KERNEL; i < image_width; ++i)
|
||||
{
|
||||
SSIM += get_ssimg(org, rec, i, j, image_width, image_height, stride1, stride2);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = image_height - KERNEL; j < image_height; ++j)
|
||||
{
|
||||
for (i = 0; i < image_width; ++i)
|
||||
{
|
||||
SSIM += get_ssimg(org, rec, i, j, image_width, image_height, stride1, stride2);
|
||||
}
|
||||
}
|
||||
|
||||
return SSIM;
|
||||
}
|
||||
|
||||
|
||||
double vp8_calc_ssimg
|
||||
(
|
||||
YV12_BUFFER_CONFIG *source,
|
||||
YV12_BUFFER_CONFIG *dest,
|
||||
double *ssim_y,
|
||||
double *ssim_u,
|
||||
double *ssim_v
|
||||
)
|
||||
{
|
||||
double ssim_all = 0;
|
||||
int ysize = source->y_width * source->y_height;
|
||||
int uvsize = ysize / 4;
|
||||
|
||||
*ssim_y = calc_ssimg(source->y_buffer, dest->y_buffer,
|
||||
source->y_width, source->y_height,
|
||||
source->y_stride, dest->y_stride);
|
||||
|
||||
|
||||
*ssim_u = calc_ssimg(source->u_buffer, dest->u_buffer,
|
||||
source->uv_width, source->uv_height,
|
||||
source->uv_stride, dest->uv_stride);
|
||||
|
||||
|
||||
*ssim_v = calc_ssimg(source->v_buffer, dest->v_buffer,
|
||||
source->uv_width, source->uv_height,
|
||||
source->uv_stride, dest->uv_stride);
|
||||
|
||||
ssim_all = (*ssim_y + *ssim_u + *ssim_v) / (ysize + uvsize + uvsize);
|
||||
*ssim_y /= ysize;
|
||||
*ssim_u /= uvsize;
|
||||
*ssim_v /= uvsize;
|
||||
return ssim_all;
|
||||
}
|
||||
|
||||
|
||||
void ssim_parms_c
|
||||
|
@ -369,10 +152,10 @@ long dssim(unsigned char *s,int sp, unsigned char *r,int rp,
|
|||
ssim3=0;
|
||||
return (long)( ssim3 );
|
||||
}
|
||||
// TODO: (jbb) this 8x8 window might be too big + we may want to pick pixels
|
||||
// such that the window regions overlap block boundaries to penalize blocking
|
||||
// artifacts.
|
||||
|
||||
// We are using a 8x8 moving window with starting location of each 8x8 window
|
||||
// on the 4x4 pixel grid. Such arrangement allows the windows to overlap
|
||||
// block boundaries to penalize blocking artifacts.
|
||||
double vp8_ssim2
|
||||
(
|
||||
unsigned char *img1,
|
||||
|
@ -388,7 +171,7 @@ double vp8_ssim2
|
|||
int samples =0;
|
||||
double ssim_total=0;
|
||||
|
||||
// we can sample points as frequently as we like start with 1 per 4x4
|
||||
// sample point start with each 4x4 location
|
||||
for(i=0; i < height-8; i+=4, img1 += stride_img1*4, img2 += stride_img2*4)
|
||||
{
|
||||
for(j=0; j < width-8; j+=4 )
|
||||
|
@ -400,7 +183,6 @@ double vp8_ssim2
|
|||
}
|
||||
ssim_total /= samples;
|
||||
return ssim_total;
|
||||
|
||||
}
|
||||
double vp8_calc_ssim
|
||||
(
|
||||
|
@ -431,4 +213,36 @@ double vp8_calc_ssim
|
|||
*weight = 1;
|
||||
|
||||
return ssimv;
|
||||
}
|
||||
|
||||
double vp8_calc_ssimg
|
||||
(
|
||||
YV12_BUFFER_CONFIG *source,
|
||||
YV12_BUFFER_CONFIG *dest,
|
||||
double *ssim_y,
|
||||
double *ssim_u,
|
||||
double *ssim_v,
|
||||
const vp8_variance_rtcd_vtable_t *rtcd
|
||||
)
|
||||
{
|
||||
double ssim_all = 0;
|
||||
double a, b, c;
|
||||
|
||||
a = vp8_ssim2(source->y_buffer, dest->y_buffer,
|
||||
source->y_stride, dest->y_stride, source->y_width,
|
||||
source->y_height, rtcd);
|
||||
|
||||
b = vp8_ssim2(source->u_buffer, dest->u_buffer,
|
||||
source->uv_stride, dest->uv_stride, source->uv_width,
|
||||
source->uv_height, rtcd);
|
||||
|
||||
c = vp8_ssim2(source->v_buffer, dest->v_buffer,
|
||||
source->uv_stride, dest->uv_stride, source->uv_width,
|
||||
source->uv_height, rtcd);
|
||||
*ssim_y = a;
|
||||
*ssim_u = b;
|
||||
*ssim_v = c;
|
||||
ssim_all = (a * 4 + b + c) /6;
|
||||
|
||||
return ssim_all;
|
||||
}
|
Загрузка…
Ссылка в новой задаче