1 /* 2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 #ifndef AOM_AV1_ENCODER_PICKLPF_H_ 13 #define AOM_AV1_ENCODER_PICKLPF_H_ 14 15 #ifdef __cplusplus 16 extern "C" { 17 #endif 18 19 #include "av1/encoder/encoder.h" 20 21 struct yv12_buffer_config; 22 struct AV1_COMP; 23 int av1_get_max_filter_level(const AV1_COMP *cpi); 24 25 /*!\brief Algorithm for AV1 loop filter level selection. 26 * 27 * \ingroup in_loop_filter 28 * This function determines proper filter levels used for in-loop filter 29 * (deblock filter). 30 * 31 * \param[in] sd The pointer of frame buffer 32 * \param[in] cpi Top-level encoder structure 33 * \param[in] method The method used to select filter levels 34 * 35 * \par 36 * method includes: 37 * \arg \c LPF_PICK_FROM_FULL_IMAGE: Try the full image with different values. 38 * \arg \c LPF_PICK_FROM_FULL_IMAGE_NON_DUAL: Try the full image filter search 39 * with non-dual filter only. 40 * \arg \c LPF_PICK_FROM_SUBIMAGE: Try a small portion of the image with 41 * different values. 42 * \arg \c LPF_PICK_FROM_Q: Estimate the level based on quantizer and frame type 43 * \arg \c LPF_PICK_MINIMAL_LPF: Pick 0 to disable LPF if LPF was enabled last 44 * frame 45 * 46 * \return Nothing is returned. Instead, filter levels below are stored in the 47 * "loopfilter" structure inside "cpi": 48 * \arg \c filter_level[0]: the vertical filter level for Y plane 49 * \arg \c filter_level[1]: the horizontal filter level for Y plane 50 * \arg \c filter_level_u: the filter level for U plane 51 * \arg \c filter_level_v: the filter level for V plane 52 * 53 * \n 54 * \b Overview 55 * \par 56 * The workflow of deblock filter is shown in Fig.1. \n 57 * Boundary pixels pass through a non-flatness check, followed by a step that 58 * determines smoothness and selects proper types of filters 59 * (4-, 6-, 8-, 14-tap filter). \n 60 * If non-flatness criteria is not satisfied, the encoder will not apply 61 * deblock filtering on these boundary pixels. 62 * \image html filter_flow.png "Fig.1. The workflow of deblock filter" width=70% 63 * 64 * \par 65 * The non-flatness is determined by the boundary pixels and thresholds as shown 66 * in Fig.2. \n 67 * Filtering is applied when \n 68 * \f$|p_0-p_1|<thr_1\f$ and \f$|q_0-q_1|<thr_1\f$ and 69 * \f$2*|p_0-q_0|+|p_1-q_1|/2<thr_2\f$ \n 70 * \image html filter_thr.png "Fig.2. Non-flatness of pixel boundary" height=40% 71 * 72 * \par 73 * Thresholds ("thr_1" and "thr_2") are determined by the filter level. \n 74 * In AV1, for each frame, we employ the four filter levels, based on these 75 * observations: \n 76 * Luma and chroma planes have different characteristics, including subsampling 77 * (different plane size), coding quality (chroma planes are better coded). \n 78 * Therefore chroma planes need less deblocking filtering than luma plane. \n 79 * In addition, content texture has different spatial characteristics: vertical 80 * and horizontal direction may need different level of filtering. \n 81 * The selection of these filter levels is described in the following section. 82 * 83 * \par 84 * \b Algorithm 85 * \par 86 * The encoder selects filter levels given the current frame buffer, and the 87 * method. \n 88 * By default, "LPF_PICK_FROM_FULL_IMAGE" is used, which should provide 89 * the most appropriate filter levels. \n 90 * For video on demand (VOD) mode, if speed setting is larger than 5, 91 * "LPF_PICK_FROM_FULL_IMAGE_NON_DUAL" is used. \n 92 * For real-time mode, if speed setting is larger than 5, "LPF_PICK_FROM_Q" is 93 * used. 94 * 95 * \par 96 * "LPF_PICK_FROM_FULL_IMAGE" method: determine filter levels sequentially 97 * by a filter level search procedure (function "search_filter_level"). \n 98 * The order is: \n 99 * First search and determine the filter level for Y plane. 100 * Let vertical filter level (filter_level[0]) and the horizontal filter level 101 * (filter_level[1]) be equal to it. \n 102 * Keep the horizontal filter level the same and search and determine the 103 * vertical filter level. \n 104 * Search and determine the horizontal filter level. \n 105 * Search and determine filter level for U plane. \n 106 * Search and determine filter level for V plane. 107 * 108 * \par 109 * Search and determine filter level is fulfilled by function 110 * "search_filter_level". \n 111 * It starts with a base filter level ("filt_mid") initialized by the 112 * corresponding last frame's filter level. \n 113 * A filter step ("filter_step") is determined as: 114 * filter_step = filt_mid < 16 ? 4 : filt_mid / 4. \n 115 * Then a modified binary search strategy is employed to find a proper 116 * filter level. \n 117 * In each iteration, set filt_low = filt_mid - filter_step, 118 * filt_high = filt_mid + filter_step. \n 119 * We now have three candidate levels, "filt_mid", "filt_low" and "filt_high". 120 * \n 121 * Deblock filtering is applied on the current frame with candidate filter 122 * levels and the sum of squared error (SSE) between source and filtered frame 123 * is computed. \n 124 * Set "filt_best" to the filter level of the smallest SSE. If "filter_best" 125 * equals to "filt_mid", halve the filter_step. Otherwise, set filt_mid = 126 * filt_best. \n 127 * Go to the next iteration until "filter_step" is 0. \n 128 * Note that in the comparison of SSEs between SSE[filt_low] and SSE[filt_mid], 129 * a "bias" is introduced to slightly raise the filter level. \n 130 * It is based on the observation that low filter levels tend to yield a smaller 131 * SSE and produce a higher PSNR for the current frame, \n 132 * while oversmoothing it and degradating the quality for prediction for future 133 * frames and leanding to a suboptimal performance overall. \n 134 * Function "try_filter_frame" is the referrence for applying deblock filtering 135 * with a given filter level and computatition of SSE. 136 * 137 * \par 138 * "LPF_PICK_FROM_FULL_IMAGE_NON_DUAL" method: almost the same as 139 * "LPF_PICK_FROM_FULL_IMAGE", \n 140 * just without separately searching for appropriate filter levels for vertical 141 * and horizontal filters. 142 * 143 * \par 144 * "LPF_PICK_FROM_Q" method: filter levels are determined by the 145 * quantization factor (q). \n 146 * For 8 bit: \n 147 * Keyframes: filt_guess = q * 0.06699 - 1.60817 \n 148 * Other frames: filt_guess = q * inter_frame_multiplier + 2.48225 \n 149 * inter_frame_multiplier = q > 700 ? 0.04590 : 0.02295 \n 150 * For 10 bit and 12 bit: \n 151 * filt_guess = q * 0.316206 + 3.87252 \n 152 * Then filter_level[0] = filter_level[1] = filter_level_u = filter_level_v = 153 * clamp(filt_guess, min_filter_level, max_filter_level) \n 154 * Where min_filter_level = 0, max_filter_level = 64 \n 155 * The equations were determined by linear fitting using filter levels 156 * generated by "LPF_PICK_FROM_FULL_IMAGE" method. 157 * 158 */ 159 void av1_pick_filter_level(const struct yv12_buffer_config *sd, 160 struct AV1_COMP *cpi, LPF_PICK_METHOD method); 161 #ifdef __cplusplus 162 } // extern "C" 163 #endif 164 165 #endif // AOM_AV1_ENCODER_PICKLPF_H_ 166