/* * Copyright (c) 2014 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
// Initialize the cyclic refresh parameters. If spatial layers are used // (i.e., ss_number_layers > 1), these need to be updated per spatial // layer. // Cyclic refresh is only applied on base temporal layer. if (oxcf->ss_number_layers > 1 && tl == 0) {
size_t last_coded_q_map_size;
size_t consec_zero_mv_size;
VP9_COMMON *const cm = &cpi->common;
lc->sb_index = 0;
lc->actual_num_seg1_blocks = 0;
lc->actual_num_seg2_blocks = 0;
lc->counter_encode_maxq_scene_change = 0;
CHECK_MEM_ERROR(&cm->error, lc->map,
vpx_malloc(mi_rows * mi_cols * sizeof(*lc->map)));
memset(lc->map, 0, mi_rows * mi_cols);
last_coded_q_map_size =
mi_rows * mi_cols * sizeof(*lc->last_coded_q_map);
CHECK_MEM_ERROR(&cm->error, lc->last_coded_q_map,
vpx_malloc(last_coded_q_map_size));
assert(MAXQ <= 255);
memset(lc->last_coded_q_map, MAXQ, last_coded_q_map_size);
consec_zero_mv_size = mi_rows * mi_cols * sizeof(*lc->consec_zero_mv);
CHECK_MEM_ERROR(&cm->error, lc->consec_zero_mv,
vpx_malloc(consec_zero_mv_size));
memset(lc->consec_zero_mv, 0, consec_zero_mv_size);
}
}
}
// Still have extra buffer for base layer golden frame if (!(svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) &&
alt_ref_idx < REF_FRAMES)
svc->layer_context[0].gold_ref_idx = alt_ref_idx;
}
// Update the layer context from a change_config() call. void vp9_update_layer_context_change_config(VP9_COMP *const cpi, constint target_bandwidth) {
SVC *const svc = &cpi->svc; const VP9EncoderConfig *const oxcf = &cpi->oxcf; const RATE_CONTROL *const rc = &cpi->rc; int sl, tl, layer = 0, spatial_layer_target; float bitrate_alloc = 1.0; int num_spatial_layers_nonzero_rate = 0;
void 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) return;
if (den == 0 || num == 0) {
*width_out = width_org;
*height_out = height_org; return;
}
w = width_org * num / den;
h = height_org * num / den;
// make height and width even to make chrome player happy
w += w % 2;
h += h % 2;
*width_out = w;
*height_out = h;
}
staticvoid reset_fb_idx_unused(VP9_COMP *const cpi) { // If a reference frame is not referenced or refreshed, then set the // fb_idx for that reference to the first one used/referenced. // This is to avoid setting fb_idx for a reference to a slot that is not // used/needed (i.e., since that reference is not referenced or refreshed).
MV_REFERENCE_FRAME ref_frame;
MV_REFERENCE_FRAME first_ref = 0; int first_fb_idx = 0; int fb_idx[3] = { cpi->lst_fb_idx, cpi->gld_fb_idx, cpi->alt_fb_idx }; for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) { if (cpi->ref_frame_flags & ref_frame_to_flag(ref_frame)) {
first_ref = ref_frame;
first_fb_idx = fb_idx[ref_frame - 1]; break;
}
} if (first_ref > 0) { if (first_ref != LAST_FRAME && !(cpi->ref_frame_flags & VP9_LAST_FLAG) &&
!cpi->ext_refresh_last_frame)
cpi->lst_fb_idx = first_fb_idx; elseif (first_ref != GOLDEN_FRAME &&
!(cpi->ref_frame_flags & VP9_GOLD_FLAG) &&
!cpi->ext_refresh_golden_frame)
cpi->gld_fb_idx = first_fb_idx; elseif (first_ref != ALTREF_FRAME &&
!(cpi->ref_frame_flags & VP9_ALT_FLAG) &&
!cpi->ext_refresh_alt_ref_frame)
cpi->alt_fb_idx = first_fb_idx;
}
}
// Never refresh any reference frame buffers on top temporal layers in // simulcast mode, which has interlayer prediction disabled. staticvoid non_reference_frame_simulcast(VP9_COMP *const cpi) { if (cpi->svc.temporal_layer_id == cpi->svc.number_temporal_layers - 1 &&
cpi->svc.temporal_layer_id > 0) {
cpi->ext_refresh_last_frame = 0;
cpi->ext_refresh_golden_frame = 0;
cpi->ext_refresh_alt_ref_frame = 0;
}
}
// For constrained_from_above drop mode: before encoding superframe (i.e., // at SL0 frame) check all spatial layers (starting from top) for possible // drop, and if so, set a flag to force drop of that layer and all its lower // layers. if (svc->spatial_layer_to_encode == svc->first_spatial_layer_to_encode) { int sl; for (sl = 0; sl < svc->number_spatial_layers; sl++)
svc->force_drop_constrained_from_above[sl] = 0; if (svc->framedrop_mode == CONSTRAINED_FROM_ABOVE_DROP) { for (sl = svc->number_spatial_layers - 1;
sl >= svc->first_spatial_layer_to_encode; sl--) { int layer = sl * svc->number_temporal_layers + svc->temporal_layer_id;
LAYER_CONTEXT *const sl_lc = &svc->layer_context[layer];
cpi->rc = sl_lc->rc;
cpi->oxcf.target_bandwidth = sl_lc->target_bandwidth; if (vp9_test_drop(cpi)) { int sl2; // Set flag to force drop in encoding for this mode. for (sl2 = sl; sl2 >= svc->first_spatial_layer_to_encode; sl2--)
svc->force_drop_constrained_from_above[sl2] = 1; break;
}
}
}
}
// For the fixed (non-flexible/bypass) SVC mode: // If long term temporal reference is enabled at the sequence level // (use_gf_temporal_ref == 1), and inter_layer is disabled (on inter-frames), // we can use golden as a second temporal reference // (since the spatial/inter-layer reference is disabled). // We check that the fb_idx for this reference (buffer_gf_temporal_ref.idx) is // unused (slot 7 and 6 should be available for 3-3 layer system). // For now usage of this second temporal reference will only be used for // highest and next to highest spatial layer (i.e., top and middle layer for // 3 spatial layers).
svc->use_gf_temporal_ref_current_layer = 0; if (svc->use_gf_temporal_ref && !svc->buffer_gf_temporal_ref[0].is_used &&
!svc->buffer_gf_temporal_ref[1].is_used &&
svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS &&
svc->disable_inter_layer_pred != INTER_LAYER_PRED_ON &&
svc->number_spatial_layers <= 3 && svc->number_temporal_layers <= 3 &&
svc->spatial_layer_id >= svc->number_spatial_layers - 2) { // Enable the second (long-term) temporal reference at the frame-level.
svc->use_gf_temporal_ref_current_layer = 1;
}
// Check if current superframe has any layer sync, only check once on // base layer. if (svc->spatial_layer_id == 0) { int sl = 0; // Default is no sync.
svc->superframe_has_layer_sync = 0; for (sl = 0; sl < svc->number_spatial_layers; ++sl) { if (cpi->svc.spatial_layer_sync[sl]) svc->superframe_has_layer_sync = 1;
}
}
// Reset the drop flags for all spatial layers, on the // first_spatial_layer_to_encode. if (svc->spatial_layer_id == svc->first_spatial_layer_to_encode) {
vp9_zero(svc->drop_spatial_layer); // TODO(jianj/marpan): Investigate why setting svc->lst/gld/alt_fb_idx // causes an issue with frame dropping and temporal layers, when the frame // flags are passed via the encode call (bypass mode). Issue is that we're // resetting ext_refresh_frame_flags_pending to 0 on frame drops. if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
memset(&svc->lst_fb_idx, -1, sizeof(svc->lst_fb_idx));
memset(&svc->gld_fb_idx, -1, sizeof(svc->lst_fb_idx));
memset(&svc->alt_fb_idx, -1, sizeof(svc->lst_fb_idx)); // These are set by API before the superframe is encoded and they are // passed to encoder layer by layer. Don't reset them on layer 0 in bypass // mode.
vp9_zero(svc->update_buffer_slot);
vp9_zero(svc->reference_last);
vp9_zero(svc->reference_golden);
vp9_zero(svc->reference_altref); // TODO(jianj): Remove these 3, deprecated.
vp9_zero(svc->update_last);
vp9_zero(svc->update_golden);
vp9_zero(svc->update_altref);
}
}
// Use Eightap_smooth for low resolutions. if (width * height <= 320 * 240)
svc->downsample_filter_type[svc->spatial_layer_id] = EIGHTTAP_SMOOTH; // For scale factors > 0.75, set the phase to 0 (aligns decimated pixel // to source pixel). if (scaling_factor_num > (3 * scaling_factor_den) >> 2)
svc->downsample_filter_phase[svc->spatial_layer_id] = 0;
// The usage of use_base_mv or partition_reuse assumes down-scale of 2x2. // For now, turn off use of base motion vectors and partition reuse if the // spatial scale factors for any layers are not 2, // keep the case of 3 spatial layers with scale factor of 4x4 for base layer. // TODO(marpan): Fix this to allow for use_base_mv for scale factors != 2. if (svc->number_spatial_layers > 1) { int sl; for (sl = 0; sl < svc->number_spatial_layers - 1; ++sl) {
lc = &svc->layer_context[sl * svc->number_temporal_layers +
svc->temporal_layer_id]; if ((lc->scaling_factor_num != lc->scaling_factor_den >> 1) &&
!(lc->scaling_factor_num == lc->scaling_factor_den >> 2 && sl == 0 &&
svc->number_spatial_layers == 3)) {
svc->use_base_mv = 0;
svc->use_partition_reuse = 0; break;
}
} // For non-zero spatial layers: if the previous spatial layer was dropped // disable the base_mv and partition_reuse features. if (svc->spatial_layer_id > 0 &&
svc->drop_spatial_layer[svc->spatial_layer_id - 1]) {
svc->use_base_mv = 0;
svc->use_partition_reuse = 0;
}
}
svc->non_reference_frame = 0; if (cpi->common.frame_type != KEY_FRAME && !cpi->ext_refresh_last_frame &&
!cpi->ext_refresh_golden_frame && !cpi->ext_refresh_alt_ref_frame)
svc->non_reference_frame = 1; // For flexible mode, where update_buffer_slot is used, need to check if // all buffer slots are not refreshed. if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { if (svc->update_buffer_slot[svc->spatial_layer_id] != 0)
svc->non_reference_frame = 0;
}
if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS &&
svc->last_layer_dropped[svc->spatial_layer_id] &&
svc->fb_idx_upd_tl0[svc->spatial_layer_id] != -1 &&
!svc->layer_context[svc->temporal_layer_id].is_key_frame) { // For fixed/non-flexible mode, if the previous frame (same spatial layer // from previous superframe) was dropped, make sure the lst_fb_idx // for this frame corresponds to the buffer index updated on (last) encoded // TL0 frame (with same spatial layer).
cpi->lst_fb_idx = svc->fb_idx_upd_tl0[svc->spatial_layer_id];
}
if (vp9_set_size_literal(cpi, width, height) != 0) return VPX_CODEC_INVALID_PARAM;
void vp9_svc_check_reset_layer_rc_flag(VP9_COMP *const cpi) {
SVC *svc = &cpi->svc; int sl, tl; for (sl = 0; sl < svc->number_spatial_layers; ++sl) { // Check for reset based on avg_frame_bandwidth for spatial layer sl. constint spatial_layer_idx = LAYER_IDS_TO_IDX(
sl, svc->number_temporal_layers - 1, svc->number_temporal_layers);
LAYER_CONTEXT *lc = &svc->layer_context[spatial_layer_idx];
RATE_CONTROL *lrc = &lc->rc; if (lrc->avg_frame_bandwidth / 3 > (lrc->last_avg_frame_bandwidth >> 1) ||
lrc->avg_frame_bandwidth < (lrc->last_avg_frame_bandwidth >> 1)) { // Reset for all temporal layers with spatial layer sl. for (tl = 0; tl < svc->number_temporal_layers; ++tl) { int temporal_layer_idx =
LAYER_IDS_TO_IDX(sl, tl, svc->number_temporal_layers);
lrc = &svc->layer_context[temporal_layer_idx].rc;
lrc->rc_1_frame = 0;
lrc->rc_2_frame = 0;
lrc->bits_off_target = lrc->optimal_buffer_level;
lrc->buffer_level = lrc->optimal_buffer_level;
}
}
}
}
void vp9_svc_constrain_inter_layer_pred(VP9_COMP *const cpi) {
VP9_COMMON *const cm = &cpi->common;
SVC *const svc = &cpi->svc; constint sl = svc->spatial_layer_id; // Check for disabling inter-layer (spatial) prediction, if // svc.disable_inter_layer_pred is set. If the previous spatial layer was // dropped then disable the prediction from this (scaled) reference. // For INTER_LAYER_PRED_OFF_NONKEY: inter-layer prediction is disabled // on key frames or if any spatial layer is a sync layer. if ((svc->disable_inter_layer_pred == INTER_LAYER_PRED_OFF_NONKEY &&
!svc->layer_context[svc->temporal_layer_id].is_key_frame &&
!svc->superframe_has_layer_sync) ||
svc->disable_inter_layer_pred == INTER_LAYER_PRED_OFF ||
svc->drop_spatial_layer[sl - 1]) {
MV_REFERENCE_FRAME ref_frame; for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, ref_frame); if (yv12 != NULL &&
(cpi->ref_frame_flags & ref_frame_to_flag(ref_frame))) { conststruct scale_factors *const scale_fac =
&cm->frame_refs[ref_frame - 1].sf; if (vp9_is_scaled(scale_fac)) {
cpi->ref_frame_flags &= (~ref_frame_to_flag(ref_frame)); // Point golden/altref frame buffer index to last. if (!svc->simulcast_mode) { if (ref_frame == GOLDEN_FRAME)
cpi->gld_fb_idx = cpi->lst_fb_idx; elseif (ref_frame == ALTREF_FRAME)
cpi->alt_fb_idx = cpi->lst_fb_idx;
}
}
}
}
} // For fixed/non-flexible SVC: check for disabling inter-layer prediction. // If the reference for inter-layer prediction (the reference that is scaled) // is not the previous spatial layer from the same superframe, then we disable // inter-layer prediction. Only need to check when inter_layer prediction is // not set to OFF mode. if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS &&
svc->disable_inter_layer_pred != INTER_LAYER_PRED_OFF) { // We only use LAST and GOLDEN for prediction in real-time mode, so we // check both here.
MV_REFERENCE_FRAME ref_frame; for (ref_frame = LAST_FRAME; ref_frame <= GOLDEN_FRAME; ref_frame++) { struct scale_factors *scale_fac = &cm->frame_refs[ref_frame - 1].sf; if (vp9_is_scaled(scale_fac)) { // If this reference was updated on the previous spatial layer of the // current superframe, then we keep this reference (don't disable). // Otherwise we disable the inter-layer prediction. // This condition is verified by checking if the current frame buffer // index is equal to any of the slots for the previous spatial layer, // and if so, check if that slot was updated/refreshed. If that is the // case, then this reference is valid for inter-layer prediction under // the mode INTER_LAYER_PRED_ON_CONSTRAINED. int fb_idx =
ref_frame == LAST_FRAME ? cpi->lst_fb_idx : cpi->gld_fb_idx; int ref_flag = ref_frame == LAST_FRAME ? VP9_LAST_FLAG : VP9_GOLD_FLAG; int disable = 1; if (fb_idx < 0) continue; if ((fb_idx == svc->lst_fb_idx[sl - 1] &&
(svc->update_buffer_slot[sl - 1] & (1 << fb_idx))) ||
(fb_idx == svc->gld_fb_idx[sl - 1] &&
(svc->update_buffer_slot[sl - 1] & (1 << fb_idx))) ||
(fb_idx == svc->alt_fb_idx[sl - 1] &&
(svc->update_buffer_slot[sl - 1] & (1 << fb_idx))))
disable = 0; if (disable) cpi->ref_frame_flags &= (~ref_flag);
}
}
}
}
void vp9_svc_assert_constraints_pattern(VP9_COMP *const cpi) {
SVC *const svc = &cpi->svc; // For fixed/non-flexible mode, the following constraint are expected, // when inter-layer prediction is on (default). if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS &&
svc->disable_inter_layer_pred == INTER_LAYER_PRED_ON &&
svc->framedrop_mode != LAYER_DROP) { if (!svc->layer_context[svc->temporal_layer_id].is_key_frame) { // On non-key frames: LAST is always temporal reference, GOLDEN is // spatial reference. if (svc->temporal_layer_id == 0) // Base temporal only predicts from base temporal.
assert(svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] == 0); else // Non-base temporal only predicts from lower temporal layer.
assert(svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] <
svc->temporal_layer_id); if (svc->spatial_layer_id > 0 && cpi->ref_frame_flags & VP9_GOLD_FLAG &&
svc->spatial_layer_id > svc->first_spatial_layer_to_encode) { // Non-base spatial only predicts from lower spatial layer with same // temporal_id.
assert(svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] ==
svc->spatial_layer_id - 1);
assert(svc->fb_idx_temporal_layer_id[cpi->gld_fb_idx] ==
svc->temporal_layer_id);
}
} elseif (svc->spatial_layer_id > 0 &&
svc->spatial_layer_id > svc->first_spatial_layer_to_encode) { // Only 1 reference for frame whose base is key; reference may be LAST // or GOLDEN, so we check both. if (cpi->ref_frame_flags & VP9_LAST_FLAG) {
assert(svc->fb_idx_spatial_layer_id[cpi->lst_fb_idx] ==
svc->spatial_layer_id - 1);
assert(svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] ==
svc->temporal_layer_id);
} elseif (cpi->ref_frame_flags & VP9_GOLD_FLAG) {
assert(svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] ==
svc->spatial_layer_id - 1);
assert(svc->fb_idx_temporal_layer_id[cpi->gld_fb_idx] ==
svc->temporal_layer_id);
}
}
} elseif (svc->use_gf_temporal_ref_current_layer &&
!svc->layer_context[svc->temporal_layer_id].is_key_frame) { // For the usage of golden as second long term reference: the // temporal_layer_id of that reference must be base temporal layer 0, and // spatial_layer_id of that reference must be same as current // spatial_layer_id. If not, disable feature. // TODO(marpan): Investigate when this can happen, and maybe put this check // and reset in a different place. if (svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] !=
svc->spatial_layer_id ||
svc->fb_idx_temporal_layer_id[cpi->gld_fb_idx] != 0)
svc->use_gf_temporal_ref_current_layer = 0;
}
}
void vp9_svc_check_spatial_layer_sync(VP9_COMP *const cpi) {
SVC *const svc = &cpi->svc; // Only for superframes whose base is not key, as those are // already sync frames. if (!svc->layer_context[svc->temporal_layer_id].is_key_frame) { if (svc->spatial_layer_id == 0) { // On base spatial layer: if the current superframe has a layer sync then // reset the pattern counters and reset to base temporal layer. if (svc->superframe_has_layer_sync)
vp9_svc_reset_temporal_layers(cpi, cpi->common.frame_type == KEY_FRAME);
} // If the layer sync is set for this current spatial layer then // disable the temporal reference. if (svc->spatial_layer_id > 0 &&
svc->spatial_layer_sync[svc->spatial_layer_id]) {
cpi->ref_frame_flags &= (~VP9_LAST_FLAG); if (svc->use_gf_temporal_ref_current_layer) { int index = svc->spatial_layer_id; // If golden is used as second reference: need to remove it from // prediction, reset refresh period to 0, and update the reference.
svc->use_gf_temporal_ref_current_layer = 0;
cpi->rc.baseline_gf_interval = 0;
cpi->rc.frames_till_gf_update_due = 0; // On layer sync frame we must update the buffer index used for long // term reference. Use the alt_ref since it is not used or updated on // sync frames. if (svc->number_spatial_layers == 3) index = svc->spatial_layer_id - 1;
assert(index >= 0);
cpi->alt_fb_idx = svc->buffer_gf_temporal_ref[index].idx;
cpi->ext_refresh_alt_ref_frame = 1;
}
}
}
}
void vp9_svc_update_ref_frame_buffer_idx(VP9_COMP *const cpi) {
SVC *const svc = &cpi->svc; int i = 0; // Update the usage of frame buffer index for base spatial layers. if (svc->spatial_layer_id == 0) { if ((cpi->ref_frame_flags & VP9_LAST_FLAG) || cpi->refresh_last_frame)
svc->fb_idx_base[cpi->lst_fb_idx] = 1; if ((cpi->ref_frame_flags & VP9_GOLD_FLAG) || cpi->refresh_golden_frame)
svc->fb_idx_base[cpi->gld_fb_idx] = 1; if ((cpi->ref_frame_flags & VP9_ALT_FLAG) || cpi->refresh_alt_ref_frame)
svc->fb_idx_base[cpi->alt_fb_idx] = 1; // For bypass/flexible mode: check for refresh slots. if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { for (i = 0; i < REF_FRAMES; ++i) if (svc->update_buffer_slot[0] & (1 << i)) svc->fb_idx_base[i] = 1;
}
}
}
staticvoid vp9_svc_update_ref_frame_bypass_mode(VP9_COMP *const cpi) { // For non-flexible/bypass SVC mode: check for refreshing other buffer // slots.
SVC *const svc = &cpi->svc;
VP9_COMMON *const cm = &cpi->common;
BufferPool *const pool = cm->buffer_pool; int i; for (i = 0; i < REF_FRAMES; i++) { if ((cm->frame_type == KEY_FRAME && !svc->simulcast_mode) ||
svc->update_buffer_slot[svc->spatial_layer_id] & (1 << i)) {
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[i], cm->new_fb_idx);
svc->fb_idx_spatial_layer_id[i] = svc->spatial_layer_id;
svc->fb_idx_temporal_layer_id[i] = svc->temporal_layer_id;
}
}
}
void vp9_svc_update_ref_frame(VP9_COMP *const cpi) {
VP9_COMMON *const cm = &cpi->common;
SVC *const svc = &cpi->svc;
BufferPool *const pool = cm->buffer_pool;
if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS &&
svc->use_set_ref_frame_config) {
vp9_svc_update_ref_frame_bypass_mode(cpi);
} elseif (cm->frame_type == KEY_FRAME && !svc->simulcast_mode) { // Keep track of frame index for each reference frame. int i; // On key frame update all reference frame slots. for (i = 0; i < REF_FRAMES; i++) {
svc->fb_idx_spatial_layer_id[i] = svc->spatial_layer_id;
svc->fb_idx_temporal_layer_id[i] = svc->temporal_layer_id; // LAST/GOLDEN/ALTREF is already updated above. if (i != cpi->lst_fb_idx && i != cpi->gld_fb_idx && i != cpi->alt_fb_idx)
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[i], cm->new_fb_idx);
}
} else { if (cpi->refresh_last_frame) {
svc->fb_idx_spatial_layer_id[cpi->lst_fb_idx] = svc->spatial_layer_id;
svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] = svc->temporal_layer_id;
} if (cpi->refresh_golden_frame) {
svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] = svc->spatial_layer_id;
svc->fb_idx_temporal_layer_id[cpi->gld_fb_idx] = svc->temporal_layer_id;
} if (cpi->refresh_alt_ref_frame) {
svc->fb_idx_spatial_layer_id[cpi->alt_fb_idx] = svc->spatial_layer_id;
svc->fb_idx_temporal_layer_id[cpi->alt_fb_idx] = svc->temporal_layer_id;
}
} // Copy flags from encoder to SVC struct.
vp9_copy_flags_ref_update_idx(cpi);
vp9_svc_update_ref_frame_buffer_idx(cpi);
}
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.