• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_TEMPORAL_FILTER_H_
13 #define AOM_AV1_ENCODER_TEMPORAL_FILTER_H_
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 /*!\cond */
19 struct AV1_COMP;
20 struct ThreadData;
21 // TODO(any): These two variables are only used in avx2, sse2, sse4
22 // implementations, where the block size is still hard coded. This should be
23 // fixed to align with the c implementation.
24 #define BH 32
25 #define BW 32
26 
27 // Block size used in temporal filtering.
28 #define TF_BLOCK_SIZE BLOCK_32X32
29 
30 // Window size for temporal filtering.
31 #define TF_WINDOW_LENGTH 5
32 
33 // Hyper-parameters used to compute filtering weight. These hyper-parameters can
34 // be tuned for a better performance.
35 // 0. A scale factor used in temporal filtering to raise the filter weight from
36 //    `double` with range [0, 1] to `int` with range [0, 1000].
37 #define TF_WEIGHT_SCALE 1000
38 // 1. Weight factor used to balance the weighted-average between window error
39 //    and block error. The weight is for window error while the weight for block
40 //    error is always set as 1.
41 #define TF_WINDOW_BLOCK_BALANCE_WEIGHT 5
42 // 2. Threshold for using q to adjust the filtering weight. Concretely, when
43 //    using a small q (high bitrate), we would like to reduce the filtering
44 //    strength such that more detailed information can be preserved. Hence, when
45 //    q is smaller than this threshold, we will adjust the filtering weight
46 //    based on the q-value.
47 #define TF_Q_DECAY_THRESHOLD 20
48 // 3. Normalization factor used to normalize the motion search error. Since the
49 //    motion search error can be large and uncontrollable, we will simply
50 //    normalize it before using it to compute the filtering weight.
51 #define TF_SEARCH_ERROR_NORM_WEIGHT 20
52 // 4. Threshold for using `arnr_strength` to adjust the filtering strength.
53 //    Concretely, users can use `arnr_strength` arguments to control the
54 //    strength of temporal filtering. When `arnr_strength` is small enough (
55 //    i.e., smaller than this threshold), we will adjust the filtering weight
56 //    based on the strength value.
57 #define TF_STRENGTH_THRESHOLD 4
58 // 5. Threshold for using motion search distance to adjust the filtering weight.
59 //    Concretely, larger motion search vector leads to a higher probability of
60 //    unreliable search. Hence, we would like to reduce the filtering strength
61 //    when the distance is large enough. Considering that the distance actually
62 //    relies on the frame size, this threshold is also a resolution-based
63 //    threshold. Taking 720p videos as an instance, if this field equals to 0.1,
64 //    then the actual threshold will be 720 * 0.1 = 72. Similarly, the threshold
65 //    for 360p videos will be 360 * 0.1 = 36.
66 #define TF_SEARCH_DISTANCE_THRESHOLD 0.1
67 // 6. Threshold to identify if the q is in a relative high range.
68 //    Above this cutoff q, a stronger filtering is applied.
69 //    For a high q, the quantization throws away more information, and thus a
70 //    stronger filtering is less likely to distort the encoded quality, while a
71 //    stronger filtering could reduce bit rates.
72 //    Ror a low q, more details are expected to be retained. Filtering is thus
73 //    more conservative.
74 #define TF_QINDEX_CUTOFF 128
75 
76 #define NOISE_ESTIMATION_EDGE_THRESHOLD 50
77 
78 /*!\endcond */
79 
80 /*!
81  * \brief Parameters related to temporal filtering.
82  */
83 typedef struct {
84   /*!
85    * Frame buffers used for temporal filtering.
86    */
87   YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS];
88   /*!
89    * Number of frames in the frame buffer.
90    */
91   int num_frames;
92   /*!
93    * Index of the frame to be filtered.
94    */
95   int filter_frame_idx;
96   /*!
97    * Whether to accumulate diff for show existing condition check.
98    */
99   int check_show_existing;
100   /*!
101    * Frame scaling factor.
102    */
103   struct scale_factors sf;
104   /*!
105    * Estimated noise levels for each plane in the frame.
106    */
107   double noise_levels[MAX_MB_PLANE];
108   /*!
109    * Number of pixels in the temporal filtering block across all planes.
110    */
111   int num_pels;
112   /*!
113    * Number of temporal filtering block rows.
114    */
115   int mb_rows;
116   /*!
117    * Number of temporal filtering block columns.
118    */
119   int mb_cols;
120   /*!
121    * Whether the frame is high-bitdepth or not.
122    */
123   int is_highbitdepth;
124   /*!
125    * Quantization factor used in temporal filtering.
126    */
127   int q_factor;
128 } TemporalFilterCtx;
129 
130 /*!\cond */
131 
132 // Sum and SSE source vs filtered frame difference returned by
133 // temporal filter.
134 typedef struct {
135   int64_t sum;
136   int64_t sse;
137 } FRAME_DIFF;
138 
139 // Data related to temporal filtering.
140 typedef struct {
141   // Source vs filtered frame error.
142   FRAME_DIFF diff;
143   // Pointer to temporary block info used to store state in temporal filtering
144   // process.
145   MB_MODE_INFO *tmp_mbmi;
146   // Pointer to accumulator buffer used in temporal filtering process.
147   uint32_t *accum;
148   // Pointer to count buffer used in temporal filtering process.
149   uint16_t *count;
150   // Pointer to predictor used in temporal filtering process.
151   uint8_t *pred;
152 } TemporalFilterData;
153 
154 // Data related to temporal filter multi-thread synchronization.
155 typedef struct {
156 #if CONFIG_MULTITHREAD
157   // Mutex lock used for dispatching jobs.
158   pthread_mutex_t *mutex_;
159 #endif  // CONFIG_MULTITHREAD
160   // Next temporal filter block row to be filtered.
161   int next_tf_row;
162 } AV1TemporalFilterSync;
163 
164 // Estimates noise level from a given frame using a single plane (Y, U, or V).
165 // This is an adaptation of the mehtod in the following paper:
166 // Shen-Chuan Tai, Shih-Ming Yang, "A fast method for image noise
167 // estimation using Laplacian operator and adaptive edge detection",
168 // Proc. 3rd International Symposium on Communications, Control and
169 // Signal Processing, 2008, St Julians, Malta.
170 // Inputs:
171 //   frame: Pointer to the frame to estimate noise level from.
172 //   plane: Index of the plane used for noise estimation. Commonly, 0 for
173 //          Y-plane, 1 for U-plane, and 2 for V-plane.
174 //   bit_depth: Actual bit-depth instead of the encoding bit-depth of the frame.
175 // Returns:
176 //   The estimated noise, or -1.0 if there are too few smooth pixels.
177 double av1_estimate_noise_from_single_plane(const YV12_BUFFER_CONFIG *frame,
178                                             const int plane,
179                                             const int bit_depth);
180 /*!\endcond */
181 
182 /*!\brief Does temporal filter for a given macroblock row.
183 *
184 * \ingroup src_frame_proc
185 * \param[in]   cpi                   Top level encoder instance structure
186 * \param[in]   td                    Pointer to thread data
187 * \param[in]   mb_row                Macroblock row to be filtered
188 filtering
189 *
190 * \return Nothing will be returned, but the contents of td->diff will be
191 modified.
192 */
193 void av1_tf_do_filtering_row(struct AV1_COMP *cpi, struct ThreadData *td,
194                              int mb_row);
195 
196 /*!\brief Performs temporal filtering if needed on a source frame.
197  * For example to create a filtered alternate reference frame (ARF)
198  *
199  * In this function, the lookahead index is different from the 0-based
200  * real index. For example, if we want to filter the first frame in the
201  * pre-fetched buffer `cpi->lookahead`, the lookahead index will be -1 instead
202  * of 0. More concretely, 0 indicates the first LOOKAHEAD frame, which is the
203  * second frame in the pre-fetched buffer. Another example: if we want to filter
204  * the 17-th frame, which is an ARF, the lookahead index is 15 instead of 16.
205  * Futhermore, negative number is used for key frame in one-pass mode, where key
206  * frame is filtered with the frames before it instead of after it. For example,
207  * -15 means to filter the 17-th frame, which is a key frame in one-pass mode.
208  *
209  * \ingroup src_frame_proc
210  * \param[in]   cpi                        Top level encoder instance structure
211  * \param[in]   filter_frame_lookahead_idx The index of the to-filter frame in
212  *                                         the lookahead buffer cpi->lookahead.
213  * \param[in]   update_type                This frame's update type.
214  * \param[in]   is_forward_keyframe        Indicate whether this is a forward
215  *                                         keyframe.
216  * \param[in,out]   show_existing_arf      Whether to show existing ARF. This
217  *                                         field is updated in this function.
218  *
219  * \return Whether temporal filtering is successfully done.
220  */
221 int av1_temporal_filter(struct AV1_COMP *cpi,
222                         const int filter_frame_lookahead_idx,
223                         FRAME_UPDATE_TYPE update_type, int is_forward_keyframe,
224                         int *show_existing_arf);
225 
226 /*!\cond */
227 // Helper function to get `q` used for encoding.
228 int av1_get_q(const struct AV1_COMP *cpi);
229 
230 // Allocates memory for members of TemporalFilterData.
231 // Inputs:
232 //   tf_data: Pointer to the structure containing temporal filter related data.
233 //   num_pels: Number of pixels in the block across all planes.
234 //   is_high_bitdepth: Whether the frame is high-bitdepth or not.
235 // Returns:
236 //   Nothing will be returned. But the contents of tf_data will be modified.
tf_alloc_and_reset_data(TemporalFilterData * tf_data,int num_pels,int is_high_bitdepth)237 static AOM_INLINE void tf_alloc_and_reset_data(TemporalFilterData *tf_data,
238                                                int num_pels,
239                                                int is_high_bitdepth) {
240   tf_data->tmp_mbmi = (MB_MODE_INFO *)malloc(sizeof(*tf_data->tmp_mbmi));
241   memset(tf_data->tmp_mbmi, 0, sizeof(*tf_data->tmp_mbmi));
242   tf_data->accum =
243       (uint32_t *)aom_memalign(16, num_pels * sizeof(*tf_data->accum));
244   tf_data->count =
245       (uint16_t *)aom_memalign(16, num_pels * sizeof(*tf_data->count));
246   memset(&tf_data->diff, 0, sizeof(tf_data->diff));
247   if (is_high_bitdepth)
248     tf_data->pred = CONVERT_TO_BYTEPTR(
249         aom_memalign(32, num_pels * 2 * sizeof(*tf_data->pred)));
250   else
251     tf_data->pred =
252         (uint8_t *)aom_memalign(32, num_pels * sizeof(*tf_data->pred));
253 }
254 
255 // Setup macroblockd params for temporal filtering process.
256 // Inputs:
257 //   mbd: Pointer to the block for filtering.
258 //   tf_data: Pointer to the structure containing temporal filter related data.
259 //   scale: Scaling factor.
260 // Returns:
261 //   Nothing will be returned. Contents of mbd will be modified.
tf_setup_macroblockd(MACROBLOCKD * mbd,TemporalFilterData * tf_data,const struct scale_factors * scale)262 static AOM_INLINE void tf_setup_macroblockd(MACROBLOCKD *mbd,
263                                             TemporalFilterData *tf_data,
264                                             const struct scale_factors *scale) {
265   mbd->block_ref_scale_factors[0] = scale;
266   mbd->block_ref_scale_factors[1] = scale;
267   mbd->mi = &tf_data->tmp_mbmi;
268   mbd->mi[0]->motion_mode = SIMPLE_TRANSLATION;
269 }
270 
271 // Deallocates the memory allocated for members of TemporalFilterData.
272 // Inputs:
273 //   tf_data: Pointer to the structure containing temporal filter related data.
274 //   is_high_bitdepth: Whether the frame is high-bitdepth or not.
275 // Returns:
276 //   Nothing will be returned.
tf_dealloc_data(TemporalFilterData * tf_data,int is_high_bitdepth)277 static AOM_INLINE void tf_dealloc_data(TemporalFilterData *tf_data,
278                                        int is_high_bitdepth) {
279   if (is_high_bitdepth)
280     tf_data->pred = (uint8_t *)CONVERT_TO_SHORTPTR(tf_data->pred);
281   free(tf_data->tmp_mbmi);
282   aom_free(tf_data->accum);
283   aom_free(tf_data->count);
284   aom_free(tf_data->pred);
285 }
286 
287 // Saves the state prior to temporal filter process.
288 // Inputs:
289 //   mbd: Pointer to the block for filtering.
290 //   input_mbmi: Backup block info to save input state.
291 //   input_buffer: Backup buffer pointer to save input state.
292 //   num_planes: Number of planes.
293 // Returns:
294 //   Nothing will be returned. Contents of input_mbmi and input_buffer will be
295 //   modified.
tf_save_state(MACROBLOCKD * mbd,MB_MODE_INFO *** input_mbmi,uint8_t ** input_buffer,int num_planes)296 static INLINE void tf_save_state(MACROBLOCKD *mbd, MB_MODE_INFO ***input_mbmi,
297                                  uint8_t **input_buffer, int num_planes) {
298   for (int i = 0; i < num_planes; i++) {
299     input_buffer[i] = mbd->plane[i].pre[0].buf;
300   }
301   *input_mbmi = mbd->mi;
302 }
303 
304 // Restores the initial state after temporal filter process.
305 // Inputs:
306 //   mbd: Pointer to the block for filtering.
307 //   input_mbmi: Backup block info from where input state is restored.
308 //   input_buffer: Backup buffer pointer from where input state is restored.
309 //   num_planes: Number of planes.
310 // Returns:
311 //   Nothing will be returned. Contents of mbd will be modified.
tf_restore_state(MACROBLOCKD * mbd,MB_MODE_INFO ** input_mbmi,uint8_t ** input_buffer,int num_planes)312 static INLINE void tf_restore_state(MACROBLOCKD *mbd, MB_MODE_INFO **input_mbmi,
313                                     uint8_t **input_buffer, int num_planes) {
314   for (int i = 0; i < num_planes; i++) {
315     mbd->plane[i].pre[0].buf = input_buffer[i];
316   }
317   mbd->mi = input_mbmi;
318 }
319 
320 /*!\endcond */
321 #ifdef __cplusplus
322 }  // extern "C"
323 #endif
324 
325 #endif  // AOM_AV1_ENCODER_TEMPORAL_FILTER_H_
326