diff options
Diffstat (limited to 'third_party/libaom/source/libaom/av1/encoder/gop_structure.c')
-rw-r--r-- | third_party/libaom/source/libaom/av1/encoder/gop_structure.c | 165 |
1 files changed, 143 insertions, 22 deletions
diff --git a/third_party/libaom/source/libaom/av1/encoder/gop_structure.c b/third_party/libaom/source/libaom/av1/encoder/gop_structure.c index 0e4968a72f..9cf72d2733 100644 --- a/third_party/libaom/source/libaom/av1/encoder/gop_structure.c +++ b/third_party/libaom/source/libaom/av1/encoder/gop_structure.c @@ -26,12 +26,51 @@ #include "av1/encoder/firstpass.h" #include "av1/encoder/gop_structure.h" +#if CONFIG_FRAME_PARALLEL_ENCODE +// This function sets gf_group->frame_parallel_level for LF_UPDATE frames based +// on the value of parallel_frame_count. +static void set_frame_parallel_level(int *frame_parallel_level, + int *parallel_frame_count, + int max_parallel_frames) { + assert(*parallel_frame_count > 0); + // parallel_frame_count > 1 indicates subsequent frame(s) in the current + // parallel encode set. + *frame_parallel_level = 1 + (*parallel_frame_count > 1); + // Update the count of no. of parallel frames. + (*parallel_frame_count)++; + if (*parallel_frame_count > max_parallel_frames) *parallel_frame_count = 1; +} + +// This function sets gf_group->src_offset based on frame_parallel_level. +// Outputs are gf_group->src_offset and first_frame_index +static void set_src_offset(GF_GROUP *const gf_group, int *first_frame_index, + int cur_frame_idx, int frame_ind) { + if (gf_group->frame_parallel_level[frame_ind] > 0) { + if (gf_group->frame_parallel_level[frame_ind] == 1) { + *first_frame_index = cur_frame_idx; + } + + // Obtain the offset of the frame at frame_ind in the lookahead queue by + // subtracting the display order hints of the current frame from the display + // order hint of the first frame in parallel encoding set (at + // first_frame_index). + gf_group->src_offset[frame_ind] = + (cur_frame_idx + gf_group->arf_src_offset[frame_ind]) - + *first_frame_index; + } +} +#endif // CONFIG_FRAME_PARALLEL_ENCODE + // Set parameters for frames between 'start' and 'end' (excluding both). -static void set_multi_layer_params(const TWO_PASS *twopass, - GF_GROUP *const gf_group, RATE_CONTROL *rc, - FRAME_INFO *frame_info, int start, int end, - int *cur_frame_idx, int *frame_ind, - int layer_depth) { +static void set_multi_layer_params( + const TWO_PASS *twopass, GF_GROUP *const gf_group, + const PRIMARY_RATE_CONTROL *p_rc, RATE_CONTROL *rc, FRAME_INFO *frame_info, + int start, int end, int *cur_frame_idx, int *frame_ind, +#if CONFIG_FRAME_PARALLEL_ENCODE + int *parallel_frame_count, int max_parallel_frames, + int do_frame_parallel_encode, int *first_frame_index, +#endif // CONFIG_FRAME_PARALLEL_ENCODE + int layer_depth) { const int num_frames_to_process = end - start; // Either we are at the last level of the pyramid, or we don't have enough @@ -45,11 +84,21 @@ static void set_multi_layer_params(const TWO_PASS *twopass, gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx; gf_group->layer_depth[*frame_ind] = MAX_ARF_LAYERS; gf_group->arf_boost[*frame_ind] = av1_calc_arf_boost( - twopass, rc, frame_info, start, end - start, 0, NULL, NULL); + twopass, p_rc, rc, frame_info, start, end - start, 0, NULL, NULL, 0); gf_group->frame_type[*frame_ind] = INTER_FRAME; gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE; gf_group->max_layer_depth = AOMMAX(gf_group->max_layer_depth, layer_depth); +#if CONFIG_FRAME_PARALLEL_ENCODE + // Set the level of parallelism for the LF_UPDATE frame. + if (do_frame_parallel_encode) { + set_frame_parallel_level(&gf_group->frame_parallel_level[*frame_ind], + parallel_frame_count, max_parallel_frames); + // Set LF_UPDATE frames as non-reference frames. + gf_group->is_frame_non_ref[*frame_ind] = 1; + } + set_src_offset(gf_group, first_frame_index, *cur_frame_idx, *frame_ind); +#endif // CONFIG_FRAME_PARALLEL_ENCODE ++(*frame_ind); ++(*cur_frame_idx); ++start; @@ -65,14 +114,32 @@ static void set_multi_layer_params(const TWO_PASS *twopass, gf_group->frame_type[*frame_ind] = INTER_FRAME; gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE; +#if CONFIG_FRAME_PARALLEL_ENCODE + if (do_frame_parallel_encode) { + // If max_parallel_frames is not exceeded, encode the next internal ARF + // frame in parallel. + if (*parallel_frame_count > 1 && + *parallel_frame_count <= max_parallel_frames) { + gf_group->frame_parallel_level[*frame_ind] = 2; + *parallel_frame_count = 1; + } + } + set_src_offset(gf_group, first_frame_index, *cur_frame_idx, *frame_ind); +#endif // CONFIG_FRAME_PARALLEL_ENCODE + // Get the boost factor for intermediate ARF frames. gf_group->arf_boost[*frame_ind] = av1_calc_arf_boost( - twopass, rc, frame_info, m, end - m, m - start, NULL, NULL); + twopass, p_rc, rc, frame_info, m, end - m, m - start, NULL, NULL, 0); ++(*frame_ind); // Frames displayed before this internal ARF. - set_multi_layer_params(twopass, gf_group, rc, frame_info, start, m, - cur_frame_idx, frame_ind, layer_depth + 1); + set_multi_layer_params(twopass, gf_group, p_rc, rc, frame_info, start, m, + cur_frame_idx, frame_ind, +#if CONFIG_FRAME_PARALLEL_ENCODE + parallel_frame_count, max_parallel_frames, + do_frame_parallel_encode, first_frame_index, +#endif // CONFIG_FRAME_PARALLEL_ENCODE + layer_depth + 1); // Overlay for internal ARF. gf_group->update_type[*frame_ind] = INTNL_OVERLAY_UPDATE; @@ -82,12 +149,21 @@ static void set_multi_layer_params(const TWO_PASS *twopass, gf_group->layer_depth[*frame_ind] = layer_depth; gf_group->frame_type[*frame_ind] = INTER_FRAME; gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE; + +#if CONFIG_FRAME_PARALLEL_ENCODE + set_src_offset(gf_group, first_frame_index, *cur_frame_idx, *frame_ind); +#endif // CONFIG_FRAME_PARALLEL_ENCODE ++(*frame_ind); ++(*cur_frame_idx); // Frames displayed after this internal ARF. - set_multi_layer_params(twopass, gf_group, rc, frame_info, m + 1, end, - cur_frame_idx, frame_ind, layer_depth + 1); + set_multi_layer_params(twopass, gf_group, p_rc, rc, frame_info, m + 1, end, + cur_frame_idx, frame_ind, +#if CONFIG_FRAME_PARALLEL_ENCODE + parallel_frame_count, max_parallel_frames, + do_frame_parallel_encode, first_frame_index, +#endif // CONFIG_FRAME_PARALLEL_ENCODE + layer_depth + 1); } } @@ -95,6 +171,7 @@ static int construct_multi_layer_gf_structure( AV1_COMP *cpi, TWO_PASS *twopass, GF_GROUP *const gf_group, RATE_CONTROL *rc, FRAME_INFO *const frame_info, int gf_interval, FRAME_UPDATE_TYPE first_frame_update_type) { + PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; int frame_index = 0; int cur_frame_index = 0; @@ -103,6 +180,18 @@ static int construct_multi_layer_gf_structure( first_frame_update_type == OVERLAY_UPDATE || first_frame_update_type == GF_UPDATE); +#if CONFIG_FRAME_PARALLEL_ENCODE + // Initialize gf_group->frame_parallel_level and gf_group->is_frame_non_ref to + // 0. + memset( + gf_group->frame_parallel_level, 0, + sizeof(gf_group->frame_parallel_level[0]) * MAX_STATIC_GF_GROUP_LENGTH); + memset(gf_group->is_frame_non_ref, 0, + sizeof(gf_group->is_frame_non_ref[0]) * MAX_STATIC_GF_GROUP_LENGTH); + memset(gf_group->src_offset, 0, + sizeof(gf_group->src_offset[0]) * MAX_STATIC_GF_GROUP_LENGTH); +#endif + if (first_frame_update_type == KF_UPDATE && cpi->oxcf.kf_cfg.enable_keyframe_filtering > 1) { gf_group->update_type[frame_index] = ARF_UPDATE; @@ -146,7 +235,7 @@ static int construct_multi_layer_gf_structure( gf_group->arf_src_offset[frame_index] = gf_interval - cur_frame_index; gf_group->cur_frame_idx[frame_index] = cur_frame_index; gf_group->layer_depth[frame_index] = 1; - gf_group->arf_boost[frame_index] = cpi->rc.gfu_boost; + gf_group->arf_boost[frame_index] = cpi->ppi->p_rc.gfu_boost; gf_group->frame_type[frame_index] = is_fwd_kf ? KEY_FRAME : INTER_FRAME; gf_group->refbuf_state[frame_index] = REFBUF_UPDATE; gf_group->max_layer_depth = 1; @@ -156,9 +245,25 @@ static int construct_multi_layer_gf_structure( gf_group->arf_index = -1; } +#if CONFIG_FRAME_PARALLEL_ENCODE + // Running count of no. of frames that is part of a given parallel + // encode set in a gf_group. Value of 1 indicates no parallel encode. + int parallel_frame_count = 1; + // Enable parallel encode of frames if gf_group has a multi-layer pyramid + // structure. + int do_frame_parallel_encode = (cpi->ppi->num_fp_contexts > 1 && use_altref); + + int first_frame_index = cur_frame_index; +#endif // CONFIG_FRAME_PARALLEL_ENCODE + // Rest of the frames. - set_multi_layer_params(twopass, gf_group, rc, frame_info, cur_frame_index, - gf_interval, &cur_frame_index, &frame_index, + set_multi_layer_params(twopass, gf_group, p_rc, rc, frame_info, + cur_frame_index, gf_interval, &cur_frame_index, + &frame_index, +#if CONFIG_FRAME_PARALLEL_ENCODE + ¶llel_frame_count, cpi->ppi->num_fp_contexts, + do_frame_parallel_encode, &first_frame_index, +#endif // CONFIG_FRAME_PARALLEL_ENCODE use_altref + 1); if (use_altref) { @@ -181,25 +286,41 @@ static int construct_multi_layer_gf_structure( gf_group->frame_type[frame_index] = INTER_FRAME; gf_group->refbuf_state[frame_index] = REFBUF_UPDATE; gf_group->max_layer_depth = AOMMAX(gf_group->max_layer_depth, 2); +#if CONFIG_FRAME_PARALLEL_ENCODE + set_src_offset(gf_group, &first_frame_index, cur_frame_index, + frame_index); +#endif ++frame_index; } } +#if CONFIG_FRAME_PARALLEL_ENCODE + if (do_frame_parallel_encode) { + // If frame_parallel_level is set to 1 for the last LF_UPDATE + // frame in the gf_group, reset it to zero since there are no subsequent + // frames in the gf_group. + if (gf_group->frame_parallel_level[frame_index - 2] == 1) { + assert(gf_group->update_type[frame_index - 2] == LF_UPDATE); + gf_group->frame_parallel_level[frame_index - 2] = 0; + } + } +#endif return frame_index; } void av1_gop_setup_structure(AV1_COMP *cpi) { RATE_CONTROL *const rc = &cpi->rc; - GF_GROUP *const gf_group = &cpi->gf_group; - TWO_PASS *const twopass = &cpi->twopass; + PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; + GF_GROUP *const gf_group = &cpi->ppi->gf_group; + TWO_PASS *const twopass = &cpi->ppi->twopass; FRAME_INFO *const frame_info = &cpi->frame_info; const int key_frame = rc->frames_since_key == 0; const FRAME_UPDATE_TYPE first_frame_update_type = - key_frame - ? KF_UPDATE - : cpi->gf_state.arf_gf_boost_lst || (rc->baseline_gf_interval == 1) - ? OVERLAY_UPDATE - : GF_UPDATE; + key_frame ? KF_UPDATE + : cpi->ppi->gf_state.arf_gf_boost_lst || + (p_rc->baseline_gf_interval == 1) + ? OVERLAY_UPDATE + : GF_UPDATE; gf_group->size = construct_multi_layer_gf_structure( - cpi, twopass, gf_group, rc, frame_info, rc->baseline_gf_interval - 1, + cpi, twopass, gf_group, rc, frame_info, p_rc->baseline_gf_interval - 1, first_frame_update_type); } |