av1/encoder/temporal_filter.c
// Does motion search for blocks in temporal filtering. This is the first step
// for temporal filtering. More specifically, given a frame to be filtered and
// another frame as reference, this function searches the reference frame to
// find out the most alike block as that from the frame to be filtered. This
// found block will be further used for weighted averaging.
// NOTE: Besides doing motion search for the entire block, this function will
// also do motion search for each 1/4 sub-block to get more precise prediction.
// Inputs:
//   cpi: Pointer to the composed information of input video.
//   frame_to_filter: Pointer to the frame to be filtered.
//   ref_frame: Pointer to the reference frame.
//   block_size: Block size used for motion search.
//   mb_row: Row index of the block in the entire frame.
//   mb_col: Column index of the block in the entire frame.
//   ref_mv: Reference motion vector, which is commonly inherited from the
//           motion search result of previous frame.
//   subblock_mvs: Pointer to the result motion vectors for 4 sub-blocks.
//   subblock_errors: Pointer to the search errors for 4 sub-blocks.
// Returns:
//   Search error of the entire block.
Does motion search for blocks in temporal filtering. This is the first step
for temporal filtering. More specifically, given a frame to be filtered and
another frame as reference, this function searches the reference frame to
find out the most alike block as that from the frame to be filtered. This
found block will be further used for weighted averaging.
NOTE: Besides doing motion search for the entire block, this function will
also do motion search for each 1/4 sub-block to get more precise prediction.
Inputs:
cpi: Pointer to the composed information of input video.
frame_to_filter: Pointer to the frame to be filtered.
ref_frame: Pointer to the reference frame.
block_size: Block size used for motion search.
mb_row: Row index of the block in the entire frame.
mb_col: Column index of the block in the entire frame.
ref_mv: Reference motion vector, which is commonly inherited from the
motion search result of previous frame.
subblock_mvs: Pointer to the result motion vectors for 4 sub-blocks.
subblock_errors: Pointer to the search errors for 4 sub-blocks.
Returns:
Search error of the entire block.
Does motion search for blocks in temporal filtering . This is the first step for temporal filtering . More specifically given a frame to be filtered and another frame as reference this function searches the reference frame to find out the most alike block as that from the frame to be filtered . This found block will be further used for weighted averaging . NOTE : Besides doing motion search for the entire block this function will also do motion search for each 1 / 4 sub - block to get more precise prediction . Inputs : cpi : Pointer to the composed information of input video . frame_to_filter : Pointer to the frame to be filtered . ref_frame : Pointer to the reference frame . block_size : Block size used for motion search . mb_row : Row index of the block in the entire frame . mb_col : Column index of the block in the entire frame . ref_mv : Reference motion vector which is commonly inherited from the motion search result of previous frame . subblock_mvs : Pointer to the result motion vectors for 4 sub - blocks . subblock_errors : Pointer to the search errors for 4 sub - blocks . Returns : Search error of the entire block .
static int tf_motion_search(AV1_COMP *cpi,
                            const YV12_BUFFER_CONFIG *frame_to_filter,
                            const YV12_BUFFER_CONFIG *ref_frame,
                            const BLOCK_SIZE block_size, const int mb_row,
                            const int mb_col, MV *ref_mv, MV *subblock_mvs,
                            int *subblock_errors) {
  const int min_frame_size = AOMMIN(cpi->common.width, cpi->common.height);
  const int mb_height = block_size_high[block_size];
  const int mb_width = block_size_wide[block_size];
  const int y_stride = frame_to_filter->y_stride;
  assert(y_stride == ref_frame->y_stride);
  const int y_offset = mb_row * mb_height * y_stride + mb_col * mb_width;
  MACROBLOCK *const mb = &cpi->td.mb;
  MACROBLOCKD *const mbd = &mb->e_mbd;
  const struct buf_2d ori_src_buf = mb->plane[0].src;
  const struct buf_2d ori_pre_buf = mbd->plane[0].pre[0];
  const FullMvLimits ori_mv_limits = mb->mv_limits;
  const MV_COST_TYPE ori_mv_cost_type = mb->mv_cost_type;
  const uint8_t *second_pred = NULL;
  const uint8_t *mask = NULL;
  const int mask_stride = 0;
  const int invert_mask = 0;
  const int do_reset_fractional_mv = 1;
  SUBPEL_MOTION_SEARCH_PARAMS ms_params;
  const int sadperbit = mb->sadperbit;
  const search_site_config ss_cfg = cpi->ss_cfg[SS_CFG_LOOKAHEAD];
  const SEARCH_METHODS full_search_method = NSTEP;
  const int step_param = av1_init_search_range(
      AOMMAX(frame_to_filter->y_crop_width, frame_to_filter->y_crop_height));
  const SUBPEL_SEARCH_TYPE subpel_search_type = USE_8_TAPS;
  const int force_integer_mv = cpi->common.cur_frame_force_integer_mv;
  const MV_COST_TYPE mv_cost_type =
      min_frame_size >= 720
          ? MV_COST_L1_HDRES
          : (min_frame_size >= 480 ? MV_COST_L1_MIDRES : MV_COST_L1_LOWRES);
  FULLPEL_MV start_mv = get_fullmv_from_mv(ref_mv);
  const MV baseline_mv = kZeroMv;
  mb->plane[0].src.buf = frame_to_filter->y_buffer + y_offset;
  mb->plane[0].src.stride = y_stride;
  mbd->plane[0].pre[0].buf = ref_frame->y_buffer + y_offset;
  mbd->plane[0].pre[0].stride = y_stride;
  av1_set_mv_search_range(&mb->mv_limits, &baseline_mv);
  unsigned int sse;
  int distortion;
  int cost_list[5];
  int block_error = INT_MAX;
  mb->mv_cost_type = mv_cost_type;
  av1_full_pixel_search(cpi, mb, block_size, start_mv, step_param,
                        full_search_method, 1, sadperbit,
                        cond_cost_list(cpi, cost_list), &baseline_mv, 0,
                        &ss_cfg, &mb->best_mv.as_fullmv, NULL);
  mb->mv_cost_type = MV_COST_NONE;
  if (force_integer_mv == 1) {  
    const int mv_row = mb->best_mv.as_mv.row;
    const int mv_col = mb->best_mv.as_mv.col;
    mb->best_mv.as_mv.row = GET_MV_SUBPEL(mv_row);
    mb->best_mv.as_mv.col = GET_MV_SUBPEL(mv_col);
    const int mv_offset = mv_row * y_stride + mv_col;
    block_error = cpi->fn_ptr[block_size].vf(
        ref_frame->y_buffer + y_offset + mv_offset, y_stride,
        frame_to_filter->y_buffer + y_offset, y_stride, &sse);
    mb->e_mbd.mi[0]->mv[0] = mb->best_mv;
  } else {  
    av1_make_default_subpel_ms_params(
        &ms_params, cpi, mb, block_size, &baseline_mv, cost_list, second_pred,
        mask, mask_stride, invert_mask, do_reset_fractional_mv);
    ms_params.forced_stop = EIGHTH_PEL;
    ms_params.var_params.subpel_search_type = subpel_search_type;
    block_error = cpi->find_fractional_mv_step(mb, &cpi->common, &ms_params,
                                               &distortion, &sse);
    mb->e_mbd.mi[0]->mv[0] = mb->best_mv;
    *ref_mv = mb->best_mv.as_mv;
    const BLOCK_SIZE subblock_size = ss_size_lookup[block_size][1][1];
    const int subblock_height = block_size_high[subblock_size];
    const int subblock_width = block_size_wide[subblock_size];
    start_mv = get_fullmv_from_mv(ref_mv);
    int subblock_idx = 0;
    for (int i = 0; i < mb_height; i += subblock_height) {
      for (int j = 0; j < mb_width; j += subblock_width) {
        const int offset = i * y_stride + j;
        mb->plane[0].src.buf = frame_to_filter->y_buffer + y_offset + offset;
        mbd->plane[0].pre[0].buf = ref_frame->y_buffer + y_offset + offset;
        av1_set_mv_search_range(&mb->mv_limits, &baseline_mv);
        mb->mv_cost_type = mv_cost_type;
        av1_full_pixel_search(cpi, mb, subblock_size, start_mv, step_param,
                              full_search_method, 1, sadperbit,
                              cond_cost_list(cpi, cost_list), &baseline_mv, 0,
                              &ss_cfg, &mb->best_mv.as_fullmv, NULL);
        mb->mv_cost_type = MV_COST_NONE;
        av1_make_default_subpel_ms_params(&ms_params, cpi, mb, subblock_size,
                                          &baseline_mv, cost_list, second_pred,
                                          mask, mask_stride, invert_mask,
                                          do_reset_fractional_mv);
        ms_params.forced_stop = EIGHTH_PEL;
        ms_params.var_params.subpel_search_type = subpel_search_type;
        subblock_errors[subblock_idx] = cpi->find_fractional_mv_step(
            mb, &cpi->common, &ms_params, &distortion, &sse);
        subblock_mvs[subblock_idx] = mb->best_mv.as_mv;
        ++subblock_idx;
      }
    }
  }
  mb->plane[0].src = ori_src_buf;
  mbd->plane[0].pre[0] = ori_pre_buf;
  mb->mv_limits = ori_mv_limits;
  mb->mv_cost_type = ori_mv_cost_type;
  return block_error;
}
static int tf_motion_search ( AV1_COMP * cpi , const YV12_BUFFER_CONFIG * frame_to_filter , const YV12_BUFFER_CONFIG * ref_frame , const BLOCK_SIZE block_size , const int mb_row , const int mb_col , MV * ref_mv , MV * subblock_mvs , int * subblock_errors ) { const int min_frame_size = AOMMIN ( cpi -> common . width , cpi -> common . height ) ; const int mb_height = block_size_high [ block_size ] ; const int mb_width = block_size_wide [ block_size ] ; const int y_stride = frame_to_filter -> y_stride ; assert ( y_stride == ref_frame -> y_stride ) ; const int y_offset = mb_row * mb_height * y_stride + mb_col * mb_width ; MACROBLOCK * const mb = & cpi -> td . mb ; MACROBLOCKD * const mbd = & mb -> e_mbd ; const struct buf_2d ori_src_buf = mb -> plane [ 0 ] . src ; const struct buf_2d ori_pre_buf = mbd -> plane [ 0 ] . pre [ 0 ] ; const FullMvLimits ori_mv_limits = mb -> mv_limits ; const MV_COST_TYPE ori_mv_cost_type = mb -> mv_cost_type ; const uint8_t * second_pred = NULL ; const uint8_t * mask = NULL ; const int mask_stride = 0 ; const int invert_mask = 0 ; const int do_reset_fractional_mv = 1 ; SUBPEL_MOTION_SEARCH_PARAMS ms_params ; const int sadperbit = mb -> sadperbit ; const search_site_config ss_cfg = cpi -> ss_cfg [ SS_CFG_LOOKAHEAD ] ; const SEARCH_METHODS full_search_method = NSTEP ; const int step_param = av1_init_search_range ( AOMMAX ( frame_to_filter -> y_crop_width , frame_to_filter -> y_crop_height ) ) ; const SUBPEL_SEARCH_TYPE subpel_search_type = USE_8_TAPS ; const int force_integer_mv = cpi -> common . cur_frame_force_integer_mv ; const MV_COST_TYPE mv_cost_type = min_frame_size >= 720 ? MV_COST_L1_HDRES : ( min_frame_size >= 480 ? MV_COST_L1_MIDRES : MV_COST_L1_LOWRES ) ; FULLPEL_MV start_mv = get_fullmv_from_mv ( ref_mv ) ; const MV baseline_mv = kZeroMv ; mb -> plane [ 0 ] . src . buf = frame_to_filter -> y_buffer + y_offset ; mb -> plane [ 0 ] . src . stride = y_stride ; mbd -> plane [ 0 ] . pre [ 0 ] . buf = ref_frame -> y_buffer + y_offset ; mbd -> plane [ 0 ] . pre [ 0 ] . stride = y_stride ; av1_set_mv_search_range ( & mb -> mv_limits , & baseline_mv ) ; unsigned int sse ; int distortion ; int cost_list [ 5 ] ; int block_error = INT_MAX ; mb -> mv_cost_type = mv_cost_type ; av1_full_pixel_search ( cpi , mb , block_size , start_mv , step_param , full_search_method , 1 , sadperbit , cond_cost_list ( cpi , cost_list ) , & baseline_mv , 0 , & ss_cfg , & mb -> best_mv . as_fullmv , NULL ) ; mb -> mv_cost_type = MV_COST_NONE ; if ( force_integer_mv == 1 ) { const int mv_row = mb -> best_mv . as_mv . row ; const int mv_col = mb -> best_mv . as_mv . col ; mb -> best_mv . as_mv . row = GET_MV_SUBPEL ( mv_row ) ; mb -> best_mv . as_mv . col = GET_MV_SUBPEL ( mv_col ) ; const int mv_offset = mv_row * y_stride + mv_col ; block_error = cpi -> fn_ptr [ block_size ] . vf ( ref_frame -> y_buffer + y_offset + mv_offset , y_stride , frame_to_filter -> y_buffer + y_offset , y_stride , & sse ) ; mb -> e_mbd . mi [ 0 ] -> mv [ 0 ] = mb -> best_mv ; } else { av1_make_default_subpel_ms_params ( & ms_params , cpi , mb , block_size , & baseline_mv , cost_list , second_pred , mask , mask_stride , invert_mask , do_reset_fractional_mv ) ; ms_params . forced_stop = EIGHTH_PEL ; ms_params . var_params . subpel_search_type = subpel_search_type ; block_error = cpi -> find_fractional_mv_step ( mb , & cpi -> common , & ms_params , & distortion , & sse ) ; mb -> e_mbd . mi [ 0 ] -> mv [ 0 ] = mb -> best_mv ; * ref_mv = mb -> best_mv . as_mv ; const BLOCK_SIZE subblock_size = ss_size_lookup [ block_size ] [ 1 ] [ 1 ] ; const int subblock_height = block_size_high [ subblock_size ] ; const int subblock_width = block_size_wide [ subblock_size ] ; start_mv = get_fullmv_from_mv ( ref_mv ) ; int subblock_idx = 0 ; for ( int i = 0 ; i < mb_height ; i += subblock_height ) { for ( int j = 0 ; j < mb_width ; j += subblock_width ) { const int offset = i * y_stride + j ; mb -> plane [ 0 ] . src . buf = frame_to_filter -> y_buffer + y_offset + offset ; mbd -> plane [ 0 ] . pre [ 0 ] . buf = ref_frame -> y_buffer + y_offset + offset ; av1_set_mv_search_range ( & mb -> mv_limits , & baseline_mv ) ; mb -> mv_cost_type = mv_cost_type ; av1_full_pixel_search ( cpi , mb , subblock_size , start_mv , step_param , full_search_method , 1 , sadperbit , cond_cost_list ( cpi , cost_list ) , & baseline_mv , 0 , & ss_cfg , & mb -> best_mv . as_fullmv , NULL ) ; mb -> mv_cost_type = MV_COST_NONE ; av1_make_default_subpel_ms_params ( & ms_params , cpi , mb , subblock_size , & baseline_mv , cost_list , second_pred , mask , mask_stride , invert_mask , do_reset_fractional_mv ) ; ms_params . forced_stop = EIGHTH_PEL ; ms_params . var_params . subpel_search_type = subpel_search_type ; subblock_errors [ subblock_idx ] = cpi -> find_fractional_mv_step ( mb , & cpi -> common , & ms_params , & distortion , & sse ) ; subblock_mvs [ subblock_idx ] = mb -> best_mv . as_mv ; ++ subblock_idx ; } } } mb -> plane [ 0 ] . src = ori_src_buf ; mbd -> plane [ 0 ] . pre [ 0 ] = ori_pre_buf ; mb -> mv_limits = ori_mv_limits ; mb -> mv_cost_type = ori_mv_cost_type ; return block_error ; }
Does motion search for blocks in temporal filtering.
Does motion search for blocks in temporal filtering .
// Frame information // Block information (ONLY Y-plane is used for motion search). // Save input state. // Parameters used for motion search. // Starting position for motion search. // Baseline position for motion search (used for rate distortion comparison). // Setup. // Unused intermediate results for motion search. // Do motion search. // NOTE: In `av1_full_pixel_search()` and `find_fractional_mv_step()`, the // searched result will be stored in `mb->best_mv`. // Since we are merely refining the result from full pixel search, we don't // need regularization for subpel search // Only do full search on the entire block. // Do fractional search on the entire block and all sub-blocks. // On 4 sub-blocks. // Since we are merely refining the result from full pixel search, we // don't need regularization for subpel search // Restore input state.