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