blob: 9cf72d27337bd12912b398b8ee0936a4b872d443 [file] [log] [blame]
/*
* Copyright (c) 2019, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. 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 www.aomedia.org/license/patent.
*/
#include <stdint.h>
#include "av1/common/blockd.h"
#include "config/aom_config.h"
#include "config/aom_scale_rtcd.h"
#include "aom/aom_codec.h"
#include "aom/aom_encoder.h"
#include "aom_ports/system_state.h"
#include "av1/common/av1_common_int.h"
#include "av1/encoder/encoder.h"
#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,
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
// frames between 'l' and 'r' to create one more level.
if (layer_depth > gf_group->max_layer_depth_allowed ||
num_frames_to_process < 3) {
// Leaf nodes.
while (start < end) {
gf_group->update_type[*frame_ind] = LF_UPDATE;
gf_group->arf_src_offset[*frame_ind] = 0;
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, 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;
}
} else {
const int m = (start + end - 1) / 2;
// Internal ARF.
gf_group->update_type[*frame_ind] = INTNL_ARF_UPDATE;
gf_group->arf_src_offset[*frame_ind] = m - start;
gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
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
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, 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, 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;
gf_group->arf_src_offset[*frame_ind] = 0;
gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
gf_group->arf_boost[*frame_ind] = 0;
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, 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);
}
}
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;
// Keyframe / Overlay frame / Golden frame.
assert(first_frame_update_type == KF_UPDATE ||
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;
gf_group->arf_src_offset[frame_index] = 0;
gf_group->cur_frame_idx[frame_index] = cur_frame_index;
gf_group->layer_depth[frame_index] = 0;
gf_group->frame_type[frame_index] = KEY_FRAME;
gf_group->refbuf_state[frame_index] = REFBUF_RESET;
gf_group->max_layer_depth = 0;
++frame_index;
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
gf_group->arf_src_offset[frame_index] = 0;
gf_group->cur_frame_idx[frame_index] = cur_frame_index;
gf_group->layer_depth[frame_index] = 0;
gf_group->frame_type[frame_index] = INTER_FRAME;
gf_group->refbuf_state[frame_index] = REFBUF_UPDATE;
gf_group->max_layer_depth = 0;
++frame_index;
cur_frame_index++;
} else if (first_frame_update_type != OVERLAY_UPDATE) {
gf_group->update_type[frame_index] = first_frame_update_type;
gf_group->arf_src_offset[frame_index] = 0;
gf_group->cur_frame_idx[frame_index] = cur_frame_index;
gf_group->layer_depth[frame_index] =
first_frame_update_type == OVERLAY_UPDATE ? MAX_ARF_LAYERS + 1 : 0;
gf_group->frame_type[frame_index] =
(first_frame_update_type == KF_UPDATE) ? KEY_FRAME : INTER_FRAME;
gf_group->refbuf_state[frame_index] =
(first_frame_update_type == KF_UPDATE) ? REFBUF_RESET : REFBUF_UPDATE;
gf_group->max_layer_depth = 0;
++frame_index;
++cur_frame_index;
}
// ALTREF.
const int use_altref = gf_group->max_layer_depth_allowed > 0;
int is_fwd_kf = (gf_interval == cpi->rc.frames_to_key);
if (use_altref) {
gf_group->update_type[frame_index] = ARF_UPDATE;
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->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;
gf_group->arf_index = frame_index;
++frame_index;
} else {
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, p_rc, rc, frame_info,
cur_frame_index, gf_interval, &cur_frame_index,
&frame_index,
#if CONFIG_FRAME_PARALLEL_ENCODE
&parallel_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) {
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
gf_group->arf_src_offset[frame_index] = 0;
gf_group->cur_frame_idx[frame_index] = cur_frame_index;
gf_group->layer_depth[frame_index] = MAX_ARF_LAYERS;
gf_group->arf_boost[frame_index] = NORMAL_BOOST;
gf_group->frame_type[frame_index] = is_fwd_kf ? KEY_FRAME : INTER_FRAME;
gf_group->refbuf_state[frame_index] =
is_fwd_kf ? REFBUF_RESET : REFBUF_UPDATE;
++frame_index;
} else {
for (; cur_frame_index <= gf_interval; ++cur_frame_index) {
gf_group->update_type[frame_index] = LF_UPDATE;
gf_group->arf_src_offset[frame_index] = 0;
gf_group->cur_frame_idx[frame_index] = cur_frame_index;
gf_group->layer_depth[frame_index] = MAX_ARF_LAYERS;
gf_group->arf_boost[frame_index] = NORMAL_BOOST;
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;
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->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, p_rc->baseline_gf_interval - 1,
first_frame_update_type);
}