|  | /* | 
|  | * Copyright (c) 2022, Alliance for Open Media. All rights reserved | 
|  | * | 
|  | * This source code is subject to the terms of the BSD 3-Clause Clear License | 
|  | * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear | 
|  | * License was not distributed with this source code in the LICENSE file, you | 
|  | * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  If the | 
|  | * Alliance for Open Media Patent License 1.0 was not distributed with this | 
|  | * source code in the PATENTS file, you can obtain it at | 
|  | * aomedia.org/license/patent-license/. | 
|  | */ | 
|  |  | 
|  | #include "av1/common/bru.h" | 
|  | #include "av1/common/common_data.h" | 
|  | #include "config/aom_config.h" | 
|  | #include "config/aom_dsp_rtcd.h" | 
|  | #include "config/av1_rtcd.h" | 
|  | #include "av1/common/reconinter.h" | 
|  | #include "av1/common/ccso.h" | 
|  |  | 
|  | /* clean up tx_skip array for support and inactive SBs */ | 
|  | void bru_update_txk_skip_array(const AV1_COMMON *cm, int mi_row, int mi_col, | 
|  | TREE_TYPE tree_type, | 
|  | const CHROMA_REF_INFO *chroma_ref_info, | 
|  | int plane, int blk_w, int blk_h) { | 
|  | (void)tree_type; | 
|  | (void)chroma_ref_info; | 
|  | if (mi_col + blk_w > cm->mi_params.mi_cols) | 
|  | blk_w = cm->mi_params.mi_cols - mi_col; | 
|  |  | 
|  | if (mi_row + blk_h > cm->mi_params.mi_rows) | 
|  | blk_h = cm->mi_params.mi_rows - mi_row; | 
|  |  | 
|  | blk_w = blk_w >> ((plane == 0) ? 0 : cm->seq_params.subsampling_x); | 
|  | blk_h = blk_h >> ((plane == 0) ? 0 : cm->seq_params.subsampling_y); | 
|  |  | 
|  | int w = ((cm->width + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2) | 
|  | << MAX_SB_SIZE_LOG2; | 
|  | w >>= ((plane == 0) ? 0 : cm->seq_params.subsampling_x); | 
|  | const uint32_t stride = (w + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2; | 
|  | const int cols = (blk_w << MI_SIZE_LOG2) >> MIN_TX_SIZE_LOG2; | 
|  | const int rows = (blk_h << MI_SIZE_LOG2) >> MIN_TX_SIZE_LOG2; | 
|  | int x = (mi_col << MI_SIZE_LOG2) >> | 
|  | ((plane == 0) ? 0 : cm->seq_params.subsampling_x); | 
|  | int y = (mi_row << MI_SIZE_LOG2) >> | 
|  | ((plane == 0) ? 0 : cm->seq_params.subsampling_y); | 
|  | x = x >> MIN_TX_SIZE_LOG2; | 
|  | y = y >> MIN_TX_SIZE_LOG2; | 
|  | for (int r = 0; r < rows; r++) { | 
|  | for (int c = 0; c < cols; c++) { | 
|  | const uint32_t idx = (y + r) * stride + x + c; | 
|  | assert(idx < cm->mi_params.tx_skip_buf_size[plane]); | 
|  | assert(stride == cm->mi_params.tx_skip_stride[plane]); | 
|  | cm->mi_params.tx_skip[plane][idx] = 1; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Set correct mbmi address for inactive and support SB since there is no chance | 
|  | * to set them in later stage  */ | 
|  | BruActiveMode set_sb_mbmi_bru_mode(const AV1_COMMON *cm, MACROBLOCKD *const xd, | 
|  | const int mi_col, const int mi_row, | 
|  | const BLOCK_SIZE bsize, | 
|  | const BruActiveMode bru_sb_mode) { | 
|  | // only set very first mi | 
|  | // for inactive SB, other location on the mi_grid is invalid | 
|  | // for active SB, later set_offset will redo the address assignment | 
|  | if (cm->bru.enabled) { | 
|  | xd->mi_col = mi_col; | 
|  | xd->mi_row = mi_row; | 
|  | const int mi_grid_idx = get_mi_grid_idx(&cm->mi_params, mi_row, mi_col); | 
|  | const int mi_alloc_idx = get_alloc_mi_idx(&cm->mi_params, mi_row, mi_col); | 
|  | cm->mi_params.mi_grid_base[mi_grid_idx] = | 
|  | &cm->mi_params.mi_alloc[mi_alloc_idx]; | 
|  | xd->mi = cm->mi_params.mi_grid_base + mi_grid_idx; | 
|  | xd->mi[0]->sb_active_mode = bru_sb_mode; | 
|  | // if not active, propagate to all the mi in bsize | 
|  | // this function will also be used in decoder | 
|  | if (bru_sb_mode != BRU_ACTIVE_SB) { | 
|  | const int mi_h = mi_size_high[bsize]; | 
|  | const int mi_w = mi_size_wide[bsize]; | 
|  | MB_MODE_INFO *const mi_addr = xd->mi[0]; | 
|  | const int x_inside_boundary = | 
|  | AOMMIN(mi_w, cm->mi_params.mi_cols - mi_col); | 
|  | const int y_inside_boundary = | 
|  | AOMMIN(mi_h, cm->mi_params.mi_rows - mi_row); | 
|  | const int mis = cm->mi_params.mi_stride; | 
|  | for (int y = 0; y < y_inside_boundary; y++) { | 
|  | for (int x_idx = 0; x_idx < x_inside_boundary; x_idx++) { | 
|  | xd->mi[x_idx + y * mis] = mi_addr; | 
|  | } | 
|  | } | 
|  | } | 
|  | return bru_sb_mode; | 
|  | } | 
|  | return BRU_ACTIVE_SB; | 
|  | } | 
|  |  | 
|  | /* Copy recon data from BRU ref to current frame buffer. This is only used for | 
|  | * BRU_SUPPORT_SB of BRU optimized decoder/encoder */ | 
|  | void bru_copy_sb(const struct AV1Common *cm, const int mi_col, | 
|  | const int mi_row) { | 
|  | if (cm->bru.update_ref_idx < 0) | 
|  | return;  // now ref_idx is the sole indicator of frame level bru | 
|  | const int sb_size = cm->seq_params.sb_size; | 
|  | const int w = mi_size_wide[sb_size]; | 
|  | const int h = mi_size_high[sb_size]; | 
|  | RefCntBuffer *const ref_buf = get_ref_frame_buf(cm, cm->bru.update_ref_idx); | 
|  | YV12_BUFFER_CONFIG *const ref_src = &ref_buf->buf; | 
|  | YV12_BUFFER_CONFIG *const rec_dst = &cm->cur_frame->buf; | 
|  | const int x_inside_boundary = AOMMIN(w, cm->mi_params.mi_cols - mi_col) | 
|  | << MI_SIZE_LOG2; | 
|  | const int y_inside_boundary = AOMMIN(h, cm->mi_params.mi_rows - mi_row) | 
|  | << MI_SIZE_LOG2; | 
|  | const int x = mi_col << MI_SIZE_LOG2; | 
|  | const int y = mi_row << MI_SIZE_LOG2; | 
|  | for (int i_plane = 0; i_plane < av1_num_planes(cm); ++i_plane) { | 
|  | uint16_t *rec_data = rec_dst->buffers[i_plane]; | 
|  | uint16_t *ref_data = ref_src->buffers[i_plane]; | 
|  | int rec_stride = i_plane > 0 ? rec_dst->uv_stride : rec_dst->y_stride; | 
|  | int ref_stride = i_plane > 0 ? ref_src->uv_stride : ref_src->y_stride; | 
|  | int subsample_x = i_plane > 0 ? ref_src->subsampling_x : 0; | 
|  | int subsample_y = i_plane > 0 ? ref_src->subsampling_y : 0; | 
|  | uint64_t rec_offset = scaled_buffer_offset( | 
|  | x >> subsample_x, y >> subsample_y, rec_stride, NULL); | 
|  | uint64_t ref_offset = scaled_buffer_offset( | 
|  | x >> subsample_x, y >> subsample_y, ref_stride, NULL); | 
|  | copy_tile(x_inside_boundary >> subsample_x, | 
|  | y_inside_boundary >> subsample_y, ref_data + ref_offset, | 
|  | ref_stride, rec_data + rec_offset, rec_stride); | 
|  | } | 
|  | if (cm->seq_params.order_hint_info.enable_ref_frame_mvs) { | 
|  | // set cur_frame mvs to 0 | 
|  | bru_zero_sb_mvs(cm, -1, mi_row, mi_col, x_inside_boundary >> MI_SIZE_LOG2, | 
|  | y_inside_boundary >> MI_SIZE_LOG2); | 
|  | } | 
|  | return; | 
|  | } | 
|  |  | 
|  | /* Update recon data from current frame buffer to BRU ref. This is only used for | 
|  | * BRU_ACTIVE_SB of BRU optimized decoder/encoder */ | 
|  | void bru_update_sb(const struct AV1Common *cm, const int mi_col, | 
|  | const int mi_row) { | 
|  | if (cm->bru.update_ref_idx < 0) | 
|  | return;  // now ref_idx is the sole indicator of frame level bru | 
|  | RefCntBuffer *const ref_buf = get_ref_frame_buf(cm, cm->bru.update_ref_idx); | 
|  | // just swap these two | 
|  | YV12_BUFFER_CONFIG *const rec_dst = &ref_buf->buf; | 
|  | YV12_BUFFER_CONFIG *const ref_src = &cm->cur_frame->buf; | 
|  | const int sb_size = cm->seq_params.sb_size; | 
|  | const int w = mi_size_wide[sb_size]; | 
|  | const int h = mi_size_high[sb_size]; | 
|  | const int x_inside_boundary = AOMMIN(w, cm->mi_params.mi_cols - mi_col) | 
|  | << MI_SIZE_LOG2; | 
|  | const int y_inside_boundary = AOMMIN(h, cm->mi_params.mi_rows - mi_row) | 
|  | << MI_SIZE_LOG2; | 
|  | const int x = mi_col << MI_SIZE_LOG2; | 
|  | const int y = mi_row << MI_SIZE_LOG2; | 
|  |  | 
|  | for (int i_plane = 0; i_plane < av1_num_planes(cm); ++i_plane) { | 
|  | uint16_t *rec_data = rec_dst->buffers[i_plane]; | 
|  | uint16_t *ref_data = ref_src->buffers[i_plane]; | 
|  | const int rec_stride = i_plane > 0 ? rec_dst->uv_stride : rec_dst->y_stride; | 
|  | const int ref_stride = i_plane > 0 ? ref_src->uv_stride : ref_src->y_stride; | 
|  | const int subsample_x = i_plane > 0 ? ref_src->subsampling_x : 0; | 
|  | const int subsample_y = i_plane > 0 ? ref_src->subsampling_y : 0; | 
|  | const uint64_t rec_offset = scaled_buffer_offset( | 
|  | x >> subsample_x, y >> subsample_y, rec_stride, NULL); | 
|  | const uint64_t ref_offset = scaled_buffer_offset( | 
|  | x >> subsample_x, y >> subsample_y, ref_stride, NULL); | 
|  | copy_tile(x_inside_boundary >> subsample_x, | 
|  | y_inside_boundary >> subsample_y, ref_data + ref_offset, | 
|  | ref_stride, rec_data + rec_offset, rec_stride); | 
|  | } | 
|  |  | 
|  | if (cm->seq_params.order_hint_info.enable_ref_frame_mvs) { | 
|  | // copy mvs from cur frame to ref frame | 
|  | // It is ok to copy since all TMVP are collocated now | 
|  | bru_copy_sb_mvs(cm, -1, cm->bru.update_ref_idx, mi_row, mi_col, | 
|  | x_inside_boundary >> MI_SIZE_LOG2, | 
|  | y_inside_boundary >> MI_SIZE_LOG2); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Set default inter mode for Support and Inactive SBs */ | 
|  | void bru_set_default_inter_mb_mode_info(const AV1_COMMON *const cm, | 
|  | MACROBLOCKD *const xd, | 
|  | MB_MODE_INFO *const mbmi, | 
|  | BLOCK_SIZE bsize) { | 
|  | // think reuse init_mbmi() here | 
|  | mbmi->segment_id = 0; | 
|  | mbmi->skip_mode = 0; | 
|  | xd->tree_type = SHARED_PART; | 
|  | mbmi->skip_txfm[xd->tree_type == CHROMA_PART] = 1; | 
|  | mbmi->uv_mode = UV_DC_PRED; | 
|  | mbmi->palette_mode_info.palette_size[0] = 0; | 
|  | mbmi->palette_mode_info.palette_size[1] = 0; | 
|  | mbmi->fsc_mode[PLANE_TYPE_Y] = 0; | 
|  | mbmi->fsc_mode[PLANE_TYPE_UV] = 0; | 
|  | #if CONFIG_NEW_CONTEXT_MODELING | 
|  | mbmi->use_intrabc[0] = 0; | 
|  | mbmi->use_intrabc[1] = 0; | 
|  | #endif | 
|  | mbmi->bawp_flag[0] = 0; | 
|  | mbmi->bawp_flag[1] = 0; | 
|  | mbmi->cwp_idx = CWP_EQUAL; | 
|  | #if CONFIG_IBC_SR_EXT | 
|  | mbmi->use_intrabc[xd->tree_type == CHROMA_PART] = 0; | 
|  | #endif  // CONFIG_IBC_SR_EXT | 
|  | #if CONFIG_C076_INTER_MOD_CTX | 
|  | #if CONFIG_REFINEMV | 
|  | mbmi->refinemv_flag = 0; | 
|  | #endif  // CONFIG_REFINEMV | 
|  | #endif  // CONFIG_C076_INTER_MOD_CTX | 
|  | #if CONFIG_SEP_COMP_DRL | 
|  | mbmi->ref_mv_idx[0] = 0; | 
|  | mbmi->ref_mv_idx[1] = 0; | 
|  | #else | 
|  | mbmi->ref_mv_idx = 0; | 
|  | #endif | 
|  | mbmi->warp_ref_idx = 0; | 
|  | mbmi->max_num_warp_candidates = 0; | 
|  | mbmi->warpmv_with_mvd_flag = 0; | 
|  | mbmi->motion_mode = SIMPLE_TRANSLATION; | 
|  | mbmi->filter_intra_mode_info.use_filter_intra = 0; | 
|  | mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1); | 
|  | mbmi->comp_group_idx = 0; | 
|  | mbmi->interinter_comp.type = COMPOUND_AVERAGE; | 
|  | mbmi->mv[0].as_int = 0; | 
|  | mbmi->mv[1].as_int = 0; | 
|  | assert(cm->bru.update_ref_idx >= 0); | 
|  | #if CONFIG_WARP_INTER_INTRA | 
|  | mbmi->warp_inter_intra = 0; | 
|  | #endif | 
|  | // todo find del idx | 
|  | mbmi->ref_frame[0] = cm->bru.update_ref_idx; | 
|  | mbmi->ref_frame[1] = NONE_FRAME; | 
|  | mbmi->skip_mode = 0; | 
|  | mbmi->skip_txfm[xd->tree_type == CHROMA_PART] = 1; | 
|  | mbmi->mode = NEWMV; | 
|  | mbmi->region_type = MIXED_INTER_INTRA_REGION; | 
|  | mbmi->sb_type[0] = bsize; | 
|  | mbmi->sb_type[1] = bsize; | 
|  | mbmi->chroma_ref_info.bsize_base = bsize; | 
|  | mbmi->chroma_ref_info.bsize = bsize; | 
|  | xd->mi[0]->mi_col_start = xd->mi_col; | 
|  | xd->mi[0]->mi_row_start = xd->mi_row; | 
|  | xd->mi[0]->chroma_ref_info.mi_col_chroma_base = xd->mi_col; | 
|  | xd->mi[0]->chroma_ref_info.mi_row_chroma_base = xd->mi_row; | 
|  | xd->ccso_blk_y = 0; | 
|  | xd->ccso_blk_u = 0; | 
|  | xd->ccso_blk_v = 0; | 
|  | mbmi->ccso_blk_y = 0; | 
|  | mbmi->ccso_blk_u = 0; | 
|  | mbmi->ccso_blk_v = 0; | 
|  | mbmi->cdef_strength = -1; | 
|  | mbmi->local_rest_type = 0; | 
|  | mbmi->local_ccso_blk_flag = 0; | 
|  | set_default_max_mv_precision(mbmi, xd->sbi->sb_mv_precision); | 
|  | /// bru use only pixel precision | 
|  | set_mv_precision(mbmi, MV_PRECISION_ONE_PEL); | 
|  | // set_mv_precision(mbmi, mbmi->max_mv_precision); | 
|  | set_default_precision_set(cm, mbmi, cm->seq_params.sb_size); | 
|  | set_most_probable_mv_precision(cm, mbmi, cm->seq_params.sb_size); | 
|  | mbmi->interp_fltr = MULTITAP_SHARP; | 
|  | #if !CONFIG_TX_PARTITION_CTX | 
|  | xd->above_txfm_context = | 
|  | cm->above_contexts.txfm[xd->tile.tile_row] + xd->mi_col; | 
|  | xd->left_txfm_context = | 
|  | xd->left_txfm_context_buffer + (xd->mi_row & MAX_MIB_MASK); | 
|  | #endif | 
|  | if (is_bru_not_active_and_not_on_partial_border(cm, xd->mi_col, xd->mi_row, | 
|  | bsize)) { | 
|  | mbmi->tx_size = TX_64X64; | 
|  | } else { | 
|  | mbmi->tx_size = tx_size_from_tx_mode(bsize, cm->features.tx_mode); | 
|  | } | 
|  | for (int plane = 0; plane < 1; plane++) { | 
|  | bru_update_txk_skip_array(cm, xd->mi_row, xd->mi_col, xd->tree_type, | 
|  | &mbmi->chroma_ref_info, plane, MAX_MIB_SIZE, | 
|  | MAX_MIB_SIZE); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Core function of swap BRU reference frame and current frame for BRU optimized | 
|  | * decoder/encoder*/ | 
|  | RefCntBuffer *bru_swap_common(AV1_COMMON *cm) { | 
|  | // should not use this function at all in none bru frames | 
|  | if (cm->bru.enabled) { | 
|  | assert(cm->bru.update_ref_idx >= 0); | 
|  | RefCntBuffer *ref_buf = get_ref_frame_buf(cm, cm->bru.update_ref_idx); | 
|  | assert(ref_buf != NULL); | 
|  | cm->bru.update_ref_fc = ref_buf->frame_context;  // pass all the values | 
|  | MV_REFERENCE_FRAME ref_frame; | 
|  | for (ref_frame = 0; ref_frame < INTER_REFS_PER_FRAME; ++ref_frame) { | 
|  | const RefCntBuffer *const buf = get_ref_frame_buf(cm, ref_frame); | 
|  | if (buf != NULL && ref_frame < cm->ref_frames_info.num_total_refs) { | 
|  | ref_buf->ref_order_hints[ref_frame] = buf->order_hint; | 
|  | ref_buf->ref_display_order_hint[ref_frame] = buf->display_order_hint; | 
|  | } else { | 
|  | ref_buf->ref_order_hints[ref_frame] = -1; | 
|  | ref_buf->ref_display_order_hint[ref_frame] = -1; | 
|  | } | 
|  | } | 
|  | #if CONFIG_TEMP_LR | 
|  | RefCntBuffer *tmp_buf = cm->cur_frame; | 
|  | #endif | 
|  | ref_buf->order_hint = cm->cur_frame->order_hint; | 
|  | ref_buf->display_order_hint = cm->cur_frame->display_order_hint; | 
|  | ref_buf->absolute_poc = cm->cur_frame->absolute_poc; | 
|  | ref_buf->pyramid_level = cm->cur_frame->pyramid_level; | 
|  | ref_buf->base_qindex = cm->cur_frame->base_qindex; | 
|  | ref_buf->num_ref_frames = cm->cur_frame->num_ref_frames; | 
|  | #if CONFIG_OUTPUT_FRAME_BASED_ON_ORDER_HINT_ENHANCEMENT | 
|  | ref_buf->frame_output_done = 0; | 
|  | #endif | 
|  | #if CONFIG_TEMP_LR | 
|  | ref_buf->rst_info[0] = tmp_buf->rst_info[0]; | 
|  | ref_buf->rst_info[1] = tmp_buf->rst_info[1]; | 
|  | ref_buf->rst_info[2] = tmp_buf->rst_info[2]; | 
|  | av1_copy_rst_frame_filters(&ref_buf->rst_info[0], &tmp_buf->rst_info[0]); | 
|  | av1_copy_rst_frame_filters(&ref_buf->rst_info[1], &tmp_buf->rst_info[1]); | 
|  | av1_copy_rst_frame_filters(&ref_buf->rst_info[2], &tmp_buf->rst_info[2]); | 
|  | #endif | 
|  | if (cm->bru.frame_inactive_flag) { | 
|  | ref_buf->ccso_info.ccso_frame_flag = 0; | 
|  | } else { | 
|  | ref_buf->ccso_info.ccso_frame_flag = tmp_buf->ccso_info.ccso_frame_flag; | 
|  | } | 
|  | for (int plane = 0; plane < CCSO_NUM_COMPONENTS; plane++) { | 
|  | if (cm->bru.frame_inactive_flag) { | 
|  | av1_copy_ccso_filters(&ref_buf->ccso_info, &cm->ccso_info, plane, 1, 0, | 
|  | 0); | 
|  | continue; | 
|  | } | 
|  | // copy from current to bru ref | 
|  | ref_buf->ccso_info.reuse_ccso[plane] = | 
|  | tmp_buf->ccso_info.reuse_ccso[plane]; | 
|  | ref_buf->ccso_info.sb_reuse_ccso[plane] = | 
|  | tmp_buf->ccso_info.sb_reuse_ccso[plane]; | 
|  | ref_buf->ccso_info.ccso_enable[plane] = | 
|  | tmp_buf->ccso_info.ccso_enable[plane]; | 
|  | ref_buf->ccso_info.ccso_ref_idx[plane] = | 
|  | tmp_buf->ccso_info.ccso_ref_idx[plane]; | 
|  | ref_buf->ccso_info.subsampling_x[plane] = | 
|  | plane > 0 ? cm->seq_params.subsampling_x : 0; | 
|  | ref_buf->ccso_info.subsampling_y[plane] = | 
|  | plane > 0 ? cm->seq_params.subsampling_y : 0; | 
|  | ref_buf->ccso_info.reuse_root_ref[plane] = | 
|  | tmp_buf->ccso_info.reuse_root_ref[plane]; | 
|  | #if CONFIG_CCSO_FU_BUGFIX | 
|  | const int log2_filter_unit_size_y = | 
|  | plane == 0 ? CCSO_BLK_SIZE | 
|  | : CCSO_BLK_SIZE - cm->seq_params.subsampling_y; | 
|  | const int log2_filter_unit_size_x = | 
|  | plane == 0 ? CCSO_BLK_SIZE | 
|  | : CCSO_BLK_SIZE - cm->seq_params.subsampling_x; | 
|  | #else | 
|  | const int log2_filter_unit_size_y = | 
|  | pli > 0 ? CCSO_BLK_SIZE | 
|  | : CCSO_BLK_SIZE + cm->seq_params.subsampling_y; | 
|  | const int log2_filter_unit_size_x = | 
|  | pli > 0 ? CCSO_BLK_SIZE | 
|  | : CCSO_BLK_SIZE + cm->seq_params.subsampling_x; | 
|  | #endif  // CONFIG_CCSO_FU_BUGFIX | 
|  |  | 
|  | const int ccso_nvfb = ((cm->mi_params.mi_rows >> | 
|  | (plane ? cm->seq_params.subsampling_y : 0)) + | 
|  | (1 << log2_filter_unit_size_y >> 2) - 1) / | 
|  | (1 << log2_filter_unit_size_y >> 2); | 
|  | const int ccso_nhfb = ((cm->mi_params.mi_cols >> | 
|  | (plane ? cm->seq_params.subsampling_x : 0)) + | 
|  | (1 << log2_filter_unit_size_x >> 2) - 1) / | 
|  | (1 << log2_filter_unit_size_x >> 2); | 
|  | const int sb_count = ccso_nvfb * ccso_nhfb; | 
|  | av1_copy_ccso_filters(&ref_buf->ccso_info, &tmp_buf->ccso_info, plane, 1, | 
|  | 1, sb_count); | 
|  | } | 
|  | // replace cur by bru_ref | 
|  | assign_frame_buffer_p(&cm->cur_frame, ref_buf); | 
|  | return ref_buf; | 
|  | } | 
|  | return NULL; | 
|  | } |