summaryrefslogtreecommitdiffstats
path: root/third_party/aom/av1/encoder/picklpf.h
blob: f567937c327b413109870a2a03f4e658613bfe05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */

#ifndef AOM_AV1_ENCODER_PICKLPF_H_
#define AOM_AV1_ENCODER_PICKLPF_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "av1/encoder/encoder.h"

struct yv12_buffer_config;
struct AV1_COMP;
int av1_get_max_filter_level(const AV1_COMP *cpi);

/*!\brief Algorithm for AV1 loop filter level selection.
 *
 * \ingroup in_loop_filter
 * This function determines proper filter levels used for in-loop filter
 * (deblock filter).
 *
 * \param[in]    sd             The pointer of frame buffer
 * \param[in]    cpi            Top-level encoder structure
 * \param[in]    method         The method used to select filter levels
 *
 * \par
 * method includes:
 * \arg \c LPF_PICK_FROM_FULL_IMAGE:  Try the full image with different values.
 * \arg \c LPF_PICK_FROM_FULL_IMAGE_NON_DUAL: Try the full image filter search
 * with non-dual filter only.
 * \arg \c LPF_PICK_FROM_SUBIMAGE: Try a small portion of the image with
 * different values.
 * \arg \c LPF_PICK_FROM_Q: Estimate the level based on quantizer and frame type
 * \arg \c LPF_PICK_MINIMAL_LPF: Pick 0 to disable LPF if LPF was enabled last
 * frame
 *
 * \remark Nothing is returned. Instead, filter levels below are stored in the
 * "loopfilter" structure inside "cpi":
 * \arg \c filter_level[0]: the vertical filter level for Y plane
 * \arg \c filter_level[1]: the horizontal filter level for Y plane
 * \arg \c filter_level_u: the filter level for U plane
 * \arg \c filter_level_v: the filter level for V plane
 *
 * \n
 * \b Overview
 * \par
 * The workflow of deblock filter is shown in Fig.1. \n
 * Boundary pixels pass through a non-flatness check, followed by a step that
 * determines smoothness and selects proper types of filters
 * (4-, 6-, 8-, 14-tap filter). \n
 * If non-flatness criteria is not satisfied, the encoder will not apply
 * deblock filtering on these boundary pixels.
 * \image html filter_flow.png "Fig.1. The workflow of deblock filter" width=70%
 *
 * \par
 * The non-flatness is determined by the boundary pixels and thresholds as shown
 * in Fig.2. \n
 * Filtering is applied when \n
 * \f$|p_0-p_1|<thr_1\f$   and   \f$|q_0-q_1|<thr_1\f$   and
 * \f$2*|p_0-q_0|+|p_1-q_1|/2<thr_2\f$ \n
 * \image html filter_thr.png "Fig.2. Non-flatness of pixel boundary" height=40%
 *
 * \par
 * Thresholds ("thr_1" and "thr_2") are determined by the filter level. \n
 * In AV1, for each frame, we employ the four filter levels, based on these
 * observations: \n
 * Luma and chroma planes have different characteristics, including subsampling
 * (different plane size), coding quality (chroma planes are better coded). \n
 * Therefore chroma planes need less deblocking filtering than luma plane. \n
 * In addition, content texture has different spatial characteristics: vertical
 * and horizontal direction may need different level of filtering. \n
 * The selection of these filter levels is described in the following section.
 *
 * \par
 * \b Algorithm
 * \par
 * The encoder selects filter levels given the current frame buffer, and the
 * method. \n
 * By default, "LPF_PICK_FROM_FULL_IMAGE" is used, which should provide
 * the most appropriate filter levels. \n
 * For video on demand (VOD) mode, if speed setting is larger than 5,
 * "LPF_PICK_FROM_FULL_IMAGE_NON_DUAL" is used. \n
 * For real-time mode, if speed setting is larger than 5, "LPF_PICK_FROM_Q" is
 * used.
 *
 * \par
 * "LPF_PICK_FROM_FULL_IMAGE" method: determine filter levels sequentially
 * by a filter level search procedure (function "search_filter_level"). \n
 * The order is: \n
 * First search and determine the filter level for Y plane.
 * Let vertical filter level (filter_level[0]) and the horizontal filter level
 * (filter_level[1]) be equal to it. \n
 * Keep the horizontal filter level the same and search and determine the
 * vertical filter level. \n
 * Search and determine the horizontal filter level. \n
 * Search and determine filter level for U plane. \n
 * Search and determine filter level for V plane.
 *
 * \par
 * Search and determine filter level is fulfilled by function
 * "search_filter_level". \n
 * It starts with a base filter level ("filt_mid") initialized by the
 * corresponding last frame's filter level. \n
 * A filter step ("filter_step") is determined as:
 * filter_step = filt_mid < 16 ? 4 : filt_mid / 4. \n
 * Then a modified binary search strategy is employed to find a proper
 * filter level. \n
 * In each iteration, set filt_low = filt_mid - filter_step,
 * filt_high = filt_mid + filter_step. \n
 * We now have three candidate levels, "filt_mid", "filt_low" and "filt_high".
 * \n
 * Deblock filtering is applied on the current frame with candidate filter
 * levels and the sum of squared error (SSE) between source and filtered frame
 * is computed. \n
 * Set "filt_best" to the filter level of the smallest SSE. If "filter_best"
 * equals to "filt_mid", halve the filter_step. Otherwise, set filt_mid =
 * filt_best. \n
 * Go to the next iteration until "filter_step" is 0. \n
 * Note that in the comparison of SSEs between SSE[filt_low] and SSE[filt_mid],
 * a "bias" is introduced to slightly raise the filter level. \n
 * It is based on the observation that low filter levels tend to yield a smaller
 * SSE and produce a higher PSNR for the current frame, \n
 * while oversmoothing it and degradating the quality for prediction for future
 * frames and leanding to a suboptimal performance overall. \n
 * Function "try_filter_frame" is the referrence for applying deblock filtering
 * with a given filter level and computatition of SSE.
 *
 * \par
 * "LPF_PICK_FROM_FULL_IMAGE_NON_DUAL" method: almost the same as
 * "LPF_PICK_FROM_FULL_IMAGE", \n
 * just without separately searching for appropriate filter levels for vertical
 * and horizontal filters.
 *
 * \par
 * "LPF_PICK_FROM_Q" method: filter levels are determined by the
 * quantization factor (q). \n
 * For 8 bit: \n
 *   Keyframes: filt_guess = q * 0.06699 - 1.60817 \n
 *   Other frames: filt_guess = q * inter_frame_multiplier + 2.48225 \n
 *   inter_frame_multiplier = q > 700 ? 0.04590 : 0.02295 \n
 * For 10 bit and 12 bit: \n
 * filt_guess = q * 0.316206 + 3.87252 \n
 * Then filter_level[0] = filter_level[1] = filter_level_u = filter_level_v =
 * clamp(filt_guess, min_filter_level, max_filter_level) \n
 * Where min_filter_level = 0, max_filter_level = 64 \n
 * The equations were determined by linear fitting using filter levels
 * generated by "LPF_PICK_FROM_FULL_IMAGE" method.
 *
 */
void av1_pick_filter_level(const struct yv12_buffer_config *sd,
                           struct AV1_COMP *cpi, LPF_PICK_METHOD method);
#ifdef __cplusplus
}  // extern "C"
#endif

#endif  // AOM_AV1_ENCODER_PICKLPF_H_