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