blob: 1e3940cede2eea9a8ba870f299db6803bc658f0a [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 "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/onyxc_int.h"
#include "av1/encoder/encoder.h"
#include "av1/encoder/firstpass.h"
#include "av1/encoder/gop_structure.h"
static void set_multi_layer_params(GF_GROUP *const gf_group, int l, int r,
int *frame_ind, int arf_ind, int level) {
if (r - l < 4) {
while (++l < r) {
// leaf nodes, not a look-ahead frame
gf_group->update_type[*frame_ind] = LF_UPDATE;
gf_group->arf_src_offset[*frame_ind] = 0;
gf_group->arf_pos_in_gf[*frame_ind] = 0;
gf_group->arf_update_idx[*frame_ind] = arf_ind;
gf_group->pyramid_level[*frame_ind] = 0;
++gf_group->pyramid_lvl_nodes[0];
++(*frame_ind);
}
} else {
int m = (l + r) / 2;
int arf_pos_in_gf = *frame_ind;
gf_group->update_type[*frame_ind] = INTNL_ARF_UPDATE;
gf_group->arf_src_offset[*frame_ind] = m - l - 1;
gf_group->arf_pos_in_gf[*frame_ind] = 0;
gf_group->arf_update_idx[*frame_ind] = 1; // mark all internal ARF 1
gf_group->pyramid_level[*frame_ind] = level;
++gf_group->pyramid_lvl_nodes[level];
++(*frame_ind);
// set parameters for frames displayed before this frame
set_multi_layer_params(gf_group, l, m, frame_ind, 1, level - 1);
// for overlay frames, we need to record the position of its corresponding
// arf frames for bit allocation
gf_group->update_type[*frame_ind] = INTNL_OVERLAY_UPDATE;
gf_group->arf_src_offset[*frame_ind] = 0;
gf_group->arf_pos_in_gf[*frame_ind] = arf_pos_in_gf;
gf_group->arf_update_idx[*frame_ind] = 1;
gf_group->pyramid_level[*frame_ind] = 0;
++(*frame_ind);
// set parameters for frames displayed after this frame
set_multi_layer_params(gf_group, m, r, frame_ind, arf_ind, level - 1);
}
}
static INLINE unsigned char get_pyramid_height(int pyramid_width) {
assert(pyramid_width <= MAX_GF_INTERVAL && pyramid_width >= MIN_GF_INTERVAL &&
"invalid gf interval for pyramid structure");
return pyramid_width > 12 ? 4 : (pyramid_width > 6 ? 3 : 2);
}
static int construct_multi_layer_gf_structure(GF_GROUP *const gf_group,
const int gf_interval) {
int frame_index = 0;
gf_group->pyramid_height = get_pyramid_height(gf_interval);
assert(gf_group->pyramid_height <= MAX_PYRAMID_LVL);
av1_zero_array(gf_group->pyramid_lvl_nodes, MAX_PYRAMID_LVL);
// At the beginning of each GF group it will be a key or overlay frame,
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
gf_group->arf_src_offset[frame_index] = 0;
gf_group->arf_pos_in_gf[frame_index] = 0;
gf_group->arf_update_idx[frame_index] = 0;
gf_group->pyramid_level[frame_index] = 0;
++frame_index;
// ALT0
gf_group->update_type[frame_index] = ARF_UPDATE;
gf_group->arf_src_offset[frame_index] = gf_interval - 1;
gf_group->arf_pos_in_gf[frame_index] = 0;
gf_group->arf_update_idx[frame_index] = 0;
gf_group->pyramid_level[frame_index] = gf_group->pyramid_height;
++frame_index;
// set parameters for the rest of the frames
set_multi_layer_params(gf_group, 0, gf_interval, &frame_index, 0,
gf_group->pyramid_height - 1);
return frame_index;
}
#define CHECK_GF_PARAMETER 0
#if CHECK_GF_PARAMETER
void check_frame_params(GF_GROUP *const gf_group, int gf_interval,
int frame_nums) {
static const char *update_type_strings[] = {
"KF_UPDATE", "LF_UPDATE", "GF_UPDATE",
"ARF_UPDATE", "OVERLAY_UPDATE", "BRF_UPDATE",
"LAST_BIPRED_UPDATE", "BIPRED_UPDATE", "INTNL_OVERLAY_UPDATE",
"INTNL_ARF_UPDATE"
};
FILE *fid = fopen("GF_PARAMS.txt", "a");
fprintf(fid, "\n{%d}\n", gf_interval);
for (int i = 0; i <= frame_nums; ++i) {
fprintf(fid, "%s %d %d %d %d\n",
update_type_strings[gf_group->update_type[i]],
gf_group->arf_src_offset[i], gf_group->arf_pos_in_gf[i],
gf_group->arf_update_idx[i], gf_group->pyramid_level[i]);
}
fprintf(fid, "number of nodes in each level: \n");
for (int i = 0; i < gf_group->pyramid_height; ++i) {
fprintf(fid, "lvl %d: %d ", i, gf_group->pyramid_lvl_nodes[i]);
}
fprintf(fid, "\n");
fclose(fid);
}
#endif // CHECK_GF_PARAMETER
static int update_type_2_rf_level(FRAME_UPDATE_TYPE update_type) {
// Derive rf_level from update_type
switch (update_type) {
case LF_UPDATE: return INTER_NORMAL;
case ARF_UPDATE: return GF_ARF_STD;
case OVERLAY_UPDATE: return INTER_NORMAL;
case BRF_UPDATE: return GF_ARF_LOW;
case LAST_BIPRED_UPDATE: return INTER_NORMAL;
case BIPRED_UPDATE: return INTER_NORMAL;
case INTNL_ARF_UPDATE: return GF_ARF_LOW;
case INTNL_OVERLAY_UPDATE: return INTER_NORMAL;
default: return INTER_NORMAL;
}
}
static void define_pyramid_gf_group_structure(
AV1_COMP *cpi, const EncodeFrameParams *const frame_params) {
RATE_CONTROL *const rc = &cpi->rc;
TWO_PASS *const twopass = &cpi->twopass;
GF_GROUP *const gf_group = &twopass->gf_group;
const int key_frame = frame_params->frame_type == KEY_FRAME;
assert(rc->baseline_gf_interval >= MIN_GF_INTERVAL &&
rc->baseline_gf_interval <=
get_max_gf_length(cpi->oxcf.gf_max_pyr_height));
assert(cpi->oxcf.gf_max_pyr_height >= MIN_PYRAMID_LVL &&
cpi->oxcf.gf_max_pyr_height <= MAX_PYRAMID_LVL);
const int gf_update_frames =
construct_multi_layer_gf_structure(gf_group, rc->baseline_gf_interval);
int frame_index;
cpi->num_extra_arfs = 0;
for (frame_index = 0; frame_index < gf_update_frames; ++frame_index) {
// Set unused variables to default values
gf_group->bidir_pred_enabled[frame_index] = 0;
gf_group->brf_src_offset[frame_index] = 0;
// Special handle for the first frame for assigning update_type
if (frame_index == 0) {
// For key frames the frame target rate is already set and it
// is also the golden frame.
if (key_frame) {
gf_group->update_type[frame_index] = KF_UPDATE;
continue;
}
if (rc->source_alt_ref_active) {
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
} else {
gf_group->update_type[frame_index] = GF_UPDATE;
}
} else {
if (gf_group->update_type[frame_index] == INTNL_ARF_UPDATE)
++cpi->num_extra_arfs;
}
// Assign rf level based on update type
gf_group->rf_level[frame_index] =
update_type_2_rf_level(gf_group->update_type[frame_index]);
}
// NOTE: We need to configure the frame at the end of the sequence + 1 that
// will be the start frame for the next group. Otherwise prior to the
// call to av1_get_second_pass_params() the data will be undefined.
if (rc->source_alt_ref_pending) {
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
gf_group->rf_level[frame_index] = INTER_NORMAL;
} else {
gf_group->update_type[frame_index] = GF_UPDATE;
gf_group->rf_level[frame_index] = GF_ARF_STD;
}
gf_group->bidir_pred_enabled[frame_index] = 0;
gf_group->brf_src_offset[frame_index] = 0;
gf_group->arf_update_idx[frame_index] = 0;
// This value is only used for INTNL_OVERLAY_UPDATE
gf_group->arf_pos_in_gf[frame_index] = 0;
// This parameter is useless?
gf_group->arf_ref_idx[frame_index] = 0;
#ifdef CHCEK_GF_PARAMETER
check_frame_params(gf_group, rc->baseline_gf_interval, gf_update_frames);
#endif
}
static void define_flat_gf_group_structure(
AV1_COMP *cpi, const EncodeFrameParams *const frame_params) {
RATE_CONTROL *const rc = &cpi->rc;
TWO_PASS *const twopass = &cpi->twopass;
GF_GROUP *const gf_group = &twopass->gf_group;
int i;
int frame_index = 0;
const int key_frame = frame_params->frame_type == KEY_FRAME;
// The use of bi-predictive frames are only enabled when following 3
// conditions are met:
// (1) ALTREF is enabled;
// (2) The bi-predictive group interval is at least 2; and
// (3) The bi-predictive group interval is strictly smaller than the
// golden group interval.
const int is_bipred_enabled =
cpi->extra_arf_allowed && rc->source_alt_ref_pending &&
rc->bipred_group_interval &&
rc->bipred_group_interval <=
(rc->baseline_gf_interval - rc->source_alt_ref_pending);
int bipred_group_end = 0;
int bipred_frame_index = 0;
const unsigned char ext_arf_interval =
(unsigned char)(rc->baseline_gf_interval / (cpi->num_extra_arfs + 1) - 1);
int which_arf = cpi->num_extra_arfs;
int subgroup_interval[MAX_EXT_ARFS + 1];
int is_sg_bipred_enabled = is_bipred_enabled;
int accumulative_subgroup_interval = 0;
// For key frames the frame target rate is already set and it
// is also the golden frame.
// === [frame_index == 0] ===
if (!key_frame) {
if (rc->source_alt_ref_active) {
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
gf_group->rf_level[frame_index] = INTER_NORMAL;
} else {
gf_group->update_type[frame_index] = GF_UPDATE;
gf_group->rf_level[frame_index] = GF_ARF_STD;
}
gf_group->arf_update_idx[frame_index] = 0;
gf_group->arf_ref_idx[frame_index] = 0;
}
gf_group->bidir_pred_enabled[frame_index] = 0;
gf_group->brf_src_offset[frame_index] = 0;
frame_index++;
bipred_frame_index++;
// === [frame_index == 1] ===
if (rc->source_alt_ref_pending) {
gf_group->update_type[frame_index] = ARF_UPDATE;
gf_group->rf_level[frame_index] = GF_ARF_STD;
gf_group->arf_src_offset[frame_index] =
(unsigned char)(rc->baseline_gf_interval - 1);
gf_group->arf_update_idx[frame_index] = 0;
gf_group->arf_ref_idx[frame_index] = 0;
gf_group->bidir_pred_enabled[frame_index] = 0;
gf_group->brf_src_offset[frame_index] = 0;
// NOTE: "bidir_pred_frame_index" stays unchanged for ARF_UPDATE frames.
// Work out the ARFs' positions in this gf group
// NOTE(weitinglin): ALT_REFs' are indexed inversely, but coded in display
// order (except for the original ARF). In the example of three ALT_REF's,
// We index ALTREF's as: KEY ----- ALT2 ----- ALT1 ----- ALT0
// but code them in the following order:
// KEY-ALT0-ALT2 ----- OVERLAY2-ALT1 ----- OVERLAY1 ----- OVERLAY0
//
// arf_pos_for_ovrly[]: Position for OVERLAY
// arf_pos_in_gf[]: Position for ALTREF
cpi->arf_pos_for_ovrly[0] = frame_index + cpi->num_extra_arfs +
gf_group->arf_src_offset[frame_index] + 1;
for (i = 0; i < cpi->num_extra_arfs; ++i) {
cpi->arf_pos_for_ovrly[i + 1] =
frame_index + (cpi->num_extra_arfs - i) * (ext_arf_interval + 2);
subgroup_interval[i] = cpi->arf_pos_for_ovrly[i] -
cpi->arf_pos_for_ovrly[i + 1] - (i == 0 ? 1 : 2);
}
subgroup_interval[cpi->num_extra_arfs] =
cpi->arf_pos_for_ovrly[cpi->num_extra_arfs] - frame_index -
(cpi->num_extra_arfs == 0 ? 1 : 2);
++frame_index;
// Insert an extra ARF
// === [frame_index == 2] ===
if (cpi->num_extra_arfs) {
gf_group->update_type[frame_index] = INTNL_ARF_UPDATE;
gf_group->rf_level[frame_index] = GF_ARF_LOW;
gf_group->arf_src_offset[frame_index] = ext_arf_interval;
gf_group->arf_update_idx[frame_index] = which_arf;
gf_group->arf_ref_idx[frame_index] = 0;
++frame_index;
}
accumulative_subgroup_interval += subgroup_interval[cpi->num_extra_arfs];
}
const int normal_frames =
rc->baseline_gf_interval - (key_frame || rc->source_alt_ref_pending);
for (i = 0; i < normal_frames; ++i) {
gf_group->arf_update_idx[frame_index] = which_arf;
gf_group->arf_ref_idx[frame_index] = which_arf;
// If we are going to have ARFs, check whether we can have BWDREF in this
// subgroup, and further, whether we can have ARF subgroup which contains
// the BWDREF subgroup but contained within the GF group:
//
// GF group --> ARF subgroup --> BWDREF subgroup
if (rc->source_alt_ref_pending) {
is_sg_bipred_enabled =
is_bipred_enabled &&
(subgroup_interval[which_arf] > rc->bipred_group_interval);
}
// NOTE: BIDIR_PRED is only enabled when the length of the bi-predictive
// frame group interval is strictly smaller than that of the GOLDEN
// FRAME group interval.
// TODO(zoeliu): Currently BIDIR_PRED is only enabled when alt-ref is on.
if (is_sg_bipred_enabled && !bipred_group_end) {
const int cur_brf_src_offset = rc->bipred_group_interval - 1;
if (bipred_frame_index == 1) {
// --- BRF_UPDATE ---
gf_group->update_type[frame_index] = BRF_UPDATE;
gf_group->rf_level[frame_index] = GF_ARF_LOW;
gf_group->brf_src_offset[frame_index] = cur_brf_src_offset;
} else if (bipred_frame_index == rc->bipred_group_interval) {
// --- LAST_BIPRED_UPDATE ---
gf_group->update_type[frame_index] = LAST_BIPRED_UPDATE;
gf_group->rf_level[frame_index] = INTER_NORMAL;
gf_group->brf_src_offset[frame_index] = 0;
// Reset the bi-predictive frame index.
bipred_frame_index = 0;
} else {
// --- BIPRED_UPDATE ---
gf_group->update_type[frame_index] = BIPRED_UPDATE;
gf_group->rf_level[frame_index] = INTER_NORMAL;
gf_group->brf_src_offset[frame_index] = 0;
}
gf_group->bidir_pred_enabled[frame_index] = 1;
bipred_frame_index++;
// Check whether the next bi-predictive frame group would entirely be
// included within the current golden frame group.
// In addition, we need to avoid coding a BRF right before an ARF.
if (bipred_frame_index == 1 &&
(i + 2 + cur_brf_src_offset) >= accumulative_subgroup_interval) {
bipred_group_end = 1;
}
} else {
gf_group->update_type[frame_index] = LF_UPDATE;
gf_group->rf_level[frame_index] = INTER_NORMAL;
gf_group->bidir_pred_enabled[frame_index] = 0;
gf_group->brf_src_offset[frame_index] = 0;
}
++frame_index;
// Check if we need to update the ARF.
if (is_sg_bipred_enabled && cpi->num_extra_arfs && which_arf > 0 &&
frame_index > cpi->arf_pos_for_ovrly[which_arf]) {
--which_arf;
accumulative_subgroup_interval += subgroup_interval[which_arf] + 1;
// Meet the new subgroup; Reset the bipred_group_end flag.
bipred_group_end = 0;
// Insert another extra ARF after the overlay frame
if (which_arf) {
gf_group->update_type[frame_index] = INTNL_ARF_UPDATE;
gf_group->rf_level[frame_index] = GF_ARF_LOW;
gf_group->arf_src_offset[frame_index] = ext_arf_interval;
gf_group->arf_update_idx[frame_index] = which_arf;
gf_group->arf_ref_idx[frame_index] = 0;
++frame_index;
}
}
}
// NOTE: We need to configure the frame at the end of the sequence + 1 that
// will be the start frame for the next group. Otherwise prior to the
// call to av1_get_second_pass_params() the data will be undefined.
gf_group->arf_update_idx[frame_index] = 0;
gf_group->arf_ref_idx[frame_index] = 0;
if (rc->source_alt_ref_pending) {
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
gf_group->rf_level[frame_index] = INTER_NORMAL;
cpi->arf_pos_in_gf[0] = 1;
if (cpi->num_extra_arfs) {
// Overwrite the update_type for extra-ARF's corresponding internal
// OVERLAY's: Change from LF_UPDATE to INTNL_OVERLAY_UPDATE.
for (i = cpi->num_extra_arfs; i > 0; --i) {
cpi->arf_pos_in_gf[i] =
(i == cpi->num_extra_arfs ? 2 : cpi->arf_pos_for_ovrly[i + 1] + 1);
gf_group->update_type[cpi->arf_pos_for_ovrly[i]] = INTNL_OVERLAY_UPDATE;
gf_group->rf_level[cpi->arf_pos_for_ovrly[i]] = INTER_NORMAL;
}
}
} else {
gf_group->update_type[frame_index] = GF_UPDATE;
gf_group->rf_level[frame_index] = GF_ARF_STD;
}
gf_group->bidir_pred_enabled[frame_index] = 0;
gf_group->brf_src_offset[frame_index] = 0;
}
void av1_gop_setup_structure(AV1_COMP *cpi,
const EncodeFrameParams *const frame_params) {
RATE_CONTROL *const rc = &cpi->rc;
const int max_pyr_height = cpi->oxcf.gf_max_pyr_height;
const int valid_pyramid_gf_length =
max_pyr_height >= MIN_PYRAMID_LVL && max_pyr_height <= MAX_PYRAMID_LVL &&
rc->baseline_gf_interval >= MIN_GF_INTERVAL &&
rc->baseline_gf_interval <= get_max_gf_length(max_pyr_height);
// Decide whether to use a flat or pyramid structure for this GF
if (valid_pyramid_gf_length && rc->source_alt_ref_pending &&
cpi->extra_arf_allowed > 0) {
define_pyramid_gf_group_structure(cpi, frame_params);
cpi->new_bwdref_update_rule = 1;
} else {
define_flat_gf_group_structure(cpi, frame_params);
cpi->new_bwdref_update_rule = 0;
}
}