Files
vpx/vp10/encoder/pickdering.c
Yaowu Xu 253c001f8f Port dering experiment from aom
Mannually cherry-picked:
1579133 Use OD_DIVU for small divisions in temporal_filter.
0312229 Replace divides by small values with multiplies.
9c48eec Removing divisions from od_dir_find8()
0950ed8 Merge "Port active map / cyclic refresh fixes to vp10."
efefdad Port active map / cyclic refresh fixes to vp10.
1eaf748 Port switch to 9-bit rate cost to aom.
0b1606e Only build deringing code when --enable-dering.
e2511e1 Deringing cleanup: don't hardcode the number of levels
8fe5c5d Rename dering_in to od_dering_in to sync with Daala
4eb1380 Makes second filters for 45-degree directions horizontal
7f4c3f5 Removes the superblock variance contribution to the threshold
3dc56f9 Simplifying arithmetic by using multiply+shift
cf2aaba Return 0 explicitly for OD_ILOG(0).
49ca22a Use the Daala implementation of OD_ILOG().
8518724 Fix compiler warning in od_dering.c.
485d6a6 Prevent multiple inclusion of odintrin.h.
51b7a99 Adds the Daala deringing filter as experimental

Note that a few of the changes were already in libvpx codebse.

Change-Id: I1c32ee7694e5ad22c98b06ff97737cd792cd88ae
2016-08-16 13:47:18 +00:00

181 lines
5.8 KiB
C

/*
* Copyright (c) 2015 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string.h>
#include "./vpx_scale_rtcd.h"
#include "vp10/common/dering.h"
#include "vp10/common/onyxc_int.h"
#include "vp10/common/reconinter.h"
#include "vp10/encoder/encoder.h"
#include "vpx/vpx_integer.h"
static double compute_dist(int16_t *x, int xstride, int16_t *y, int ystride,
int nhb, int nvb, int coeff_shift) {
int i, j;
double sum;
sum = 0;
for (i = 0; i < nvb << 3; i++) {
for (j = 0; j < nhb << 3; j++) {
double tmp;
tmp = x[i*xstride + j] - y[i*ystride + j];
sum += tmp*tmp;
}
}
return sum/(double)(1 << 2*coeff_shift);
}
int vp10_dering_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
VP10_COMMON *cm,
MACROBLOCKD *xd) {
int r, c;
int sbr, sbc;
int nhsb, nvsb;
od_dering_in *src;
int16_t *ref_coeff;
unsigned char *bskip;
int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS] = {{0}};
int stride;
int bsize[3];
int dec[3];
int pli;
int (*mse)[MAX_DERING_LEVEL];
int best_count[MAX_DERING_LEVEL] = {0};
double tot_mse[MAX_DERING_LEVEL] = {0};
int level;
int best_level;
int global_level;
double best_tot_mse = 1e15;
int coeff_shift = VPXMAX(cm->bit_depth - 8, 0);
src = vpx_malloc(sizeof(*src)*cm->mi_rows*cm->mi_cols*64);
ref_coeff = vpx_malloc(sizeof(*ref_coeff)*cm->mi_rows*cm->mi_cols*64);
bskip = vpx_malloc(sizeof(*bskip)*cm->mi_rows*cm->mi_cols);
vp10_setup_dst_planes(xd->plane, frame, 0, 0);
for (pli = 0; pli < 3; pli++) {
dec[pli] = xd->plane[pli].subsampling_x;
bsize[pli] = 8 >> dec[pli];
}
stride = bsize[0]*cm->mi_cols;
for (r = 0; r < bsize[0]*cm->mi_rows; ++r) {
for (c = 0; c < bsize[0]*cm->mi_cols; ++c) {
#if CONFIG_VPX_HIGHBITDEPTH
if (cm->use_highbitdepth) {
src[r * stride + c] =
CONVERT_TO_SHORTPTR(xd->plane[0].dst.buf)
[r*xd->plane[0].dst.stride + c];
ref_coeff[r * stride + c] =
CONVERT_TO_SHORTPTR(ref->y_buffer)[r * ref->y_stride + c];
} else {
#endif
src[r * stride + c] =
xd->plane[0].dst.buf[r*xd->plane[0].dst.stride + c];
ref_coeff[r * stride + c] = ref->y_buffer[r * ref->y_stride + c];
#if CONFIG_VPX_HIGHBITDEPTH
}
#endif
}
}
for (r = 0; r < cm->mi_rows; ++r) {
for (c = 0; c < cm->mi_cols; ++c) {
const MB_MODE_INFO *mbmi =
&cm->mi_grid_visible[r * cm->mi_stride + c]->mbmi;
bskip[r * cm->mi_cols + c] = mbmi->skip;
}
}
nvsb = (cm->mi_rows + MAX_MIB_SIZE - 1)/MAX_MIB_SIZE;
nhsb = (cm->mi_cols + MAX_MIB_SIZE - 1)/MAX_MIB_SIZE;
mse = vpx_malloc(nvsb*nhsb*sizeof(*mse));
for (sbr = 0; sbr < nvsb; sbr++) {
for (sbc = 0; sbc < nhsb; sbc++) {
int best_mse = 1000000000;
int nvb, nhb;
int16_t dst[MAX_MIB_SIZE*MAX_MIB_SIZE*8*8];
best_level = 0;
nhb = VPXMIN(MAX_MIB_SIZE, cm->mi_cols - MAX_MIB_SIZE*sbc);
nvb = VPXMIN(MAX_MIB_SIZE, cm->mi_rows - MAX_MIB_SIZE*sbr);
for (level = 0; level < 64; level++) {
int threshold;
threshold = level << coeff_shift;
od_dering(
&OD_DERING_VTBL_C,
dst,
MAX_MIB_SIZE*bsize[0],
&src[sbr*stride*bsize[0]*MAX_MIB_SIZE +
sbc*bsize[0]*MAX_MIB_SIZE],
cm->mi_cols*bsize[0], nhb, nvb, sbc, sbr, nhsb, nvsb, 0, dir, 0,
&bskip[MAX_MIB_SIZE*sbr*cm->mi_cols + MAX_MIB_SIZE*sbc],
cm->mi_cols, threshold, OD_DERING_NO_CHECK_OVERLAP, coeff_shift);
mse[nhsb*sbr+sbc][level] = (int)compute_dist(
dst, MAX_MIB_SIZE*bsize[0],
&ref_coeff[sbr*stride*bsize[0]*MAX_MIB_SIZE +
sbc*bsize[0]*MAX_MIB_SIZE],
stride, nhb, nvb, coeff_shift);
tot_mse[level] += mse[nhsb*sbr+sbc][level];
if (mse[nhsb*sbr+sbc][level] < best_mse) {
best_mse = mse[nhsb*sbr+sbc][level];
best_level = level;
}
}
best_count[best_level]++;
}
}
#if DERING_REFINEMENT
best_level = 0;
/* Search for the best global level one value at a time. */
for (global_level = 2; global_level < MAX_DERING_LEVEL; global_level++) {
double tot_mse = 0;
for (sbr = 0; sbr < nvsb; sbr++) {
for (sbc = 0; sbc < nhsb; sbc++) {
int gi;
int best_mse = mse[nhsb*sbr+sbc][0];
for (gi = 1; gi < 4; gi++) {
level = compute_level_from_index(global_level, gi);
if (mse[nhsb*sbr+sbc][level] < best_mse) {
best_mse = mse[nhsb*sbr+sbc][level];
}
}
tot_mse += best_mse;
}
}
if (tot_mse < best_tot_mse) {
best_level = global_level;
best_tot_mse = tot_mse;
}
}
for (sbr = 0; sbr < nvsb; sbr++) {
for (sbc = 0; sbc < nhsb; sbc++) {
int gi;
int best_gi;
int best_mse = mse[nhsb*sbr+sbc][0];
best_gi = 0;
for (gi = 1; gi < DERING_REFINEMENT_LEVELS; gi++) {
level = compute_level_from_index(best_level, gi);
if (mse[nhsb*sbr+sbc][level] < best_mse) {
best_gi = gi;
best_mse = mse[nhsb*sbr+sbc][level];
}
}
cm->mi_grid_visible[MAX_MIB_SIZE*sbr*cm->mi_stride + MAX_MIB_SIZE*sbc]->
mbmi.dering_gain = best_gi;
}
}
#else
best_level = 0;
for (level = 0; level < MAX_DERING_LEVEL; level++) {
if (tot_mse[level] < tot_mse[best_level]) best_level = level;
}
#endif
vpx_free(src);
vpx_free(ref_coeff);
vpx_free(bskip);
vpx_free(mse);
return best_level;
}