Commit 8b0a5b87 authored by Debargha Mukherjee's avatar Debargha Mukherjee

Adding loop wiener restoration

Adds a wiener filter based restoration scheme in loop which can
be optionally selected instead of the bilateral filter.

The LMMSE filter generated per frame is a separable symmetric 7
tap filter. Three parameters for each of horizontal and vertical
filters are transmitted in the bitstream. The fourth parameter
is obtained assuming the sum is normalized to 1.
Also integerizes the bilateral filters, along with other
refactoring necessary in order to support the new switchable
restoration type framework.

derflr: -0.75% BDRATE

[A lot of videos still prefer bilateral, however since many frames
now use the simpler separable filter, the decoding speed is
much better].

Further experiments to follow, related to replacing the bilateral.

Change-Id: I6b1879983d50aab7ec5647340b6aef6b22299636
parent 13efa8a0
......@@ -1568,8 +1568,7 @@ void vp10_setup_past_independence(VP10_COMMON *cm) {
// To force update of the sharpness
lf->last_sharpness_level = -1;
#if CONFIG_LOOP_RESTORATION
lf->restoration_level = 0;
lf->last_restoration_level = 0;
cm->rst_info.restoration_level = -1;
#endif // CONFIG_LOOP_RESTORATION
vp10_default_coef_probs(cm);
......
......@@ -52,11 +52,6 @@ struct loopfilter {
// 0 = ZERO_MV, MV
signed char mode_deltas[MAX_MODE_LF_DELTAS];
signed char last_mode_deltas[MAX_MODE_LF_DELTAS];
#if CONFIG_LOOP_RESTORATION
int restoration_level;
int last_restoration_level;
#endif // CONFIG_LOOP_RESTORATION
};
// Need to align this structure so when it is declared and
......
......@@ -258,7 +258,8 @@ typedef struct VP10Common {
loop_filter_info_n lf_info;
#if CONFIG_LOOP_RESTORATION
restoration_info_n rst_info;
RestorationInfo rst_info;
RestorationInternal rst_internal;
#endif // CONFIG_LOOP_RESTORATION
// Flag signaling how frame contexts should be updated at the end of
......
This diff is collapsed.
......@@ -26,74 +26,54 @@ extern "C" {
#define RESTORATION_LEVELS (1 << RESTORATION_LEVEL_BITS)
#define DEF_RESTORATION_LEVEL 2
#define RESTORATION_PRECISION 16
#define RESTORATION_HALFWIN 3
#define RESTORATION_HALFWIN1 (RESTORATION_HALFWIN + 1)
#define RESTORATION_WIN (2 * RESTORATION_HALFWIN + 1)
#define RESTORATION_WIN2 ((RESTORATION_WIN) * (RESTORATION_WIN))
typedef struct restoration_params {
int sigma_x; // spatial variance x
int sigma_y; // spatial variance y
int sigma_r; // range variance
} restoration_params_t;
#define RESTORATION_FILT_BITS 7
#define RESTORATION_FILT_STEP (1 << RESTORATION_FILT_BITS)
static restoration_params_t
restoration_level_to_params_arr[RESTORATION_LEVELS + 1] = {
// Values are rounded to 1/16 th precision
{0, 0, 0}, // 0 - default
{8, 9, 30},
{9, 8, 30},
{9, 11, 32},
{11, 9, 32},
{14, 14, 32},
{18, 18, 36},
{24, 24, 40},
{32, 32, 40},
};
#define WIENER_FILT_TAP0_MINV 3
#define WIENER_FILT_TAP1_MINV (-23)
#define WIENER_FILT_TAP2_MINV 5
static restoration_params_t
restoration_level_to_params_arr_kf[RESTORATION_LEVELS_KF + 1] = {
// Values are rounded to 1/16 th precision
{0, 0, 0}, // 0 - default
{8, 8, 30},
{9, 9, 32},
{10, 10, 32},
{12, 12, 32},
{14, 14, 32},
{18, 18, 36},
{24, 24, 40},
{30, 30, 44},
{36, 36, 48},
{42, 42, 48},
{48, 48, 48},
{48, 48, 56},
{56, 56, 48},
{56, 56, 56},
{56, 56, 64},
{64, 64, 48},
};
#define WIENER_FILT_TAP0_BITS 2
#define WIENER_FILT_TAP1_BITS 4
#define WIENER_FILT_TAP2_BITS 5
typedef struct {
double *wx_lut[RESTORATION_WIN];
double *wr_lut;
int restoration_sigma_x_set;
int restoration_sigma_y_set;
int restoration_sigma_r_set;
int restoration_used;
} restoration_info_n;
#define WIENER_FILT_TAP0_MAXV \
(WIENER_FILT_TAP0_MINV -1 + (1 << WIENER_FILT_TAP0_BITS))
#define WIENER_FILT_TAP1_MAXV \
(WIENER_FILT_TAP1_MINV -1 + (1 << WIENER_FILT_TAP1_BITS))
#define WIENER_FILT_TAP2_MAXV \
(WIENER_FILT_TAP2_MINV -1 + (1 << WIENER_FILT_TAP2_BITS))
typedef enum {
RESTORE_NONE,
RESTORE_BILATERAL,
RESTORE_WIENER,
} RestorationType;
int vp10_restoration_level_bits(const struct VP10Common *const cm);
int vp10_loop_restoration_used(int level, int kf);
typedef struct {
RestorationType restoration_type;
int restoration_level;
int vfilter[RESTORATION_HALFWIN], hfilter[RESTORATION_HALFWIN];
} RestorationInfo;
static INLINE restoration_params_t vp10_restoration_level_to_params(
int index, int kf) {
return kf ? restoration_level_to_params_arr_kf[index] :
restoration_level_to_params_arr[index];
}
typedef struct {
RestorationType restoration_type;
uint8_t *wx_lut[RESTORATION_WIN];
uint8_t *wr_lut;
int vfilter[RESTORATION_WIN], hfilter[RESTORATION_WIN];
} RestorationInternal;
void vp10_loop_restoration_init(restoration_info_n *rst, int T, int kf);
int vp10_restoration_level_bits(const struct VP10Common *const cm);
void vp10_loop_restoration_init(RestorationInternal *rst,
RestorationInfo *rsi, int kf);
void vp10_loop_restoration_frame(YV12_BUFFER_CONFIG *frame,
struct VP10Common *cm,
int restoration_level,
RestorationInfo *rsi,
int y_only, int partial_frame);
void vp10_loop_restoration_rows(YV12_BUFFER_CONFIG *frame,
struct VP10Common *cm,
......
......@@ -2126,6 +2126,36 @@ static void setup_segmentation(VP10_COMMON *const cm,
}
}
#if CONFIG_LOOP_RESTORATION
static void setup_restoration(VP10_COMMON *cm,
struct vpx_read_bit_buffer *rb) {
RestorationInfo *rst = &cm->rst_info;
if (vpx_rb_read_bit(rb)) {
if (vpx_rb_read_bit(rb)) {
rst->restoration_type = RESTORE_BILATERAL;
rst->restoration_level =
vpx_rb_read_literal(rb, vp10_restoration_level_bits(cm));
} else {
rst->restoration_type = RESTORE_WIENER;
rst->vfilter[0] = vpx_rb_read_literal(rb, WIENER_FILT_TAP0_BITS) +
WIENER_FILT_TAP0_MINV;
rst->vfilter[1] = vpx_rb_read_literal(rb, WIENER_FILT_TAP1_BITS) +
WIENER_FILT_TAP1_MINV;
rst->vfilter[2] = vpx_rb_read_literal(rb, WIENER_FILT_TAP2_BITS) +
WIENER_FILT_TAP2_MINV;
rst->hfilter[0] = vpx_rb_read_literal(rb, WIENER_FILT_TAP0_BITS) +
WIENER_FILT_TAP0_MINV;
rst->hfilter[1] = vpx_rb_read_literal(rb, WIENER_FILT_TAP1_BITS) +
WIENER_FILT_TAP1_MINV;
rst->hfilter[2] = vpx_rb_read_literal(rb, WIENER_FILT_TAP2_BITS) +
WIENER_FILT_TAP2_MINV;
}
} else {
rst->restoration_type = RESTORE_NONE;
}
}
#endif // CONFIG_LOOP_RESTORATION
static void setup_loopfilter(VP10_COMMON *cm,
struct vpx_read_bit_buffer *rb) {
struct loopfilter *lf = &cm->lf;
......@@ -2151,19 +2181,6 @@ static void setup_loopfilter(VP10_COMMON *cm,
lf->mode_deltas[i] = vpx_rb_read_inv_signed_literal(rb, 6);
}
}
#if CONFIG_LOOP_RESTORATION
lf->restoration_level = vpx_rb_read_bit(rb);
if (lf->restoration_level) {
int level = vpx_rb_read_literal(rb, vp10_restoration_level_bits(cm));
lf->restoration_level = level + (level >= lf->last_restoration_level);
} else {
lf->restoration_level = lf->last_restoration_level;
}
if (cm->frame_type != KEY_FRAME)
cm->lf.last_restoration_level = cm->lf.restoration_level;
else
cm->lf.last_restoration_level = 0;
#endif // CONFIG_LOOP_RESTORATION
}
static INLINE int read_delta_q(struct vpx_read_bit_buffer *rb) {
......@@ -3135,6 +3152,9 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
vp10_setup_past_independence(cm);
setup_loopfilter(cm, rb);
#if CONFIG_LOOP_RESTORATION
setup_restoration(cm, rb);
#endif // CONFIG_LOOP_RESTORATION
setup_quantization(cm, rb);
#if CONFIG_VP9_HIGHBITDEPTH
xd->bd = (int)cm->bit_depth;
......@@ -3499,9 +3519,10 @@ void vp10_decode_frame(VP10Decoder *pbi,
*p_data_end = decode_tiles(pbi, data + first_partition_size, data_end);
}
#if CONFIG_LOOP_RESTORATION
vp10_loop_restoration_init(&cm->rst_info, cm->lf.restoration_level,
cm->frame_type == KEY_FRAME);
if (cm->rst_info.restoration_used) {
if (cm->rst_info.restoration_type != RESTORE_NONE) {
vp10_loop_restoration_init(&cm->rst_internal,
&cm->rst_info,
cm->frame_type == KEY_FRAME);
vp10_loop_restoration_rows(new_fb, cm, 0, cm->mi_rows, 0);
}
#endif // CONFIG_LOOP_RESTORATION
......
......@@ -1795,6 +1795,35 @@ static void update_coef_probs(VP10_COMP *cpi, vpx_writer* w) {
}
}
#if CONFIG_LOOP_RESTORATION
static void encode_restoration(VP10_COMMON *cm,
struct vpx_write_bit_buffer *wb) {
RestorationInfo *rst = &cm->rst_info;
vpx_wb_write_bit(wb, rst->restoration_type != RESTORE_NONE);
if (rst->restoration_type != RESTORE_NONE) {
if (rst->restoration_type == RESTORE_BILATERAL) {
vpx_wb_write_bit(wb, 1);
vpx_wb_write_literal(wb, rst->restoration_level,
vp10_restoration_level_bits(cm));
} else {
vpx_wb_write_bit(wb, 0);
vpx_wb_write_literal(
wb, rst->vfilter[0] - WIENER_FILT_TAP0_MINV, WIENER_FILT_TAP0_BITS);
vpx_wb_write_literal(
wb, rst->vfilter[1] - WIENER_FILT_TAP1_MINV, WIENER_FILT_TAP1_BITS);
vpx_wb_write_literal(
wb, rst->vfilter[2] - WIENER_FILT_TAP2_MINV, WIENER_FILT_TAP2_BITS);
vpx_wb_write_literal(
wb, rst->hfilter[0] - WIENER_FILT_TAP0_MINV, WIENER_FILT_TAP0_BITS);
vpx_wb_write_literal(
wb, rst->hfilter[1] - WIENER_FILT_TAP1_MINV, WIENER_FILT_TAP1_BITS);
vpx_wb_write_literal(
wb, rst->hfilter[2] - WIENER_FILT_TAP2_MINV, WIENER_FILT_TAP2_BITS);
}
}
}
#endif // CONFIG_LOOP_RESTORATION
static void encode_loopfilter(VP10_COMMON *cm,
struct vpx_write_bit_buffer *wb) {
int i;
......@@ -1832,15 +1861,6 @@ static void encode_loopfilter(VP10_COMMON *cm,
}
}
}
#if CONFIG_LOOP_RESTORATION
vpx_wb_write_bit(wb, lf->restoration_level != lf->last_restoration_level);
if (lf->restoration_level != lf->last_restoration_level) {
int level = lf->restoration_level -
(lf->restoration_level > lf->last_restoration_level);
vpx_wb_write_literal(wb, level,
vp10_restoration_level_bits(cm));
}
#endif // CONFIG_LOOP_RESTORATION
}
static void write_delta_q(struct vpx_write_bit_buffer *wb, int delta_q) {
......@@ -2300,6 +2320,9 @@ static void write_uncompressed_header(VP10_COMP *cpi,
vpx_wb_write_literal(wb, cm->frame_context_idx, FRAME_CONTEXTS_LOG2);
encode_loopfilter(cm, wb);
#if CONFIG_LOOP_RESTORATION
encode_restoration(cm, wb);
#endif // CONFIG_LOOP_RESTORATION
encode_quantization(cm, wb);
encode_segmentation(cm, xd, wb);
if (!cm->seg.enabled && xd->lossless[0])
......
......@@ -36,6 +36,9 @@
#include "vp10/encoder/firstpass.h"
#include "vp10/encoder/mbgraph.h"
#include "vp10/encoder/picklpf.h"
#if CONFIG_LOOP_RESTORATION
#include "vp10/encoder/pickrst.h"
#endif // CONFIG_LOOP_RESTORATION
#include "vp10/encoder/ratectrl.h"
#include "vp10/encoder/rd.h"
#include "vp10/encoder/resize.h"
......@@ -2738,7 +2741,11 @@ static void loopfilter_frame(VP10_COMP *cpi, VP10_COMMON *cm) {
vpx_usec_timer_start(&timer);
#if CONFIG_LOOP_RESTORATION
vp10_pick_filter_restoration(cpi->Source, cpi, cpi->sf.lpf_pick);
#else
vp10_pick_filter_level(cpi->Source, cpi, cpi->sf.lpf_pick);
#endif // CONFIG_LOOP_RESTORATION
vpx_usec_timer_mark(&timer);
cpi->time_pick_lpf += vpx_usec_timer_elapsed(&timer);
......@@ -2758,10 +2765,11 @@ static void loopfilter_frame(VP10_COMP *cpi, VP10_COMMON *cm) {
#endif
}
#if CONFIG_LOOP_RESTORATION
vp10_loop_restoration_init(&cm->rst_info, cm->lf.restoration_level,
cm->frame_type == KEY_FRAME);
if (cm->rst_info.restoration_used)
if (cm->rst_info.restoration_type != RESTORE_NONE) {
vp10_loop_restoration_init(&cm->rst_internal, &cm->rst_info,
cm->frame_type == KEY_FRAME);
vp10_loop_restoration_rows(cm->frame_to_show, cm, 0, cm->mi_rows, 0);
}
#endif // CONFIG_LOOP_RESTORATION
vpx_extend_frame_inner_borders(cm->frame_to_show);
......@@ -3871,12 +3879,6 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
cm->last2_frame_type = cm->last_frame_type;
#endif // CONFIG_EXT_REFS
cm->last_frame_type = cm->frame_type;
#if CONFIG_LOOP_RESTORATION
if (cm->frame_type != KEY_FRAME)
cm->lf.last_restoration_level = cm->lf.restoration_level;
else
cm->lf.last_restoration_level = 0;
#endif // CONFIG_LOOP_RESTORATION
vp10_rc_postencode_update(cpi, *size);
......
......@@ -25,7 +25,7 @@
#include "vp10/encoder/picklpf.h"
#include "vp10/encoder/quantize.h"
static int get_max_filter_level(const VP10_COMP *cpi) {
int vp10_get_max_filter_level(const VP10_COMP *cpi) {
if (cpi->oxcf.pass == 2) {
return cpi->twopass.section_intra_rating > 8 ? MAX_LOOP_FILTER * 3 / 4
: MAX_LOOP_FILTER;
......@@ -34,8 +34,6 @@ static int get_max_filter_level(const VP10_COMP *cpi) {
}
}
#if !CONFIG_LOOP_RESTORATION
#if !JOINT_FILTER_RESTORATION_SEARCH
static int64_t try_filter_frame(const YV12_BUFFER_CONFIG *sd,
VP10_COMP *const cpi,
int filt_level, int partial_frame) {
......@@ -71,191 +69,17 @@ static int64_t try_filter_frame(const YV12_BUFFER_CONFIG *sd,
return filt_err;
}
#endif
#endif
#if CONFIG_LOOP_RESTORATION
#define JOINT_FILTER_RESTORATION_SEARCH
#define USE_RD_LOOP_POSTFILTER_SEARCH
static int try_restoration_frame(const YV12_BUFFER_CONFIG *sd,
VP10_COMP *const cpi,
int restoration_level,
int partial_frame) {
VP10_COMMON *const cm = &cpi->common;
int filt_err;
vp10_loop_restoration_frame(cm->frame_to_show, cm,
restoration_level, 1, partial_frame);
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
filt_err = vp10_highbd_get_y_sse(sd, cm->frame_to_show);
} else {
filt_err = vp10_get_y_sse(sd, cm->frame_to_show);
}
#else
filt_err = vp10_get_y_sse(sd, cm->frame_to_show);
#endif // CONFIG_VP9_HIGHBITDEPTH
// Re-instate the unfiltered frame
vpx_yv12_copy_y(&cpi->last_frame_db, cm->frame_to_show);
return filt_err;
}
static int search_restoration_level(const YV12_BUFFER_CONFIG *sd,
VP10_COMP *cpi,
int filter_level, int partial_frame,
double *best_cost_ret) {
VP10_COMMON *const cm = &cpi->common;
int i, restoration_best, err;
double best_cost;
double cost;
const int restoration_level_bits = vp10_restoration_level_bits(&cpi->common);
const int restoration_levels = 1 << restoration_level_bits;
#ifdef USE_RD_LOOP_POSTFILTER_SEARCH
MACROBLOCK *x = &cpi->td.mb;
int bits;
#endif
// Make a copy of the unfiltered / processed recon buffer
vpx_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
vp10_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filter_level,
1, partial_frame);
vpx_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db);
restoration_best = 0;
err = try_restoration_frame(sd, cpi, 0, partial_frame);
#ifdef USE_RD_LOOP_POSTFILTER_SEARCH
bits = cm->lf.last_restoration_level == 0 ? 0 : restoration_level_bits;
cost = RDCOST_DBL(x->rdmult, x->rddiv, (bits << 2), err);
#else
cost = (double)err;
#endif // USE_RD_LOOP_POSTFILTER_SEARCH
best_cost = cost;
for (i = 1; i <= restoration_levels; ++i) {
err = try_restoration_frame(sd, cpi, i, partial_frame);
#ifdef USE_RD_LOOP_POSTFILTER_SEARCH
// Normally the rate is rate in bits * 256 and dist is sum sq err * 64
// when RDCOST is used. However below we just scale both in the correct
// ratios appropriately but not exactly by these values.
bits = cm->lf.last_restoration_level == i ? 0 : restoration_level_bits;
cost = RDCOST_DBL(x->rdmult, x->rddiv, (bits << 2), err);
#else
cost = (double)err;
#endif // USE_RD_LOOP_POSTFILTER_SEARCH
if (cost < best_cost) {
restoration_best = i;
best_cost = cost;
}
}
if (best_cost_ret) *best_cost_ret = best_cost;
vpx_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
return restoration_best;
}
#ifdef JOINT_FILTER_RESTORATION_SEARCH
static int search_filter_restoration_level(const YV12_BUFFER_CONFIG *sd,
VP10_COMP *cpi,
int partial_frame,
int *restoration_level) {
int vp10_search_filter_level(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
int partial_frame, double *best_cost_ret) {
const VP10_COMMON *const cm = &cpi->common;
const struct loopfilter *const lf = &cm->lf;
const int min_filter_level = 0;
const int max_filter_level = get_max_filter_level(cpi);
int filt_direction = 0;
int filt_best, restoration_best;
double best_err;
int i;
// Start the search at the previous frame filter level unless it is now out of
// range.
int filt_mid = clamp(lf->filter_level, min_filter_level, max_filter_level);
int filter_step = filt_mid < 16 ? 4 : filt_mid / 4;
double ss_err[MAX_LOOP_FILTER + 1];
int bilateral;
// Set each entry to -1
for (i = 0; i <= MAX_LOOP_FILTER; ++i)
ss_err[i] = -1.0;
bilateral = search_restoration_level(sd, cpi, filt_mid,
partial_frame, &best_err);
filt_best = filt_mid;
restoration_best = bilateral;
ss_err[filt_mid] = best_err;
while (filter_step > 0) {
const int filt_high = VPXMIN(filt_mid + filter_step, max_filter_level);
const int filt_low = VPXMAX(filt_mid - filter_step, min_filter_level);
// Bias against raising loop filter in favor of lowering it.
double bias = (best_err / (1 << (15 - (filt_mid / 8)))) * filter_step;
if ((cpi->oxcf.pass == 2) && (cpi->twopass.section_intra_rating < 20))
bias = (bias * cpi->twopass.section_intra_rating) / 20;
// yx, bias less for large block size
if (cm->tx_mode != ONLY_4X4)
bias /= 2;
if (filt_direction <= 0 && filt_low != filt_mid) {
// Get Low filter error score
if (ss_err[filt_low] < 0) {
bilateral = search_restoration_level(sd, cpi, filt_low,
partial_frame,
&ss_err[filt_low]);
}
// If value is close to the best so far then bias towards a lower loop
// filter value.
if ((ss_err[filt_low] - bias) < best_err) {
// Was it actually better than the previous best?
if (ss_err[filt_low] < best_err) {
best_err = ss_err[filt_low];
}
filt_best = filt_low;
restoration_best = bilateral;
}
}
// Now look at filt_high
if (filt_direction >= 0 && filt_high != filt_mid) {
if (ss_err[filt_high] < 0) {
bilateral = search_restoration_level(sd, cpi, filt_high, partial_frame,
&ss_err[filt_high]);
}
// Was it better than the previous best?
if (ss_err[filt_high] < (best_err - bias)) {
best_err = ss_err[filt_high];
filt_best = filt_high;
restoration_best = bilateral;
}
}
// Half the step distance if the best filter value was the same as last time
if (filt_best == filt_mid) {
filter_step /= 2;
filt_direction = 0;
} else {
filt_direction = (filt_best < filt_mid) ? -1 : 1;
filt_mid = filt_best;
}
}
*restoration_level = restoration_best;
return filt_best;
}
#endif // JOINT_FILTER_RESTORATION_SEARCH
#endif // CONFIG_LOOP_RESTORATION
#if !CONFIG_LOOP_RESTORATION
#if !JOINT_FILTER_RESTORATION_SEARCH
static int search_filter_level(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
int partial_frame) {
const VP10_COMMON *const cm = &cpi->common;
const struct loopfilter *const lf = &cm->lf;
const int min_filter_level = 0;
const int max_filter_level = get_max_filter_level(cpi);
const int max_filter_level = vp10_get_max_filter_level(cpi);
int filt_direction = 0;
int64_t best_err;
int filt_best;
MACROBLOCK *x = &cpi->td.mb;
// Start the search at the previous frame filter level unless it is now out of
// range.
......@@ -325,12 +149,12 @@ static int search_filter_level(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
filt_mid = filt_best;
}
}
if (best_cost_ret)
*best_cost_ret = RDCOST_DBL(x->rdmult, x->rddiv, 0, best_err);
return filt_best;
}
#endif
#endif
#if !CONFIG_LOOP_RESTORATION
void vp10_pick_filter_level(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
LPF_PICK_METHOD method) {
VP10_COMMON *const cm = &cpi->common;
......@@ -343,7 +167,7 @@ void vp10_pick_filter_level(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
lf->filter_level = 0;
} else if (method >= LPF_PICK_FROM_Q) {
const int min_filter_level = 0;
const int max_filter_level = get_max_filter_level(cpi);
const int max_filter_level = vp10_get_max_filter_level(cpi);
const int q = vp10_ac_quant(cm->base_qindex, 0, cm->bit_depth);
// These values were determined by linear fitting the result of the
// searched level, filt_guess = q * 0.316206 + 3.87252
......@@ -370,24 +194,9 @@ void vp10_pick_filter_level(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
if (cm->frame_type == KEY_FRAME)
filt_guess -= 4;
lf->filter_level = clamp(filt_guess, min_filter_level, max_filter_level);
#if CONFIG_LOOP_RESTORATION
lf->restoration_level = search_restoration_level(
sd, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE, NULL);
#endif // CONFIG_LOOP_RESTORATION
} else {
#if CONFIG_LOOP_RESTORATION
#ifdef JOINT_FILTER_RESTORATION_SEARCH
lf->filter_level = search_filter_restoration_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, &lf->restoration_level);
#else
lf->filter_level = search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE);
lf->restoration_level = search_restoration_level(
sd, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE, NULL);
#endif // JOINT_FILTER_RESTORATION_SEARCH
#else
lf->filter_level = search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE);
#endif // CONFIG_LOOP_RESTORATION
lf->filter_level = vp10_search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL);
}
}
#endif // !CONFIG_LOOP_RESTORATION
......@@ -20,9 +20,11 @@ extern "C" {
struct yv12_buffer_config;
struct VP10_COMP;
int vp10_get_max_filter_level(const VP10_COMP *cpi);
int vp10_search_filter_level(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
int partial_frame, double *err);
void vp10_pick_filter_level(const struct yv12_buffer_config *sd,
struct VP10_COMP *cpi, LPF_PICK_METHOD method);
struct VP10_COMP *cpi, LPF_PICK_METHOD method);
#ifdef __cplusplus
} // extern "C"
#endif
......
This diff is collapsed.
/*
* Copyright (c) 2010 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.
*/
#ifndef VP10_ENCODER_PICKRST_H_
#define VP10_ENCODER_PICKRST_H_