av1/encoder/temporal_filter.c
// Applies temporal filter with YUV strategy.
// Inputs:
//   frame_to_filter: Pointer to the frame to be filtered, which is used as
//                    reference to compute squared differece from the predictor.
//   mbd: Pointer to the block for filtering, which is ONLY used to get
//        subsampling information of all YUV planes.
//   block_size: Size of the block.
//   mb_row: Row index of the block in the entire frame.
//   mb_col: Column index of the block in the entire frame.
//   num_planes: Number of planes in the frame.
//   strength: Strength for filter weight adjustment.
//   use_subblock: Whether to use 4 sub-blocks to replace the original block.
//   subblock_filter_weights: The filter weights for each sub-block (row-major
//                            order). If `use_subblock` is set as 0, the first
//                            weight will be applied to the entire block.
//   pred: Pointer to the well-built predictors.
//   accum: Pointer to the pixel-wise accumulator for filtering.
//   count: Pointer to the pixel-wise counter fot filtering.
// Returns:
//   Nothing will be returned. But the content to which `accum` and `pred`
//   point will be modified.
Applies temporal filter with YUV strategy.
Inputs:
frame_to_filter: Pointer to the frame to be filtered, which is used as
reference to compute squared differece from the predictor.
mbd: Pointer to the block for filtering, which is ONLY used to get
subsampling information of all YUV planes.
block_size: Size of the block.
mb_row: Row index of the block in the entire frame.
mb_col: Column index of the block in the entire frame.
num_planes: Number of planes in the frame.
strength: Strength for filter weight adjustment.
use_subblock: Whether to use 4 sub-blocks to replace the original block.
subblock_filter_weights: The filter weights for each sub-block (row-major
order). If `use_subblock` is set as 0, the first
weight will be applied to the entire block.
pred: Pointer to the well-built predictors.
accum: Pointer to the pixel-wise accumulator for filtering.
count: Pointer to the pixel-wise counter fot filtering.
Returns:
Nothing will be returned. But the content to which `accum` and `pred`
point will be modified.
Applies temporal filter with YUV strategy . Inputs : frame_to_filter : Pointer to the frame to be filtered which is used as reference to compute squared differece from the predictor . mbd : Pointer to the block for filtering which is ONLY used to get subsampling information of all YUV planes . block_size : Size of the block . mb_row : Row index of the block in the entire frame . mb_col : Column index of the block in the entire frame . num_planes : Number of planes in the frame . strength : Strength for filter weight adjustment . use_subblock : Whether to use 4 sub - blocks to replace the original block . subblock_filter_weights : The filter weights for each sub - block ( row - major order ) . If ` use_subblock ` is set as 0 the first weight will be applied to the entire block . pred : Pointer to the well - built predictors . accum : Pointer to the pixel - wise accumulator for filtering . count : Pointer to the pixel - wise counter fot filtering . Returns : Nothing will be returned . But the content to which ` accum ` and ` pred ` point will be modified .
void av1_apply_temporal_filter_yuv_c(
    const YV12_BUFFER_CONFIG *frame_to_filter, const MACROBLOCKD *mbd,
    const BLOCK_SIZE block_size, const int mb_row, const int mb_col,
    const int num_planes, const int strength, const int use_subblock,
    const int *subblock_filter_weights, const uint8_t *pred, uint32_t *accum,
    uint16_t *count) {
  assert(num_planes >= 1 && num_planes <= MAX_MB_PLANE);
  const int mb_height = block_size_high[block_size];
  const int mb_width = block_size_wide[block_size];
  const int mb_pels = mb_height * mb_width;
  const int is_high_bitdepth = is_frame_high_bitdepth(frame_to_filter);
  const uint16_t *pred16 = CONVERT_TO_SHORTPTR(pred);
  uint32_t *square_diff =
      aom_memalign(16, num_planes * mb_pels * sizeof(uint32_t));
  memset(square_diff, 0, num_planes * mb_pels * sizeof(square_diff[0]));
  int plane_offset = 0;
  for (int plane = 0; plane < num_planes; ++plane) {
    const int plane_h = mb_height >> mbd->plane[plane].subsampling_y;
    const int plane_w = mb_width >> mbd->plane[plane].subsampling_x;
    const int frame_stride = frame_to_filter->strides[plane == 0 ? 0 : 1];
    const int frame_offset = mb_row * plane_h * frame_stride + mb_col * plane_w;
    const uint8_t *ref = frame_to_filter->buffers[plane];
    compute_square_diff(ref, frame_offset, frame_stride, pred, plane_offset,
                        plane_w, plane_h, plane_w, is_high_bitdepth,
                        square_diff + plane_offset);
    plane_offset += mb_pels;
  }
  assert(TF_YUV_FILTER_WINDOW_LENGTH % 2 == 1);
  const int half_window = TF_YUV_FILTER_WINDOW_LENGTH >> 1;
  plane_offset = 0;
  for (int plane = 0; plane < num_planes; ++plane) {
    const int subsampling_y = mbd->plane[plane].subsampling_y;
    const int subsampling_x = mbd->plane[plane].subsampling_x;
    const int h = mb_height >> subsampling_y;  
    const int w = mb_width >> subsampling_x;   
    int pred_idx = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        uint64_t sum_square_diff = 0;
        int num_ref_pixels = 0;
        for (int wi = -half_window; wi <= half_window; ++wi) {
          for (int wj = -half_window; wj <= half_window; ++wj) {
            const int y = i + wi;  
            const int x = j + wj;  
            if (y >= 0 && y < h && x >= 0 && x < w) {
              sum_square_diff += square_diff[plane_offset + y * w + x];
              ++num_ref_pixels;
            }
          }
        }
        if (plane == 0) {  
          for (int p = 1; p < num_planes; ++p) {
            const int ss_y_shift = mbd->plane[p].subsampling_y - subsampling_y;
            const int ss_x_shift = mbd->plane[p].subsampling_x - subsampling_x;
            const int yy = i >> ss_y_shift;  
            const int xx = j >> ss_x_shift;  
            const int ww = w >> ss_x_shift;  
            sum_square_diff += square_diff[p * mb_pels + yy * ww + xx];
            ++num_ref_pixels;
          }
        } else {  
          const int ss_y_shift = subsampling_y - mbd->plane[0].subsampling_y;
          const int ss_x_shift = subsampling_x - mbd->plane[0].subsampling_x;
          for (int ii = 0; ii < (1 << ss_y_shift); ++ii) {
            for (int jj = 0; jj < (1 << ss_x_shift); ++jj) {
              const int yy = (i << ss_y_shift) + ii;  
              const int xx = (j << ss_x_shift) + jj;  
              const int ww = w << ss_x_shift;         
              sum_square_diff += square_diff[yy * ww + xx];
              ++num_ref_pixels;
            }
          }
        }
        const int subblock_idx =
            use_subblock ? (i >= h / 2) * 2 + (j >= w / 2) : 0;
        const int filter_weight = subblock_filter_weights[subblock_idx];
        const int idx = plane_offset + pred_idx;  
        const int pred_value = is_high_bitdepth ? pred16[idx] : pred[idx];
        const int adjusted_weight = adjust_filter_weight_yuv(
            filter_weight, sum_square_diff, num_ref_pixels, strength);
        accum[idx] += adjusted_weight * pred_value;
        count[idx] += adjusted_weight;
        ++pred_idx;
      }
    }
    plane_offset += mb_pels;
  }
  aom_free(square_diff);
}
void av1_apply_temporal_filter_yuv_c ( const YV12_BUFFER_CONFIG * frame_to_filter , const MACROBLOCKD * mbd , const BLOCK_SIZE block_size , const int mb_row , const int mb_col , const int num_planes , const int strength , const int use_subblock , const int * subblock_filter_weights , const uint8_t * pred , uint32_t * accum , uint16_t * count ) { assert ( num_planes >= 1 && num_planes <= MAX_MB_PLANE ) ; const int mb_height = block_size_high [ block_size ] ; const int mb_width = block_size_wide [ block_size ] ; const int mb_pels = mb_height * mb_width ; const int is_high_bitdepth = is_frame_high_bitdepth ( frame_to_filter ) ; const uint16_t * pred16 = CONVERT_TO_SHORTPTR ( pred ) ; uint32_t * square_diff = aom_memalign ( 16 , num_planes * mb_pels * sizeof ( uint32_t ) ) ; memset ( square_diff , 0 , num_planes * mb_pels * sizeof ( square_diff [ 0 ] ) ) ; int plane_offset = 0 ; for ( int plane = 0 ; plane < num_planes ; ++ plane ) { const int plane_h = mb_height >> mbd -> plane [ plane ] . subsampling_y ; const int plane_w = mb_width >> mbd -> plane [ plane ] . subsampling_x ; const int frame_stride = frame_to_filter -> strides [ plane == 0 ? 0 : 1 ] ; const int frame_offset = mb_row * plane_h * frame_stride + mb_col * plane_w ; const uint8_t * ref = frame_to_filter -> buffers [ plane ] ; compute_square_diff ( ref , frame_offset , frame_stride , pred , plane_offset , plane_w , plane_h , plane_w , is_high_bitdepth , square_diff + plane_offset ) ; plane_offset += mb_pels ; } assert ( TF_YUV_FILTER_WINDOW_LENGTH % 2 == 1 ) ; const int half_window = TF_YUV_FILTER_WINDOW_LENGTH >> 1 ; plane_offset = 0 ; for ( int plane = 0 ; plane < num_planes ; ++ plane ) { const int subsampling_y = mbd -> plane [ plane ] . subsampling_y ; const int subsampling_x = mbd -> plane [ plane ] . subsampling_x ; const int h = mb_height >> subsampling_y ; const int w = mb_width >> subsampling_x ; int pred_idx = 0 ; for ( int i = 0 ; i < h ; ++ i ) { for ( int j = 0 ; j < w ; ++ j ) { uint64_t sum_square_diff = 0 ; int num_ref_pixels = 0 ; for ( int wi = - half_window ; wi <= half_window ; ++ wi ) { for ( int wj = - half_window ; wj <= half_window ; ++ wj ) { const int y = i + wi ; const int x = j + wj ; if ( y >= 0 && y < h && x >= 0 && x < w ) { sum_square_diff += square_diff [ plane_offset + y * w + x ] ; ++ num_ref_pixels ; } } } if ( plane == 0 ) { for ( int p = 1 ; p < num_planes ; ++ p ) { const int ss_y_shift = mbd -> plane [ p ] . subsampling_y - subsampling_y ; const int ss_x_shift = mbd -> plane [ p ] . subsampling_x - subsampling_x ; const int yy = i >> ss_y_shift ; const int xx = j >> ss_x_shift ; const int ww = w >> ss_x_shift ; sum_square_diff += square_diff [ p * mb_pels + yy * ww + xx ] ; ++ num_ref_pixels ; } } else { const int ss_y_shift = subsampling_y - mbd -> plane [ 0 ] . subsampling_y ; const int ss_x_shift = subsampling_x - mbd -> plane [ 0 ] . subsampling_x ; for ( int ii = 0 ; ii < ( 1 << ss_y_shift ) ; ++ ii ) { for ( int jj = 0 ; jj < ( 1 << ss_x_shift ) ; ++ jj ) { const int yy = ( i << ss_y_shift ) + ii ; const int xx = ( j << ss_x_shift ) + jj ; const int ww = w << ss_x_shift ; sum_square_diff += square_diff [ yy * ww + xx ] ; ++ num_ref_pixels ; } } } const int subblock_idx = use_subblock ? ( i >= h / 2 ) * 2 + ( j >= w / 2 ) : 0 ; const int filter_weight = subblock_filter_weights [ subblock_idx ] ; const int idx = plane_offset + pred_idx ; const int pred_value = is_high_bitdepth ? pred16 [ idx ] : pred [ idx ] ; const int adjusted_weight = adjust_filter_weight_yuv ( filter_weight , sum_square_diff , num_ref_pixels , strength ) ; accum [ idx ] += adjusted_weight * pred_value ; count [ idx ] += adjusted_weight ; ++ pred_idx ; } } plane_offset += mb_pels ; } aom_free ( square_diff ) ; }
Applies temporal filter with YUV strategy.
Applies temporal filter with YUV strategy .
// Block information. // Allocate memory for pixel-wise squared differences for all planes. They, // regardless of the subsampling, are assigned with memory of size `mb_pels`. // Locate pixel on reference frame. // Get window size for pixel-wise filtering. // Handle planes in sequence. // Plane height. // Plane width. // Perform filtering. // non-local mean approach // Y-coord on the current plane. // X-coord on the current plane. // Filter Y-plane using both U-plane and V-plane. // Y-coord on UV-plane. // X-coord on UV-plane. // Width of UV-plane. // Filter U-plane and V-plane using Y-plane. // Y-coord on Y-plane. // X-coord on Y-plane. // Width of Y-plane. // Base filter weight estimated by motion search error. // Index with plane shift.