/* * 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.
*/
staticvoid ref_config_rps(aom_svc_ref_frame_config_t *ref_frame_config, int frame_cnt, int rps_recovery_frame) { // Pattern of 3 references with (ALTREF and GOLDEN) trailing // LAST by 4 and 8 frame, with some switching logic to // only predict from longer-term reference. int last_idx = 0; int last_idx_refresh = 0; int gld_idx = 0; int alt_ref_idx = 0; constint lag_alt = 4; constint lag_gld = 8; constint sh = 8; // slots 0 - 7. // Moving index slot for last: 0 - (sh - 1) if (frame_cnt > 1) last_idx = (frame_cnt - 1) % sh; // Moving index for refresh of last: one ahead for next frame.
last_idx_refresh = frame_cnt % sh; // Moving index for gld_ref, lag behind current by lag_gld if (frame_cnt > lag_gld) gld_idx = (frame_cnt - lag_gld) % sh; // Moving index for alt_ref, lag behind LAST by lag_alt frames. if (frame_cnt > lag_alt) alt_ref_idx = (frame_cnt - lag_alt) % sh; // Set the ref_idx. // Default all references (7) to slot for last. // LAST_FRAME (0), LAST2_FRAME(1), LAST3_FRAME(2), GOLDEN_FRAME(3), // BWDREF_FRAME(4), ALTREF2_FRAME(5), ALTREF_FRAME(6). for (int i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = last_idx; // Set the ref_idx for the relevant references.
ref_frame_config->ref_idx[0] = last_idx;
ref_frame_config->ref_idx[1] = last_idx_refresh;
ref_frame_config->ref_idx[3] = gld_idx;
ref_frame_config->ref_idx[6] = alt_ref_idx; // Refresh this slot, which will become LAST on next frame.
ref_frame_config->refresh[last_idx_refresh] = 1; // Reference LAST, ALTREF, and GOLDEN
ref_frame_config->reference[0] = 1;
ref_frame_config->reference[6] = 1;
ref_frame_config->reference[3] = 1; if (frame_cnt == rps_recovery_frame) { // Switch to only reference GOLDEN at recovery_frame.
ref_frame_config->reference[0] = 0;
ref_frame_config->reference[6] = 0;
ref_frame_config->reference[3] = 1;
} elseif (frame_cnt > rps_recovery_frame &&
frame_cnt < rps_recovery_frame + 8) { // Go back to predicting from LAST, and after // 8 frames (GOLDEN is 8 frames aways) go back // to predicting off GOLDEN and ALTREF.
ref_frame_config->reference[0] = 1;
ref_frame_config->reference[6] = 0;
ref_frame_config->reference[3] = 0;
}
}
// Simulcast mode for 3 spatial and 3 temporal layers. // No inter-layer predicton, only prediction is temporal and single // reference (LAST). // No overlap in buffer slots between spatial layers. So for example, // SL0 only uses slots 0 and 1. // SL1 only uses slots 2 and 3. // SL2 only uses slots 4 and 5. // All 7 references for each inter-frame must only access buffer slots // for that spatial layer. // On key (super)frames: SL1 and SL2 must have no references set // and must refresh all the slots for that layer only (so 2 and 3 // for SL1, 4 and 5 for SL2). The base SL0 will be labelled internally // as a Key frame (refresh all slots). SL1/SL2 will be labelled // internally as Intra-only frames that allow that stream to be decoded. // These conditions will allow for each spatial stream to be // independently decodeable. staticvoid ref_config_simulcast3SL3TL(
aom_svc_ref_frame_config_t *ref_frame_config,
aom_svc_layer_id_t *layer_id, int is_key_frame, int superframe_cnt) { int i; // Initialize all references to 0 (don't use reference). for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->reference[i] = 0; // Initialize as no refresh/update for all slots. for (i = 0; i < REF_FRAMES; i++) ref_frame_config->refresh[i] = 0; for (i = 0; i < INTER_REFS_PER_FRAME; i++) ref_frame_config->ref_idx[i] = 0;
if (is_key_frame) { if (layer_id->spatial_layer_id == 0) { // Assign LAST/GOLDEN to slot 0/1. // Refesh slots 0 and 1 for SL0. // SL0: this will get set to KEY frame internally.
ref_frame_config->ref_idx[0] = 0;
ref_frame_config->ref_idx[3] = 1;
ref_frame_config->refresh[0] = 1;
ref_frame_config->refresh[1] = 1;
} elseif (layer_id->spatial_layer_id == 1) { // Assign LAST/GOLDEN to slot 2/3. // Refesh slots 2 and 3 for SL1. // This will get set to Intra-only frame internally.
ref_frame_config->ref_idx[0] = 2;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->refresh[2] = 1;
ref_frame_config->refresh[3] = 1;
} elseif (layer_id->spatial_layer_id == 2) { // Assign LAST/GOLDEN to slot 4/5. // Refresh slots 4 and 5 for SL2. // This will get set to Intra-only frame internally.
ref_frame_config->ref_idx[0] = 4;
ref_frame_config->ref_idx[3] = 5;
ref_frame_config->refresh[4] = 1;
ref_frame_config->refresh[5] = 1;
}
} elseif (superframe_cnt % 4 == 0) { // Base temporal layer: TL0
layer_id->temporal_layer_id = 0; if (layer_id->spatial_layer_id == 0) { // SL0 // Reference LAST. Assign all references to either slot // 0 or 1. Here we assign LAST to slot 0, all others to 1. // Update slot 0 (LAST).
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 1;
ref_frame_config->ref_idx[0] = 0;
ref_frame_config->refresh[0] = 1;
} elseif (layer_id->spatial_layer_id == 1) { // SL1 // Reference LAST. Assign all references to either slot // 2 or 3. Here we assign LAST to slot 2, all others to 3. // Update slot 2 (LAST).
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 3;
ref_frame_config->ref_idx[0] = 2;
ref_frame_config->refresh[2] = 1;
} elseif (layer_id->spatial_layer_id == 2) { // SL2 // Reference LAST. Assign all references to either slot // 4 or 5. Here we assign LAST to slot 4, all others to 5. // Update slot 4 (LAST).
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 5;
ref_frame_config->ref_idx[0] = 4;
ref_frame_config->refresh[4] = 1;
}
} elseif ((superframe_cnt - 1) % 4 == 0) { // First top temporal enhancement layer: TL2
layer_id->temporal_layer_id = 2; if (layer_id->spatial_layer_id == 0) { // SL0 // Reference LAST (slot 0). Assign other references to slot 1. // No update/refresh on any slots.
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 1;
ref_frame_config->ref_idx[0] = 0;
} elseif (layer_id->spatial_layer_id == 1) { // SL1 // Reference LAST (slot 2). Assign other references to slot 3. // No update/refresh on any slots.
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 3;
ref_frame_config->ref_idx[0] = 2;
} elseif (layer_id->spatial_layer_id == 2) { // SL2 // Reference LAST (slot 4). Assign other references to slot 4. // No update/refresh on any slots.
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 5;
ref_frame_config->ref_idx[0] = 4;
}
} elseif ((superframe_cnt - 2) % 4 == 0) { // Middle temporal enhancement layer: TL1
layer_id->temporal_layer_id = 1; if (layer_id->spatial_layer_id == 0) { // SL0 // Reference LAST (slot 0). // Set GOLDEN to slot 1 and update slot 1. // This will be used as reference for next TL2.
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 1;
ref_frame_config->ref_idx[0] = 0;
ref_frame_config->refresh[1] = 1;
} elseif (layer_id->spatial_layer_id == 1) { // SL1 // Reference LAST (slot 2). // Set GOLDEN to slot 3 and update slot 3. // This will be used as reference for next TL2.
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 3;
ref_frame_config->ref_idx[0] = 2;
ref_frame_config->refresh[3] = 1;
} elseif (layer_id->spatial_layer_id == 2) { // SL2 // Reference LAST (slot 4). // Set GOLDEN to slot 5 and update slot 5. // This will be used as reference for next TL2.
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 5;
ref_frame_config->ref_idx[0] = 4;
ref_frame_config->refresh[5] = 1;
}
} elseif ((superframe_cnt - 3) % 4 == 0) { // Second top temporal enhancement layer: TL2
layer_id->temporal_layer_id = 2; if (layer_id->spatial_layer_id == 0) { // SL0 // Reference LAST (slot 1). Assign other references to slot 0. // No update/refresh on any slots.
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[0] = 1;
} elseif (layer_id->spatial_layer_id == 1) { // SL1 // Reference LAST (slot 3). Assign other references to slot 2. // No update/refresh on any slots.
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 2;
ref_frame_config->ref_idx[0] = 3;
} elseif (layer_id->spatial_layer_id == 2) { // SL2 // Reference LAST (slot 5). Assign other references to slot 4. // No update/refresh on any slots.
ref_frame_config->reference[0] = 1; for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 4;
ref_frame_config->ref_idx[0] = 5;
}
}
}
// 3 spatial and 3 temporal layer. // Overlap in the buffer slot updates: the slots 3 and 4 updated by // first TL2 are reused for update in TL1 superframe. staticvoid ref_config_3SL3TL(aom_svc_ref_frame_config_t *ref_frame_config,
aom_svc_layer_id_t *layer_id, int is_key_frame, int superframe_cnt) { if (superframe_cnt % 4 == 0) { // Base temporal layer.
layer_id->temporal_layer_id = 0; if (layer_id->spatial_layer_id == 0) { // Reference LAST, update LAST. // Set all buffer_idx to 0. for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->refresh[0] = 1;
} elseif (layer_id->spatial_layer_id == 1) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1, // GOLDEN (and all other refs) to slot 0. // Update slot 1 (LAST). for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[0] = 1;
ref_frame_config->refresh[1] = 1;
} elseif (layer_id->spatial_layer_id == 2) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 2, // GOLDEN (and all other refs) to slot 1. // Update slot 2 (LAST). for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 1;
ref_frame_config->ref_idx[0] = 2;
ref_frame_config->refresh[2] = 1;
}
} elseif ((superframe_cnt - 1) % 4 == 0) { // First top temporal enhancement layer.
layer_id->temporal_layer_id = 2; if (layer_id->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 (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->refresh[3] = 1;
} elseif (layer_id->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 (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 3;
ref_frame_config->ref_idx[0] = 1;
ref_frame_config->ref_idx[1] = 4;
ref_frame_config->refresh[4] = 1;
} elseif (layer_id->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 (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 4;
ref_frame_config->ref_idx[0] = 2;
}
} elseif ((superframe_cnt - 2) % 4 == 0) { // Middle temporal enhancement layer.
layer_id->temporal_layer_id = 1; if (layer_id->spatial_layer_id == 0) { // Reference LAST. // Set all buffer_idx to 0. // Set GOLDEN to slot 3 and update slot 3. for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->refresh[3] = 1;
} elseif (layer_id->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 (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 3;
ref_frame_config->ref_idx[0] = 1;
ref_frame_config->ref_idx[2] = 4;
ref_frame_config->refresh[4] = 1;
} elseif (layer_id->spatial_layer_id == 2) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 2, // GOLDEN (and all other refs) to slot 4. // Set LAST2 to slot 5 and update slot 5. for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 4;
ref_frame_config->ref_idx[0] = 2;
ref_frame_config->ref_idx[2] = 5;
ref_frame_config->refresh[5] = 1;
}
} elseif ((superframe_cnt - 3) % 4 == 0) { // Second top temporal enhancement layer.
layer_id->temporal_layer_id = 2; if (layer_id->spatial_layer_id == 0) { // Set LAST to slot 3 and reference LAST. // Set GOLDEN to slot 3 and update slot 3. // Set all other buffer_idx to 0. for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[0] = 3;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->refresh[3] = 1;
} elseif (layer_id->spatial_layer_id == 1) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 4, // GOLDEN to slot 3. Set LAST2 to slot 4 and update slot 4. for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[0] = 4;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->ref_idx[1] = 4;
ref_frame_config->refresh[4] = 1;
} elseif (layer_id->spatial_layer_id == 2) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 5, // GOLDEN to slot 4. No update. for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[0] = 5;
ref_frame_config->ref_idx[3] = 4;
}
} if (layer_id->spatial_layer_id > 0) { // Always reference GOLDEN (inter-layer prediction).
ref_frame_config->reference[3] = 1; if (is_key_frame && layer_id->spatial_layer_id > 0) { // On superframes whose base is key: remove LAST since GOLDEN // is used as reference.
ref_frame_config->reference[0] = 0;
}
}
}
// Layer pattern configuration. virtualint set_layer_pattern( int frame_cnt, aom_svc_layer_id_t *layer_id,
aom_svc_ref_frame_config_t *ref_frame_config,
aom_svc_ref_frame_comp_pred_t *ref_frame_comp_pred, int spatial_layer, int multi_ref, int comp_pred, int is_key_frame, int dynamic_enable_disable_mode, int rps_mode, int rps_recovery_frame, int simulcast_mode, bool use_last_as_scaled, bool use_last_as_scaled_single_ref) { int lag_index = 0; int base_count = frame_cnt >> 2;
layer_id->spatial_layer_id = spatial_layer; // 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 (int i = 0; i < INTER_REFS_PER_FRAME; i++) {
ref_frame_config->ref_idx[i] = i;
ref_frame_config->reference[i] = 0;
} for (int i = 0; i < REF_FRAMES; i++) ref_frame_config->refresh[i] = 0; if (comp_pred) {
ref_frame_comp_pred->use_comp_pred[0] = 1; // GOLDEN_LAST
ref_frame_comp_pred->use_comp_pred[1] = 1; // LAST2_LAST
ref_frame_comp_pred->use_comp_pred[2] = 1; // ALTREF_LAST
} // Set layer_flags to 0 when using ref_frame_config->reference. int layer_flags = 0; // Always reference LAST.
ref_frame_config->reference[0] = 1; if (number_temporal_layers_ == 1 && number_spatial_layers_ == 1) {
layer_id->temporal_layer_id = 0;
ref_frame_config->refresh[0] = 1; if (rps_mode)
ref_config_rps(ref_frame_config, frame_cnt, rps_recovery_frame); if (intra_only_single_layer_) { // This repros the crash in Bug: 363016123.
ref_frame_config->ref_idx[0] = 0;
ref_frame_config->ref_idx[3] = 1;
ref_frame_config->ref_idx[6] = 2; if (frame_cnt == 1) { for (int i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->reference[i] = 0;
}
}
} if (number_temporal_layers_ == 2 && number_spatial_layers_ == 1) { // 2-temporal layer. // 1 3 5 // 0 2 4 // Keep golden fixed at slot 3.
base_count = frame_cnt >> 1;
ref_frame_config->ref_idx[3] = 3; // Cyclically refresh slots 5, 6, 7, for lag alt ref.
lag_index = 5; if (base_count > 0) {
lag_index = 5 + (base_count % 3); if (frame_cnt % 2 != 0) lag_index = 5 + ((base_count + 1) % 3);
} // Set the altref slot to lag_index.
ref_frame_config->ref_idx[6] = lag_index; if (frame_cnt % 2 == 0) {
layer_id->temporal_layer_id = 0; // Update LAST on layer 0, reference LAST.
ref_frame_config->refresh[0] = 1;
ref_frame_config->reference[0] = 1; // Refresh lag_index slot, needed for lagging golen.
ref_frame_config->refresh[lag_index] = 1; // Refresh GOLDEN every x base layer frames. if (base_count % 32 == 0) ref_frame_config->refresh[3] = 1;
} else {
layer_id->temporal_layer_id = 1; // No updates on layer 1, reference LAST (TL0).
ref_frame_config->reference[0] = 1;
} // Always reference golden and altref on TL0. if (layer_id->temporal_layer_id == 0) {
ref_frame_config->reference[3] = 1;
ref_frame_config->reference[6] = 1;
}
} elseif (number_temporal_layers_ == 3 && number_spatial_layers_ == 1) { // 3-layer: // 1 3 5 7 // 2 6 // 0 4 8 if (multi_ref) { // Keep golden fixed at slot 3.
ref_frame_config->ref_idx[3] = 3; // Cyclically refresh slots 4, 5, 6, 7, for lag altref.
lag_index = 4 + (base_count % 4); // Set the altref slot to lag_index.
ref_frame_config->ref_idx[6] = lag_index;
} if (frame_cnt % 4 == 0) { // Base layer.
layer_id->temporal_layer_id = 0; // Update LAST on layer 0, reference LAST and GF.
ref_frame_config->refresh[0] = 1;
ref_frame_config->reference[3] = 1; if (multi_ref) { // Refresh GOLDEN every x ~10 base layer frames. if (base_count % 10 == 0) ref_frame_config->refresh[3] = 1; // Refresh lag_index slot, needed for lagging altref.
ref_frame_config->refresh[lag_index] = 1;
}
} elseif ((frame_cnt - 1) % 4 == 0) {
layer_id->temporal_layer_id = 2; // First top layer: no updates, only reference LAST (TL0).
} elseif ((frame_cnt - 2) % 4 == 0) {
layer_id->temporal_layer_id = 1; // Middle layer (TL1): update LAST2, only reference LAST (TL0).
ref_frame_config->refresh[1] = 1;
} elseif ((frame_cnt - 3) % 4 == 0) {
layer_id->temporal_layer_id = 2; // Second top layer: no updates, only reference LAST. // Set buffer idx for LAST to slot 1, since that was the slot // updated in previous frame. So LAST is TL1 frame.
ref_frame_config->ref_idx[0] = 1;
ref_frame_config->ref_idx[1] = 0;
} if (multi_ref) { // Every frame can reference GOLDEN AND ALTREF.
ref_frame_config->reference[3] = 1;
ref_frame_config->reference[6] = 1;
}
} elseif (number_temporal_layers_ == 1 && number_spatial_layers_ == 2) {
layer_id->temporal_layer_id = 0; if (layer_id->spatial_layer_id == 0) { // Reference LAST, update LAST. Keep LAST and GOLDEN in slots 0 and 3.
ref_frame_config->ref_idx[0] = 0;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->refresh[0] = 1;
} elseif (layer_id->spatial_layer_id == 1) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 3 // and GOLDEN to slot 0. Update slot 3 (LAST).
ref_frame_config->ref_idx[0] = 3;
ref_frame_config->ref_idx[3] = 0;
ref_frame_config->refresh[3] = 1;
} // Reference GOLDEN. if (layer_id->spatial_layer_id > 0) ref_frame_config->reference[3] = 1;
} elseif (number_temporal_layers_ == 1 && number_spatial_layers_ == 3) { // 3 spatial layers, 1 temporal. // Note for this case , we set the buffer idx for all references to be // either LAST or GOLDEN, which are always valid references, since decoder // will check if any of the 7 references is valid scale in // valid_ref_frame_size().
layer_id->temporal_layer_id = 0; if (layer_id->spatial_layer_id == 0) { // Reference LAST, update LAST. Set all other buffer_idx to 0. for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->refresh[0] = 1;
} elseif (layer_id->spatial_layer_id == 1) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1 // and GOLDEN (and all other refs) to slot 0. // Update slot 1 (LAST). for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[0] = 1; if (use_last_as_scaled) { for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 1;
ref_frame_config->ref_idx[0] = 0;
ref_frame_config->ref_idx[3] = 1;
}
ref_frame_config->refresh[1] = 1;
} elseif (layer_id->spatial_layer_id == 2) { // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 2 // and GOLDEN (and all other refs) to slot 1. // Update slot 2 (LAST). for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 1;
ref_frame_config->ref_idx[0] = 2;
ref_frame_config->refresh[2] = 1; if (multi_ref) {
ref_frame_config->ref_idx[6] = 7;
ref_frame_config->reference[6] = 1; if (base_count % 10 == 0) ref_frame_config->refresh[7] = 1;
}
} // Reference GOLDEN. if (layer_id->spatial_layer_id > 0) { if (use_last_as_scaled_single_ref)
ref_frame_config->reference[3] = 0; else
ref_frame_config->reference[3] = 1;
}
} elseif (number_temporal_layers_ == 3 && number_spatial_layers_ == 3) { if (simulcast_mode) {
ref_config_simulcast3SL3TL(ref_frame_config, layer_id, is_key_frame,
superframe_cnt_);
} else {
ref_config_3SL3TL(ref_frame_config, layer_id, is_key_frame,
superframe_cnt_); // Allow for top spatial layer to use additional temporal reference. // Additional reference is only updated on base temporal layer, every // 10 TL0 frames here. if (multi_ref && layer_id->spatial_layer_id == 2) {
ref_frame_config->ref_idx[6] = 7; if (!is_key_frame) ref_frame_config->reference[6] = 1; if (base_count % 10 == 0 && layer_id->temporal_layer_id == 0)
ref_frame_config->refresh[7] = 1;
}
}
} // If the top spatial layer is first-time encoded in mid-sequence // (i.e., dynamic_enable_disable_mode = 1), then don't predict from LAST, // since it will have been last updated on first key frame (SL0) and so // be different resolution from SL2. if (dynamic_enable_disable_mode == 1 &&
layer_id->spatial_layer_id == number_spatial_layers_ - 1)
ref_frame_config->reference[0] = 0; return layer_flags;
}
::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352,
288, 30, 1, 0, 300); constint bitrate_array[2] = { 200, 550 };
cfg_.rc_target_bitrate = bitrate_array[GET_PARAM(4)];
ResetModel();
number_temporal_layers_ = 3;
target_layer_bitrate_[0] = 50 * cfg_.rc_target_bitrate / 100;
target_layer_bitrate_[1] = 70 * cfg_.rc_target_bitrate / 100;
target_layer_bitrate_[2] = cfg_.rc_target_bitrate;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); for (int i = 0; i < number_temporal_layers_ * number_spatial_layers_; i++) {
ASSERT_GE(effective_datarate_tl[i], target_layer_bitrate_[i] * 0.60)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_tl[i], target_layer_bitrate_[i] * 1.60)
<< " The datarate for the file is greater than target by too much!";
} #if CONFIG_AV1_DECODER // Top temporal layers are non_reference, so exlcude them from // mismatch count, since loopfilter/cdef is not applied for these on // encoder side, but is always applied on decoder. // This means 150 = #frames(300) - #TL2_frames(150).
EXPECT_EQ((int)GetMismatchFrames(), 150); #endif
}
constint bitrate_array[2] = { 1000, 1500 };
cfg_.rc_target_bitrate = bitrate_array[GET_PARAM(4)];
ResetModel();
screen_mode_ = 1;
number_temporal_layers_ = 3;
number_spatial_layers_ = 1;
target_layer_bitrate_[0] = 50 * cfg_.rc_target_bitrate / 100;
target_layer_bitrate_[1] = 70 * cfg_.rc_target_bitrate / 100;
target_layer_bitrate_[2] = cfg_.rc_target_bitrate;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); for (int i = 0; i < number_temporal_layers_ * number_spatial_layers_; i++) {
ASSERT_GE(effective_datarate_tl[i], target_layer_bitrate_[i] * 0.40)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_tl[i], target_layer_bitrate_[i] * 2.0)
<< " The datarate for the file is greater than target by too much!";
} #if CONFIG_AV1_DECODER // Top temporal layers are non_reference, so exlcude them from // mismatch count, since loopfilter/cdef is not applied for these on // encoder side, but is always applied on decoder. // This means 30 = #frames(60) - #TL2_frames(30). // We use LE for screen since loopfilter level can become very small // or zero and then the frame is not a mismatch.
EXPECT_LE((int)GetMismatchFrames(), 30); #endif
}
constint bitrate_array[2] = { 60, 100 };
cfg_.rc_target_bitrate = bitrate_array[GET_PARAM(4)];
ResetModel();
screen_mode_ = 1;
number_temporal_layers_ = 2;
number_spatial_layers_ = 1;
target_layer_bitrate_[0] = 60 * cfg_.rc_target_bitrate / 100;
target_layer_bitrate_[1] = cfg_.rc_target_bitrate;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); for (int i = 0; i < number_temporal_layers_ * number_spatial_layers_; i++) {
ASSERT_GE(effective_datarate_tl[i], target_layer_bitrate_[i] * 0.75)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_tl[i], target_layer_bitrate_[i] * 1.8)
<< " The datarate for the file is greater than target by too much!";
} #if CONFIG_AV1_DECODER // Top temporal layers are non_reference, so exlcude them from // mismatch count, since loopfilter/cdef is not applied for these on // encoder side, but is always applied on decoder. // This means 300 = #frames(300) - #TL2_frames(150). // We use LE for screen since loopfilter level can become very small // or zero and then the frame is not a mismatch.
EXPECT_LE((int)GetMismatchFrames(), 150); #endif
}
constint bitrate_array[2] = { 200, 500 };
cfg_.rc_target_bitrate = bitrate_array[GET_PARAM(4)];
ResetModel();
screen_mode_ = 1;
number_temporal_layers_ = 1;
number_spatial_layers_ = 1;
target_layer_bitrate_[0] = cfg_.rc_target_bitrate;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); for (int i = 0; i < number_temporal_layers_ * number_spatial_layers_; i++) {
ASSERT_GE(effective_datarate_tl[i], target_layer_bitrate_[i] * 0.40)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_tl[i], target_layer_bitrate_[i] * 1.7)
<< " The datarate for the file is greater than target by too much!";
} #if CONFIG_AV1_DECODER
EXPECT_EQ((int)GetMismatchFrames(), 0); #endif
}
::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352,
288, 30, 1, 0, 300); constint bitrate_array[2] = { 300, 600 };
cfg_.rc_target_bitrate = bitrate_array[GET_PARAM(4)];
ResetModel();
intra_only_single_layer_ = true;
number_temporal_layers_ = 1;
number_spatial_layers_ = 1;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_tl[0], cfg_.rc_target_bitrate * 0.80)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_tl[0], cfg_.rc_target_bitrate * 1.60)
<< " The datarate for the file is greater than target by too much!";
}
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.