summaryrefslogtreecommitdiffstats
path: root/third_party/aom/av1/encoder/encoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/aom/av1/encoder/encoder.c')
-rw-r--r--third_party/aom/av1/encoder/encoder.c604
1 files changed, 412 insertions, 192 deletions
diff --git a/third_party/aom/av1/encoder/encoder.c b/third_party/aom/av1/encoder/encoder.c
index 196e18d8a..13ea32e38 100644
--- a/third_party/aom/av1/encoder/encoder.c
+++ b/third_party/aom/av1/encoder/encoder.c
@@ -56,6 +56,11 @@
#include "av1/encoder/grain_test_vectors.h"
#include "aom_dsp/aom_dsp_common.h"
#include "aom_dsp/aom_filter.h"
+#if CONFIG_DENOISE
+#include "aom_dsp/grain_table.h"
+#include "aom_dsp/noise_util.h"
+#include "aom_dsp/noise_model.h"
+#endif
#include "aom_ports/aom_timer.h"
#include "aom_ports/mem.h"
#include "aom_ports/system_state.h"
@@ -290,7 +295,8 @@ static void setup_frame(AV1_COMP *cpi) {
cm->fb_of_context_type[i] = -1;
}
cm->fb_of_context_type[REGULAR_FRAME] =
- get_ref_frame_map_idx(cpi, GOLDEN_FRAME);
+ cm->show_frame ? get_ref_frame_map_idx(cpi, GOLDEN_FRAME)
+ : get_ref_frame_map_idx(cpi, ALTREF_FRAME);
cm->frame_context_idx = REGULAR_FRAME;
} else {
const GF_GROUP *gf_group = &cpi->twopass.gf_group;
@@ -315,7 +321,7 @@ static void setup_frame(AV1_COMP *cpi) {
}
}
- if (cm->frame_type == KEY_FRAME) {
+ if (cm->frame_type == KEY_FRAME && cm->show_frame) {
cpi->refresh_golden_frame = 1;
cpi->refresh_alt_ref_frame = 1;
av1_zero(cpi->interp_filter_selected);
@@ -344,19 +350,20 @@ static void setup_frame(AV1_COMP *cpi) {
static void enc_setup_mi(AV1_COMMON *cm) {
int i;
+ int mi_rows_sb_aligned = calc_mi_size(cm->mi_rows);
cm->mi = cm->mip;
- memset(cm->mip, 0, cm->mi_stride * cm->mi_rows * sizeof(*cm->mip));
+ memset(cm->mip, 0, cm->mi_stride * mi_rows_sb_aligned * sizeof(*cm->mip));
cm->prev_mi = cm->prev_mip;
// Clear top border row
memset(cm->prev_mip, 0, sizeof(*cm->prev_mip) * cm->mi_stride);
// Clear left border column
- for (i = 0; i < cm->mi_rows; ++i)
+ for (i = 0; i < mi_rows_sb_aligned; ++i)
memset(&cm->prev_mip[i * cm->mi_stride], 0, sizeof(*cm->prev_mip));
cm->mi_grid_visible = cm->mi_grid_base;
cm->prev_mi_grid_visible = cm->prev_mi_grid_base;
memset(cm->mi_grid_base, 0,
- cm->mi_stride * cm->mi_rows * sizeof(*cm->mi_grid_base));
+ cm->mi_stride * mi_rows_sb_aligned * sizeof(*cm->mi_grid_base));
}
static int enc_alloc_mi(AV1_COMMON *cm, int mi_size) {
@@ -441,32 +448,32 @@ static void update_film_grain_parameters(struct AV1_COMP *cpi,
AV1_COMMON *const cm = &cpi->common;
cpi->oxcf = *oxcf;
- if (cm->film_grain_table) {
- aom_film_grain_table_free(cm->film_grain_table);
- aom_free(cm->film_grain_table);
+ if (cpi->film_grain_table) {
+ aom_film_grain_table_free(cpi->film_grain_table);
+ aom_free(cpi->film_grain_table);
+ cpi->film_grain_table = NULL;
}
- cm->film_grain_table = 0;
if (oxcf->film_grain_test_vector) {
- cm->film_grain_params_present = 1;
+ cm->seq_params.film_grain_params_present = 1;
if (cm->frame_type == KEY_FRAME) {
memcpy(&cm->film_grain_params,
film_grain_test_vectors + oxcf->film_grain_test_vector - 1,
sizeof(cm->film_grain_params));
- cm->film_grain_params.bit_depth = cm->bit_depth;
- if (cm->color_range == AOM_CR_FULL_RANGE) {
+ cm->film_grain_params.bit_depth = cm->seq_params.bit_depth;
+ if (cm->seq_params.color_range == AOM_CR_FULL_RANGE) {
cm->film_grain_params.clip_to_restricted_range = 0;
}
}
} else if (oxcf->film_grain_table_filename) {
- cm->film_grain_table = aom_malloc(sizeof(*cm->film_grain_table));
- memset(cm->film_grain_table, 0, sizeof(aom_film_grain_table_t));
+ cpi->film_grain_table = aom_malloc(sizeof(*cpi->film_grain_table));
+ memset(cpi->film_grain_table, 0, sizeof(aom_film_grain_table_t));
- aom_film_grain_table_read(cm->film_grain_table,
+ aom_film_grain_table_read(cpi->film_grain_table,
oxcf->film_grain_table_filename, &cm->error);
} else {
- cm->film_grain_params_present = 0;
+ cm->seq_params.film_grain_params_present = 0;
memset(&cm->film_grain_params, 0, sizeof(cm->film_grain_params));
}
}
@@ -523,6 +530,17 @@ static void dealloc_compressor_data(AV1_COMP *cpi) {
av1_free_pc_tree(&cpi->td, num_planes);
aom_free(cpi->td.mb.palette_buffer);
+
+#if CONFIG_DENOISE
+ if (cpi->denoise_and_model) {
+ aom_denoise_and_model_free(cpi->denoise_and_model);
+ cpi->denoise_and_model = NULL;
+ }
+#endif
+ if (cpi->film_grain_table) {
+ aom_film_grain_table_free(cpi->film_grain_table);
+ cpi->film_grain_table = NULL;
+ }
}
static void save_coding_context(AV1_COMP *cpi) {
@@ -596,8 +614,8 @@ static void configure_static_seg_features(AV1_COMP *cpi) {
seg->update_map = 1;
seg->update_data = 1;
- qi_delta =
- av1_compute_qdelta(rc, rc->avg_q, rc->avg_q * 0.875, cm->bit_depth);
+ qi_delta = av1_compute_qdelta(rc, rc->avg_q, rc->avg_q * 0.875,
+ cm->seq_params.bit_depth);
av1_set_segdata(seg, 1, SEG_LVL_ALT_Q, qi_delta - 2);
av1_set_segdata(seg, 1, SEG_LVL_ALT_LF_Y_H, -2);
av1_set_segdata(seg, 1, SEG_LVL_ALT_LF_Y_V, -2);
@@ -621,8 +639,8 @@ static void configure_static_seg_features(AV1_COMP *cpi) {
seg->update_map = 0;
seg->update_data = 1;
- qi_delta =
- av1_compute_qdelta(rc, rc->avg_q, rc->avg_q * 1.125, cm->bit_depth);
+ qi_delta = av1_compute_qdelta(rc, rc->avg_q, rc->avg_q * 1.125,
+ cm->seq_params.bit_depth);
av1_set_segdata(seg, 1, SEG_LVL_ALT_Q, qi_delta + 2);
av1_enable_segfeature(seg, 1, SEG_LVL_ALT_Q);
@@ -705,53 +723,58 @@ static void update_reference_segmentation_map(AV1_COMP *cpi) {
static void alloc_raw_frame_buffers(AV1_COMP *cpi) {
AV1_COMMON *cm = &cpi->common;
+ const SequenceHeader *const seq_params = &cm->seq_params;
const AV1EncoderConfig *oxcf = &cpi->oxcf;
if (!cpi->lookahead)
- cpi->lookahead = av1_lookahead_init(
- oxcf->width, oxcf->height, cm->subsampling_x, cm->subsampling_y,
- cm->use_highbitdepth, oxcf->lag_in_frames);
+ cpi->lookahead =
+ av1_lookahead_init(oxcf->width, oxcf->height, seq_params->subsampling_x,
+ seq_params->subsampling_y,
+ seq_params->use_highbitdepth, oxcf->lag_in_frames);
if (!cpi->lookahead)
aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to allocate lag buffers");
// TODO(agrange) Check if ARF is enabled and skip allocation if not.
- if (aom_realloc_frame_buffer(&cpi->alt_ref_buffer, oxcf->width, oxcf->height,
- cm->subsampling_x, cm->subsampling_y,
- cm->use_highbitdepth, AOM_BORDER_IN_PIXELS,
- cm->byte_alignment, NULL, NULL, NULL))
+ if (aom_realloc_frame_buffer(
+ &cpi->alt_ref_buffer, oxcf->width, oxcf->height,
+ seq_params->subsampling_x, seq_params->subsampling_y,
+ seq_params->use_highbitdepth, AOM_BORDER_IN_PIXELS,
+ cm->byte_alignment, NULL, NULL, NULL))
aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to allocate altref buffer");
}
static void alloc_util_frame_buffers(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
- if (aom_realloc_frame_buffer(&cpi->last_frame_uf, cm->width, cm->height,
- cm->subsampling_x, cm->subsampling_y,
- cm->use_highbitdepth, AOM_BORDER_IN_PIXELS,
- cm->byte_alignment, NULL, NULL, NULL))
+ const SequenceHeader *const seq_params = &cm->seq_params;
+ if (aom_realloc_frame_buffer(
+ &cpi->last_frame_uf, cm->width, cm->height, seq_params->subsampling_x,
+ seq_params->subsampling_y, seq_params->use_highbitdepth,
+ AOM_BORDER_IN_PIXELS, cm->byte_alignment, NULL, NULL, NULL))
aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to allocate last frame buffer");
if (aom_realloc_frame_buffer(
&cpi->trial_frame_rst, cm->superres_upscaled_width,
- cm->superres_upscaled_height, cm->subsampling_x, cm->subsampling_y,
- cm->use_highbitdepth, AOM_BORDER_IN_PIXELS, cm->byte_alignment, NULL,
- NULL, NULL))
+ cm->superres_upscaled_height, seq_params->subsampling_x,
+ seq_params->subsampling_y, seq_params->use_highbitdepth,
+ AOM_BORDER_IN_PIXELS, cm->byte_alignment, NULL, NULL, NULL))
aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to allocate trial restored frame buffer");
- if (aom_realloc_frame_buffer(&cpi->scaled_source, cm->width, cm->height,
- cm->subsampling_x, cm->subsampling_y,
- cm->use_highbitdepth, AOM_BORDER_IN_PIXELS,
- cm->byte_alignment, NULL, NULL, NULL))
+ if (aom_realloc_frame_buffer(
+ &cpi->scaled_source, cm->width, cm->height, seq_params->subsampling_x,
+ seq_params->subsampling_y, seq_params->use_highbitdepth,
+ AOM_BORDER_IN_PIXELS, cm->byte_alignment, NULL, NULL, NULL))
aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to allocate scaled source buffer");
- if (aom_realloc_frame_buffer(&cpi->scaled_last_source, cm->width, cm->height,
- cm->subsampling_x, cm->subsampling_y,
- cm->use_highbitdepth, AOM_BORDER_IN_PIXELS,
- cm->byte_alignment, NULL, NULL, NULL))
+ if (aom_realloc_frame_buffer(
+ &cpi->scaled_last_source, cm->width, cm->height,
+ seq_params->subsampling_x, seq_params->subsampling_y,
+ seq_params->use_highbitdepth, AOM_BORDER_IN_PIXELS,
+ cm->byte_alignment, NULL, NULL, NULL))
aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to allocate scaled last source buffer");
}
@@ -846,8 +869,6 @@ static void init_buffer_indices(AV1_COMP *cpi) {
int fb_idx;
for (fb_idx = 0; fb_idx < REF_FRAMES; ++fb_idx)
cpi->ref_fb_idx[fb_idx] = fb_idx;
- for (fb_idx = 0; fb_idx < MAX_EXT_ARFS + 1; ++fb_idx)
- cpi->arf_map[fb_idx] = LAST_REF_FRAMES + 2 + fb_idx;
cpi->rate_index = 0;
cpi->rate_size = 0;
cpi->cur_poc = -1;
@@ -941,7 +962,8 @@ static void set_bitstream_level_tier(SequenceHeader *seq, AV1_COMMON *cm,
// Set the maximum parameters for bitrate and buffer size for this profile,
// level, and tier
cm->op_params[i].bitrate = max_level_bitrate(
- cm->profile, major_minor_to_seq_level_idx(seq->level[i]), seq->tier[i]);
+ cm->seq_params.profile, major_minor_to_seq_level_idx(seq->level[i]),
+ seq->tier[i]);
// Level with seq_level_idx = 31 returns a high "dummy" bitrate to pass the
// check
if (cm->op_params[i].bitrate == 0)
@@ -1006,15 +1028,15 @@ static void init_config(struct AV1_COMP *cpi, AV1EncoderConfig *oxcf) {
cpi->oxcf = *oxcf;
cpi->framerate = oxcf->init_framerate;
- cm->profile = oxcf->profile;
- cm->bit_depth = oxcf->bit_depth;
- cm->use_highbitdepth = oxcf->use_highbitdepth;
- cm->color_primaries = oxcf->color_primaries;
- cm->transfer_characteristics = oxcf->transfer_characteristics;
- cm->matrix_coefficients = oxcf->matrix_coefficients;
+ cm->seq_params.profile = oxcf->profile;
+ cm->seq_params.bit_depth = oxcf->bit_depth;
+ cm->seq_params.use_highbitdepth = oxcf->use_highbitdepth;
+ cm->seq_params.color_primaries = oxcf->color_primaries;
+ cm->seq_params.transfer_characteristics = oxcf->transfer_characteristics;
+ cm->seq_params.matrix_coefficients = oxcf->matrix_coefficients;
cm->seq_params.monochrome = oxcf->monochrome;
- cm->chroma_sample_position = oxcf->chroma_sample_position;
- cm->color_range = oxcf->color_range;
+ cm->seq_params.chroma_sample_position = oxcf->chroma_sample_position;
+ cm->seq_params.color_range = oxcf->color_range;
cm->timing_info_present = oxcf->timing_info_present;
cm->timing_info.num_units_in_display_tick =
oxcf->timing_info.num_units_in_display_tick;
@@ -1032,7 +1054,7 @@ static void init_config(struct AV1_COMP *cpi, AV1EncoderConfig *oxcf) {
// set the decoder model parameters in schedule mode
cm->buffer_model.num_units_in_decoding_tick =
oxcf->buffer_model.num_units_in_decoding_tick;
- cm->buffer_removal_delay_present = 1;
+ cm->buffer_removal_time_present = 1;
set_aom_dec_model_info(&cm->buffer_model);
set_dec_model_op_parameters(&cm->op_params[0]);
} else if (cm->timing_info_present &&
@@ -1365,8 +1387,8 @@ MAKE_OBFP_SAD_WRAPPER(aom_highbd_obmc_sad64x16)
static void highbd_set_var_fns(AV1_COMP *const cpi) {
AV1_COMMON *const cm = &cpi->common;
- if (cm->use_highbitdepth) {
- switch (cm->bit_depth) {
+ if (cm->seq_params.use_highbitdepth) {
+ switch (cm->seq_params.bit_depth) {
case AOM_BITS_8:
HIGHBD_BFP(BLOCK_64X16, aom_highbd_sad64x16_bits8,
aom_highbd_sad64x16_avg_bits8, aom_highbd_8_variance64x16,
@@ -2226,7 +2248,7 @@ static void highbd_set_var_fns(AV1_COMP *const cpi) {
default:
assert(0 &&
- "cm->bit_depth should be AOM_BITS_8, "
+ "cm->seq_params.bit_depth should be AOM_BITS_8, "
"AOM_BITS_10 or AOM_BITS_12");
}
}
@@ -2253,20 +2275,22 @@ static void realloc_segmentation_maps(AV1_COMP *cpi) {
void av1_change_config(struct AV1_COMP *cpi, const AV1EncoderConfig *oxcf) {
AV1_COMMON *const cm = &cpi->common;
+ SequenceHeader *const seq_params = &cm->seq_params;
const int num_planes = av1_num_planes(cm);
RATE_CONTROL *const rc = &cpi->rc;
MACROBLOCK *const x = &cpi->td.mb;
- if (cm->profile != oxcf->profile) cm->profile = oxcf->profile;
- cm->bit_depth = oxcf->bit_depth;
- cm->color_primaries = oxcf->color_primaries;
- cm->transfer_characteristics = oxcf->transfer_characteristics;
- cm->matrix_coefficients = oxcf->matrix_coefficients;
- cm->seq_params.monochrome = oxcf->monochrome;
- cm->chroma_sample_position = oxcf->chroma_sample_position;
- cm->color_range = oxcf->color_range;
+ if (seq_params->profile != oxcf->profile) seq_params->profile = oxcf->profile;
+ seq_params->bit_depth = oxcf->bit_depth;
+ seq_params->color_primaries = oxcf->color_primaries;
+ seq_params->transfer_characteristics = oxcf->transfer_characteristics;
+ seq_params->matrix_coefficients = oxcf->matrix_coefficients;
+ seq_params->monochrome = oxcf->monochrome;
+ seq_params->chroma_sample_position = oxcf->chroma_sample_position;
+ seq_params->color_range = oxcf->color_range;
- assert(IMPLIES(cm->profile <= PROFILE_1, cm->bit_depth <= AOM_BITS_10));
+ assert(IMPLIES(seq_params->profile <= PROFILE_1,
+ seq_params->bit_depth <= AOM_BITS_10));
cm->timing_info_present = oxcf->timing_info_present;
cm->timing_info.num_units_in_display_tick =
@@ -2277,20 +2301,20 @@ void av1_change_config(struct AV1_COMP *cpi, const AV1EncoderConfig *oxcf) {
cm->timing_info.num_ticks_per_picture =
oxcf->timing_info.num_ticks_per_picture;
- cm->seq_params.display_model_info_present_flag =
+ seq_params->display_model_info_present_flag =
oxcf->display_model_info_present_flag;
- cm->seq_params.decoder_model_info_present_flag =
+ seq_params->decoder_model_info_present_flag =
oxcf->decoder_model_info_present_flag;
if (oxcf->decoder_model_info_present_flag) {
// set the decoder model parameters in schedule mode
cm->buffer_model.num_units_in_decoding_tick =
oxcf->buffer_model.num_units_in_decoding_tick;
- cm->buffer_removal_delay_present = 1;
+ cm->buffer_removal_time_present = 1;
set_aom_dec_model_info(&cm->buffer_model);
set_dec_model_op_parameters(&cm->op_params[0]);
} else if (cm->timing_info_present &&
cm->timing_info.equal_picture_interval &&
- !cm->seq_params.decoder_model_info_present_flag) {
+ !seq_params->decoder_model_info_present_flag) {
// set the decoder model parameters in resource availability mode
set_resource_availability_parameters(&cm->op_params[0]);
} else {
@@ -2302,7 +2326,7 @@ void av1_change_config(struct AV1_COMP *cpi, const AV1EncoderConfig *oxcf) {
cpi->oxcf = *oxcf;
cpi->common.options = oxcf->cfg;
- x->e_mbd.bd = (int)cm->bit_depth;
+ x->e_mbd.bd = (int)seq_params->bit_depth;
x->e_mbd.global_motion = cm->global_motion;
if ((oxcf->pass == 0) && (oxcf->rc_mode == AOM_Q)) {
@@ -2360,15 +2384,15 @@ void av1_change_config(struct AV1_COMP *cpi, const AV1EncoderConfig *oxcf) {
cm->width = cpi->oxcf.width;
cm->height = cpi->oxcf.height;
- int sb_size = cm->seq_params.sb_size;
+ int sb_size = seq_params->sb_size;
// Superblock size should not be updated after the first key frame.
if (!cpi->seq_params_locked) {
set_sb_size(&cm->seq_params, select_sb_size(cpi));
}
- if (cpi->initial_width || sb_size != cm->seq_params.sb_size) {
+ if (cpi->initial_width || sb_size != seq_params->sb_size) {
if (cm->width > cpi->initial_width || cm->height > cpi->initial_height ||
- cm->seq_params.sb_size != sb_size) {
+ seq_params->sb_size != sb_size) {
av1_free_context_buffers(cm);
av1_free_pc_tree(&cpi->td, num_planes);
alloc_compressor_data(cpi);
@@ -2395,7 +2419,7 @@ void av1_change_config(struct AV1_COMP *cpi, const AV1EncoderConfig *oxcf) {
// Init sequence level coding tools
// This should not be called after the first key frame.
if (!cpi->seq_params_locked) {
- cm->seq_params.operating_points_cnt_minus_1 =
+ seq_params->operating_points_cnt_minus_1 =
cm->number_spatial_layers > 1 ? cm->number_spatial_layers - 1 : 0;
init_seq_coding_tools(&cm->seq_params, cm, oxcf);
}
@@ -2411,6 +2435,9 @@ AV1_COMP *av1_create_compressor(AV1EncoderConfig *oxcf,
av1_zero(*cpi);
+ // The jmp_buf is valid only for the duration of the function that calls
+ // setjmp(). Therefore, this function must reset the 'setjmp' field to 0
+ // before it returns.
if (setjmp(cm->error.jmp)) {
cm->error.setjmp = 0;
av1_remove_compressor(cpi);
@@ -3082,28 +3109,52 @@ static void check_show_existing_frame(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
const FRAME_UPDATE_TYPE next_frame_update_type =
gf_group->update_type[gf_group->index];
+#if USE_SYMM_MULTI_LAYER
+ const int which_arf = (cpi->new_bwdref_update_rule == 1)
+ ? gf_group->arf_update_idx[gf_group->index] > 0
+ : gf_group->arf_update_idx[gf_group->index];
+#else
const int which_arf = gf_group->arf_update_idx[gf_group->index];
+#endif
if (cm->show_existing_frame == 1) {
cm->show_existing_frame = 0;
} else if (cpi->rc.is_last_bipred_frame) {
- // NOTE: If the current frame is a last bi-predictive frame, it is
- // needed next to show the BWDREF_FRAME, which is pointed by
- // the last_fb_idxes[0] after reference frame buffer update
- cpi->rc.is_last_bipred_frame = 0;
- cm->show_existing_frame = 1;
- cpi->existing_fb_idx_to_show = cpi->ref_fb_idx[0];
+#if USE_SYMM_MULTI_LAYER
+ // NOTE: When new structure is used, every bwdref will have one overlay
+ // frame. Therefore, there is no need to find out which frame to
+ // show in advance.
+ if (cpi->new_bwdref_update_rule == 0) {
+#endif
+ // NOTE: If the current frame is a last bi-predictive frame, it is
+ // needed next to show the BWDREF_FRAME, which is pointed by
+ // the last_fb_idxes[0] after reference frame buffer update
+ cpi->rc.is_last_bipred_frame = 0;
+ cm->show_existing_frame = 1;
+ cpi->existing_fb_idx_to_show = cpi->ref_fb_idx[0];
+#if USE_SYMM_MULTI_LAYER
+ }
+#endif
} else if (cpi->is_arf_filter_off[which_arf] &&
(next_frame_update_type == OVERLAY_UPDATE ||
next_frame_update_type == INTNL_OVERLAY_UPDATE)) {
+#if USE_SYMM_MULTI_LAYER
+ const int bwdref_to_show =
+ (cpi->new_bwdref_update_rule == 1) ? BWDREF_FRAME : ALTREF2_FRAME;
+#else
+ const int bwdref_to_show = ALTREF2_FRAME;
+#endif
// Other parameters related to OVERLAY_UPDATE will be taken care of
// in av1_rc_get_second_pass_params(cpi)
cm->show_existing_frame = 1;
cpi->rc.is_src_frame_alt_ref = 1;
cpi->existing_fb_idx_to_show = (next_frame_update_type == OVERLAY_UPDATE)
? cpi->ref_fb_idx[ALTREF_FRAME - 1]
- : cpi->ref_fb_idx[ALTREF2_FRAME - 1];
- cpi->is_arf_filter_off[which_arf] = 0;
+ : cpi->ref_fb_idx[bwdref_to_show - 1];
+#if USE_SYMM_MULTI_LAYER
+ if (cpi->new_bwdref_update_rule == 0)
+#endif
+ cpi->is_arf_filter_off[which_arf] = 0;
}
cpi->rc.is_src_frame_ext_arf = 0;
}
@@ -3288,6 +3339,48 @@ static INLINE void shift_last_ref_frames(AV1_COMP *cpi) {
}
}
+#if USE_SYMM_MULTI_LAYER
+// This function is used to shift the virtual indices of bwd reference
+// frames as follows:
+// BWD_REF -> ALT2_REF -> EXT_REF
+// to clear a space to store the closest bwdref
+static INLINE void rshift_bwd_ref_frames(AV1_COMP *cpi) {
+ // TODO(isbs): shift the scaled indices as well
+ static const int ordered_bwd[3] = { BWDREF_FRAME - 1, ALTREF2_FRAME - 1,
+ EXTREF_FRAME - 1 };
+
+ for (int i = 2; i > 0; --i) {
+ cpi->ref_fb_idx[ordered_bwd[i]] = cpi->ref_fb_idx[ordered_bwd[i - 1]];
+
+ // [0] is allocated to the current coded frame, i.e. bwdref
+ memcpy(
+ cpi->interp_filter_selected[ordered_bwd[i] + LAST_FRAME],
+ cpi->interp_filter_selected[ordered_bwd[i - 1] + LAST_FRAME],
+ sizeof(cpi->interp_filter_selected[ordered_bwd[i - 1] + LAST_FRAME]));
+ }
+}
+
+// This function is used to shift the virtual indices of bwd reference
+// frames as follows:
+// BWD_REF <- ALT2_REF <- EXT_REF
+// to update the bwd reference frame for coding the next frame.
+static INLINE void lshift_bwd_ref_frames(AV1_COMP *cpi) {
+ // TODO(isbs): shift the scaled indices as well
+ static const int ordered_bwd[3] = { BWDREF_FRAME - 1, ALTREF2_FRAME - 1,
+ EXTREF_FRAME - 1 };
+
+ for (int i = 0; i < 2; ++i) {
+ cpi->ref_fb_idx[ordered_bwd[i]] = cpi->ref_fb_idx[ordered_bwd[i + 1]];
+
+ // [0] is allocated to the current coded frame, i.e. bwdref
+ memcpy(
+ cpi->interp_filter_selected[ordered_bwd[i] + LAST_FRAME],
+ cpi->interp_filter_selected[ordered_bwd[i + 1] + LAST_FRAME],
+ sizeof(cpi->interp_filter_selected[ordered_bwd[i + 1] + LAST_FRAME]));
+ }
+}
+#endif // USE_SYMM_MULTI_LAYER
+
#if USE_GF16_MULTI_LAYER
static void update_reference_frames_gf16(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
@@ -3343,7 +3436,9 @@ static void update_reference_frames(AV1_COMP *cpi) {
// At this point the new frame has been encoded.
// If any buffer copy / swapping is signaled it should be done here.
- if (cm->frame_type == KEY_FRAME || frame_is_sframe(cm)) {
+ // Only update all of the reference buffers if a KEY_FRAME is also a
+ // show_frame. This ensures a fwd keyframe does not update all of the buffers
+ if ((cm->frame_type == KEY_FRAME && cm->show_frame) || frame_is_sframe(cm)) {
for (int ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame) {
ref_cnt_fb(pool->frame_bufs,
&cm->ref_frame_map[cpi->ref_fb_idx[ref_frame]],
@@ -3370,37 +3465,49 @@ static void update_reference_frames(AV1_COMP *cpi) {
cpi->ref_fb_idx[ALTREF_FRAME - 1] = cpi->ref_fb_idx[GOLDEN_FRAME - 1];
cpi->ref_fb_idx[GOLDEN_FRAME - 1] = tmp;
- // We need to modify the mapping accordingly
- cpi->arf_map[0] = cpi->ref_fb_idx[ALTREF_FRAME - 1];
// TODO(zoeliu): Do we need to copy cpi->interp_filter_selected[0] over to
// cpi->interp_filter_selected[GOLDEN_FRAME]?
} else if (cpi->rc.is_src_frame_ext_arf && cm->show_existing_frame) {
+#if CONFIG_DEBUG
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ assert(gf_group->update_type[gf_group->index] == INTNL_OVERLAY_UPDATE);
+#endif
+#if USE_SYMM_MULTI_LAYER
+ const int bwdref_to_show =
+ (cpi->new_bwdref_update_rule == 1) ? BWDREF_FRAME : ALTREF2_FRAME;
+#else
+ const int bwdref_to_show = ALTREF2_FRAME;
+#endif
// Deal with the special case for showing existing internal ALTREF_FRAME
// Refresh the LAST_FRAME with the ALTREF_FRAME and retire the LAST3_FRAME
// by updating the virtual indices.
- const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
- const int which_arf = gf_group->arf_ref_idx[gf_group->index];
- assert(gf_group->update_type[gf_group->index] == INTNL_OVERLAY_UPDATE);
-
const int tmp = cpi->ref_fb_idx[LAST_REF_FRAMES - 1];
shift_last_ref_frames(cpi);
- cpi->ref_fb_idx[LAST_FRAME - 1] = cpi->ref_fb_idx[ALTREF2_FRAME - 1];
- cpi->ref_fb_idx[ALTREF2_FRAME - 1] = tmp;
- // We need to modify the mapping accordingly
- cpi->arf_map[which_arf] = cpi->ref_fb_idx[ALTREF2_FRAME - 1];
+ cpi->ref_fb_idx[LAST_FRAME - 1] = cpi->ref_fb_idx[bwdref_to_show - 1];
memcpy(cpi->interp_filter_selected[LAST_FRAME],
- cpi->interp_filter_selected[ALTREF2_FRAME],
- sizeof(cpi->interp_filter_selected[ALTREF2_FRAME]));
+ cpi->interp_filter_selected[bwdref_to_show],
+ sizeof(cpi->interp_filter_selected[bwdref_to_show]));
+#if USE_SYMM_MULTI_LAYER
+ if (cpi->new_bwdref_update_rule == 1) {
+ lshift_bwd_ref_frames(cpi);
+ // pass outdated forward reference frame (previous LAST3) to the
+ // spared space
+ cpi->ref_fb_idx[EXTREF_FRAME - 1] = tmp;
+ } else {
+#endif
+ cpi->ref_fb_idx[bwdref_to_show - 1] = tmp;
+#if USE_SYMM_MULTI_LAYER
+ }
+#endif
} else { /* For non key/golden frames */
// === ALTREF_FRAME ===
if (cpi->refresh_alt_ref_frame) {
int arf_idx = cpi->ref_fb_idx[ALTREF_FRAME - 1];
- int which_arf = 0;
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[arf_idx], cm->new_fb_idx);
- memcpy(cpi->interp_filter_selected[ALTREF_FRAME + which_arf],
+ memcpy(cpi->interp_filter_selected[ALTREF_FRAME],
cpi->interp_filter_selected[0],
sizeof(cpi->interp_filter_selected[0]));
}
@@ -3418,10 +3525,25 @@ static void update_reference_frames(AV1_COMP *cpi) {
// === BWDREF_FRAME ===
if (cpi->refresh_bwd_ref_frame) {
- ref_cnt_fb(pool->frame_bufs,
- &cm->ref_frame_map[cpi->ref_fb_idx[BWDREF_FRAME - 1]],
- cm->new_fb_idx);
-
+#if USE_SYMM_MULTI_LAYER
+ if (cpi->new_bwdref_update_rule) {
+ // We shift the backward reference frame as follows:
+ // BWDREF -> ALTREF2 -> EXTREF
+ // and assign the newly coded frame to BWDREF so that it always
+ // keeps the nearest future frame
+ int tmp = cpi->ref_fb_idx[EXTREF_FRAME - 1];
+ ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[tmp], cm->new_fb_idx);
+
+ rshift_bwd_ref_frames(cpi);
+ cpi->ref_fb_idx[BWDREF_FRAME - 1] = tmp;
+ } else {
+#endif // USE_SYMM_MULTI_LAYER
+ ref_cnt_fb(pool->frame_bufs,
+ &cm->ref_frame_map[cpi->ref_fb_idx[BWDREF_FRAME - 1]],
+ cm->new_fb_idx);
+#if USE_SYMM_MULTI_LAYER
+ }
+#endif
memcpy(cpi->interp_filter_selected[BWDREF_FRAME],
cpi->interp_filter_selected[0],
sizeof(cpi->interp_filter_selected[0]));
@@ -3486,7 +3608,14 @@ static void update_reference_frames(AV1_COMP *cpi) {
cpi->interp_filter_selected[0],
sizeof(cpi->interp_filter_selected[0]));
+ // If the new structure is used, we will always have overlay frames coupled
+ // with bwdref frames. Therefore, we won't have to perform this update
+ // in advance (we do this update when the overlay frame shows up).
+#if USE_SYMM_MULTI_LAYER
+ if (cpi->new_bwdref_update_rule == 0 && cpi->rc.is_last_bipred_frame) {
+#else
if (cpi->rc.is_last_bipred_frame) {
+#endif
// Refresh the LAST_FRAME with the BWDREF_FRAME and retire the
// LAST3_FRAME by updating the virtual indices.
//
@@ -3555,13 +3684,14 @@ static void scale_references(AV1_COMP *cpi) {
if (force_scaling || new_fb_ptr->buf.y_crop_width != cm->width ||
new_fb_ptr->buf.y_crop_height != cm->height) {
if (aom_realloc_frame_buffer(
- &new_fb_ptr->buf, cm->width, cm->height, cm->subsampling_x,
- cm->subsampling_y, cm->use_highbitdepth, AOM_BORDER_IN_PIXELS,
+ &new_fb_ptr->buf, cm->width, cm->height,
+ cm->seq_params.subsampling_x, cm->seq_params.subsampling_y,
+ cm->seq_params.use_highbitdepth, AOM_BORDER_IN_PIXELS,
cm->byte_alignment, NULL, NULL, NULL))
aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to allocate frame buffer");
- av1_resize_and_extend_frame(ref, &new_fb_ptr->buf, (int)cm->bit_depth,
- num_planes);
+ av1_resize_and_extend_frame(
+ ref, &new_fb_ptr->buf, (int)cm->seq_params.bit_depth, num_planes);
cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
alloc_frame_mvs(cm, new_fb);
}
@@ -3706,13 +3836,14 @@ static void init_ref_frame_bufs(AV1_COMMON *cm) {
static void check_initial_width(AV1_COMP *cpi, int use_highbitdepth,
int subsampling_x, int subsampling_y) {
AV1_COMMON *const cm = &cpi->common;
+ SequenceHeader *const seq_params = &cm->seq_params;
- if (!cpi->initial_width || cm->use_highbitdepth != use_highbitdepth ||
- cm->subsampling_x != subsampling_x ||
- cm->subsampling_y != subsampling_y) {
- cm->subsampling_x = subsampling_x;
- cm->subsampling_y = subsampling_y;
- cm->use_highbitdepth = use_highbitdepth;
+ if (!cpi->initial_width || seq_params->use_highbitdepth != use_highbitdepth ||
+ seq_params->subsampling_x != subsampling_x ||
+ seq_params->subsampling_y != subsampling_y) {
+ seq_params->subsampling_x = subsampling_x;
+ seq_params->subsampling_y = subsampling_y;
+ seq_params->use_highbitdepth = use_highbitdepth;
alloc_raw_frame_buffers(cpi);
init_ref_frame_bufs(cm);
@@ -3730,8 +3861,9 @@ static void check_initial_width(AV1_COMP *cpi, int use_highbitdepth,
static int set_size_literal(AV1_COMP *cpi, int width, int height) {
AV1_COMMON *cm = &cpi->common;
const int num_planes = av1_num_planes(cm);
- check_initial_width(cpi, cm->use_highbitdepth, cm->subsampling_x,
- cm->subsampling_y);
+ check_initial_width(cpi, cm->seq_params.use_highbitdepth,
+ cm->seq_params.subsampling_x,
+ cm->seq_params.subsampling_y);
if (width <= 0 || height <= 0) return 1;
@@ -3753,6 +3885,7 @@ static int set_size_literal(AV1_COMP *cpi, int width, int height) {
static void set_frame_size(AV1_COMP *cpi, int width, int height) {
AV1_COMMON *const cm = &cpi->common;
+ const SequenceHeader *const seq_params = &cm->seq_params;
const int num_planes = av1_num_planes(cm);
MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
int ref_frame;
@@ -3782,17 +3915,19 @@ static void set_frame_size(AV1_COMP *cpi, int width, int height) {
}
// Reset the frame pointers to the current frame size.
- if (aom_realloc_frame_buffer(get_frame_new_buffer(cm), cm->width, cm->height,
- cm->subsampling_x, cm->subsampling_y,
- cm->use_highbitdepth, AOM_BORDER_IN_PIXELS,
- cm->byte_alignment, NULL, NULL, NULL))
+ if (aom_realloc_frame_buffer(
+ get_frame_new_buffer(cm), cm->width, cm->height,
+ seq_params->subsampling_x, seq_params->subsampling_y,
+ seq_params->use_highbitdepth, AOM_BORDER_IN_PIXELS,
+ cm->byte_alignment, NULL, NULL, NULL))
aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to allocate frame buffer");
const int frame_width = cm->superres_upscaled_width;
const int frame_height = cm->superres_upscaled_height;
- set_restoration_unit_size(frame_width, frame_height, cm->subsampling_x,
- cm->subsampling_y, cm->rst_info);
+ set_restoration_unit_size(frame_width, frame_height,
+ seq_params->subsampling_x,
+ seq_params->subsampling_y, cm->rst_info);
for (int i = 0; i < num_planes; ++i)
cm->rst_info[i].frame_restoration_type = RESTORE_NONE;
@@ -4038,16 +4173,16 @@ static void superres_post_encode(AV1_COMP *cpi) {
// av1_superres_upscale
if (aom_realloc_frame_buffer(
&cpi->scaled_source, cm->superres_upscaled_width,
- cm->superres_upscaled_height, cm->subsampling_x, cm->subsampling_y,
- cm->use_highbitdepth, AOM_BORDER_IN_PIXELS, cm->byte_alignment,
- NULL, NULL, NULL))
+ cm->superres_upscaled_height, cm->seq_params.subsampling_x,
+ cm->seq_params.subsampling_y, cm->seq_params.use_highbitdepth,
+ AOM_BORDER_IN_PIXELS, cm->byte_alignment, NULL, NULL, NULL))
aom_internal_error(
&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to reallocate scaled source buffer for superres");
assert(cpi->scaled_source.y_crop_width == cm->superres_upscaled_width);
assert(cpi->scaled_source.y_crop_height == cm->superres_upscaled_height);
av1_resize_and_extend_frame(cpi->unscaled_source, &cpi->scaled_source,
- (int)cm->bit_depth, num_planes);
+ (int)cm->seq_params.bit_depth, num_planes);
cpi->source = &cpi->scaled_source;
}
}
@@ -4331,7 +4466,7 @@ static int encode_with_recode_loop(AV1_COMP *cpi, size_t *size, uint8_t *dest) {
int64_t high_err_target = cpi->ambient_err;
int64_t low_err_target = cpi->ambient_err >> 1;
- if (cm->use_highbitdepth) {
+ if (cm->seq_params.use_highbitdepth) {
kf_err = aom_highbd_get_y_sse(cpi->source, get_frame_new_buffer(cm));
} else {
kf_err = aom_get_y_sse(cpi->source, get_frame_new_buffer(cm));
@@ -4574,7 +4709,11 @@ static void set_ext_overrides(AV1_COMP *cpi) {
cpi->ext_refresh_frame_flags_pending = 0;
}
cpi->common.allow_ref_frame_mvs = cpi->ext_use_ref_frame_mvs;
- cpi->common.error_resilient_mode = cpi->ext_use_error_resilient;
+ // A keyframe is already error resilient and keyframes with
+ // error_resilient_mode interferes with the use of show_existing_frame
+ // when forward reference keyframes are enabled.
+ cpi->common.error_resilient_mode =
+ cpi->ext_use_error_resilient && cpi->common.frame_type != KEY_FRAME;
}
static int setup_interp_filter_search_mask(AV1_COMP *cpi) {
@@ -4725,10 +4864,17 @@ static void dump_filtered_recon_frames(AV1_COMP *cpi) {
}
#endif // DUMP_RECON_FRAMES
+static INLINE int is_frame_droppable(AV1_COMP *cpi) {
+ return !(cpi->refresh_alt_ref_frame || cpi->refresh_alt2_ref_frame ||
+ cpi->refresh_bwd_ref_frame || cpi->refresh_golden_frame ||
+ cpi->refresh_last_frame);
+}
+
static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
int skip_adapt,
unsigned int *frame_flags) {
AV1_COMMON *const cm = &cpi->common;
+ SequenceHeader *const seq_params = &cm->seq_params;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
struct segmentation *const seg = &cm->seg;
@@ -4744,7 +4890,7 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
cm->large_scale_tile = cpi->oxcf.large_scale_tile;
cm->single_tile_decoding = cpi->oxcf.single_tile_decoding;
- if (cm->large_scale_tile) cm->seq_params.frame_id_numbers_present_flag = 0;
+ if (cm->large_scale_tile) seq_params->frame_id_numbers_present_flag = 0;
cm->allow_ref_frame_mvs &= frame_might_allow_ref_frame_mvs(cm);
// cm->allow_ref_frame_mvs needs to be written into the frame header while
@@ -4756,7 +4902,8 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
cpi->oxcf.allow_warped_motion && frame_might_allow_warped_motion(cm);
// Reset the frame packet stamp index.
- if (cm->frame_type == KEY_FRAME) cm->current_video_frame = 0;
+ if (cm->frame_type == KEY_FRAME && cm->show_frame)
+ cm->current_video_frame = 0;
// NOTE:
// (1) Move the setup of the ref_frame_flags upfront as it would be
@@ -4770,7 +4917,11 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
if (cm->show_existing_frame) {
// NOTE(zoeliu): In BIDIR_PRED, the existing frame to show is the current
// BWDREF_FRAME in the reference frame buffer.
- cm->frame_type = INTER_FRAME;
+ if (cm->frame_type == KEY_FRAME) {
+ cm->reset_decoder_state = 1;
+ } else {
+ cm->frame_type = INTER_FRAME;
+ }
cm->show_frame = 1;
cpi->frame_flags = *frame_flags;
@@ -4839,6 +4990,10 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
av1_rc_postencode_update(cpi, *size);
}
+ // Decrement count down till next gf
+ if (cpi->rc.frames_till_gf_update_due > 0)
+ cpi->rc.frames_till_gf_update_due--;
+
++cm->current_video_frame;
return AOM_CODEC_OK;
@@ -4889,7 +5044,7 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
MAX_MODES * sizeof(*cpi->mode_chosen_counts));
#endif
- if (cm->seq_params.frame_id_numbers_present_flag) {
+ if (seq_params->frame_id_numbers_present_flag) {
/* Non-normative definition of current_frame_id ("frame counter" with
* wraparound) */
const int frame_id_length = FRAME_ID_LENGTH;
@@ -4935,7 +5090,7 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
(frame_is_intra_only(cm) || !cm->show_frame) ? 0 : 1;
break;
}
- cm->timing_info_present &= !cm->seq_params.reduced_still_picture_hdr;
+ cm->timing_info_present &= !seq_params->reduced_still_picture_hdr;
if (cpi->sf.recode_loop == DISALLOW_RECODE) {
if (encode_without_recode_loop(cpi) != AOM_CODEC_OK) return AOM_CODEC_ERROR;
@@ -4957,7 +5112,7 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
// fixed interval. Note the reconstruction error if it is the frame before
// the force key frame
if (cpi->rc.next_key_frame_forced && cpi->rc.frames_to_key == 1) {
- if (cm->use_highbitdepth) {
+ if (seq_params->use_highbitdepth) {
cpi->ambient_err =
aom_highbd_get_y_sse(cpi->source, get_frame_new_buffer(cm));
} else {
@@ -4966,17 +5121,19 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
}
// If the encoder forced a KEY_FRAME decision or if frame is an S_FRAME
- if (cm->frame_type == KEY_FRAME || frame_is_sframe(cm)) {
+ if ((cm->frame_type == KEY_FRAME && cm->show_frame) || frame_is_sframe(cm)) {
cpi->refresh_last_frame = 1;
}
cm->frame_to_show = get_frame_new_buffer(cm);
- cm->frame_to_show->color_primaries = cm->color_primaries;
- cm->frame_to_show->transfer_characteristics = cm->transfer_characteristics;
- cm->frame_to_show->matrix_coefficients = cm->matrix_coefficients;
- cm->frame_to_show->monochrome = cm->seq_params.monochrome;
- cm->frame_to_show->chroma_sample_position = cm->chroma_sample_position;
- cm->frame_to_show->color_range = cm->color_range;
+ cm->frame_to_show->color_primaries = seq_params->color_primaries;
+ cm->frame_to_show->transfer_characteristics =
+ seq_params->transfer_characteristics;
+ cm->frame_to_show->matrix_coefficients = seq_params->matrix_coefficients;
+ cm->frame_to_show->monochrome = seq_params->monochrome;
+ cm->frame_to_show->chroma_sample_position =
+ seq_params->chroma_sample_position;
+ cm->frame_to_show->color_range = seq_params->color_range;
cm->frame_to_show->render_width = cm->render_width;
cm->frame_to_show->render_height = cm->render_height;
@@ -5014,7 +5171,7 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
if (skip_adapt) return AOM_CODEC_OK;
- if (cm->seq_params.frame_id_numbers_present_flag) {
+ if (seq_params->frame_id_numbers_present_flag) {
int i;
// Update reference frame id values based on the value of refresh_frame_mask
for (i = 0; i < REF_FRAMES; i++) {
@@ -5085,6 +5242,19 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
cm->seg.update_data = 0;
cm->lf.mode_ref_delta_update = 0;
+ // A droppable frame might not be shown but it always
+ // takes a space in the gf group. Therefore, even when
+ // it is not shown, we still need update the count down.
+
+ // TODO(weitinglin): This is a work-around to handle the condition
+ // when a frame is drop. We should fix the cm->show_frame flag
+ // instead of checking the other condition to update the counter properly.
+ if (cm->show_frame || is_frame_droppable(cpi)) {
+ // Decrement count down till next gf
+ if (cpi->rc.frames_till_gf_update_due > 0)
+ cpi->rc.frames_till_gf_update_due--;
+ }
+
if (cm->show_frame) {
// TODO(zoeliu): We may only swamp mi and prev_mi for those frames that
// are
@@ -5092,6 +5262,7 @@ static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
swap_mi_and_prev_mi(cm);
// Don't increment frame counters if this was an altref buffer
// update not a real frame
+
++cm->current_video_frame;
}
@@ -5160,10 +5331,45 @@ static int Pass2Encode(AV1_COMP *cpi, size_t *size, uint8_t *dest,
return AOM_CODEC_OK;
}
+#if CONFIG_DENOISE
+static int apply_denoise_2d(AV1_COMP *cpi, YV12_BUFFER_CONFIG *sd,
+ int block_size, float noise_level,
+ int64_t time_stamp, int64_t end_time) {
+ AV1_COMMON *const cm = &cpi->common;
+ if (!cpi->denoise_and_model) {
+ cpi->denoise_and_model = aom_denoise_and_model_alloc(
+ cm->seq_params.bit_depth, block_size, noise_level);
+ if (!cpi->denoise_and_model) {
+ aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
+ "Error allocating denoise and model");
+ return -1;
+ }
+ }
+ if (!cpi->film_grain_table) {
+ cpi->film_grain_table = aom_malloc(sizeof(*cpi->film_grain_table));
+ if (!cpi->film_grain_table) {
+ aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
+ "Error allocating grain table");
+ return -1;
+ }
+ memset(cpi->film_grain_table, 0, sizeof(*cpi->film_grain_table));
+ }
+ if (aom_denoise_and_model_run(cpi->denoise_and_model, sd,
+ &cm->film_grain_params)) {
+ if (cm->film_grain_params.apply_grain) {
+ aom_film_grain_table_append(cpi->film_grain_table, time_stamp, end_time,
+ &cm->film_grain_params);
+ }
+ }
+ return 0;
+}
+#endif
+
int av1_receive_raw_frame(AV1_COMP *cpi, aom_enc_frame_flags_t frame_flags,
YV12_BUFFER_CONFIG *sd, int64_t time_stamp,
int64_t end_time) {
AV1_COMMON *const cm = &cpi->common;
+ const SequenceHeader *const seq_params = &cm->seq_params;
struct aom_usec_timer timer;
int res = 0;
const int subsampling_x = sd->subsampling_x;
@@ -5174,25 +5380,33 @@ int av1_receive_raw_frame(AV1_COMP *cpi, aom_enc_frame_flags_t frame_flags,
aom_usec_timer_start(&timer);
+#if CONFIG_DENOISE
+ if (cpi->oxcf.noise_level > 0)
+ if (apply_denoise_2d(cpi, sd, cpi->oxcf.noise_block_size,
+ cpi->oxcf.noise_level, time_stamp, end_time) < 0)
+ res = -1;
+#endif // CONFIG_DENOISE
+
if (av1_lookahead_push(cpi->lookahead, sd, time_stamp, end_time,
use_highbitdepth, frame_flags))
res = -1;
aom_usec_timer_mark(&timer);
cpi->time_receive_data += aom_usec_timer_elapsed(&timer);
- if ((cm->profile == PROFILE_0) && !cm->seq_params.monochrome &&
+ if ((seq_params->profile == PROFILE_0) && !seq_params->monochrome &&
(subsampling_x != 1 || subsampling_y != 1)) {
aom_internal_error(&cm->error, AOM_CODEC_INVALID_PARAM,
"Non-4:2:0 color format requires profile 1 or 2");
res = -1;
}
- if ((cm->profile == PROFILE_1) &&
+ if ((seq_params->profile == PROFILE_1) &&
!(subsampling_x == 0 && subsampling_y == 0)) {
aom_internal_error(&cm->error, AOM_CODEC_INVALID_PARAM,
"Profile 1 requires 4:4:4 color format");
res = -1;
}
- if ((cm->profile == PROFILE_2) && (cm->bit_depth <= AOM_BITS_10) &&
+ if ((seq_params->profile == PROFILE_2) &&
+ (seq_params->bit_depth <= AOM_BITS_10) &&
!(subsampling_x == 1 && subsampling_y == 0)) {
aom_internal_error(&cm->error, AOM_CODEC_INVALID_PARAM,
"Profile 2 bit-depth < 10 requires 4:2:2 color format");
@@ -5364,9 +5578,9 @@ static void compute_internal_stats(AV1_COMP *cpi, int frame_bytes) {
#endif
cpi->bytes += frame_bytes;
- if (cm->use_highbitdepth) {
+ if (cm->seq_params.use_highbitdepth) {
in_bit_depth = cpi->oxcf.input_bit_depth;
- bit_depth = cm->bit_depth;
+ bit_depth = cm->seq_params.bit_depth;
}
if (cm->show_frame) {
const YV12_BUFFER_CONFIG *orig = cpi->source;
@@ -5387,7 +5601,7 @@ static void compute_internal_stats(AV1_COMP *cpi, int frame_bytes) {
cpi->total_samples += psnr.samples[0];
samples = psnr.samples[0];
// TODO(yaowu): unify these two versions into one.
- if (cm->use_highbitdepth)
+ if (cm->seq_params.use_highbitdepth)
frame_ssim2 =
aom_highbd_calc_ssim(orig, recon, &weight, bit_depth, in_bit_depth);
else
@@ -5412,7 +5626,7 @@ static void compute_internal_stats(AV1_COMP *cpi, int frame_bytes) {
#endif
}
if (cpi->b_calculate_blockiness) {
- if (!cm->use_highbitdepth) {
+ if (!cm->seq_params.use_highbitdepth) {
const double frame_blockiness =
av1_get_blockiness(orig->y_buffer, orig->y_stride, recon->y_buffer,
recon->y_stride, orig->y_width, orig->y_height);
@@ -5421,7 +5635,7 @@ static void compute_internal_stats(AV1_COMP *cpi, int frame_bytes) {
}
if (cpi->b_calculate_consistency) {
- if (!cm->use_highbitdepth) {
+ if (!cm->seq_params.use_highbitdepth) {
const double this_inconsistency = aom_get_ssim_metrics(
orig->y_buffer, orig->y_stride, recon->y_buffer, recon->y_stride,
orig->y_width, orig->y_height, cpi->ssim_vars, &cpi->metrics, 1);
@@ -5622,18 +5836,17 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
if (oxcf->large_scale_tile)
cm->refresh_frame_context = REFRESH_FRAME_CONTEXT_DISABLED;
- cpi->refresh_last_frame = 1;
- cpi->refresh_golden_frame = 0;
- cpi->refresh_bwd_ref_frame = 0;
- cpi->refresh_alt2_ref_frame = 0;
- cpi->refresh_alt_ref_frame = 0;
+ // default reference buffers update config
+ av1_configure_buffer_updates_firstpass(cpi, LF_UPDATE);
- // TODO(zoeliu@gmail.com): To support forward-KEY_FRAME and set up the
- // following flag accordingly.
+ // Initialize fields related to forward keyframes
+ cpi->no_show_kf = 0;
cm->reset_decoder_state = 0;
// Don't allow a show_existing_frame to coincide with an error resilient or
- // S-Frame
+ // S-Frame. An exception can be made in the case of a keyframe, since it
+ // does not depend on any previous frames. We must make this exception here
+ // because of the use of show_existing_frame with forward coded keyframes.
struct lookahead_entry *lookahead_src = NULL;
if (cm->current_video_frame > 0)
lookahead_src = av1_lookahead_peek(cpi->lookahead, 0);
@@ -5641,7 +5854,8 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
((cpi->oxcf.error_resilient_mode |
((lookahead_src->flags & AOM_EFLAG_ERROR_RESILIENT) != 0)) ||
(cpi->oxcf.s_frame_mode |
- ((lookahead_src->flags & AOM_EFLAG_SET_S_FRAME) != 0)))) {
+ ((lookahead_src->flags & AOM_EFLAG_SET_S_FRAME) != 0))) &&
+ !(rc->frames_to_key == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY))) {
cm->show_existing_frame = 0;
}
@@ -5719,22 +5933,29 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
if ((source = av1_lookahead_peek(cpi->lookahead, arf_src_index)) != NULL) {
cm->showable_frame = 1;
cpi->alt_ref_source = source;
-
- if (oxcf->arnr_max_frames > 0) {
- // Produce the filtered ARF frame.
- av1_temporal_filter(cpi, arf_src_index);
- aom_extend_frame_borders(&cpi->alt_ref_buffer, num_planes);
- force_src_buffer = &cpi->alt_ref_buffer;
+ // When arf_src_index == rc->frames_to_key, it indicates a fwd_kf
+ if (arf_src_index == rc->frames_to_key) {
+ // Skip temporal filtering and mark as intra_only if we have a fwd_kf
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ int which_arf = gf_group->arf_update_idx[gf_group->index];
+ cpi->is_arf_filter_off[which_arf] = 1;
+ cpi->no_show_kf = 1;
+ } else {
+ if (oxcf->arnr_max_frames > 0) {
+ // Produce the filtered ARF frame.
+ av1_temporal_filter(cpi, arf_src_index);
+ aom_extend_frame_borders(&cpi->alt_ref_buffer, num_planes);
+ force_src_buffer = &cpi->alt_ref_buffer;
+ }
}
-
cm->show_frame = 0;
cm->intra_only = 0;
- cpi->refresh_alt_ref_frame = 1;
- cpi->refresh_last_frame = 0;
- cpi->refresh_golden_frame = 0;
- cpi->refresh_bwd_ref_frame = 0;
- cpi->refresh_alt2_ref_frame = 0;
- rc->is_src_frame_alt_ref = 0;
+
+ if (oxcf->pass < 2) {
+ // In second pass, the buffer updates configure will be set
+ // in the function av1_rc_get_second_pass_params
+ av1_configure_buffer_updates_firstpass(cpi, ARF_UPDATE);
+ }
}
rc->source_alt_ref_pending = 0;
}
@@ -5771,13 +5992,12 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
cm->show_frame = 0;
cm->intra_only = 0;
- cpi->refresh_alt2_ref_frame = 1;
- cpi->refresh_last_frame = 0;
- cpi->refresh_golden_frame = 0;
- cpi->refresh_bwd_ref_frame = 0;
- cpi->refresh_alt_ref_frame = 0;
- rc->is_src_frame_alt_ref = 0;
- rc->is_src_frame_ext_arf = 0;
+
+ if (oxcf->pass < 2) {
+ // In second pass, the buffer updates configure will be set
+ // in the function av1_rc_get_second_pass_params
+ av1_configure_buffer_updates_firstpass(cpi, INTNL_ARF_UPDATE);
+ }
}
rc->source_alt_ref_pending = 0;
}
@@ -5791,13 +6011,11 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
cm->show_frame = 0;
cm->intra_only = 0;
- cpi->refresh_bwd_ref_frame = 1;
- cpi->refresh_last_frame = 0;
- cpi->refresh_golden_frame = 0;
- cpi->refresh_alt2_ref_frame = 0;
- cpi->refresh_alt_ref_frame = 0;
-
- rc->is_bwd_ref_frame = 1;
+ if (oxcf->pass < 2) {
+ // In second pass, the buffer updates configure will be set
+ // in the function av1_rc_get_second_pass_params
+ av1_configure_buffer_updates_firstpass(cpi, BIPRED_UPDATE);
+ }
}
}
@@ -5865,16 +6083,18 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
cm->cur_frame->buf.buf_8bit_valid = 0;
- if (cm->film_grain_table) {
- cm->film_grain_params_present = aom_film_grain_table_lookup(
- cm->film_grain_table, *time_stamp, *time_end, 0 /* erase */,
+ if (cpi->film_grain_table) {
+ cm->seq_params.film_grain_params_present = aom_film_grain_table_lookup(
+ cpi->film_grain_table, *time_stamp, *time_end, 0 /* =erase */,
&cm->film_grain_params);
}
- cm->cur_frame->film_grain_params_present = cm->film_grain_params_present;
+ cm->cur_frame->film_grain_params_present =
+ cm->seq_params.film_grain_params_present;
// only one operating point supported now
- cpi->common.tu_presentation_delay =
- ticks_to_timebase_units(timebase, *time_stamp);
+ const int64_t pts64 = ticks_to_timebase_units(timebase, *time_stamp);
+ if (pts64 < 0 || pts64 > UINT32_MAX) return AOM_CODEC_ERROR;
+ cpi->common.frame_presentation_time = (uint32_t)pts64;
// Start with a 0 size frame.
*size = 0;
@@ -6004,8 +6224,8 @@ int av1_get_preview_raw_frame(AV1_COMP *cpi, YV12_BUFFER_CONFIG *dest) {
*dest = *cm->frame_to_show;
dest->y_width = cm->width;
dest->y_height = cm->height;
- dest->uv_width = cm->width >> cm->subsampling_x;
- dest->uv_height = cm->height >> cm->subsampling_y;
+ dest->uv_width = cm->width >> cm->seq_params.subsampling_x;
+ dest->uv_height = cm->height >> cm->seq_params.subsampling_y;
ret = 0;
} else {
ret = -1;