xref: /aosp_15_r20/external/libaom/av1/encoder/temporal_filter.h (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
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 #include <stdbool.h>
16 
17 #include "aom_util/aom_pthread.h"
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 /*!\cond */
23 struct AV1_COMP;
24 struct AV1EncoderConfig;
25 struct ThreadData;
26 // TODO(wtc): These two variables are only used in avx2, sse2, neon
27 // implementations, where the block size is still hard coded to TF_BLOCK_SIZE.
28 // This should be fixed to align with the c implementation.
29 #define BH 32
30 #define BW 32
31 
32 // Block size used in temporal filtering.
33 #define TF_BLOCK_SIZE BLOCK_32X32
34 
35 // Window size for temporal filtering.
36 #define TF_WINDOW_LENGTH 5
37 
38 // A constant number, sqrt(pi / 2),  used for noise estimation.
39 static const double SQRT_PI_BY_2 = 1.25331413732;
40 
41 // Hyper-parameters used to compute filtering weight. These hyper-parameters can
42 // be tuned for a better performance.
43 // 0. A scale factor used in temporal filtering to raise the filter weight from
44 //    `double` with range [0, 1] to `int` with range [0, 1000].
45 #define TF_WEIGHT_SCALE 1000
46 // 1. Weight factor used to balance the weighted-average between window error
47 //    and block error. The weight is for window error while the weight for block
48 //    error is always set as 1.
49 #define TF_WINDOW_BLOCK_BALANCE_WEIGHT 5
50 // 2. Threshold for using q to adjust the filtering weight. Concretely, when
51 //    using a small q (high bitrate), we would like to reduce the filtering
52 //    strength such that more detailed information can be preserved. Hence, when
53 //    q is smaller than this threshold, we will adjust the filtering weight
54 //    based on the q-value.
55 #define TF_Q_DECAY_THRESHOLD 20
56 // 3. Normalization factor used to normalize the motion search error. Since the
57 //    motion search error can be large and uncontrollable, we will simply
58 //    normalize it before using it to compute the filtering weight.
59 #define TF_SEARCH_ERROR_NORM_WEIGHT 20
60 // 4. Threshold for using `arnr_strength` to adjust the filtering strength.
61 //    Concretely, users can use `arnr_strength` arguments to control the
62 //    strength of temporal filtering. When `arnr_strength` is small enough (
63 //    i.e., smaller than this threshold), we will adjust the filtering weight
64 //    based on the strength value.
65 #define TF_STRENGTH_THRESHOLD 4
66 // 5. Threshold for using motion search distance to adjust the filtering weight.
67 //    Concretely, larger motion search vector leads to a higher probability of
68 //    unreliable search. Hence, we would like to reduce the filtering strength
69 //    when the distance is large enough. Considering that the distance actually
70 //    relies on the frame size, this threshold is also a resolution-based
71 //    threshold. Taking 720p videos as an instance, if this field equals to 0.1,
72 //    then the actual threshold will be 720 * 0.1 = 72. Similarly, the threshold
73 //    for 360p videos will be 360 * 0.1 = 36.
74 #define TF_SEARCH_DISTANCE_THRESHOLD 0.1
75 // 6. Threshold to identify if the q is in a relative high range.
76 //    Above this cutoff q, a stronger filtering is applied.
77 //    For a high q, the quantization throws away more information, and thus a
78 //    stronger filtering is less likely to distort the encoded quality, while a
79 //    stronger filtering could reduce bit rates.
80 //    Ror a low q, more details are expected to be retained. Filtering is thus
81 //    more conservative.
82 #define TF_QINDEX_CUTOFF 128
83 
84 #define NOISE_ESTIMATION_EDGE_THRESHOLD 50
85 
86 // Sum and SSE source vs filtered frame difference returned by
87 // temporal filter.
88 typedef struct {
89   int64_t sum;
90   int64_t sse;
91 } FRAME_DIFF;
92 
93 /*!\endcond */
94 
95 /*!
96  * \brief Parameters related to temporal filtering.
97  */
98 typedef struct {
99   /*!
100    * Frame buffers used for temporal filtering.
101    */
102   YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS];
103   /*!
104    * Number of frames in the frame buffer.
105    */
106   int num_frames;
107 
108   /*!
109    * Output filtered frame
110    */
111   YV12_BUFFER_CONFIG *output_frame;
112 
113   /*!
114    * Index of the frame to be filtered.
115    */
116   int filter_frame_idx;
117   /*!
118    * Whether to accumulate diff for show existing condition check.
119    */
120   int compute_frame_diff;
121   /*!
122    * Frame scaling factor.
123    */
124   struct scale_factors sf;
125   /*!
126    * Estimated noise levels for each plane in the frame.
127    */
128   double noise_levels[MAX_MB_PLANE];
129   /*!
130    * Number of pixels in the temporal filtering block across all planes.
131    */
132   int num_pels;
133   /*!
134    * Number of temporal filtering block rows.
135    */
136   int mb_rows;
137   /*!
138    * Number of temporal filtering block columns.
139    */
140   int mb_cols;
141   /*!
142    * Whether the frame is high-bitdepth or not.
143    */
144   int is_highbitdepth;
145   /*!
146    * Quantization factor used in temporal filtering.
147    */
148   int q_factor;
149 } TemporalFilterCtx;
150 
151 /*!
152  * buffer count in TEMPORAL_FILTER_INFO
153  * Currently we only apply filtering on KEY and ARF after
154  * define_gf_group(). Hence, the count is two.
155  */
156 #define TF_INFO_BUF_COUNT 2
157 
158 /*!
159  * \brief Temporal filter info for a gop
160  */
161 typedef struct TEMPORAL_FILTER_INFO {
162   /*!
163    * A flag indicate whether temporal filter shoud be applied.
164    * This flag will stored the result of
165    * av1_is_temporal_filter_on()
166    */
167   int is_temporal_filter_on;
168   /*!
169    * buffers used for temporal filtering in a GOP
170    * index 0 for key frame and index 1 for ARF
171    */
172   YV12_BUFFER_CONFIG tf_buf[TF_INFO_BUF_COUNT];
173 
174   /*!
175    * buffers used for temporal filtering for
176    * INTNL_ARF_UPDATE
177    * Check av1_gop_is_second_arf() for the
178    * definition of second_arf in detail
179    */
180   YV12_BUFFER_CONFIG tf_buf_second_arf;
181   /*!
182    * whether to show the buffer directly or not.
183    */
184   FRAME_DIFF frame_diff[TF_INFO_BUF_COUNT];
185   /*!
186    * the corresponding gf_index for the buffer.
187    */
188   int tf_buf_gf_index[TF_INFO_BUF_COUNT];
189   /*!
190    * the display_index offset between next show frame and the frames in the GOP
191    */
192   int tf_buf_display_index_offset[TF_INFO_BUF_COUNT];
193   /*!
194    * whether the buf is valid or not.
195    */
196   int tf_buf_valid[TF_INFO_BUF_COUNT];
197 } TEMPORAL_FILTER_INFO;
198 
199 /*!\brief Check whether we should apply temporal filter at all.
200  * \param[in]   oxcf           AV1 encoder config
201  *
202  * \return 1: temporal filter is on 0: temporal is off
203  */
204 int av1_is_temporal_filter_on(const struct AV1EncoderConfig *oxcf);
205 
206 /*!\brief Allocate buffers for TEMPORAL_FILTER_INFO
207  * \param[in,out]   tf_info           Temporal filter info for a gop
208  * \param[in,out]   cpi               Top level encoder instance structure
209  *
210  * \return True on success, false on memory allocation failure.
211  */
212 bool av1_tf_info_alloc(TEMPORAL_FILTER_INFO *tf_info,
213                        const struct AV1_COMP *cpi);
214 
215 /*!\brief Free buffers for TEMPORAL_FILTER_INFO
216  * \param[in,out]   tf_info           Temporal filter info for a gop
217  */
218 void av1_tf_info_free(TEMPORAL_FILTER_INFO *tf_info);
219 
220 /*!\brief Reset validity of tf_buf in TEMPORAL_FILTER_INFO
221  * \param[in,out]   tf_info           Temporal filter info for a gop
222  */
223 void av1_tf_info_reset(TEMPORAL_FILTER_INFO *tf_info);
224 
225 /*!\brief Apply temporal filter for key frame and ARF in a gop
226  * \param[in,out]   tf_info           Temporal filter info for a gop
227  * \param[in,out]   cpi               Top level encoder instance structure
228  * \param[in]       gf_group          GF/ARF group data structure
229  */
230 void av1_tf_info_filtering(TEMPORAL_FILTER_INFO *tf_info, struct AV1_COMP *cpi,
231                            const GF_GROUP *gf_group);
232 
233 /*!\brief Get a filtered buffer from TEMPORAL_FILTER_INFO
234  * \param[in,out]   tf_info           Temporal filter info for a gop
235  * \param[in]       gf_index          gf_index for the target buffer
236  * \param[out]      show_tf_buf       whether the target buffer can be shown
237  * directly
238  */
239 YV12_BUFFER_CONFIG *av1_tf_info_get_filtered_buf(TEMPORAL_FILTER_INFO *tf_info,
240                                                  int gf_index,
241                                                  FRAME_DIFF *frame_diff);
242 
243 /*!\cond */
244 
245 // Data related to temporal filtering.
246 typedef struct {
247   // Source vs filtered frame error.
248   FRAME_DIFF diff;
249   // Pointer to temporary block info used to store state in temporal filtering
250   // process.
251   MB_MODE_INFO *tmp_mbmi;
252   // Pointer to accumulator buffer used in temporal filtering process.
253   uint32_t *accum;
254   // Pointer to count buffer used in temporal filtering process.
255   uint16_t *count;
256   // Pointer to predictor used in temporal filtering process.
257   uint8_t *pred;
258 } TemporalFilterData;
259 
260 // Data related to temporal filter multi-thread synchronization.
261 typedef struct {
262 #if CONFIG_MULTITHREAD
263   // Mutex lock used for dispatching jobs.
264   pthread_mutex_t *mutex_;
265 #endif  // CONFIG_MULTITHREAD
266   // Next temporal filter block row to be filtered.
267   int next_tf_row;
268   // Initialized to false, set to true by the worker thread that encounters an
269   // error in order to abort the processing of other worker threads.
270   bool tf_mt_exit;
271 } AV1TemporalFilterSync;
272 
273 // Estimates noise level from a given frame using a single plane (Y, U, or V).
274 // This is an adaptation of the mehtod in the following paper:
275 // Shen-Chuan Tai, Shih-Ming Yang, "A fast method for image noise
276 // estimation using Laplacian operator and adaptive edge detection",
277 // Proc. 3rd International Symposium on Communications, Control and
278 // Signal Processing, 2008, St Julians, Malta.
279 // Inputs:
280 //   frame: Pointer to the frame to estimate noise level from.
281 //   noise_level: Pointer to store the estimated noise.
282 //   plane_from: Index of the starting plane used for noise estimation.
283 //               Commonly, 0 for Y-plane, 1 for U-plane, and 2 for V-plane.
284 //   plane_to: Index of the end plane used for noise estimation.
285 //   bit_depth: Actual bit-depth instead of the encoding bit-depth of the frame.
286 //   edge_thresh: Edge threshold.
287 void av1_estimate_noise_level(const YV12_BUFFER_CONFIG *frame,
288                               double *noise_level, int plane_from, int plane_to,
289                               int bit_depth, int edge_thresh);
290 /*!\endcond */
291 
292 /*!\brief Does temporal filter for a given macroblock row.
293 *
294 * \ingroup src_frame_proc
295 * \param[in]   cpi                   Top level encoder instance structure
296 * \param[in]   td                    Pointer to thread data
297 * \param[in]   mb_row                Macroblock row to be filtered
298 filtering
299 *
300 * \remark Nothing will be returned, but the contents of td->diff will be
301 modified.
302 */
303 void av1_tf_do_filtering_row(struct AV1_COMP *cpi, struct ThreadData *td,
304                              int mb_row);
305 
306 /*!\brief Performs temporal filtering if needed on a source frame.
307  * For example to create a filtered alternate reference frame (ARF)
308  *
309  * In this function, the lookahead index is different from the 0-based
310  * real index. For example, if we want to filter the first frame in the
311  * pre-fetched buffer `cpi->lookahead`, the lookahead index will be -1 instead
312  * of 0. More concretely, 0 indicates the first LOOKAHEAD frame, which is the
313  * second frame in the pre-fetched buffer. Another example: if we want to filter
314  * the 17-th frame, which is an ARF, the lookahead index is 15 instead of 16.
315  * Futhermore, negative number is used for key frame in one-pass mode, where key
316  * frame is filtered with the frames before it instead of after it. For example,
317  * -15 means to filter the 17-th frame, which is a key frame in one-pass mode.
318  *
319  * \ingroup src_frame_proc
320  * \param[in]      cpi                        Top level encoder instance
321  *                                            structure
322  * \param[in]      filter_frame_lookahead_idx The index of the
323  *                                            to-filter frame in the lookahead
324  *                                            buffer cpi->lookahead.
325  * \param[in]      gf_frame_index             Index of GOP
326  * \param[in,out]  frame_diff                 structure of sse and sum of the
327  *                                            filtered frame.
328  * \param[out]     output_frame               Ouput filtered frame.
329  */
330 void av1_temporal_filter(struct AV1_COMP *cpi,
331                          const int filter_frame_lookahead_idx,
332                          int gf_frame_index, FRAME_DIFF *frame_diff,
333                          YV12_BUFFER_CONFIG *output_frame);
334 
335 /*!\brief Check whether a filtered frame can be show directly
336  *
337  * This function will use the filtered frame's sse and current q index
338  * to make decision.
339  *
340  * \ingroup src_frame_proc
341  * \param[in]  frame        filtered frame's buffer
342  * \param[in]  frame_diff   structure of sse and sum of the
343  *                          filtered frame.
344  * \param[in]  q_index      q_index used for this frame
345  * \param[in]  bit_depth    bit depth
346  * \return     return 1 if this frame can be shown directly, otherwise
347  *             return 0
348  */
349 int av1_check_show_filtered_frame(const YV12_BUFFER_CONFIG *frame,
350                                   const FRAME_DIFF *frame_diff, int q_index,
351                                   aom_bit_depth_t bit_depth);
352 
353 /*!\cond */
354 // Allocates memory for members of TemporalFilterData.
355 // Inputs:
356 //   tf_data: Pointer to the structure containing temporal filter related data.
357 //   num_pels: Number of pixels in the block across all planes.
358 //   is_high_bitdepth: Whether the frame is high-bitdepth or not.
359 // Returns:
360 //   True if allocation is successful and false otherwise.
tf_alloc_and_reset_data(TemporalFilterData * tf_data,int num_pels,int is_high_bitdepth)361 static inline bool tf_alloc_and_reset_data(TemporalFilterData *tf_data,
362                                            int num_pels, int is_high_bitdepth) {
363   tf_data->tmp_mbmi = (MB_MODE_INFO *)aom_calloc(1, sizeof(*tf_data->tmp_mbmi));
364   tf_data->accum =
365       (uint32_t *)aom_memalign(16, num_pels * sizeof(*tf_data->accum));
366   tf_data->count =
367       (uint16_t *)aom_memalign(16, num_pels * sizeof(*tf_data->count));
368   if (is_high_bitdepth)
369     tf_data->pred = CONVERT_TO_BYTEPTR(
370         aom_memalign(32, num_pels * 2 * sizeof(*tf_data->pred)));
371   else
372     tf_data->pred =
373         (uint8_t *)aom_memalign(32, num_pels * sizeof(*tf_data->pred));
374   // In case of an allocation failure, other successfully allocated buffers will
375   // be freed by the tf_dealloc_data() call in encoder_destroy().
376   if (!(tf_data->tmp_mbmi && tf_data->accum && tf_data->count && tf_data->pred))
377     return false;
378   memset(&tf_data->diff, 0, sizeof(tf_data->diff));
379   return true;
380 }
381 
382 // Setup macroblockd params for temporal filtering process.
383 // Inputs:
384 //   mbd: Pointer to the block for filtering.
385 //   tf_data: Pointer to the structure containing temporal filter related data.
386 //   scale: Scaling factor.
387 // Returns:
388 //   Nothing will be returned. Contents of mbd will be modified.
tf_setup_macroblockd(MACROBLOCKD * mbd,TemporalFilterData * tf_data,const struct scale_factors * scale)389 static inline void tf_setup_macroblockd(MACROBLOCKD *mbd,
390                                         TemporalFilterData *tf_data,
391                                         const struct scale_factors *scale) {
392   mbd->block_ref_scale_factors[0] = scale;
393   mbd->block_ref_scale_factors[1] = scale;
394   mbd->mi = &tf_data->tmp_mbmi;
395   mbd->mi[0]->motion_mode = SIMPLE_TRANSLATION;
396 }
397 
398 // Deallocates the memory allocated for members of TemporalFilterData.
399 // Inputs:
400 //   tf_data: Pointer to the structure containing temporal filter related data.
401 //   is_high_bitdepth: Whether the frame is high-bitdepth or not.
402 // Returns:
403 //   Nothing will be returned.
tf_dealloc_data(TemporalFilterData * tf_data,int is_high_bitdepth)404 static inline void tf_dealloc_data(TemporalFilterData *tf_data,
405                                    int is_high_bitdepth) {
406   if (is_high_bitdepth)
407     tf_data->pred = (uint8_t *)CONVERT_TO_SHORTPTR(tf_data->pred);
408   aom_free(tf_data->tmp_mbmi);
409   tf_data->tmp_mbmi = NULL;
410   aom_free(tf_data->accum);
411   tf_data->accum = NULL;
412   aom_free(tf_data->count);
413   tf_data->count = NULL;
414   aom_free(tf_data->pred);
415   tf_data->pred = NULL;
416 }
417 
418 // Saves the state prior to temporal filter process.
419 // Inputs:
420 //   mbd: Pointer to the block for filtering.
421 //   input_mbmi: Backup block info to save input state.
422 //   input_buffer: Backup buffer pointer to save input state.
423 //   num_planes: Number of planes.
424 // Returns:
425 //   Nothing will be returned. Contents of input_mbmi and input_buffer will be
426 //   modified.
tf_save_state(MACROBLOCKD * mbd,MB_MODE_INFO *** input_mbmi,uint8_t ** input_buffer,int num_planes)427 static inline void tf_save_state(MACROBLOCKD *mbd, MB_MODE_INFO ***input_mbmi,
428                                  uint8_t **input_buffer, int num_planes) {
429   for (int i = 0; i < num_planes; i++) {
430     input_buffer[i] = mbd->plane[i].pre[0].buf;
431   }
432   *input_mbmi = mbd->mi;
433 }
434 
435 // Restores the initial state after temporal filter process.
436 // Inputs:
437 //   mbd: Pointer to the block for filtering.
438 //   input_mbmi: Backup block info from where input state is restored.
439 //   input_buffer: Backup buffer pointer from where input state is restored.
440 //   num_planes: Number of planes.
441 // Returns:
442 //   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)443 static inline void tf_restore_state(MACROBLOCKD *mbd, MB_MODE_INFO **input_mbmi,
444                                     uint8_t **input_buffer, int num_planes) {
445   for (int i = 0; i < num_planes; i++) {
446     mbd->plane[i].pre[0].buf = input_buffer[i];
447   }
448   mbd->mi = input_mbmi;
449 }
450 
451 /*!\endcond */
452 #ifdef __cplusplus
453 }  // extern "C"
454 #endif
455 
456 #endif  // AOM_AV1_ENCODER_TEMPORAL_FILTER_H_
457