Commit 179479fe authored by Cheng Chen's avatar Cheng Chen

Dual deblocking filter strength thresholds

A new experiment for deblocking filter that separates vertical
and horizontal filter strengths. This experiment is based on the
assumption that non-flatness characteristics of vertical and
horizontal direction may differ. Therefore selecting different
filter strengths for vertical and horizontal can improve deblocking
performance.

The process of finding proper filter strength:
1. Search through the filter level under the constraint that
   (vertical == horizontal), and find the best solution.
2. Fix vertical level as the best solution found in step 1 and vary
   horizontal level to find the best value.
3. Fix the selected horizontal level, vary vertical level to find
   its best value.

The experiment is working with UV_LVL, sharing the same config flag.
The searching for horizontal and vertical filter strength only applies
on Y plane for now.

The experimental flag should be changed to filter_level later.

Change-Id: I164eec8d3ccb3da7ff109c5c55f4b52c1536ddf1
parent 680b9b17
......@@ -595,6 +595,9 @@ static void update_sharpness(loop_filter_info_n *lfi, int sharpness_lvl) {
#if CONFIG_EXT_DELTA_Q
static uint8_t get_filter_level(const AV1_COMMON *cm,
const loop_filter_info_n *lfi_n,
#if CONFIG_UV_LVL
const int dir_idx,
#endif
const MB_MODE_INFO *mbmi) {
#if CONFIG_SUPERTX
const int segment_id = AOMMIN(mbmi->segment_id, mbmi->segment_id_supertx);
......@@ -606,8 +609,14 @@ static uint8_t get_filter_level(const AV1_COMMON *cm,
const int segment_id = mbmi->segment_id;
#endif // CONFIG_SUPERTX
if (cm->delta_lf_present_flag) {
#if CONFIG_UV_LVL
int lvl_seg =
clamp(mbmi->current_delta_lf_from_base + cm->lf.filter_level[dir_idx],
0, MAX_LOOP_FILTER);
#else
int lvl_seg = clamp(mbmi->current_delta_lf_from_base + cm->lf.filter_level,
0, MAX_LOOP_FILTER);
#endif
const int scale = 1 << (lvl_seg >> 5);
if (segfeature_active(&cm->seg, segment_id, SEG_LVL_ALT_LF)) {
const int data = get_segdata(&cm->seg, segment_id, SEG_LVL_ALT_LF);
......@@ -624,7 +633,12 @@ static uint8_t get_filter_level(const AV1_COMMON *cm,
}
return lvl_seg;
} else {
#if CONFIG_UV_LVL
return lfi_n
->lvl[segment_id][dir_idx][mbmi->ref_frame[0]][mode_lf_lut[mbmi->mode]];
#else
return lfi_n->lvl[segment_id][mbmi->ref_frame[0]][mode_lf_lut[mbmi->mode]];
#endif
}
}
#else
......@@ -658,12 +672,13 @@ void av1_loop_filter_init(AV1_COMMON *cm) {
memset(lfi->lfthr[lvl].hev_thr, (lvl >> 4), SIMD_WIDTH);
}
void av1_loop_filter_frame_init(AV1_COMMON *cm, int default_filt_lvl) {
void av1_loop_filter_frame_init(AV1_COMMON *cm, int default_filt_lvl,
int default_filt_lvl_r) {
int seg_id;
// n_shift is the multiplier for lf_deltas
// the multiplier is 1 for when filter_lvl is between 0 and 31;
// 2 when filter_lvl is between 32 and 63
const int scale = 1 << (default_filt_lvl >> 5);
int scale = 1 << (default_filt_lvl >> 5);
loop_filter_info_n *const lfi = &cm->lf_info;
struct loopfilter *const lf = &cm->lf;
const struct segmentation *const seg = &cm->seg;
......@@ -689,6 +704,26 @@ void av1_loop_filter_frame_init(AV1_COMMON *cm, int default_filt_lvl) {
memset(lfi->lvl[seg_id], lvl_seg, sizeof(lfi->lvl[seg_id]));
} else {
int ref, mode;
#if CONFIG_UV_LVL
for (int dir = 0; dir < 2; ++dir) {
lvl_seg = (dir == 0) ? default_filt_lvl : default_filt_lvl_r;
scale = 1 << (lvl_seg >> 5);
const int intra_lvl = lvl_seg + lf->ref_deltas[INTRA_FRAME] * scale;
lfi->lvl[seg_id][dir][INTRA_FRAME][0] =
clamp(intra_lvl, 0, MAX_LOOP_FILTER);
for (ref = LAST_FRAME; ref < TOTAL_REFS_PER_FRAME; ++ref) {
for (mode = 0; mode < MAX_MODE_LF_DELTAS; ++mode) {
const int inter_lvl = lvl_seg + lf->ref_deltas[ref] * scale +
lf->mode_deltas[mode] * scale;
lfi->lvl[seg_id][dir][ref][mode] =
clamp(inter_lvl, 0, MAX_LOOP_FILTER);
}
}
}
#else
(void)default_filt_lvl_r;
const int intra_lvl = lvl_seg + lf->ref_deltas[INTRA_FRAME] * scale;
lfi->lvl[seg_id][INTRA_FRAME][0] = clamp(intra_lvl, 0, MAX_LOOP_FILTER);
......@@ -699,6 +734,7 @@ void av1_loop_filter_frame_init(AV1_COMMON *cm, int default_filt_lvl) {
lfi->lvl[seg_id][ref][mode] = clamp(inter_lvl, 0, MAX_LOOP_FILTER);
}
}
#endif
}
}
}
......@@ -1394,7 +1430,11 @@ static void build_masks(AV1_COMMON *const cm,
const TX_SIZE tx_size_uv_above =
txsize_vert_map[uv_txsize_lookup[block_size][mbmi->tx_size][1][1]];
#if CONFIG_EXT_DELTA_Q
#if CONFIG_UV_LVL
const int filter_level = get_filter_level(cm, lfi_n, 0, mbmi);
#else
const int filter_level = get_filter_level(cm, lfi_n, mbmi);
#endif
#else
const int filter_level = get_filter_level(lfi_n, mbmi);
(void)cm;
......@@ -1488,7 +1528,11 @@ static void build_y_mask(AV1_COMMON *const cm,
const BLOCK_SIZE block_size = mbmi->sb_type;
#endif
#if CONFIG_EXT_DELTA_Q
#if CONFIG_UV_LVL
const int filter_level = get_filter_level(cm, lfi_n, 0, mbmi);
#else
const int filter_level = get_filter_level(cm, lfi_n, mbmi);
#endif
#else
const int filter_level = get_filter_level(lfi_n, mbmi);
(void)cm;
......@@ -2093,7 +2137,12 @@ static void get_filter_level_and_masks_non420(
// Filter level can vary per MI
#if CONFIG_EXT_DELTA_Q
#if CONFIG_UV_LVL
if (!(lfl_r[c_step] = get_filter_level(cm, &cm->lf_info, 0, mbmi)))
continue;
#else
if (!(lfl_r[c_step] = get_filter_level(cm, &cm->lf_info, mbmi))) continue;
#endif
#else
if (!(lfl_r[c_step] = get_filter_level(&cm->lf_info, mbmi))) continue;
#endif
......@@ -2786,7 +2835,12 @@ static void set_lpf_parameters(
plane_ptr, scale_horz, scale_vert);
#if CONFIG_EXT_DELTA_Q
#if CONFIG_UV_LVL
const uint32_t curr_level =
get_filter_level(cm, &cm->lf_info, edge_dir, mbmi);
#else
const uint32_t curr_level = get_filter_level(cm, &cm->lf_info, mbmi);
#endif
#else
const uint32_t curr_level = get_filter_level(&cm->lf_info, mbmi);
#endif // CONFIG_EXT_DELTA_Q
......@@ -2818,8 +2872,13 @@ static void set_lpf_parameters(
plane_ptr, scale_horz, scale_vert);
#if CONFIG_EXT_DELTA_Q
#if CONFIG_UV_LVL
const uint32_t pv_lvl =
get_filter_level(cm, &cm->lf_info, edge_dir, &mi_prev->mbmi);
#else
const uint32_t pv_lvl =
get_filter_level(cm, &cm->lf_info, &mi_prev->mbmi);
#endif
#else
const uint32_t pv_lvl =
get_filter_level(&cm->lf_info, &mi_prev->mbmi);
......@@ -3392,13 +3451,25 @@ void av1_loop_filter_rows(YV12_BUFFER_CONFIG *frame_buffer, AV1_COMMON *cm,
}
void av1_loop_filter_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
MACROBLOCKD *xd, int frame_filter_level, int y_only,
int partial_frame) {
MACROBLOCKD *xd, int frame_filter_level,
#if CONFIG_UV_LVL
int frame_filter_level_r,
#endif
int y_only, int partial_frame) {
int start_mi_row, end_mi_row, mi_rows_to_filter;
#if CONFIG_EXT_DELTA_Q
#if CONFIG_UV_LVL
int orig_filter_level[2] = { cm->lf.filter_level[0], cm->lf.filter_level[1] };
#else
int orig_filter_level = cm->lf.filter_level;
#endif
#endif
#if CONFIG_UV_LVL
if (!frame_filter_level && !frame_filter_level_r) return;
#else
if (!frame_filter_level) return;
#endif
start_mi_row = 0;
mi_rows_to_filter = cm->mi_rows;
if (partial_frame && cm->mi_rows > 8) {
......@@ -3407,14 +3478,29 @@ void av1_loop_filter_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
mi_rows_to_filter = AOMMAX(cm->mi_rows / 8, 8);
}
end_mi_row = start_mi_row + mi_rows_to_filter;
av1_loop_filter_frame_init(cm, frame_filter_level);
#if CONFIG_UV_LVL
av1_loop_filter_frame_init(cm, frame_filter_level, frame_filter_level_r);
#else
av1_loop_filter_frame_init(cm, frame_filter_level, frame_filter_level);
#endif
#if CONFIG_EXT_DELTA_Q
#if CONFIG_UV_LVL
cm->lf.filter_level[0] = frame_filter_level;
cm->lf.filter_level[1] = frame_filter_level_r;
#else
cm->lf.filter_level = frame_filter_level;
#endif
#endif
av1_loop_filter_rows(frame, cm, xd->plane, start_mi_row, end_mi_row, y_only);
#if CONFIG_EXT_DELTA_Q
#if CONFIG_UV_LVL
cm->lf.filter_level[0] = orig_filter_level[0];
cm->lf.filter_level[1] = orig_filter_level[1];
#else
cm->lf.filter_level = orig_filter_level;
#endif
#endif
}
void av1_loop_filter_data_reset(
......
......@@ -36,10 +36,12 @@ enum lf_path {
};
struct loopfilter {
int filter_level;
#if CONFIG_UV_LVL
int filter_level[2];
int filter_level_u;
int filter_level_v;
#else
int filter_level;
#endif
int sharpness_level;
......@@ -69,7 +71,11 @@ typedef struct {
typedef struct {
loop_filter_thresh lfthr[MAX_LOOP_FILTER + 1];
#if CONFIG_UV_LVL
uint8_t lvl[MAX_SEGMENTS][2][TOTAL_REFS_PER_FRAME][MAX_MODE_LF_DELTAS];
#else
uint8_t lvl[MAX_SEGMENTS][TOTAL_REFS_PER_FRAME][MAX_MODE_LF_DELTAS];
#endif
} loop_filter_info_n;
// This structure holds bit masks for all 8x8 blocks in a 64x64 region.
......@@ -132,10 +138,14 @@ void av1_loop_filter_init(struct AV1Common *cm);
// This should be called before av1_loop_filter_rows(),
// av1_loop_filter_frame()
// calls this function directly.
void av1_loop_filter_frame_init(struct AV1Common *cm, int default_filt_lvl);
void av1_loop_filter_frame_init(struct AV1Common *cm, int default_filt_lvl,
int default_filt_lvl_r);
void av1_loop_filter_frame(YV12_BUFFER_CONFIG *frame, struct AV1Common *cm,
struct macroblockd *mbd, int filter_level,
#if CONFIG_UV_LVL
int filter_level_r,
#endif
int y_only, int partial_frame);
// Apply the loop filter to [start, stop) macro block rows in frame_buffer.
......
......@@ -416,8 +416,11 @@ static void loop_filter_rows_mt(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
void av1_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
struct macroblockd_plane planes[MAX_MB_PLANE],
int frame_filter_level, int y_only,
int partial_frame, AVxWorker *workers,
int frame_filter_level,
#if CONFIG_UV_LVL
int frame_filter_level_r,
#endif
int y_only, int partial_frame, AVxWorker *workers,
int num_workers, AV1LfSync *lf_sync) {
int start_mi_row, end_mi_row, mi_rows_to_filter;
......@@ -431,8 +434,11 @@ void av1_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
mi_rows_to_filter = AOMMAX(cm->mi_rows / 8, 8);
}
end_mi_row = start_mi_row + mi_rows_to_filter;
av1_loop_filter_frame_init(cm, frame_filter_level);
#if CONFIG_UV_LVL
av1_loop_filter_frame_init(cm, frame_filter_level, frame_filter_level_r);
#else
av1_loop_filter_frame_init(cm, frame_filter_level, frame_filter_level);
#endif // CONFIG_UV_LVL
loop_filter_rows_mt(frame, cm, planes, start_mi_row, end_mi_row, y_only,
workers, num_workers, lf_sync);
}
......
......@@ -50,8 +50,11 @@ void av1_loop_filter_dealloc(AV1LfSync *lf_sync);
// Multi-threaded loopfilter that uses the tile threads.
void av1_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame, struct AV1Common *cm,
struct macroblockd_plane planes[MAX_MB_PLANE],
int frame_filter_level, int y_only,
int partial_frame, AVxWorker *workers,
int frame_filter_level,
#if CONFIG_UV_LVL
int frame_filter_level_r,
#endif
int y_only, int partial_frame, AVxWorker *workers,
int num_workers, AV1LfSync *lf_sync);
void av1_accumulate_frame_counts(struct FRAME_COUNTS *acc_counts,
......
......@@ -2842,12 +2842,15 @@ static void decode_restoration(AV1_COMMON *cm, aom_reader *rb) {
static void setup_loopfilter(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
struct loopfilter *lf = &cm->lf;
lf->filter_level = aom_rb_read_literal(rb, 6);
#if CONFIG_UV_LVL
if (lf->filter_level > 0) {
lf->filter_level[0] = aom_rb_read_literal(rb, 6);
lf->filter_level[1] = aom_rb_read_literal(rb, 6);
if (lf->filter_level[0] || lf->filter_level[1]) {
lf->filter_level_u = aom_rb_read_literal(rb, 6);
lf->filter_level_v = aom_rb_read_literal(rb, 6);
}
#else
lf->filter_level = aom_rb_read_literal(rb, 6);
#endif
lf->sharpness_level = aom_rb_read_literal(rb, 3);
......@@ -3808,13 +3811,13 @@ static const uint8_t *decode_tiles(AV1Decoder *pbi, const uint8_t *data,
#if CONFIG_VAR_TX || CONFIG_CB4X4
// Loopfilter the whole frame.
#if CONFIG_UV_LVL
if (cm->lf.filter_level > 0) {
if (cm->lf.filter_level[0] || cm->lf.filter_level[1]) {
av1_loop_filter_frame(get_frame_new_buffer(cm), cm, &pbi->mb,
cm->lf.filter_level, 0, 0);
cm->lf.filter_level[0], cm->lf.filter_level[1], 0, 0);
av1_loop_filter_frame(get_frame_new_buffer(cm), cm, &pbi->mb,
cm->lf.filter_level_u, 1, 0);
cm->lf.filter_level_u, cm->lf.filter_level_u, 1, 0);
av1_loop_filter_frame(get_frame_new_buffer(cm), cm, &pbi->mb,
cm->lf.filter_level_v, 2, 0);
cm->lf.filter_level_v, cm->lf.filter_level_v, 2, 0);
}
#else
av1_loop_filter_frame(get_frame_new_buffer(cm), cm, &pbi->mb,
......@@ -4340,7 +4343,12 @@ static size_t read_uncompressed_header(AV1Decoder *pbi,
ref_cnt_fb(frame_bufs, &cm->new_fb_idx, frame_to_show);
unlock_buffer_pool(pool);
#if CONFIG_UV_LVL
cm->lf.filter_level[0] = 0;
cm->lf.filter_level[1] = 0;
#else
cm->lf.filter_level = 0;
#endif
cm->show_frame = 1;
pbi->refresh_frame_flags = 0;
......@@ -5265,9 +5273,17 @@ void av1_decode_frame(AV1Decoder *pbi, const uint8_t *data,
aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
"Decode failed. Frame data header is corrupted.");
#if CONFIG_UV_LVL
if ((cm->lf.filter_level[0] || cm->lf.filter_level[1]) &&
!cm->skip_loop_filter) {
av1_loop_filter_frame_init(cm, cm->lf.filter_level[0],
cm->lf.filter_level[1]);
}
#else
if (cm->lf.filter_level && !cm->skip_loop_filter) {
av1_loop_filter_frame_init(cm, cm->lf.filter_level);
av1_loop_filter_frame_init(cm, cm->lf.filter_level, cm->lf.filter_level);
}
#endif
// If encoded in frame parallel mode, frame context is ready after decoding
// the frame header.
......@@ -5303,11 +5319,18 @@ void av1_decode_frame(AV1Decoder *pbi, const uint8_t *data,
*p_data_end = decode_tiles_mt(pbi, data + first_partition_size, data_end);
if (!xd->corrupted) {
if (!cm->skip_loop_filter) {
// If multiple threads are used to decode tiles, then we use those
// threads to do parallel loopfiltering.
// If multiple threads are used to decode tiles, then we use those
// threads to do parallel loopfiltering.
#if CONFIG_UV_LVL
av1_loop_filter_frame_mt(new_fb, cm, pbi->mb.plane,
cm->lf.filter_level[0], cm->lf.filter_level[1],
0, 0, pbi->tile_workers, pbi->num_tile_workers,
&pbi->lf_row_sync);
#else
av1_loop_filter_frame_mt(new_fb, cm, pbi->mb.plane, cm->lf.filter_level,
0, 0, pbi->tile_workers, pbi->num_tile_workers,
&pbi->lf_row_sync);
#endif // CONFIG_UV_LVL
}
} else {
aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
......
......@@ -181,7 +181,12 @@ void av1_frameworker_copy_context(AVxWorker *const dst_worker,
memcpy(dst_cm->lf_info.lfthr, src_cm->lf_info.lfthr,
(MAX_LOOP_FILTER + 1) * sizeof(loop_filter_thresh));
dst_cm->lf.last_sharpness_level = src_cm->lf.sharpness_level;
#if CONFIG_UV_LVL
dst_cm->lf.filter_level[0] = src_cm->lf.filter_level[0];
dst_cm->lf.filter_level[1] = src_cm->lf.filter_level[1];
#else
dst_cm->lf.filter_level = src_cm->lf.filter_level;
#endif
memcpy(dst_cm->lf.ref_deltas, src_cm->lf.ref_deltas, TOTAL_REFS_PER_FRAME);
memcpy(dst_cm->lf.mode_deltas, src_cm->lf.mode_deltas, MAX_MODE_LF_DELTAS);
dst_cm->seg = src_cm->seg;
......
......@@ -3418,13 +3418,16 @@ static void encode_loopfilter(AV1_COMMON *cm, struct aom_write_bit_buffer *wb) {
int i;
struct loopfilter *lf = &cm->lf;
// Encode the loop filter level and type
aom_wb_write_literal(wb, lf->filter_level, 6);
// Encode the loop filter level and type
#if CONFIG_UV_LVL
if (lf->filter_level > 0) {
aom_wb_write_literal(wb, lf->filter_level[0], 6);
aom_wb_write_literal(wb, lf->filter_level[1], 6);
if (lf->filter_level[0] || lf->filter_level[1]) {
aom_wb_write_literal(wb, lf->filter_level_u, 6);
aom_wb_write_literal(wb, lf->filter_level_v, 6);
}
#else
aom_wb_write_literal(wb, lf->filter_level, 6);
#endif
aom_wb_write_literal(wb, lf->sharpness_level, 3);
......
......@@ -4134,7 +4134,12 @@ static void loopfilter_frame(AV1_COMP *cpi, AV1_COMMON *cm) {
#endif // CONFIG_EXT_TILE
if (no_loopfilter) {
#if CONFIG_UV_LVL
lf->filter_level[0] = 0;
lf->filter_level[1] = 0;
#else
lf->filter_level = 0;
#endif
} else {
struct aom_usec_timer timer;
......@@ -4148,12 +4153,21 @@ static void loopfilter_frame(AV1_COMP *cpi, AV1_COMMON *cm) {
cpi->time_pick_lpf += aom_usec_timer_elapsed(&timer);
}
if (lf->filter_level > 0) {
#if CONFIG_UV_LVL
if (lf->filter_level[0] || lf->filter_level[1])
#else
if (lf->filter_level > 0)
#endif
{
#if CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_CB4X4
#if CONFIG_UV_LVL
av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level, 0, 0);
av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level_u, 1, 0);
av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level_v, 2, 0);
av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level[0],
lf->filter_level[1], 0, 0);
av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level_u,
lf->filter_level_u, 1, 0);
av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level_v,
lf->filter_level_v, 2, 0);
#else
av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level, 0, 0);
#endif // CONFIG_UV_LVL
......
......@@ -51,7 +51,7 @@ static int64_t try_filter_frame(const YV12_BUFFER_CONFIG *sd,
int partial_frame
#if CONFIG_UV_LVL
,
int plane
int plane, int dir
#endif
) {
AV1_COMMON *const cm = &cpi->common;
......@@ -60,8 +60,12 @@ static int64_t try_filter_frame(const YV12_BUFFER_CONFIG *sd,
#if CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_CB4X4
#if CONFIG_UV_LVL
assert(plane >= 0 && plane <= 2);
av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filt_level,
plane, partial_frame);
int filter_level[2] = { filt_level, filt_level };
if (plane == 0 && dir == 0) filter_level[1] = cm->lf.filter_level[1];
if (plane == 0 && dir == 1) filter_level[0] = cm->lf.filter_level[0];
av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd,
filter_level[0], filter_level[1], plane, partial_frame);
#else
av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filt_level, 1,
partial_frame);
......@@ -100,7 +104,7 @@ int av1_search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
int partial_frame, double *best_cost_ret
#if CONFIG_UV_LVL
,
int plane
int plane, int dir
#endif
) {
const AV1_COMMON *const cm = &cpi->common;
......@@ -117,7 +121,7 @@ int av1_search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
#if CONFIG_UV_LVL
int lvl;
switch (plane) {
case 0: lvl = lf->filter_level; break;
case 0: lvl = (dir == 1) ? lf->filter_level[1] : lf->filter_level[0]; break;
case 1: lvl = lf->filter_level_u; break;
case 2: lvl = lf->filter_level_v; break;
default: assert(plane >= 0 && plane <= 2); return 0;
......@@ -141,7 +145,7 @@ int av1_search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
#endif // CONFIG_UV_LVL
#if CONFIG_UV_LVL
best_err = try_filter_frame(sd, cpi, filt_mid, partial_frame, plane);
best_err = try_filter_frame(sd, cpi, filt_mid, partial_frame, plane, dir);
#else
best_err = try_filter_frame(sd, cpi, filt_mid, partial_frame);
#endif // CONFIG_UV_LVL
......@@ -166,7 +170,7 @@ int av1_search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
if (ss_err[filt_low] < 0) {
#if CONFIG_UV_LVL
ss_err[filt_low] =
try_filter_frame(sd, cpi, filt_low, partial_frame, plane);
try_filter_frame(sd, cpi, filt_low, partial_frame, plane, dir);
#else
ss_err[filt_low] = try_filter_frame(sd, cpi, filt_low, partial_frame);
#endif // CONFIG_UV_LVL
......@@ -187,7 +191,7 @@ int av1_search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
if (ss_err[filt_high] < 0) {
#if CONFIG_UV_LVL
ss_err[filt_high] =
try_filter_frame(sd, cpi, filt_high, partial_frame, plane);
try_filter_frame(sd, cpi, filt_high, partial_frame, plane, dir);
#else
ss_err[filt_high] = try_filter_frame(sd, cpi, filt_high, partial_frame);
#endif // CONFIG_UV_LVL
......@@ -224,8 +228,13 @@ void av1_pick_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0 : cpi->oxcf.sharpness;
if (method == LPF_PICK_MINIMAL_LPF && lf->filter_level) {
if (method == LPF_PICK_MINIMAL_LPF) {
#if CONFIG_UV_LVL
lf->filter_level[0] = 0;
lf->filter_level[1] = 0;
#else
lf->filter_level = 0;
#endif
} else if (method >= LPF_PICK_FROM_Q) {
const int min_filter_level = 0;
const int max_filter_level = av1_get_max_filter_level(cpi);
......@@ -254,15 +263,25 @@ void av1_pick_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
int filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 1015158, 18);
#endif // CONFIG_HIGHBITDEPTH
if (cm->frame_type == KEY_FRAME) filt_guess -= 4;
#if CONFIG_UV_LVL
lf->filter_level[0] = clamp(filt_guess, min_filter_level, max_filter_level);
lf->filter_level[1] = clamp(filt_guess, min_filter_level, max_filter_level);
#else
lf->filter_level = clamp(filt_guess, min_filter_level, max_filter_level);
#endif
} else {
#if CONFIG_UV_LVL
lf->filter_level = av1_search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0);
lf->filter_level[0] = lf->filter_level[1] = av1_search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0, 2);
lf->filter_level[0] = av1_search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0, 0);
lf->filter_level[1] = av1_search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0, 1);
lf->filter_level_u = av1_search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 1);
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 1, 0);
lf->filter_level_v = av1_search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 2);
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 2, 0);
#else
lf->filter_level = av1_search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL);
......
......@@ -23,7 +23,7 @@ struct AV1_COMP;
int av1_get_max_filter_level(const AV1_COMP *cpi);
#if CONFIG_UV_LVL
int av1_search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
int partial_frame, double *err, int plane);
int partial_frame, double *err, int plane, int dir);
#else
int av1_search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
int partial_frame, double *err);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment