From ba41e9d459c0f6384949a103eaaee7b631341def Mon Sep 17 00:00:00 2001 From: Dmitry Kovalev Date: Fri, 27 Dec 2013 18:44:19 -0800 Subject: [PATCH] Adding RefBuffer struct. Adding RefBuffer to simplify reference buffer management. The struct has a pointer to image data and scale factors relative to the current frame. Change-Id: If38eb1491ff687cc11428aee339f3e052e2c5d9e --- vp9/common/vp9_alloccommon.c | 3 --- vp9/common/vp9_blockd.h | 12 +++++++--- vp9/common/vp9_onyxc_int.h | 11 ++-------- vp9/common/vp9_reconinter.c | 17 +++------------ vp9/common/vp9_reconinter.h | 6 ++--- vp9/decoder/vp9_decodeframe.c | 41 +++++++++++++++++++---------------- vp9/decoder/vp9_onyxd_if.c | 25 +++++++++++---------- vp9/encoder/vp9_encodeframe.c | 3 +-- vp9/encoder/vp9_onyx_if.c | 28 ++++++++++++++---------- vp9/encoder/vp9_rdopt.c | 11 +++++----- 10 files changed, 75 insertions(+), 82 deletions(-) diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c index 6d485421a..ff20553d6 100644 --- a/vp9/common/vp9_alloccommon.c +++ b/vp9/common/vp9_alloccommon.c @@ -161,9 +161,6 @@ int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) { cm->new_fb_idx = cm->fb_count - 1; cm->fb_idx_ref_cnt[cm->new_fb_idx] = 1; - for (i = 0; i < REFS_PER_FRAME; i++) - cm->active_ref_idx[i] = i; - for (i = 0; i < REF_FRAMES; i++) { cm->ref_frame_map[i] = i; cm->fb_idx_ref_cnt[i] = 1; diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h index 38acf1e6d..c6af7f6da 100644 --- a/vp9/common/vp9_blockd.h +++ b/vp9/common/vp9_blockd.h @@ -212,11 +212,17 @@ struct macroblockd_plane { #define BLOCK_OFFSET(x, i) ((x) + (i) * 16) +typedef struct RefBuffer { + // TODO(dkovalev): idx is not really required and should be removed, now it + // is used in vp9_onyxd_if.c + int idx; + YV12_BUFFER_CONFIG *buf; + struct scale_factors sf; +} RefBuffer; + typedef struct macroblockd { struct macroblockd_plane plane[MAX_MB_PLANE]; - const struct scale_factors *scale_factors[2]; - MODE_INFO *last_mi; int mode_info_stride; @@ -235,7 +241,7 @@ typedef struct macroblockd { int mb_to_bottom_edge; /* pointers to reference frames */ - const YV12_BUFFER_CONFIG *ref_buf[2]; + RefBuffer *block_refs[2]; /* pointer to current frame */ const YV12_BUFFER_CONFIG *cur_buf; diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index ed4c044fe..b5ed959e1 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -121,8 +121,8 @@ typedef struct VP9Common { // roll new_fb_idx into it. // Each frame can reference REFS_PER_FRAME buffers - int active_ref_idx[REFS_PER_FRAME]; - struct scale_factors active_ref_scale[REFS_PER_FRAME]; + RefBuffer frame_refs[REFS_PER_FRAME]; + int new_fb_idx; YV12_BUFFER_CONFIG post_proc_buffer; @@ -224,13 +224,6 @@ typedef struct VP9Common { uint32_t fb_idx_ref_lru_count; } VP9_COMMON; -// ref == 0 => LAST_FRAME -// ref == 1 => GOLDEN_FRAME -// ref == 2 => ALTREF_FRAME -static YV12_BUFFER_CONFIG *get_frame_ref_buffer(VP9_COMMON *cm, int ref) { - return &cm->yv12_fb[cm->active_ref_idx[ref]]; -} - static YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) { return &cm->yv12_fb[cm->new_fb_idx]; } diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c index c84007e94..397f446f3 100644 --- a/vp9/common/vp9_reconinter.c +++ b/vp9/common/vp9_reconinter.c @@ -153,7 +153,7 @@ static void build_inter_predictors(MACROBLOCKD *xd, int plane, int block, int ref; for (ref = 0; ref < 1 + is_compound; ++ref) { - const struct scale_factors *const sf = xd->scale_factors[ref]; + const struct scale_factors *const sf = &xd->block_refs[ref]->sf; struct buf_2d *const pre_buf = &pd->pre[ref]; struct buf_2d *const dst_buf = &pd->dst; uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x; @@ -256,7 +256,7 @@ static void dec_build_inter_predictors(MACROBLOCKD *xd, int plane, int block, int ref; for (ref = 0; ref < 1 + is_compound; ++ref) { - const struct scale_factors *const sf = xd->scale_factors[ref]; + const struct scale_factors *const sf = &xd->block_refs[ref]->sf; struct buf_2d *const pre_buf = &pd->pre[ref]; struct buf_2d *const dst_buf = &pd->dst; uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x; @@ -283,7 +283,7 @@ static void dec_build_inter_predictors(MACROBLOCKD *xd, int plane, int block, int xs, ys, x0, y0, x0_16, y0_16, x1, y1, frame_width, frame_height, subpel_x, subpel_y; uint8_t *ref_frame, *buf_ptr; - const YV12_BUFFER_CONFIG *ref_buf = xd->ref_buf[ref]; + const YV12_BUFFER_CONFIG *ref_buf = xd->block_refs[ref]->buf; // Get reference frame pointer, width and height. if (plane == 0) { @@ -390,14 +390,3 @@ void vp9_dec_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col, } } } - -// TODO(dkovalev: find better place for this function) -void vp9_setup_scale_factors(VP9_COMMON *cm, int i) { - const int ref = cm->active_ref_idx[i]; - struct scale_factors *const sf = &cm->active_ref_scale[i]; - YV12_BUFFER_CONFIG *const fb = &cm->yv12_fb[ref]; - vp9_setup_scale_factors_for_frame(sf, - fb->y_crop_width, fb->y_crop_height, - cm->width, cm->height); -} - diff --git a/vp9/common/vp9_reconinter.h b/vp9/common/vp9_reconinter.h index a4e968ce6..9f379399c 100644 --- a/vp9/common/vp9_reconinter.h +++ b/vp9/common/vp9_reconinter.h @@ -92,10 +92,8 @@ static void setup_pre_planes(MACROBLOCKD *xd, int i, static void set_scale_factors(VP9_COMMON *cm, MACROBLOCKD *xd, int ref0, int ref1) { - xd->scale_factors[0] = &cm->active_ref_scale[ref0 >= 0 ? ref0 : 0]; - xd->scale_factors[1] = &cm->active_ref_scale[ref1 >= 0 ? ref1 : 0]; + xd->block_refs[0] = &cm->frame_refs[ref0 >= 0 ? ref0 : 0]; + xd->block_refs[1] = &cm->frame_refs[ref1 >= 0 ? ref1 : 0]; } -void vp9_setup_scale_factors(VP9_COMMON *cm, int i); - #endif // VP9_COMMON_VP9_RECONINTER_H_ diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index de6dbdcc0..59faccdf7 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -378,18 +378,13 @@ static void set_offsets(VP9_COMMON *const cm, MACROBLOCKD *const xd, static void set_ref(VP9_COMMON *const cm, MACROBLOCKD *const xd, int idx, int mi_row, int mi_col) { MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi; - const int ref = mbmi->ref_frame[idx] - LAST_FRAME; - const YV12_BUFFER_CONFIG *cfg = get_frame_ref_buffer(cm, ref); - const struct scale_factors *sf = &cm->active_ref_scale[ref]; - - xd->ref_buf[idx] = cfg; - if (!vp9_is_valid_scale(sf)) + RefBuffer *ref_buffer = &cm->frame_refs[mbmi->ref_frame[idx] - LAST_FRAME]; + xd->block_refs[idx] = ref_buffer; + if (!vp9_is_valid_scale(&ref_buffer->sf)) vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM, "Invalid scale factors"); - - xd->scale_factors[idx] = sf; - setup_pre_planes(xd, idx, cfg, mi_row, mi_col, xd->scale_factors[idx]); - xd->corrupted |= cfg->corrupted; + setup_pre_planes(xd, idx, ref_buffer->buf, mi_row, mi_col, &ref_buffer->sf); + xd->corrupted |= ref_buffer->buf->corrupted; } static void decode_modes_b(VP9_COMMON *const cm, MACROBLOCKD *const xd, @@ -737,9 +732,9 @@ static void setup_frame_size_with_refs(VP9D_COMP *pbi, int found = 0, i; for (i = 0; i < REFS_PER_FRAME; ++i) { if (vp9_rb_read_bit(rb)) { - YV12_BUFFER_CONFIG *const cfg = get_frame_ref_buffer(cm, i); - width = cfg->y_crop_width; - height = cfg->y_crop_height; + YV12_BUFFER_CONFIG *const buf = cm->frame_refs[i].buf; + width = buf->y_crop_width; + height = buf->y_crop_height; found = 1; break; } @@ -1171,8 +1166,10 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1; - for (i = 0; i < REFS_PER_FRAME; ++i) - cm->active_ref_idx[i] = cm->new_fb_idx; + for (i = 0; i < REFS_PER_FRAME; ++i) { + cm->frame_refs[i].idx = cm->new_fb_idx; + cm->frame_refs[i].buf = get_frame_new_buffer(cm); + } setup_frame_size(pbi, rb); } else { @@ -1191,7 +1188,9 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, for (i = 0; i < REFS_PER_FRAME; ++i) { const int ref = vp9_rb_read_literal(rb, REF_FRAMES_LOG2); - cm->active_ref_idx[i] = cm->ref_frame_map[ref]; + const int idx = cm->ref_frame_map[ref]; + cm->frame_refs[i].idx = idx; + cm->frame_refs[i].buf = &cm->yv12_fb[idx]; cm->ref_frame_sign_bias[LAST_FRAME + i] = vp9_rb_read_bit(rb); } @@ -1201,9 +1200,13 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, cm->mcomp_filter_type = read_interp_filter_type(rb); for (i = 0; i < REFS_PER_FRAME; ++i) { - vp9_setup_scale_factors(cm, i); - if (vp9_is_scaled(&cm->active_ref_scale[i])) - vp9_extend_frame_borders(&cm->yv12_fb[cm->active_ref_idx[i]], + RefBuffer *const ref_buf = &cm->frame_refs[i]; + vp9_setup_scale_factors_for_frame(&ref_buf->sf, + ref_buf->buf->y_crop_width, + ref_buf->buf->y_crop_height, + cm->width, cm->height); + if (vp9_is_scaled(&ref_buf->sf)) + vp9_extend_frame_borders(ref_buf->buf, cm->subsampling_x, cm->subsampling_y); } } diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c index d585b9120..75d52c25a 100644 --- a/vp9/decoder/vp9_onyxd_if.c +++ b/vp9/decoder/vp9_onyxd_if.c @@ -219,7 +219,7 @@ vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd) { VP9D_COMP *pbi = (VP9D_COMP *) ptr; VP9_COMMON *cm = &pbi->common; - int *ref_fb_ptr = NULL; + RefBuffer *ref_buf = NULL; /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the * encoder is using the frame buffers for. This is just a stub to keep the @@ -227,21 +227,23 @@ vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, * later commit that adds VP9-specific controls for this functionality. */ if (ref_frame_flag == VP9_LAST_FLAG) { - ref_fb_ptr = &pbi->common.active_ref_idx[0]; + ref_buf = &cm->frame_refs[0]; } else if (ref_frame_flag == VP9_GOLD_FLAG) { - ref_fb_ptr = &pbi->common.active_ref_idx[1]; + ref_buf = &cm->frame_refs[1]; } else if (ref_frame_flag == VP9_ALT_FLAG) { - ref_fb_ptr = &pbi->common.active_ref_idx[2]; + ref_buf = &cm->frame_refs[2]; } else { vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, "Invalid reference frame"); return pbi->common.error.error_code; } - if (!equal_dimensions(&cm->yv12_fb[*ref_fb_ptr], sd)) { + if (!equal_dimensions(ref_buf->buf, sd)) { vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, "Incorrect buffer dimensions"); } else { + int *ref_fb_ptr = &ref_buf->idx; + // Find an empty frame buffer. const int free_fb = get_free_fb(cm); // Decrease fb_idx_ref_cnt since it will be increased again in @@ -250,7 +252,8 @@ vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, // Manage the reference counters and copy image. ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb); - vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]); + ref_buf->buf = &cm->yv12_fb[*ref_fb_ptr]; + vp8_yv12_copy_frame(sd, ref_buf->buf); } return pbi->common.error.error_code; @@ -285,7 +288,7 @@ static void swap_frame_buffers(VP9D_COMP *pbi) { // Invalidate these references until the next frame starts. for (ref_index = 0; ref_index < 3; ref_index++) - cm->active_ref_idx[ref_index] = INT_MAX; + cm->frame_refs[ref_index].idx = INT_MAX; } int vp9_receive_compressed_data(VP9D_PTR ptr, @@ -317,8 +320,8 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, * at this point, but if it becomes so, [0] may not always be the correct * thing to do here. */ - if (cm->active_ref_idx[0] != INT_MAX) - get_frame_ref_buffer(cm, 0)->corrupted = 1; + if (cm->frame_refs[0].idx != INT_MAX) + cm->frame_refs[0].buf->corrupted = 1; } cm->new_fb_idx = get_free_fb(cm); @@ -334,8 +337,8 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, * at this point, but if it becomes so, [0] may not always be the correct * thing to do here. */ - if (cm->active_ref_idx[0] != INT_MAX) - get_frame_ref_buffer(cm, 0)->corrupted = 1; + if (cm->frame_refs[0].idx != INT_MAX) + cm->frame_refs[0].buf->corrupted = 1; if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) cm->fb_idx_ref_cnt[cm->new_fb_idx]--; diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 800dc4995..c37a50e48 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -2588,9 +2588,8 @@ static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t, int output_enabled, for (ref = 0; ref < 1 + is_compound; ++ref) { YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[ get_ref_frame_idx(cpi, mbmi->ref_frame[ref])]]; - setup_pre_planes(xd, ref, cfg, mi_row, mi_col, xd->scale_factors[ref]); + setup_pre_planes(xd, ref, cfg, mi_row, mi_col, &xd->block_refs[ref]->sf); } - vp9_build_inter_predictors_sb(xd, mi_row, mi_col, MAX(bsize, BLOCK_8X8)); } diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 2e34b4a78..3758f1f59 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -3317,6 +3317,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, VP9_COMMON *cm = &cpi->common; struct vpx_usec_timer cmptimer; YV12_BUFFER_CONFIG *force_src_buffer = NULL; + const int refs[] = { cpi->lst_fb_idx, cpi->gld_fb_idx, cpi->alt_fb_idx }; int i; // FILE *fp_out = fopen("enc_frame_type.txt", "a"); @@ -3518,16 +3519,13 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, } #endif - /* Get the mapping of L/G/A to the reference buffer pool */ - cm->active_ref_idx[0] = cm->ref_frame_map[cpi->lst_fb_idx]; - cm->active_ref_idx[1] = cm->ref_frame_map[cpi->gld_fb_idx]; - cm->active_ref_idx[2] = cm->ref_frame_map[cpi->alt_fb_idx]; - #if 0 // CONFIG_MULTIPLE_ARF if (cpi->multi_arf_enabled) { fprintf(fp_out, " idx(%d, %d, %d, %d) active(%d, %d, %d)", cpi->lst_fb_idx, cpi->gld_fb_idx, cpi->alt_fb_idx, cm->new_fb_idx, - cm->active_ref_idx[0], cm->active_ref_idx[1], cm->active_ref_idx[2]); + cm->ref_frame_map[cpi->lst_fb_idx], + cm->ref_frame_map[cpi->gld_fb_idx], + cm->ref_frame_map[cpi->alt_fb_idx]); if (cpi->refresh_alt_ref_frame) fprintf(fp_out, " type:ARF"); if (cpi->rc.is_src_frame_alt_ref) @@ -3544,12 +3542,20 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, cm->subsampling_x, cm->subsampling_y, VP9BORDERINPIXELS, NULL, NULL, NULL); - // Calculate scaling factors for each of the 3 available references + for (i = 0; i < REFS_PER_FRAME; ++i) { - vp9_setup_scale_factors(cm, i); - if (vp9_is_scaled(&cm->active_ref_scale[i])) - vp9_extend_frame_borders(&cm->yv12_fb[cm->active_ref_idx[i]], - cm->subsampling_x, cm->subsampling_y); + const int idx = cm->ref_frame_map[refs[i]]; + YV12_BUFFER_CONFIG *const buf = &cm->yv12_fb[idx]; + + RefBuffer *const ref_buf = &cm->frame_refs[i]; + ref_buf->buf = buf; + ref_buf->idx = idx; + vp9_setup_scale_factors_for_frame(&ref_buf->sf, + buf->y_crop_width, buf->y_crop_height, + cm->width, cm->height); + + if (vp9_is_scaled(&ref_buf->sf)) + vp9_extend_frame_borders(buf, cm->subsampling_x, cm->subsampling_y); } vp9_setup_interp_filters(&cpi->mb.e_mbd, DEFAULT_INTERP_FILTER, cm); diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index 22e480b11..561c0c312 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -1524,7 +1524,7 @@ static int64_t encode_inter_mb_segment(VP9_COMP *cpi, vp9_build_inter_predictor(pre, pd->pre[ref].stride, dst, pd->dst.stride, &mi->bmi[i].as_mv[ref].as_mv, - xd->scale_factors[ref], + &xd->block_refs[ref]->sf, width, height, ref, &xd->subpix, MV_PRECISION_Q3, mi_col * MI_SIZE + 4 * (i % 2), mi_row * MI_SIZE + 4 * (i / 2)); @@ -2267,8 +2267,7 @@ static void setup_buffer_inter(VP9_COMP *cpi, MACROBLOCK *x, YV12_BUFFER_CONFIG *yv12 = &cm->yv12_fb[cpi->common.ref_frame_map[idx]]; MACROBLOCKD *const xd = &x->e_mbd; MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi; - const struct scale_factors *const sf = - &cpi->common.active_ref_scale[frame_type - 1]; + const struct scale_factors *const sf = &cm->frame_refs[frame_type - 1].sf; // TODO(jkoleszar): Is the UV buffer ever used here? If so, need to make this @@ -2539,7 +2538,7 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x, ref_yv12[!id].stride, second_pred, pw, &frame_mv[refs[!id]].as_mv, - xd->scale_factors[!id], + &xd->block_refs[!id]->sf, pw, ph, 0, &xd->subpix, MV_PRECISION_Q3, mi_col * MI_SIZE, mi_row * MI_SIZE); @@ -3964,11 +3963,11 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, // TODO(jingning, jkoleszar): scaling reference frame not supported for // sub8x8 blocks. if (ref_frame > 0 && - vp9_is_scaled(&cpi->common.active_ref_scale[ref_frame - 1])) + vp9_is_scaled(&cpi->common.frame_refs[ref_frame - 1].sf)) continue; if (second_ref_frame > 0 && - vp9_is_scaled(&cpi->common.active_ref_scale[second_ref_frame - 1])) + vp9_is_scaled(&cpi->common.frame_refs[second_ref_frame - 1].sf)) continue; set_scale_factors(cm, xd, ref_frame - 1, second_ref_frame - 1);