From 65dd157c3c28bdfd3b4c20aa25cc6d5a28f4de03 Mon Sep 17 00:00:00 2001 From: Yunqing Wang Date: Wed, 16 May 2012 15:06:42 -0400 Subject: [PATCH] multi-res: force Key frame sychronization In multi-resolution encoding, frame_type decision for each frame is made by the lowest-resolution encoder. For all other higher- resolution encoders, kf_mode is always set to VPX_KF_DISABLED, and they are forced to use the same frame_type picked by the lowest-resolution encoder. Change-Id: Ic4d52ec65bbc012ca9c2d236210e28a295591eaf --- vp8/common/blockd.h | 12 ++++++++++-- vp8/encoder/mr_dissim.c | 8 ++++++-- vp8/encoder/onyx_if.c | 11 +++++++++++ vp8/encoder/pickinter.c | 4 ++-- vp8/vp8_cx_iface.c | 27 ++++++++++++++++++--------- vp8_multi_resolution_encoder.c | 7 ++++++- vpx/src/vpx_encoder.c | 7 +++++++ 7 files changed, 60 insertions(+), 16 deletions(-) diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h index a4c1d920c..1945edb6d 100644 --- a/vp8/common/blockd.h +++ b/vp8/common/blockd.h @@ -168,7 +168,7 @@ typedef struct } MODE_INFO; #if CONFIG_MULTI_RES_ENCODING -/* The information needed to be stored for higher-resolution encoder */ +/* The mb-level information needed to be stored for higher-resolution encoder */ typedef struct { MB_PREDICTION_MODE mode; @@ -176,7 +176,15 @@ typedef struct int_mv mv; //union b_mode_info bmi[16]; int dissim; // dissimilarity level of the macroblock -} LOWER_RES_INFO; +} LOWER_RES_MB_INFO; + +/* The frame-level information needed to be stored for higher-resolution + * encoder */ +typedef struct +{ + FRAME_TYPE frame_type; + LOWER_RES_MB_INFO *mb_info; +} LOWER_RES_FRAME_INFO; #endif typedef struct blockd diff --git a/vp8/encoder/mr_dissim.c b/vp8/encoder/mr_dissim.c index 7a62a06ec..564f963f8 100644 --- a/vp8/encoder/mr_dissim.c +++ b/vp8/encoder/mr_dissim.c @@ -65,14 +65,18 @@ void vp8_cal_dissimilarity(VP8_COMP *cpi) /* Store info for show/no-show frames for supporting alt_ref. * If parent frame is alt_ref, child has one too. */ + LOWER_RES_FRAME_INFO* store_info + = (LOWER_RES_FRAME_INFO*)cpi->oxcf.mr_low_res_mode_info; + + store_info->frame_type = cm->frame_type; + if(cm->frame_type != KEY_FRAME) { int mb_row; int mb_col; /* Point to beginning of allocated MODE_INFO arrays. */ MODE_INFO *tmp = cm->mip + cm->mode_info_stride; - LOWER_RES_INFO* store_mode_info - = (LOWER_RES_INFO*)cpi->oxcf.mr_low_res_mode_info; + LOWER_RES_MB_INFO* store_mode_info = store_info->mb_info; for (mb_row = 0; mb_row < cm->mb_rows; mb_row ++) { diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 8819633bd..536ae631b 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -3241,6 +3241,17 @@ static void encode_frame_to_data_rate cm->frame_type = KEY_FRAME; } +#if CONFIG_MULTI_RES_ENCODING + /* In multi-resolution encoding, frame_type is decided by lowest-resolution + * encoder. Same frame_type is adopted while encoding at other resolution. + */ + if (cpi->oxcf.mr_encoder_id) + { + cm->frame_type = + ((LOWER_RES_FRAME_INFO*)cpi->oxcf.mr_low_res_mode_info)->frame_type; + } +#endif + // Set default state for segment and mode based loop filter update flags cpi->mb.e_mbd.update_mb_segmentation_map = 0; cpi->mb.e_mbd.update_mb_segmentation_data = 0; diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c index 618a2966d..45acb0b0a 100644 --- a/vp8/encoder/pickinter.c +++ b/vp8/encoder/pickinter.c @@ -405,8 +405,8 @@ void get_lower_res_motion_info(VP8_COMP *cpi, MACROBLOCKD *xd, int *dissim, MB_PREDICTION_MODE *parent_mode, int_mv *parent_ref_mv, int mb_row, int mb_col) { - LOWER_RES_INFO* store_mode_info - = (LOWER_RES_INFO*)cpi->oxcf.mr_low_res_mode_info; + LOWER_RES_MB_INFO* store_mode_info + = ((LOWER_RES_FRAME_INFO*)cpi->oxcf.mr_low_res_mode_info)->mb_info; unsigned int parent_mb_index; //unsigned int parent_mb_index = map_640x480_to_320x240[mb_row][mb_col]; diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c index f55a4205f..04d4d86d5 100644 --- a/vp8/vp8_cx_iface.c +++ b/vp8/vp8_cx_iface.c @@ -549,23 +549,28 @@ static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx, static vpx_codec_err_t vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t *cfg, void **mem_loc) { - vpx_codec_err_t res = 0; - #if CONFIG_MULTI_RES_ENCODING + LOWER_RES_FRAME_INFO *shared_mem_loc; int mb_rows = ((cfg->g_w + 15) >>4); int mb_cols = ((cfg->g_h + 15) >>4); - *mem_loc = calloc(mb_rows*mb_cols, sizeof(LOWER_RES_INFO)); - if(!(*mem_loc)) + shared_mem_loc = calloc(1, sizeof(LOWER_RES_FRAME_INFO)); + if(!shared_mem_loc) { - free(*mem_loc); - res = VPX_CODEC_MEM_ERROR; + return VPX_CODEC_MEM_ERROR; + } + + shared_mem_loc->mb_info = calloc(mb_rows*mb_cols, sizeof(LOWER_RES_MB_INFO)); + if(!(shared_mem_loc->mb_info)) + { + return VPX_CODEC_MEM_ERROR; } else - res = VPX_CODEC_OK; + { + *mem_loc = (void *)shared_mem_loc; + return VPX_CODEC_OK; + } #endif - - return res; } static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx, @@ -659,7 +664,11 @@ static vpx_codec_err_t vp8e_destroy(vpx_codec_alg_priv_t *ctx) #if CONFIG_MULTI_RES_ENCODING /* Free multi-encoder shared memory */ if (ctx->oxcf.mr_total_resolutions > 0 && (ctx->oxcf.mr_encoder_id == ctx->oxcf.mr_total_resolutions-1)) + { + LOWER_RES_FRAME_INFO *shared_mem_loc = (LOWER_RES_FRAME_INFO *)ctx->oxcf.mr_low_res_mode_info; + free(shared_mem_loc->mb_info); free(ctx->oxcf.mr_low_res_mode_info); + } #endif free(ctx->cx_data); diff --git a/vp8_multi_resolution_encoder.c b/vp8_multi_resolution_encoder.c index 78f50c294..81e71375d 100644 --- a/vp8_multi_resolution_encoder.c +++ b/vp8_multi_resolution_encoder.c @@ -288,8 +288,13 @@ int main(int argc, char **argv) cfg[0].g_lag_in_frames = 0; /* Disable automatic keyframe placement */ + /* Note: These 3 settings are copied to all levels. But, except the lowest + * resolution level, all other levels are set to VPX_KF_DISABLED internally. + */ //cfg[0].kf_mode = VPX_KF_DISABLED; - cfg[0].kf_min_dist = cfg[0].kf_max_dist = 1000; + cfg[0].kf_mode = VPX_KF_AUTO; + cfg[0].kf_min_dist = 0; + cfg[0].kf_max_dist = 150; cfg[0].rc_target_bitrate = target_bitrate[0]; /* Set target bitrate */ cfg[0].g_timebase.num = 1; /* Set fps */ diff --git a/vpx/src/vpx_encoder.c b/vpx/src/vpx_encoder.c index 03ddc62b2..db0120c35 100644 --- a/vpx/src/vpx_encoder.c +++ b/vpx/src/vpx_encoder.c @@ -117,6 +117,13 @@ vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t *ctx, mr_cfg.mr_down_sampling_factor.num = dsf->num; mr_cfg.mr_down_sampling_factor.den = dsf->den; + /* Force Key-frame synchronization. Namely, encoder at higher + * resolution always use the same frame_type chosen by the + * lowest-resolution encoder. + */ + if(mr_cfg.mr_encoder_id) + cfg->kf_mode = VPX_KF_DISABLED; + ctx->iface = iface; ctx->name = iface->name; ctx->priv = NULL;