Commit 51b7a998 authored by Jean-Marc Valin's avatar Jean-Marc Valin

Adds the Daala deringing filter as experimental

The deringing filter documentation is in:
J.-M. Valin, The Daala Directional Deringing Filter, arXiv:1602.05975 [cs.MM],
2016.
http://arxiv.org/pdf/1602.05975.pdf

ntt-short1 results:
          MEDIUM (%) HIGH (%)
    PSNR  -2.488088 -2.003235
 PSNRHVS  -1.588932 -0.797850
    SSIM  -1.522767 -1.287861
FASTSSIM   4.307822  3.983496

subset1 improvement is around 2-3% on PSNR (but the rate is mostly outside
the AWCY testing range)

Change-Id: Ic02344ce9faa509f5c3a50a0fb7a7b84a7977e72
parent bb2727c2
......@@ -251,6 +251,7 @@ EXPERIMENT_LIST="
emulate_hardware
misc_fixes
clpf
dering
"
CONFIG_LIST="
dependency_tracking
......
......@@ -88,6 +88,8 @@ typedef struct {
// TODO(slavarnway): Delete and use bmi[3].as_mv[] instead.
int_mv mv[2];
/* deringing gain *per-superblock* */
int8_t dering_gain;
} MB_MODE_INFO;
typedef struct MODE_INFO {
......
/*
* 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 <math.h>
#include "./vpx_scale_rtcd.h"
#include "vpx/vpx_integer.h"
#include "vp10/common/dering.h"
#include "vp10/common/onyxc_int.h"
#include "vp10/common/reconinter.h"
#include "vp10/common/od_dering.h"
int compute_level_from_index(int global_level, int gi) {
static const double dering_gains[4] = {0, .7, 1, 1.4};
int level;
if (global_level == 0) return 0;
level = (int)floor(.5 + global_level*dering_gains[gi]);
return clamp(level, gi, MAX_DERING_LEVEL-1);
}
int sb_all_skip(const VP10_COMMON *const cm, int mi_row, int mi_col) {
int r, c;
int maxc, maxr;
int skip = 1;
maxc = cm->mi_cols - mi_col;
maxr = cm->mi_rows - mi_row;
if (maxr > MI_BLOCK_SIZE) maxr = MI_BLOCK_SIZE;
if (maxc > MI_BLOCK_SIZE) maxc = MI_BLOCK_SIZE;
for (r = 0; r < maxr; r++) {
for (c = 0; c < maxc; c++) {
skip = skip &&
cm->mi_grid_visible[(mi_row + r)*cm->mi_stride + mi_col + c]->
mbmi.skip;
}
}
return skip;
}
void vp10_dering_frame(YV12_BUFFER_CONFIG *frame, VP10_COMMON *cm,
MACROBLOCKD *xd, int global_level) {
int r, c;
int sbr, sbc;
int nhsb, nvsb;
dering_in *src[3];
unsigned char *bskip;
int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS] = {{0}};
int stride;
int bsize[3];
int dec[3];
int pli;
int coeff_shift = VPXMAX(cm->bit_depth - 8, 0);
nvsb = (cm->mi_rows + MI_BLOCK_SIZE - 1)/MI_BLOCK_SIZE;
nhsb = (cm->mi_cols + MI_BLOCK_SIZE - 1)/MI_BLOCK_SIZE;
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 (pli = 0; pli < 3; pli++) {
src[pli] = vpx_malloc(sizeof(*src)*cm->mi_rows*cm->mi_cols*64);
for (r = 0; r < bsize[pli]*cm->mi_rows; ++r) {
for (c = 0; c < bsize[pli]*cm->mi_cols; ++c) {
#if CONFIG_VPX_HIGHBITDEPTH
if (cm->use_highbitdepth) {
src[pli][r * stride + c] =
CONVERT_TO_SHORTPTR(xd->plane[pli].dst.buf)
[r * xd->plane[pli].dst.stride + c];
} else {
#endif
src[pli][r * stride + c] =
xd->plane[pli].dst.buf[r * xd->plane[pli].dst.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;
}
}
for (sbr = 0; sbr < nvsb; sbr++) {
for (sbc = 0; sbc < nhsb; sbc++) {
int level;
int nhb, nvb;
nhb = VPXMIN(MI_BLOCK_SIZE, cm->mi_cols - MI_BLOCK_SIZE*sbc);
nvb = VPXMIN(MI_BLOCK_SIZE, cm->mi_rows - MI_BLOCK_SIZE*sbr);
for (pli = 0; pli < 3; pli++) {
int16_t dst[MI_BLOCK_SIZE*MI_BLOCK_SIZE*8*8];
int threshold;
#if DERING_REFINEMENT
level = compute_level_from_index(
global_level,
cm->mi_grid_visible[MI_BLOCK_SIZE*sbr*cm->mi_stride +
MI_BLOCK_SIZE*sbc]->mbmi.dering_gain);
#else
level = global_level;
#endif
/* FIXME: This is a temporary hack that uses more conservative
deringing for chroma. */
if (pli) level = level*2/3;
if (sb_all_skip(cm, sbr*MI_BLOCK_SIZE, sbc*MI_BLOCK_SIZE)) level = 0;
threshold = level << coeff_shift;
od_dering(
&OD_DERING_VTBL_C,
dst,
MI_BLOCK_SIZE*bsize[pli],
&src[pli][sbr*stride*bsize[pli]*MI_BLOCK_SIZE +
sbc*bsize[pli]*MI_BLOCK_SIZE],
stride, nhb, nvb, sbc, sbr, nhsb, nvsb, dec[pli], dir, pli,
&bskip[MI_BLOCK_SIZE*sbr*cm->mi_cols + MI_BLOCK_SIZE*sbc],
cm->mi_cols, threshold, OD_DERING_NO_CHECK_OVERLAP, coeff_shift);
for (r = 0; r < bsize[pli]*nvb; ++r) {
for (c = 0; c < bsize[pli]*nhb; ++c) {
#if CONFIG_VPX_HIGHBITDEPTH
if (cm->use_highbitdepth) {
CONVERT_TO_SHORTPTR(xd->plane[pli].dst.buf)
[xd->plane[pli].dst.stride*(bsize[pli]*MI_BLOCK_SIZE*sbr + r)
+ sbc*bsize[pli]*MI_BLOCK_SIZE + c] =
dst[r * MI_BLOCK_SIZE * bsize[pli] + c];
} else {
#endif
xd->plane[pli].dst.buf[xd->plane[pli].dst.stride*
(bsize[pli]*MI_BLOCK_SIZE*sbr + r) +
sbc*bsize[pli]*MI_BLOCK_SIZE + c] =
dst[r * MI_BLOCK_SIZE * bsize[pli] + c];
#if CONFIG_VPX_HIGHBITDEPTH
}
#endif
}
}
}
}
}
for (pli = 0; pli < 3; pli++) {
vpx_free(src[pli]);
}
vpx_free(bskip);
}
#ifndef VP10_COMMON_DERING_H_
#define VP10_COMMON_DERING_H_
#include "vp10/common/od_dering.h"
#include "vp10/common/onyxc_int.h"
#include "vpx/vpx_integer.h"
#include "./vpx_config.h"
#include "vpx_ports/mem.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DERING_LEVEL_BITS 6
#define MAX_DERING_LEVEL (1 << DERING_LEVEL_BITS)
#define DERING_REFINEMENT 1
int compute_level_from_index(int global_level, int gi);
int sb_all_skip(const VP10_COMMON *const cm, int mi_row, int mi_col);
void vp10_dering_frame(YV12_BUFFER_CONFIG *frame, VP10_COMMON *cm,
MACROBLOCKD *xd, int global_level);
int vp10_dering_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
VP10_COMMON *cm,
MACROBLOCKD *xd);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_DERING_H_
This diff is collapsed.
/*Daala video codec
Copyright (c) 2003-2010 Daala project contributors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
#if !defined(_dering_H)
# define _dering_H (1)
# include "odintrin.h"
# if defined(DAALA_ODINTRIN)
# include "filter.h"
typedef int16_t dering_in;
# endif
#define OD_DERINGSIZES (2)
#define OD_DERING_NO_CHECK_OVERLAP (0)
#define OD_DERING_CHECK_OVERLAP (1)
#define OD_DERING_LEVELS (6)
extern const double OD_DERING_GAIN_TABLE[OD_DERING_LEVELS];
#define OD_DERING_NBLOCKS (OD_BSIZE_MAX/8)
#define OD_FILT_BORDER (3)
#define OD_FILT_BSTRIDE (OD_BSIZE_MAX + 2*OD_FILT_BORDER)
extern const int OD_DIRECTION_OFFSETS_TABLE[8][3];
typedef void (*od_filter_dering_direction_func)(int16_t *y, int ystride,
const int16_t *in, int threshold, int dir);
typedef void (*od_filter_dering_orthogonal_func)(int16_t *y, int ystride,
const int16_t *in, const dering_in *x, int xstride, int threshold, int dir);
struct od_dering_opt_vtbl {
od_filter_dering_direction_func filter_dering_direction[OD_DERINGSIZES];
od_filter_dering_orthogonal_func filter_dering_orthogonal[OD_DERINGSIZES];
};
typedef struct od_dering_opt_vtbl od_dering_opt_vtbl;
void od_dering(const od_dering_opt_vtbl *vtbl, int16_t *y, int ystride,
const dering_in *x, int xstride, int nvb, int nhb, int sbx, int sby, int nhsb,
int nvsb, int xdec, int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS], int pli,
unsigned char *bskip, int skip_stride, int threshold, int overlap,
int coeff_shift);
void od_filter_dering_direction_c(int16_t *y, int ystride, const int16_t *in,
int ln, int threshold, int dir);
void od_filter_dering_orthogonal_c(int16_t *y, int ystride, const int16_t *in,
const dering_in *x, int xstride, int ln, int threshold, int dir);
extern const od_dering_opt_vtbl OD_DERING_VTBL_C;
void od_filter_dering_direction_4x4_c(int16_t *y, int ystride,
const int16_t *in, int threshold, int dir);
void od_filter_dering_direction_8x8_c(int16_t *y, int ystride,
const int16_t *in, int threshold, int dir);
void od_filter_dering_orthogonal_4x4_c(int16_t *y, int ystride,
const int16_t *in, const dering_in *x, int xstride, int threshold, int dir);
void od_filter_dering_orthogonal_8x8_c(int16_t *y, int ystride,
const int16_t *in, const dering_in *x, int xstride, int threshold, int dir);
#endif
#include "vp10/common/enums.h"
#include "vpx/vpx_integer.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_ports/bitops.h"
/*Smallest blocks are 4x4*/
# define OD_LOG_BSIZE0 (2)
/*There are 5 block sizes total (4x4, 8x8, 16x16, 32x32 and 64x64).*/
# define OD_NBSIZES (5)
/*The log of the maximum length of the side of a block.*/
# define OD_LOG_BSIZE_MAX (OD_LOG_BSIZE0 + OD_NBSIZES - 1)
/*The maximum length of the side of a block.*/
# define OD_BSIZE_MAX (1 << OD_LOG_BSIZE_MAX)
typedef int od_coeff;
typedef int16_t dering_in;
#define OD_DIVU_SMALL(_x, _d) ((_x) / (_d))
#define OD_MINI VPXMIN
#define OD_CLAMPI(min, val, max) clamp((val), (min), (max))
# define OD_ILOG_NZ(x) get_msb(x)
/*Note that __builtin_clz is not defined when x == 0, according to the gcc
* documentation (and that of the x86 BSR instruction that implements it), so
* we have to special-case it.
* We define a special version of the macro to use when x can be zero.*/
# define OD_ILOG(x) ((x) ? OD_ILOG_NZ(x) : 0)
......@@ -312,6 +312,9 @@ typedef struct VP10Common {
// - this is intentionally not placed in FRAME_CONTEXT since it's reset upon
// each keyframe and not used afterwards
vpx_prob kf_y_prob[INTRA_MODES][INTRA_MODES][INTRA_MODES - 1];
#if CONFIG_DERING
int dering_level;
#endif
} VP10_COMMON;
// TODO(hkuang): Don't need to lock the whole pool after implementing atomic
......
......@@ -14,6 +14,7 @@
#include "./vp10_rtcd.h"
#include "./vpx_dsp_rtcd.h"
#include "./vpx_scale_rtcd.h"
#include "./vpx_config.h"
#include "vpx_dsp/bitreader_buffer.h"
#include "vpx_dsp/bitreader.h"
......@@ -29,6 +30,9 @@
#include "vp10/common/clpf.h"
#endif
#include "vp10/common/common.h"
#if CONFIG_DERING
#include "vp10/common/dering.h"
#endif // CONFIG_DERING
#include "vp10/common/entropy.h"
#include "vp10/common/entropymode.h"
#include "vp10/common/idct.h"
......@@ -967,6 +971,17 @@ static void decode_partition(VP10Decoder *const pbi, MACROBLOCKD *const xd,
if (bsize >= BLOCK_8X8 &&
(bsize == BLOCK_8X8 || partition != PARTITION_SPLIT))
dec_update_partition_context(xd, mi_row, mi_col, subsize, num_8x8_wh);
#if DERING_REFINEMENT
if (bsize == BLOCK_64X64) {
if (cm->dering_level != 0 && !sb_all_skip(cm, mi_row, mi_col)) {
cm->mi_grid_visible[mi_row*cm->mi_stride + mi_col]->mbmi.dering_gain =
vpx_read_literal(r, 2);
} else {
cm->mi_grid_visible[mi_row*cm->mi_stride + mi_col]->mbmi.dering_gain = 0;
}
}
#endif
}
static void setup_token_decoder(const uint8_t *data, const uint8_t *data_end,
......@@ -1103,6 +1118,12 @@ static void setup_clpf(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) {
}
#endif
#if CONFIG_DERING
static void setup_dering(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) {
cm->dering_level = vpx_rb_read_literal(rb, DERING_LEVEL_BITS);
}
#endif // CONFIG_DERING
static INLINE int read_delta_q(struct vpx_read_bit_buffer *rb) {
return vpx_rb_read_bit(rb)
? vpx_rb_read_inv_signed_literal(rb, CONFIG_MISC_FIXES ? 6 : 4)
......@@ -1603,6 +1624,11 @@ static const uint8_t *decode_tiles(VP10Decoder *pbi, const uint8_t *data,
if (cm->clpf && !cm->skip_loop_filter)
vp10_clpf_frame(&pbi->cur_buf->buf, cm, &pbi->mb);
#endif
#if CONFIG_DERING
if (cm->dering_level && !cm->skip_loop_filter) {
vp10_dering_frame(&pbi->cur_buf->buf, cm, &pbi->mb, cm->dering_level);
}
#endif // CONFIG_DERING
// Get last tile data.
tile_data = pbi->tile_data + tile_cols * tile_rows - 1;
......@@ -2088,6 +2114,9 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
setup_loopfilter(&cm->lf, rb);
#if CONFIG_CLPF
setup_clpf(cm, rb);
#endif
#if CONFIG_DERING
setup_dering(cm, rb);
#endif
setup_quantization(cm, rb);
#if CONFIG_VPX_HIGHBITDEPTH
......
......@@ -22,6 +22,9 @@
#if CONFIG_CLPF
#include "vp10/common/clpf.h"
#endif
#if CONFIG_DERING
#include "vp10/common/dering.h"
#endif // CONFIG_DERING
#include "vp10/common/entropy.h"
#include "vp10/common/entropymode.h"
#include "vp10/common/entropymv.h"
......@@ -602,6 +605,15 @@ static void write_modes_sb(VP10_COMP *cpi, const TileInfo *const tile,
if (bsize >= BLOCK_8X8 &&
(bsize == BLOCK_8X8 || partition != PARTITION_SPLIT))
update_partition_context(xd, mi_row, mi_col, subsize, bsize);
#if DERING_REFINEMENT
if (bsize == BLOCK_64X64 && cm->dering_level != 0 &&
!sb_all_skip(cm, mi_row, mi_col)) {
vpx_write_literal(
w, cm->mi_grid_visible[mi_row*cm->mi_stride + mi_col]->mbmi.dering_gain,
2);
}
#endif
}
static void write_modes(VP10_COMP *cpi, const TileInfo *const tile,
......@@ -848,6 +860,12 @@ static void encode_clpf(const VP10_COMMON *cm,
}
#endif
#if CONFIG_DERING
static void encode_dering(int level, struct vpx_write_bit_buffer *wb) {
vpx_wb_write_literal(wb, level, DERING_LEVEL_BITS);
}
#endif // CONFIG_DERING
static void write_delta_q(struct vpx_write_bit_buffer *wb, int delta_q) {
if (delta_q != 0) {
vpx_wb_write_bit(wb, 1);
......@@ -1317,6 +1335,9 @@ static void write_uncompressed_header(VP10_COMP *cpi,
#if CONFIG_CLPF
encode_clpf(cm, wb);
#endif
#if CONFIG_DERING
encode_dering(cm->dering_level, wb);
#endif // CONFIG_DERING
encode_quantization(cm, wb);
encode_segmentation(cm, xd, wb);
#if CONFIG_MISC_FIXES
......
......@@ -18,6 +18,9 @@
#if CONFIG_CLPF
#include "vp10/common/clpf.h"
#endif
#if CONFIG_DERING
#include "vp10/common/dering.h"
#endif // CONFIG_DERING
#include "vp10/common/filter.h"
#include "vp10/common/idct.h"
#include "vp10/common/reconinter.h"
......@@ -2432,6 +2435,16 @@ static void loopfilter_frame(VP10_COMP *cpi, VP10_COMMON *cm) {
vp10_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level, 0, 0);
}
#if CONFIG_DERING
if (is_lossless_requested(&cpi->oxcf)) {
cm->dering_level = 0;
} else {
cm->dering_level = vp10_dering_search(cm->frame_to_show, cpi->Source, cm,
xd);
vp10_dering_frame(cm->frame_to_show, cm, xd, cm->dering_level);
}
#endif // CONFIG_DERING
#if CONFIG_CLPF
cm->clpf = 0;
if (!is_lossless_requested(&cpi->oxcf)) {
......
/*
* 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;
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 + MI_BLOCK_SIZE - 1)/MI_BLOCK_SIZE;
nhsb = (cm->mi_cols + MI_BLOCK_SIZE - 1)/MI_BLOCK_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[MI_BLOCK_SIZE*MI_BLOCK_SIZE*8*8];
best_level = 0;
nhb = VPXMIN(MI_BLOCK_SIZE, cm->mi_cols - MI_BLOCK_SIZE*sbc);
nvb = VPXMIN(MI_BLOCK_SIZE, cm->mi_rows - MI_BLOCK_SIZE*sbr);
for (level = 0; level < 64; level++) {
int threshold;
threshold = level << coeff_shift;
od_dering(
&OD_DERING_VTBL_C,
dst,
MI_BLOCK_SIZE*bsize[0],
&src[sbr*stride*bsize[0]*MI_BLOCK_SIZE +
sbc*bsize[0]*MI_BLOCK_SIZE],
cm->mi_cols*bsize[0], nhb, nvb, sbc, sbr, nhsb, nvsb, 0, dir, 0,
&bskip[MI_BLOCK_SIZE*sbr*cm->mi_cols + MI_BLOCK_SIZE*sbc],
cm->mi_cols, threshold, OD_DERING_NO_CHECK_OVERLAP, coeff_shift);
mse[nhsb*sbr+sbc][level] = compute_dist(
dst, MI_BLOCK_SIZE*bsize[0],
&ref_coeff[sbr*stride*bsize[0]*MI_BLOCK_SIZE +
sbc*bsize[0]*MI_BLOCK_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 < 4; 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[MI_BLOCK_SIZE*sbr*cm->mi_stride + MI_BLOCK_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;
}
......@@ -62,6 +62,10 @@ VP10_COMMON_SRCS-yes += common/vp10_fwd_txfm.h
VP10_COMMON_SRCS-yes += common/vp10_fwd_txfm.c
VP10_COMMON_SRCS-yes += common/clpf.c
VP10_COMMON_SRCS-yes += common/clpf.h
VP10_COMMON_SRCS-yes += common/od_dering.c
VP10_COMMON_SRCS-yes += common/od_dering.h
VP10_COMMON_SRCS-yes += common/dering.c
VP10_COMMON_SRCS-yes += common/dering.h
ifneq ($(CONFIG_VPX_HIGHBITDEPTH),yes)
VP10_COMMON_SRCS-$(HAVE_DSPR2) += common/mips/dspr2/itrans4_dspr2.c
......
......@@ -79,6 +79,7 @@ VP10_CX_SRCS-yes += encoder/temporal_filter.c
VP10_CX_SRCS-yes += encoder/temporal_filter.h
VP10_CX_SRCS-yes += encoder/mbgraph.c
VP10_CX_SRCS-yes += encoder/mbgraph.h
VP10_CX_SRCS-yes += encoder/pickdering.c