Quellcode-Bibliothek svc_layercontext.c
Sprache: C
/* * 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.
*/
void av1_restore_layer_context(AV1_COMP *const cpi) {
SVC *const svc = &cpi->svc;
RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref; const AV1_COMMON *const cm = &cpi->common;
LAYER_CONTEXT *const lc = get_layer_context(cpi); constint old_frame_since_key = cpi->rc.frames_since_key; constint old_frame_to_key = cpi->rc.frames_to_key; constint frames_since_scene_change = cpi->rc.frames_since_scene_change; constint last_encoded_size_keyframe = cpi->rc.last_encoded_size_keyframe; constint last_target_size_keyframe = cpi->rc.last_target_size_keyframe; constint max_consec_drop = cpi->rc.max_consec_drop; constint postencode_drop = cpi->rc.postencode_drop; constint static_since_last_scene_change =
cpi->rc.static_since_last_scene_change; // Restore layer rate control.
cpi->rc = lc->rc;
cpi->ppi->p_rc = lc->p_rc;
cpi->oxcf.rc_cfg.target_bandwidth = lc->target_bandwidth;
cpi->gf_frame_index = 0;
cpi->mv_search_params.max_mv_magnitude = lc->max_mv_magnitude; if (cpi->mv_search_params.max_mv_magnitude == 0)
cpi->mv_search_params.max_mv_magnitude = AOMMAX(cm->width, cm->height); // Reset the following parameters to their values before // the layer restore. Keep these defined for the stream (not layer).
cpi->rc.frames_since_key = old_frame_since_key;
cpi->rc.frames_to_key = old_frame_to_key;
cpi->rc.frames_since_scene_change = frames_since_scene_change;
cpi->rc.last_encoded_size_keyframe = last_encoded_size_keyframe;
cpi->rc.last_target_size_keyframe = last_target_size_keyframe;
cpi->rc.max_consec_drop = max_consec_drop;
cpi->rc.postencode_drop = postencode_drop;
cpi->rc.static_since_last_scene_change = static_since_last_scene_change; // For spatial-svc, allow cyclic-refresh to be applied on the spatial layers, // for the base temporal layer. if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
svc->number_spatial_layers > 1 && svc->temporal_layer_id == 0) {
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
swap_ptr(&cr->map, &lc->map);
cr->sb_index = lc->sb_index;
cr->actual_num_seg1_blocks = lc->actual_num_seg1_blocks;
cr->actual_num_seg2_blocks = lc->actual_num_seg2_blocks;
cr->counter_encode_maxq_scene_change = lc->counter_encode_maxq_scene_change;
}
svc->skip_mvsearch_last = 0;
svc->skip_mvsearch_gf = 0;
svc->skip_mvsearch_altref = 0; // For each reference (LAST/GOLDEN) set the skip_mvsearch_last/gf frame flags. // This is to skip searching mv for that reference if it was last // refreshed (i.e., buffer slot holding that reference was refreshed) on the // previous spatial layer(s) at the same time (current_superframe). if (rtc_ref->set_ref_frame_config && svc->force_zero_mode_spatial_ref &&
cpi->sf.rt_sf.use_nonrd_pick_mode) { if (av1_check_ref_is_low_spatial_res_super_frame(cpi, LAST_FRAME)) {
svc->skip_mvsearch_last = 1;
} if (av1_check_ref_is_low_spatial_res_super_frame(cpi, GOLDEN_FRAME)) {
svc->skip_mvsearch_gf = 1;
} if (av1_check_ref_is_low_spatial_res_super_frame(cpi, ALTREF_FRAME)) {
svc->skip_mvsearch_altref = 1;
}
}
}
void av1_svc_update_buffer_slot_refreshed(AV1_COMP *const cpi) {
SVC *const svc = &cpi->svc;
RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref; constunsignedint current_frame =
cpi->ppi->use_svc ? svc->current_superframe
: cpi->common.current_frame.frame_number; // For any buffer slot that is refreshed, update it with // the spatial_layer_id and the current_superframe. if (cpi->common.current_frame.frame_type == KEY_FRAME) { // All slots are refreshed on KEY. for (unsignedint i = 0; i < REF_FRAMES; i++) {
rtc_ref->buffer_time_index[i] = current_frame;
rtc_ref->buffer_spatial_layer[i] = svc->spatial_layer_id;
}
} elseif (rtc_ref->set_ref_frame_config) { for (unsignedint i = 0; i < INTER_REFS_PER_FRAME; i++) { constint ref_frame_map_idx = rtc_ref->ref_idx[i]; if (rtc_ref->refresh[ref_frame_map_idx]) {
rtc_ref->buffer_time_index[ref_frame_map_idx] = current_frame;
rtc_ref->buffer_spatial_layer[ref_frame_map_idx] =
svc->spatial_layer_id;
}
}
}
}
void av1_save_layer_context(AV1_COMP *const cpi) {
SVC *const svc = &cpi->svc; const AV1_COMMON *const cm = &cpi->common;
LAYER_CONTEXT *lc = get_layer_context(cpi);
lc->rc = cpi->rc;
lc->p_rc = cpi->ppi->p_rc;
lc->target_bandwidth = (int)cpi->oxcf.rc_cfg.target_bandwidth;
lc->group_index = cpi->gf_frame_index;
lc->max_mv_magnitude = cpi->mv_search_params.max_mv_magnitude; if (svc->spatial_layer_id == 0) svc->base_framerate = cpi->framerate; // For spatial-svc, allow cyclic-refresh to be applied on the spatial layers, // for the base temporal layer. if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->svc.number_spatial_layers > 1 && svc->temporal_layer_id == 0) {
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; signedchar *temp = lc->map;
lc->map = cr->map;
cr->map = temp;
lc->sb_index = cr->sb_index;
lc->actual_num_seg1_blocks = cr->actual_num_seg1_blocks;
lc->actual_num_seg2_blocks = cr->actual_num_seg2_blocks;
lc->counter_encode_maxq_scene_change = cr->counter_encode_maxq_scene_change;
} if (!cpi->is_dropped_frame) {
av1_svc_update_buffer_slot_refreshed(cpi); for (unsignedint i = 0; i < REF_FRAMES; i++) { if (frame_is_intra_only(cm) ||
cm->current_frame.refresh_frame_flags & (1 << i)) {
svc->spatial_layer_fb[i] = svc->spatial_layer_id;
svc->temporal_layer_fb[i] = svc->temporal_layer_id;
}
}
} if (svc->spatial_layer_id == svc->number_spatial_layers - 1) {
svc->current_superframe++; // Reset drop flag to false for next superframe. for (int sl = 0; sl < svc->number_spatial_layers; sl++)
svc->drop_spatial_layer[sl] = false;
}
}
int av1_svc_primary_ref_frame(const AV1_COMP *const cpi) { const SVC *const svc = &cpi->svc; const AV1_COMMON *const cm = &cpi->common; int fb_idx = -1; int primary_ref_frame = PRIMARY_REF_NONE; if (cpi->svc.number_spatial_layers > 1 ||
cpi->svc.number_temporal_layers > 1) { // Set the primary_ref_frame to LAST_FRAME if that buffer slot for LAST // was last updated on a lower temporal layer (or base TL0) and for the // same spatial layer. For RTC patterns this allows for continued decoding // when set of enhancement layers are dropped (continued decoding starting // at next base TL0), so error_resilience can be off/0 for all layers.
fb_idx = get_ref_frame_map_idx(cm, LAST_FRAME); if (cpi->ppi->rtc_ref.reference[0] == 1 &&
svc->spatial_layer_fb[fb_idx] == svc->spatial_layer_id &&
(svc->temporal_layer_fb[fb_idx] < svc->temporal_layer_id ||
svc->temporal_layer_fb[fb_idx] == 0)) {
primary_ref_frame = 0; // LAST_FRAME: ref_frame - LAST_FRAME
}
} elseif (cpi->ppi->rtc_ref.set_ref_frame_config) { const ExternalFlags *const ext_flags = &cpi->ext_flags; int flags = ext_flags->ref_frame_flags; if (flags & AOM_LAST_FLAG) {
primary_ref_frame = 0; // LAST_FRAME: ref_frame - LAST_FRAME
} elseif (flags & AOM_GOLD_FLAG) {
primary_ref_frame = GOLDEN_FRAME - LAST_FRAME;
} elseif (flags & AOM_ALT_FLAG) {
primary_ref_frame = ALTREF_FRAME - LAST_FRAME;
}
} return primary_ref_frame;
}
void av1_get_layer_resolution(constint width_org, constint height_org, constint num, constint den, int *width_out, int *height_out) { int w, h; if (width_out == NULL || height_out == NULL || den == 0) return; if (den == 1 && num == 1) {
*width_out = width_org;
*height_out = height_org; return;
}
w = width_org * num / den;
h = height_org * num / den; // Make height and width even.
w += w % 2;
h += h % 2;
*width_out = w;
*height_out = h;
}
// For fixed svc mode: fixed pattern is set based on the number of // spatial and temporal layers, and the ksvc_fixed_mode. void av1_set_svc_fixed_mode(AV1_COMP *const cpi) {
SVC *const svc = &cpi->svc;
RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref; int i;
assert(svc->use_flexible_mode == 0); // Fixed SVC mode only supports at most 3 spatial or temporal layers.
assert(svc->number_spatial_layers >= 1 && svc->number_spatial_layers <= 3 &&
svc->number_temporal_layers >= 1 && svc->number_temporal_layers <= 3);
rtc_ref->set_ref_frame_config = 1; int superframe_cnt = svc->current_superframe; // Set the reference map buffer idx for the 7 references: // LAST_FRAME (0), LAST2_FRAME(1), LAST3_FRAME(2), GOLDEN_FRAME(3), // BWDREF_FRAME(4), ALTREF2_FRAME(5), ALTREF_FRAME(6). for (i = 0; i < INTER_REFS_PER_FRAME; i++) {
rtc_ref->reference[i] = 0;
rtc_ref->ref_idx[i] = i;
} for (i = 0; i < REF_FRAMES; i++) rtc_ref->refresh[i] = 0; // Always reference LAST, and reference GOLDEN on SL > 0. // For KSVC: GOLDEN reference will be removed on INTER_FRAMES later // when frame_type is set.
rtc_ref->reference[SVC_LAST_FRAME] = 1; if (svc->spatial_layer_id > 0) rtc_ref->reference[SVC_GOLDEN_FRAME] = 1; if (svc->temporal_layer_id == 0) { // Base temporal layer. if (svc->spatial_layer_id == 0) { // Set all buffer_idx to 0. Update slot 0 (LAST). for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
rtc_ref->refresh[0] = 1;
} elseif (svc->spatial_layer_id == 1) { // Set buffer_idx for LAST to slot 1, GOLDEN (and all other refs) to // slot 0. Update slot 1 (LAST). for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
rtc_ref->ref_idx[SVC_LAST_FRAME] = 1;
rtc_ref->refresh[1] = 1;
} elseif (svc->spatial_layer_id == 2) { // Set buffer_idx for LAST to slot 2, GOLDEN (and all other refs) to // slot 1. Update slot 2 (LAST). for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 1;
rtc_ref->ref_idx[SVC_LAST_FRAME] = 2;
rtc_ref->refresh[2] = 1;
}
} elseif (svc->temporal_layer_id == 2 && (superframe_cnt - 1) % 4 == 0) { // First top temporal enhancement layer. if (svc->spatial_layer_id == 0) { // Reference LAST (slot 0). // Set GOLDEN to slot 3 and update slot 3. // Set all other buffer_idx to slot 0. for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0; if (svc->spatial_layer_id < svc->number_spatial_layers - 1) {
rtc_ref->ref_idx[SVC_GOLDEN_FRAME] = 3;
rtc_ref->refresh[3] = 1;
}
} elseif (svc->spatial_layer_id == 1) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1, // GOLDEN (and all other refs) to slot 3. // Set LAST2 to slot 4 and Update slot 4. for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 3;
rtc_ref->ref_idx[SVC_LAST_FRAME] = 1; if (svc->spatial_layer_id < svc->number_spatial_layers - 1) {
rtc_ref->ref_idx[SVC_LAST2_FRAME] = 4;
rtc_ref->refresh[4] = 1;
}
} elseif (svc->spatial_layer_id == 2) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 2, // GOLDEN (and all other refs) to slot 4. // No update. for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 4;
rtc_ref->ref_idx[SVC_LAST_FRAME] = 2;
}
} elseif (svc->temporal_layer_id == 1) { // Middle temporal enhancement layer. if (svc->spatial_layer_id == 0) { // Reference LAST. // Set all buffer_idx to 0. // Set GOLDEN to slot 5 and update slot 5. for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0; if (svc->temporal_layer_id < svc->number_temporal_layers - 1 ||
svc->spatial_layer_id < svc->number_spatial_layers - 1) {
rtc_ref->ref_idx[SVC_GOLDEN_FRAME] = 5;
rtc_ref->refresh[5] = 1;
}
} elseif (svc->spatial_layer_id == 1) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1, // GOLDEN (and all other refs) to slot 5. // Set LAST3 to slot 6 and update slot 6. for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 5;
rtc_ref->ref_idx[SVC_LAST_FRAME] = 1; if (svc->temporal_layer_id < svc->number_temporal_layers - 1 ||
svc->spatial_layer_id < svc->number_spatial_layers - 1) {
rtc_ref->ref_idx[SVC_LAST3_FRAME] = 6;
rtc_ref->refresh[6] = 1;
}
} elseif (svc->spatial_layer_id == 2) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 2, // GOLDEN (and all other refs) to slot 6. // Set LAST3 to slot 7 and update slot 7. for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 6;
rtc_ref->ref_idx[SVC_LAST_FRAME] = 2; if (svc->temporal_layer_id < svc->number_temporal_layers - 1) {
rtc_ref->ref_idx[SVC_LAST3_FRAME] = 7;
rtc_ref->refresh[7] = 1;
}
}
} elseif (svc->temporal_layer_id == 2 && (superframe_cnt - 3) % 4 == 0) { // Second top temporal enhancement layer. if (svc->spatial_layer_id == 0) { // Set LAST to slot 5 and reference LAST. // Set GOLDEN to slot 3 and update slot 3. // Set all other buffer_idx to 0. for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
rtc_ref->ref_idx[SVC_LAST_FRAME] = 5; if (svc->spatial_layer_id < svc->number_spatial_layers - 1) {
rtc_ref->ref_idx[SVC_GOLDEN_FRAME] = 3;
rtc_ref->refresh[3] = 1;
}
} elseif (svc->spatial_layer_id == 1) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 6, // GOLDEN to slot 3. Set LAST2 to slot 4 and update slot 4. for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
rtc_ref->ref_idx[SVC_LAST_FRAME] = 6;
rtc_ref->ref_idx[SVC_GOLDEN_FRAME] = 3; if (svc->spatial_layer_id < svc->number_spatial_layers - 1) {
rtc_ref->ref_idx[SVC_LAST2_FRAME] = 4;
rtc_ref->refresh[4] = 1;
}
} elseif (svc->spatial_layer_id == 2) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 7, // GOLDEN to slot 4. No update. for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
rtc_ref->ref_idx[SVC_LAST_FRAME] = 7;
rtc_ref->ref_idx[SVC_GOLDEN_FRAME] = 4;
}
}
}
void av1_svc_check_reset_layer_rc_flag(AV1_COMP *const cpi) {
SVC *const svc = &cpi->svc; for (int sl = 0; sl < svc->number_spatial_layers; ++sl) { // Check for reset based on avg_frame_bandwidth for spatial layer sl. // If avg_frame_bandwidth for top temporal layer is not set // (because enhancement layer was inactive), use the base TL0 int layer = LAYER_IDS_TO_IDX(sl, svc->number_temporal_layers - 1,
svc->number_temporal_layers);
LAYER_CONTEXT *lc = &svc->layer_context[layer];
RATE_CONTROL *lrc = &lc->rc; int avg_frame_bandwidth = lrc->avg_frame_bandwidth; int prev_avg_frame_bandwidth = lrc->prev_avg_frame_bandwidth; if (avg_frame_bandwidth == 0 || prev_avg_frame_bandwidth == 0) { // Use base TL0.
layer = LAYER_IDS_TO_IDX(sl, 0, svc->number_temporal_layers);
lc = &svc->layer_context[layer];
lrc = &lc->rc;
avg_frame_bandwidth = lrc->avg_frame_bandwidth;
prev_avg_frame_bandwidth = lrc->prev_avg_frame_bandwidth;
} if (avg_frame_bandwidth / 3 > (prev_avg_frame_bandwidth >> 1) ||
avg_frame_bandwidth < (prev_avg_frame_bandwidth >> 1)) { // Reset for all temporal layers with spatial layer sl. for (int tl = 0; tl < svc->number_temporal_layers; ++tl) { int layer2 = LAYER_IDS_TO_IDX(sl, tl, svc->number_temporal_layers);
LAYER_CONTEXT *lc2 = &svc->layer_context[layer2];
RATE_CONTROL *lrc2 = &lc2->rc;
PRIMARY_RATE_CONTROL *lp_rc2 = &lc2->p_rc;
PRIMARY_RATE_CONTROL *const lp_rc = &lc2->p_rc;
lrc2->rc_1_frame = 0;
lrc2->rc_2_frame = 0;
lp_rc2->bits_off_target = lp_rc->optimal_buffer_level;
lp_rc2->buffer_level = lp_rc->optimal_buffer_level;
}
}
}
}
void av1_svc_set_last_source(AV1_COMP *const cpi, EncodeFrameInput *frame_input,
YV12_BUFFER_CONFIG *prev_source) {
frame_input->last_source = prev_source != NULL ? prev_source : NULL; if (!cpi->ppi->use_svc && cpi->rc.prev_frame_is_dropped &&
cpi->rc.frame_number_encoded > 0) {
frame_input->last_source = &cpi->svc.source_last_TL0;
} else {
RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref; if (cpi->svc.spatial_layer_id == 0) { // For base spatial layer: if the LAST reference (index 0) is not // the previous (super)frame set the last_source to the source // corresponding to the last TL0, otherwise keep it at prev_source. // Always use source_last_TL0 if previous base TL0 was dropped. if (cpi->svc.current_superframe > 0) { constint buffslot_last = rtc_ref->ref_idx[0]; // Check if previous frame was dropped on base TL0 layer. constint layer =
LAYER_IDS_TO_IDX(0, 0, cpi->svc.number_temporal_layers);
LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
RATE_CONTROL *lrc = &lc->rc; if (lrc->prev_frame_is_dropped ||
rtc_ref->buffer_time_index[buffslot_last] <
cpi->svc.current_superframe - 1) {
frame_input->last_source = &cpi->svc.source_last_TL0;
}
}
} elseif (cpi->svc.spatial_layer_id > 0) { // For spatial enhancement layers: the previous source (prev_source) // corresponds to the lower spatial layer (which is the same source so // we can't use that), so always set the last_source to the source of the // last TL0. if (cpi->svc.current_superframe > 0)
frame_input->last_source = &cpi->svc.source_last_TL0; else
frame_input->last_source = NULL;
}
}
}
int av1_svc_get_min_ref_dist(const AV1_COMP *cpi) {
RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref; int min_dist = INT_MAX; constunsignedint current_frame_num =
cpi->ppi->use_svc ? cpi->svc.current_superframe
: cpi->common.current_frame.frame_number; for (unsignedint i = 0; i < INTER_REFS_PER_FRAME; i++) { if (rtc_ref->reference[i]) { constint ref_frame_map_idx = rtc_ref->ref_idx[i]; constint dist =
current_frame_num - rtc_ref->buffer_time_index[ref_frame_map_idx]; if (dist < min_dist) min_dist = dist;
}
} return min_dist;
}
void av1_svc_set_reference_was_previous(AV1_COMP *cpi) {
RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref; // Check if the encoded frame had some reference that was the // previous frame. constunsignedint current_frame =
cpi->ppi->use_svc ? cpi->svc.current_superframe
: cpi->common.current_frame.frame_number;
rtc_ref->reference_was_previous_frame = true; if (current_frame > 0) {
rtc_ref->reference_was_previous_frame = false; for (unsignedint i = 0; i < INTER_REFS_PER_FRAME; i++) { if (rtc_ref->reference[i]) { constint ref_frame_map_idx = rtc_ref->ref_idx[i]; if (rtc_ref->buffer_time_index[ref_frame_map_idx] == current_frame - 1)
rtc_ref->reference_was_previous_frame = true;
}
}
}
}
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.17Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.