1ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/* 2ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * 4ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Use of this source code is governed by a BSD-style license 5ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * that can be found in the LICENSE file in the root of the source 6ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * tree. An additional intellectual property rights grant can be found 7ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * in the file PATENTS. All contributing project authors may 8ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * be found in the AUTHORS file in the root of the source tree. 9ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */ 10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <assert.h> 12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <limits.h> 136ac915abcdb404a00d927fe6308a47fcf09d9519hkuang 146ac915abcdb404a00d927fe6308a47fcf09d9519hkuang#include "./vpx_scale_rtcd.h" 156ac915abcdb404a00d927fe6308a47fcf09d9519hkuang 166ac915abcdb404a00d927fe6308a47fcf09d9519hkuang#include "vpx_mem/vpx_mem.h" 176ac915abcdb404a00d927fe6308a47fcf09d9519hkuang 186ac915abcdb404a00d927fe6308a47fcf09d9519hkuang#include "vp9/common/vp9_loopfilter.h" 19ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vp9/common/vp9_onyxc_int.h" 206ac915abcdb404a00d927fe6308a47fcf09d9519hkuang#include "vp9/common/vp9_quant_common.h" 216ac915abcdb404a00d927fe6308a47fcf09d9519hkuang 22ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vp9/encoder/vp9_onyx_int.h" 23ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vp9/encoder/vp9_picklpf.h" 24ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vp9/encoder/vp9_quantize.h" 25ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 26b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic int get_max_filter_level(VP9_COMP *cpi) { 27b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian return cpi->twopass.section_intra_rating > 8 ? MAX_LOOP_FILTER * 3 / 4 28b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian : MAX_LOOP_FILTER; 29ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang} 30ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 31ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 32b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic int try_filter_frame(const YV12_BUFFER_CONFIG *sd, VP9_COMP *const cpi, 33b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian int filt_level, int partial_frame) { 346ac915abcdb404a00d927fe6308a47fcf09d9519hkuang VP9_COMMON *const cm = &cpi->common; 35b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian int filt_err; 36ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 376ac915abcdb404a00d927fe6308a47fcf09d9519hkuang vp9_loop_filter_frame(cm, &cpi->mb.e_mbd, filt_level, 1, partial_frame); 386ac915abcdb404a00d927fe6308a47fcf09d9519hkuang filt_err = vp9_get_y_sse(sd, cm->frame_to_show); 39ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 40b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Re-instate the unfiltered frame 41b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian vpx_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show); 42ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 43b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian return filt_err; 44ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang} 45ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 46b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic void search_filter_level(const YV12_BUFFER_CONFIG *sd, VP9_COMP *cpi, 47b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian int partial_frame) { 481184aebb761cbeac9124c37189a80a1a58f04b6bhkuang VP9_COMMON *const cm = &cpi->common; 491184aebb761cbeac9124c37189a80a1a58f04b6bhkuang struct loopfilter *const lf = &cm->lf; 50b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const int min_filter_level = 0; 51b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const int max_filter_level = get_max_filter_level(cpi); 52b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian int best_err; 53ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int filt_best; 54ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int filt_direction = 0; 555ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang // Start the search at the previous frame filter level unless it is now out of 565ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang // range. 57b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian int filt_mid = clamp(lf->filter_level, min_filter_level, max_filter_level); 58b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian int filter_step = filt_mid < 16 ? 4 : filt_mid / 4; 59b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Sum squared error at each filter level 60b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian int ss_err[MAX_LOOP_FILTER + 1]; 61ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 62b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Set each entry to -1 63b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian vpx_memset(ss_err, 0xFF, sizeof(ss_err)); 64ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 65b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Make a copy of the unfiltered / processed recon buffer 66b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian vpx_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf); 67ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 686ac915abcdb404a00d927fe6308a47fcf09d9519hkuang best_err = try_filter_frame(sd, cpi, filt_mid, partial_frame); 69ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang filt_best = filt_mid; 70b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian ss_err[filt_mid] = best_err; 71ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 72ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang while (filter_step > 0) { 73b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const int filt_high = MIN(filt_mid + filter_step, max_filter_level); 74b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const int filt_low = MAX(filt_mid - filter_step, min_filter_level); 75b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian int filt_err; 76b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 77b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // Bias against raising loop filter in favor of lowering it. 78b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian int bias = (best_err >> (15 - (filt_mid / 8))) * filter_step; 79ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 80ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (cpi->twopass.section_intra_rating < 20) 81b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian bias = bias * cpi->twopass.section_intra_rating / 20; 82ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 83ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // yx, bias less for large block size 84b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian if (cm->tx_mode != ONLY_4X4) 85b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian bias >>= 1; 86ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 87b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian if (filt_direction <= 0 && filt_low != filt_mid) { 88ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Get Low filter error score 89b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian if (ss_err[filt_low] < 0) { 906ac915abcdb404a00d927fe6308a47fcf09d9519hkuang filt_err = try_filter_frame(sd, cpi, filt_low, partial_frame); 91b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian ss_err[filt_low] = filt_err; 92b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian } else { 93b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian filt_err = ss_err[filt_low]; 94b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian } 955ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang // If value is close to the best so far then bias towards a lower loop 965ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang // filter value. 97b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian if ((filt_err - bias) < best_err) { 98ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Was it actually better than the previous best? 99ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (filt_err < best_err) 100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang best_err = filt_err; 101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 102ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang filt_best = filt_low; 103ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 104ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 105ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 106ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Now look at filt_high 107b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian if (filt_direction >= 0 && filt_high != filt_mid) { 108b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian if (ss_err[filt_high] < 0) { 1096ac915abcdb404a00d927fe6308a47fcf09d9519hkuang filt_err = try_filter_frame(sd, cpi, filt_high, partial_frame); 110b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian ss_err[filt_high] = filt_err; 111b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian } else { 112b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian filt_err = ss_err[filt_high]; 113b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian } 114ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Was it better than the previous best? 115b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian if (filt_err < (best_err - bias)) { 116ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang best_err = filt_err; 117ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang filt_best = filt_high; 118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 119ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 120ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 121ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang // Half the step distance if the best filter value was the same as last time 122ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (filt_best == filt_mid) { 1236ac915abcdb404a00d927fe6308a47fcf09d9519hkuang filter_step /= 2; 124ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang filt_direction = 0; 125ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } else { 126ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang filt_direction = (filt_best < filt_mid) ? -1 : 1; 127ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang filt_mid = filt_best; 128ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 129ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 13191037db265ecdd914a26e056cf69207b4f50924ehkuang lf->filter_level = filt_best; 132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang} 133b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 134b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianvoid vp9_pick_filter_level(const YV12_BUFFER_CONFIG *sd, VP9_COMP *cpi, 1356ac915abcdb404a00d927fe6308a47fcf09d9519hkuang LPF_PICK_METHOD method) { 136b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian VP9_COMMON *const cm = &cpi->common; 137b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian struct loopfilter *const lf = &cm->lf; 138b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 139b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0 140b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian : cpi->oxcf.sharpness; 141b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian 1426ac915abcdb404a00d927fe6308a47fcf09d9519hkuang if (method == LPF_PICK_FROM_Q) { 143b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const int min_filter_level = 0; 144b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const int max_filter_level = get_max_filter_level(cpi); 145b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian const int q = vp9_ac_quant(cm->base_qindex, 0); 146b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian // These values were determined by linear fitting the result of the 1476ac915abcdb404a00d927fe6308a47fcf09d9519hkuang // searched level, filt_guess = q * 0.316206 + 3.87252 1486ac915abcdb404a00d927fe6308a47fcf09d9519hkuang int filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 1015158, 18); 149b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian if (cm->frame_type == KEY_FRAME) 150b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian filt_guess -= 4; 151b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian lf->filter_level = clamp(filt_guess, min_filter_level, max_filter_level); 152b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian } else { 1536ac915abcdb404a00d927fe6308a47fcf09d9519hkuang search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE); 154b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian } 155b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian} 156