美文网首页
av1代码学习12--encode_sb_row()

av1代码学习12--encode_sb_row()

作者: 青吟乐 | 来源:发表于2020-06-28 19:32 被阅读0次

    1,函数功能

    配置tile中superblock的属性,配置编码顺序,inter编码初始化运动搜索,rd_pick_partition()进入下一层编码

    2,代码学习

    static void encode_sb_row(AV1_COMP *cpi, ThreadData *td, TileDataEnc *tile_data,
                              int mi_row, TOKENEXTRA **tp, int use_nonrd_mode) {
      AV1_COMMON *const cm = &cpi->common;
      const int num_planes = av1_num_planes(cm);//平面
      const TileInfo *const tile_info = &tile_data->tile_info;//tile信息
      MACROBLOCK *const x = &td->mb;//Ymode
      MACROBLOCKD *const xd = &x->e_mbd;
      const SPEED_FEATURES *const sf = &cpi->sf;
      const int sb_cols_in_tile = av1_get_sb_cols_in_tile(cm, tile_data->tile_info);//列位置
      const BLOCK_SIZE sb_size = cm->seq_params.sb_size;//本帧用的sb大小
      const int mib_size = cm->seq_params.mib_size;//以MI块大小为单位的super块的MI块大小
      const int mib_size_log2 = cm->seq_params.mib_size_log2;//MI块大小的对数值
      const int sb_row = (mi_row - tile_info->mi_row_start) >> mib_size_log2;//行位置
    
    #if CONFIG_COLLECT_COMPONENT_TIMING
      start_timing(cpi, encode_sb_time);
    #endif
    
      // Initialize the left context for the new SB row
      av1_zero_left_context(xd);
    
      // Reset delta for every tile,初始化qp
      if (mi_row == tile_info->mi_row_start || cpi->row_mt) {
        if (cm->delta_q_info.delta_q_present_flag)
          xd->current_qindex = cm->base_qindex;
        if (cm->delta_q_info.delta_lf_present_flag) {
          av1_reset_loop_filter_delta(xd, av1_num_planes(cm));
        }
      }
      reset_thresh_freq_fact(x);//Ymode
    
      // Code each SB in the row
      for (int mi_col = tile_info->mi_col_start, sb_col_in_tile = 0;
           mi_col < tile_info->mi_col_end; mi_col += mib_size, sb_col_in_tile++) {
        (*(cpi->row_mt_sync_read_ptr))(&tile_data->row_mt_sync, sb_row,
                                       sb_col_in_tile);
        if (tile_data->allow_update_cdf && (cpi->row_mt == 1) &&
            (tile_info->mi_row_start != mi_row)) {
          if ((tile_info->mi_col_start == mi_col)) {
            // restore frame context of 1st column sb
            memcpy(xd->tile_ctx, x->row_ctx, sizeof(*xd->tile_ctx));
          } else {
            int wt_left = AVG_CDF_WEIGHT_LEFT;
            int wt_tr = AVG_CDF_WEIGHT_TOP_RIGHT;
            if (tile_info->mi_col_end > (mi_col + mib_size))
              avg_cdf_symbols(xd->tile_ctx, x->row_ctx + sb_col_in_tile, wt_left,
                              wt_tr);
            else
              avg_cdf_symbols(xd->tile_ctx, x->row_ctx + sb_col_in_tile - 1,
                              wt_left, wt_tr);
          }
        }
    
        switch (cpi->oxcf.coeff_cost_upd_freq) {
          case COST_UPD_TILE:  // Tile level
            if (mi_row != tile_info->mi_row_start) break;
            AOM_FALLTHROUGH_INTENDED;
          case COST_UPD_SBROW:  // SB row level in tile
            if (mi_col != tile_info->mi_col_start) break;
            AOM_FALLTHROUGH_INTENDED;
          case COST_UPD_SB:  // SB level//系数填充
            av1_fill_coeff_costs(&td->mb, xd->tile_ctx, num_planes);
            break;
          default: assert(0);
        }
    
        switch (cpi->oxcf.mode_cost_upd_freq) {//
          case COST_UPD_TILE:  // Tile level
            if (mi_row != tile_info->mi_row_start) break;
            AOM_FALLTHROUGH_INTENDED;
          case COST_UPD_SBROW:  // SB row level in tile
            if (mi_col != tile_info->mi_col_start) break;
            AOM_FALLTHROUGH_INTENDED;
          case COST_UPD_SB:  // SB level模式填充
            av1_fill_mode_rates(cm, x, xd->tile_ctx);
            break;
          default: assert(0);
        }
    
        switch (cpi->oxcf.mv_cost_upd_freq) {
          case COST_UPD_TILE:  // Tile level
            if (mi_row != tile_info->mi_row_start) break;
            AOM_FALLTHROUGH_INTENDED;
          case COST_UPD_SBROW:  // SB row level in tile
            if (mi_col != tile_info->mi_col_start) break;
            AOM_FALLTHROUGH_INTENDED;
          case COST_UPD_SB:  // SB level运动填充
            av1_fill_mv_costs(xd->tile_ctx, cm, x);
            break;
          default: assert(0);
        }
    
        x->mb_rd_record.num = x->mb_rd_record.index_start = 0;
    
        if (!use_nonrd_mode) {
          av1_zero(x->txb_rd_record_8X8);
          av1_zero(x->txb_rd_record_16X16);
          av1_zero(x->txb_rd_record_32X32);
          av1_zero(x->txb_rd_record_64X64);
          av1_zero(x->txb_rd_record_intra);
    
          av1_zero(x->picked_ref_frames_mask);
    
          av1_zero(x->pred_mv);
        }
        PC_TREE *const pc_root = td->pc_root[mib_size_log2 - MIN_MIB_SIZE_LOG2];
        pc_root->index = 0;
        //初始化运动向量
        if ((sf->simple_motion_search_split ||
             sf->simple_motion_search_prune_rect ||
             sf->simple_motion_search_early_term_none) &&
            !frame_is_intra_only(cm) && !use_nonrd_mode) {
          init_simple_motion_search_mvs(pc_root);
        }
    #if !CONFIG_REALTIME_ONLY
        td->mb.cnn_output_valid = 0;
    #endif
    
        xd->cur_frame_force_integer_mv = cm->cur_frame_force_integer_mv;//获取运动矢量(整数)
    
        x->sb_energy_level = 0;
        if (cm->delta_q_info.delta_q_present_flag)
          setup_delta_q(cpi, td, x, tile_info, mi_row, mi_col, num_planes);//qp
    
        td->mb.cb_coef_buff = av1_get_cb_coeff_buffer(cpi, mi_row, mi_col);
    
        const int idx_str = cm->mi_stride * mi_row + mi_col;
        MB_MODE_INFO **mi = cm->mi_grid_base + idx_str;
        x->source_variance = UINT_MAX;
        x->simple_motion_pred_sse = UINT_MAX;
        const struct segmentation *const seg = &cm->seg;
        int seg_skip = 0;
        if (seg->enabled) {//划分
          const uint8_t *const map =
              seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
          const int segment_id =
              map ? get_segment_id(cm, map, sb_size, mi_row, mi_col) : 0;
          seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP);
        }
    
        // Realtime non-rd path.
        if (!(sf->partition_search_type == FIXED_PARTITION || seg_skip) &&
            !cpi->partition_search_skippable_frame &&
            sf->partition_search_type == VAR_BASED_PARTITION && use_nonrd_mode) {
          set_offsets_without_segment_id(cpi, tile_info, x, mi_row, mi_col,
                                         sb_size);
          av1_choose_var_based_partitioning(cpi, tile_info, x, mi_row, mi_col);
          td->mb.cb_offset = 0;
          nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
                              pc_root);
        } else {
    #if !CONFIG_REALTIME_ONLY
          int dummy_rate;
          int64_t dummy_dist;
          RD_STATS dummy_rdc;
          av1_invalid_rd_stats(&dummy_rdc);
          adjust_rdmult_tpl_model(cpi, x, mi_row, mi_col);
          if (sf->partition_search_type == FIXED_PARTITION || seg_skip) {//根据划分模式遍历划分
            set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
            const BLOCK_SIZE bsize =
                seg_skip ? sb_size : sf->always_this_block_size;
            set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
            //遍历所有划分和模式
            rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
                             &dummy_rate, &dummy_dist, 1, pc_root);
          } else if (cpi->partition_search_skippable_frame) {
            set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
            const BLOCK_SIZE bsize =
                get_rd_var_based_fixed_partition(cpi, x, mi_row, mi_col);
            set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
            rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
                             &dummy_rate, &dummy_dist, 1, pc_root);
          } else {
            reset_partition(pc_root, sb_size);
    
    #if CONFIG_COLLECT_COMPONENT_TIMING
            start_timing(cpi, rd_pick_partition_time);
    #endif
            BLOCK_SIZE max_sq_size = BLOCK_128X128;
            switch (cpi->oxcf.max_partition_size) {//确定最大划分
              case 4: max_sq_size = BLOCK_4X4; break;
              case 8: max_sq_size = BLOCK_8X8; break;
              case 16: max_sq_size = BLOCK_16X16; break;
              case 32: max_sq_size = BLOCK_32X32; break;
              case 64: max_sq_size = BLOCK_64X64; break;
              case 128: max_sq_size = BLOCK_128X128; break;
              default: assert(0); break;
            }
            max_sq_size = AOMMIN(max_sq_size, sb_size);
    
            BLOCK_SIZE min_sq_size = BLOCK_4X4;
            switch (cpi->oxcf.min_partition_size) {//确定最小划分
              case 4: min_sq_size = BLOCK_4X4; break;
              case 8: min_sq_size = BLOCK_8X8; break;
              case 16: min_sq_size = BLOCK_16X16; break;
              case 32: min_sq_size = BLOCK_32X32; break;
              case 64: min_sq_size = BLOCK_64X64; break;
              case 128: min_sq_size = BLOCK_128X128; break;
              default: assert(0); break;
            }
    
            if (use_auto_max_partition(cpi, sb_size, mi_row, mi_col)) {//自动划分
              float features[FEATURE_SIZE_MAX_MIN_PART_PRED] = { 0.0f };
    
              av1_get_max_min_partition_features(cpi, x, mi_row, mi_col, features);
              max_sq_size =
                  AOMMIN(av1_predict_max_partition(cpi, x, features), max_sq_size);
            }
    
            min_sq_size = AOMMIN(min_sq_size, max_sq_size);
    
            //划分完下一层入口
            rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, sb_size,
                              max_sq_size, min_sq_size, &dummy_rdc, dummy_rdc,
                              pc_root, NULL);
    #if CONFIG_COLLECT_COMPONENT_TIMING
            end_timing(cpi, rd_pick_partition_time);
    #endif
          }
    #endif  // !CONFIG_REALTIME_ONLY
        }
    
        // TODO(angiebird): Let inter_mode_rd_model_estimation support multi-tile.
        if (cpi->sf.inter_mode_rd_model_estimation == 1 && cm->tile_cols == 1 &&
            cm->tile_rows == 1) {
          av1_inter_mode_data_fit(tile_data, x->rdmult);
        }
        if (tile_data->allow_update_cdf && (cpi->row_mt == 1) &&
            (tile_info->mi_row_end > (mi_row + mib_size))) {
          if (sb_cols_in_tile == 1)
            memcpy(x->row_ctx, xd->tile_ctx, sizeof(*xd->tile_ctx));
          else if (sb_col_in_tile >= 1)
            memcpy(x->row_ctx + sb_col_in_tile - 1, xd->tile_ctx,
                   sizeof(*xd->tile_ctx));
        }
        (*(cpi->row_mt_sync_write_ptr))(&tile_data->row_mt_sync, sb_row,
                                        sb_col_in_tile, sb_cols_in_tile);
      }
    #if CONFIG_COLLECT_COMPONENT_TIMING
      end_timing(cpi, encode_sb_time);
    #endif
    }
    

    相关文章

      网友评论

          本文标题:av1代码学习12--encode_sb_row()

          本文链接:https://www.haomeiwen.com/subject/ojzwfktx.html