Support parsing multi-layer gf group and 7 ref frame in tpl tool - Use precomputed reference frame map in gf_group for calculating temporal dependency. - Expand the length of tpl stats buffer from MAX_LAG_BUFFERS to MAX_STATIC_GF_GROUP_LENGTH + 3, to include maximum numbers of gf pictures + the key/golden frame + 2 extended frames in the next gop. Otherwise the encoder fails due to memory issues. - Only enable rdmult modulation on ARF frames. Change-Id: Ibfea1086445dc948fda4b9bb14024101036fb9e0
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c index 926e30a..71e8f6a 100644 --- a/av1/encoder/encodeframe.c +++ b/av1/encoder/encodeframe.c
@@ -4131,9 +4131,12 @@ int mi_col) { const BLOCK_SIZE sb_size = cpi->common.seq_params.sb_size; const int orig_rdmult = cpi->rd.RDMULT; + const int gf_group_index = cpi->twopass.gf_group.index; x->cb_rdmult = orig_rdmult; - if (cpi->twopass.gf_group.index > 0 && cpi->oxcf.enable_tpl_model && - cpi->oxcf.aq_mode == NO_AQ && cpi->oxcf.deltaq_mode == NO_DELTA_Q) { + + if (cpi->oxcf.enable_tpl_model && cpi->oxcf.aq_mode == NO_AQ && + cpi->oxcf.deltaq_mode == NO_DELTA_Q && gf_group_index > 0 && + cpi->twopass.gf_group.update_type[gf_group_index] == ARF_UPDATE) { const int dr = get_rdmult_delta(cpi, sb_size, mi_row, mi_col, orig_rdmult); x->rdmult = dr; x->cb_rdmult = x->rdmult;
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 2f2eebc..c644ec3 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -2711,7 +2711,7 @@ av1_set_speed_features_framesize_independent(cpi, oxcf->speed); av1_set_speed_features_framesize_dependent(cpi, oxcf->speed); - for (int frame = 0; frame < MAX_LAG_BUFFERS; ++frame) { + for (int frame = 0; frame < MAX_LENGTH_TPL_FRAME_STATS; ++frame) { int mi_cols = ALIGN_POWER_OF_TWO(cm->mi_cols, MAX_MIB_SIZE_LOG2); int mi_rows = ALIGN_POWER_OF_TWO(cm->mi_rows, MAX_MIB_SIZE_LOG2); @@ -3055,7 +3055,7 @@ #endif } - for (int frame = 0; frame < MAX_LAG_BUFFERS; ++frame) { + for (int frame = 0; frame < MAX_LENGTH_TPL_FRAME_STATS; ++frame) { aom_free(cpi->tpl_stats[frame].tpl_stats_ptr); cpi->tpl_stats[frame].is_valid = 0; }
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index a9e1379..b1cf0ea 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h
@@ -157,6 +157,8 @@ SS_CFG_TOTAL = 2 } UENUM1BYTE(SS_CFG_OFFSET); +#define MAX_LENGTH_TPL_FRAME_STATS MAX_STATIC_GF_GROUP_LENGTH + 3 + typedef struct TplDepStats { int64_t intra_cost; int64_t inter_cost; @@ -741,7 +743,7 @@ YV12_BUFFER_CONFIG *unscaled_last_source; YV12_BUFFER_CONFIG scaled_last_source; - TplDepFrame tpl_stats[MAX_LAG_BUFFERS]; + TplDepFrame tpl_stats[MAX_LENGTH_TPL_FRAME_STATS]; YV12_BUFFER_CONFIG *tpl_recon_frames[INTER_REFS_PER_FRAME + 1]; // For a still frame, this flag is set to 1 to skip partition search.
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c index 4b2075c..9f5dec4 100644 --- a/av1/encoder/tpl_model.c +++ b/av1/encoder/tpl_model.c
@@ -24,7 +24,7 @@ typedef struct GF_PICTURE { YV12_BUFFER_CONFIG *frame; - int ref_frame[7]; + int ref_frame[INTER_REFS_PER_FRAME]; } GF_PICTURE; static void get_quantize_error(MACROBLOCK *x, int plane, tran_low_t *coeff, @@ -459,6 +459,12 @@ } } +#define REF_IDX(ref) ((ref)-LAST_FRAME) + +static INLINE void init_ref_frame_array(GF_PICTURE *gf_picture) { + for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) gf_picture->ref_frame[i] = -1; +} + static void init_gop_frames_for_tpl(AV1_COMP *cpi, GF_PICTURE *gf_picture, const GF_GROUP *gf_group, int *tpl_group_frames, @@ -466,18 +472,15 @@ AV1_COMMON *cm = &cpi->common; const SequenceHeader *const seq_params = &cm->seq_params; int frame_idx = 0; - int i; - int gld_index = -1; - int lst_index = -1; - int extend_frame_count = 0; - int frame_gop_offset = 0; + int frame_disp_idx = 0; int pframe_qindex = cpi->tpl_stats[2].base_qindex; RefCntBuffer *frame_bufs = cm->buffer_pool->frame_bufs; int recon_frame_index[INTER_REFS_PER_FRAME + 1] = { -1, -1, -1, -1, -1, -1, -1, -1 }; - for (i = 0; i < FRAME_BUFFERS && frame_idx < INTER_REFS_PER_FRAME + 1; ++i) { + for (int i = 0; i < FRAME_BUFFERS && frame_idx < INTER_REFS_PER_FRAME + 1; + ++i) { if (frame_bufs[i].ref_count == 0) { alloc_frame_mvs(cm, &frame_bufs[i]); if (aom_realloc_frame_buffer( @@ -493,7 +496,7 @@ } } - for (i = 0; i < INTER_REFS_PER_FRAME + 1; ++i) { + for (int i = 0; i < INTER_REFS_PER_FRAME + 1; ++i) { assert(recon_frame_index[i] >= 0); cpi->tpl_recon_frames[i] = &frame_bufs[recon_frame_index[i]].buf; } @@ -503,65 +506,68 @@ // Initialize Golden reference frame. RefCntBuffer *ref_buf = get_ref_frame_buf(cm, GOLDEN_FRAME); gf_picture[0].frame = &ref_buf->buf; - for (i = 0; i < 7; ++i) gf_picture[0].ref_frame[i] = -1; - gld_index = 0; + init_ref_frame_array(&gf_picture[0]); ++*tpl_group_frames; - // Initialize base layer ARF frame - gf_picture[1].frame = frame_input->source; - gf_picture[1].ref_frame[0] = gld_index; - // TODO(yuec) Need o figure out full AV1 reference model - for (i = 1; i < 7; ++i) gf_picture[1].ref_frame[i] = -1; - ++*tpl_group_frames; + // Initialize frames in the GF group + for (frame_idx = 1; frame_idx <= gf_group->size; ++frame_idx) { + if (frame_idx == 1) { + gf_picture[1].frame = frame_input->source; + } else { + frame_disp_idx = gf_group->frame_disp_idx[frame_idx]; + struct lookahead_entry *buf = + av1_lookahead_peek(cpi->lookahead, frame_disp_idx - 1); - // Initialize P frames - for (frame_idx = 2; frame_idx < MAX_LAG_BUFFERS; ++frame_idx) { - struct lookahead_entry *buf; - frame_gop_offset = gf_group->frame_disp_idx[frame_idx]; - buf = av1_lookahead_peek(cpi->lookahead, frame_gop_offset - 1); + if (buf == NULL) break; - if (buf == NULL) break; + gf_picture[frame_idx].frame = &buf->img; + } - gf_picture[frame_idx].frame = &buf->img; - gf_picture[frame_idx].ref_frame[0] = gld_index; - gf_picture[frame_idx].ref_frame[1] = lst_index; - gf_picture[frame_idx].ref_frame[2] = 1; - for (i = 3; i < 7; ++i) gf_picture[frame_idx].ref_frame[i] = -1; + memcpy(gf_picture[frame_idx].ref_frame, + gf_group->ref_frame_gop_idx[frame_idx], + sizeof(gf_picture[0].ref_frame[0]) * INTER_REFS_PER_FRAME); ++*tpl_group_frames; - lst_index = frame_idx; - - if (frame_idx == gf_group->size) break; } - gld_index = frame_idx; - lst_index = AOMMAX(0, frame_idx - 1); - ++frame_idx; - ++frame_gop_offset; + ++frame_disp_idx; + int extend_frame_count = 0; + const int gld_idx_next_gop = gf_group->size; + const int lst_idx_next_gop = + gf_picture[gld_idx_next_gop].ref_frame[REF_IDX(LAST_FRAME)]; + const int lst2_idx_next_gop = + gf_picture[gld_idx_next_gop].ref_frame[REF_IDX(LAST2_FRAME)]; + const int lst3_idx_next_gop = + gf_picture[gld_idx_next_gop].ref_frame[REF_IDX(LAST3_FRAME)]; // Extend two frames outside the current gf group. - for (; frame_idx < MAX_LAG_BUFFERS && extend_frame_count < 2; ++frame_idx) { + for (; frame_idx < MAX_LENGTH_TPL_FRAME_STATS && extend_frame_count < 2; + ++frame_idx) { struct lookahead_entry *buf = - av1_lookahead_peek(cpi->lookahead, frame_gop_offset - 1); + av1_lookahead_peek(cpi->lookahead, frame_disp_idx - 1); if (buf == NULL) break; cpi->tpl_stats[frame_idx].base_qindex = pframe_qindex; gf_picture[frame_idx].frame = &buf->img; - gf_picture[frame_idx].ref_frame[0] = gld_index; - gf_picture[frame_idx].ref_frame[1] = lst_index; - for (i = 2; i < 7; ++i) gf_picture[frame_idx].ref_frame[i] = -1; - lst_index = frame_idx; + + init_ref_frame_array(&gf_picture[frame_idx]); + + gf_picture[frame_idx].ref_frame[REF_IDX(GOLDEN_FRAME)] = gld_idx_next_gop; + gf_picture[frame_idx].ref_frame[REF_IDX(LAST_FRAME)] = lst_idx_next_gop; + gf_picture[frame_idx].ref_frame[REF_IDX(LAST2_FRAME)] = lst2_idx_next_gop; + gf_picture[frame_idx].ref_frame[REF_IDX(LAST3_FRAME)] = lst3_idx_next_gop; + ++*tpl_group_frames; ++extend_frame_count; - ++frame_gop_offset; + ++frame_disp_idx; } } static void init_tpl_stats(AV1_COMP *cpi) { int frame_idx; - for (frame_idx = 0; frame_idx < MAX_LAG_BUFFERS; ++frame_idx) { + for (frame_idx = 0; frame_idx < MAX_LENGTH_TPL_FRAME_STATS; ++frame_idx) { TplDepFrame *tpl_frame = &cpi->tpl_stats[frame_idx]; memset(tpl_frame->tpl_stats_ptr, 0, tpl_frame->height * tpl_frame->width * @@ -572,7 +578,7 @@ void av1_tpl_setup_stats(AV1_COMP *cpi, const EncodeFrameInput *const frame_input) { - GF_PICTURE gf_picture[MAX_LAG_BUFFERS]; + GF_PICTURE gf_picture[MAX_LENGTH_TPL_FRAME_STATS]; const GF_GROUP *gf_group = &cpi->twopass.gf_group; int tpl_group_frames = 0; int frame_idx;