/* * Copyright (c) 2010 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.
*/
/* Work out the average size of a frame within this layer */ if (layer > 0) {
lc->avg_frame_size_for_layer =
(int)round((cpi->oxcf.target_bitrate[layer] -
cpi->oxcf.target_bitrate[layer - 1]) *
1000 / (lc->framerate - prev_layer_framerate));
}
// Upon a run-time change in temporal layers, reset the layer context parameters // for any "new" layers. For "existing" layers, let them inherit the parameters // from the previous layer state (at the same layer #). In future we may want // to better map the previous layer state(s) to the "new" ones. void vp8_reset_temporal_layer_change(VP8_COMP *cpi, const VP8_CONFIG *oxcf, constint prev_num_layers) { int i; double prev_layer_framerate = 0; constint curr_num_layers = cpi->oxcf.number_of_layers; // If the previous state was 1 layer, get current layer context from cpi. // We need this to set the layer context for the new layers below. if (prev_num_layers == 1) {
cpi->current_layer = 0;
vp8_save_layer_context(cpi);
} for (i = 0; i < curr_num_layers; ++i) {
LAYER_CONTEXT *lc = &cpi->layer_context[i]; if (i >= prev_num_layers) {
vp8_init_temporal_layer_context(cpi, oxcf, i, prev_layer_framerate);
} // The initial buffer levels are set based on their starting levels. // We could set the buffer levels based on the previous state (normalized // properly by the layer bandwidths) but we would need to keep track of // the previous set of layer bandwidths (i.e., target_bitrate[i]) // before the layer change. For now, reset to the starting levels.
lc->buffer_level =
cpi->oxcf.starting_buffer_level_in_ms * cpi->oxcf.target_bitrate[i];
lc->bits_off_target = lc->buffer_level; // TDOD(marpan): Should we set the rate_correction_factor and // active_worst/best_quality to values derived from the previous layer // state (to smooth-out quality dips/rate fluctuation at transition)?
// We need to treat the 1 layer case separately: oxcf.target_bitrate[i] // is not set for 1 layer, and the vp8_restore_layer_context/save_context() // are not called in the encoding loop, so we need to call it here to // pass the layer context state to |cpi|. if (curr_num_layers == 1) {
lc->target_bandwidth = cpi->oxcf.target_bandwidth;
lc->buffer_level =
cpi->oxcf.starting_buffer_level_in_ms * lc->target_bandwidth / 1000;
lc->bits_off_target = lc->buffer_level;
vp8_restore_layer_context(cpi, 0);
}
prev_layer_framerate = cpi->output_framerate / cpi->oxcf.rate_decimator[i];
}
}
staticvoid setup_features(VP8_COMP *cpi) { // If segmentation enabled set the update flags if (cpi->mb.e_mbd.segmentation_enabled) {
cpi->mb.e_mbd.update_mb_segmentation_map = 1;
cpi->mb.e_mbd.update_mb_segmentation_data = 1;
} else {
cpi->mb.e_mbd.update_mb_segmentation_map = 0;
cpi->mb.e_mbd.update_mb_segmentation_data = 0;
}
/* Structure used to monitor GF usage */
vpx_free(cpi->gf_active_flags);
cpi->gf_active_flags = 0;
/* Activity mask based per mb zbin adjustments */
vpx_free(cpi->mb_activity_map);
cpi->mb_activity_map = 0;
vpx_free(cpi->mb.pip);
cpi->mb.pip = 0;
}
staticvoid enable_segmentation(VP8_COMP *cpi) { /* Set the appropriate feature bit */
cpi->mb.e_mbd.segmentation_enabled = 1;
cpi->mb.e_mbd.update_mb_segmentation_map = 1;
cpi->mb.e_mbd.update_mb_segmentation_data = 1;
} staticvoid disable_segmentation(VP8_COMP *cpi) { /* Clear the appropriate feature bit */
cpi->mb.e_mbd.segmentation_enabled = 0;
}
/* Valid values for a segment are 0 to 3 * Segmentation map is arrange as [Rows][Columns]
*/ staticvoid set_segmentation_map(VP8_COMP *cpi, unsignedchar *segmentation_map) { /* Copy in the new segmentation map */
memcpy(cpi->segmentation_map, segmentation_map,
(cpi->common.mb_rows * cpi->common.mb_cols));
/* Signal that the map should be updated. */
cpi->mb.e_mbd.update_mb_segmentation_map = 1;
cpi->mb.e_mbd.update_mb_segmentation_data = 1;
}
/* The values given for each segment can be either deltas (from the default * value chosen for the frame) or absolute values. * * Valid range for abs values is: * (0-127 for MB_LVL_ALT_Q), (0-63 for SEGMENT_ALT_LF) * Valid range for delta values are: * (+/-127 for MB_LVL_ALT_Q), (+/-63 for SEGMENT_ALT_LF) * * abs_delta = SEGMENT_DELTADATA (deltas) * abs_delta = SEGMENT_ABSDATA (use the absolute values given). *
*/ staticvoid set_segment_data(VP8_COMP *cpi, signedchar *feature_data, unsignedchar abs_delta) {
cpi->mb.e_mbd.mb_segment_abs_delta = abs_delta;
memcpy(cpi->segment_feature_data, feature_data, sizeof(cpi->segment_feature_data));
}
/* A simple function to cyclically refresh the background at a lower Q */ staticvoid cyclic_background_refresh(VP8_COMP *cpi, int Q, int lf_adjustment) { unsignedchar *seg_map = cpi->segmentation_map; signedchar feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS]; int i; int block_count = cpi->cyclic_refresh_mode_max_mbs_perframe; int mbs_in_frame = cpi->common.mb_rows * cpi->common.mb_cols;
cpi->cyclic_refresh_q = Q / 2;
if (cpi->oxcf.screen_content_mode) { // Modify quality ramp-up based on Q. Above some Q level, increase the // number of blocks to be refreshed, and reduce it below the thredhold. // Turn-off under certain conditions (i.e., away from key frame, and if // we are at good quality (low Q) and most of the blocks were // skipped-encoded // in previous frame. int qp_thresh = (cpi->oxcf.screen_content_mode == 2) ? 80 : 100; if (Q >= qp_thresh) {
cpi->cyclic_refresh_mode_max_mbs_perframe =
(cpi->common.mb_rows * cpi->common.mb_cols) / 10;
} elseif (cpi->frames_since_key > 250 && Q < 20 &&
cpi->mb.skip_true_count > (int)(0.95 * mbs_in_frame)) {
cpi->cyclic_refresh_mode_max_mbs_perframe = 0;
} else {
cpi->cyclic_refresh_mode_max_mbs_perframe =
(cpi->common.mb_rows * cpi->common.mb_cols) / 20;
}
block_count = cpi->cyclic_refresh_mode_max_mbs_perframe;
}
// Set every macroblock to be eligible for update. // For key frame this will reset seg map to 0.
memset(cpi->segmentation_map, 0, mbs_in_frame);
if (cpi->common.frame_type != KEY_FRAME && block_count > 0) { /* Cycle through the macro_block rows */ /* MB loop to set local segmentation map */
i = cpi->cyclic_refresh_mode_index;
assert(i < mbs_in_frame); do { /* If the MB is as a candidate for clean up then mark it for * possible boost/refresh (segment 1) The segment id may get * reset to 0 later if the MB gets coded anything other than * last frame 0,0 as only (last frame 0,0) MBs are eligable for * refresh : that is to say Mbs likely to be background blocks.
*/ if (cpi->cyclic_refresh_map[i] == 0) {
seg_map[i] = 1;
block_count--;
} elseif (cpi->cyclic_refresh_map[i] < 0) {
cpi->cyclic_refresh_map[i]++;
}
i++; if (i == mbs_in_frame) i = 0;
} while (block_count && i != cpi->cyclic_refresh_mode_index);
cpi->cyclic_refresh_mode_index = i;
#if CONFIG_TEMPORAL_DENOISING if (cpi->oxcf.noise_sensitivity > 0) { if (cpi->denoiser.denoiser_mode == kDenoiserOnYUVAggressive &&
Q < (int)cpi->denoiser.denoise_pars.qp_thresh &&
(cpi->frames_since_key >
2 * cpi->denoiser.denoise_pars.consec_zerolast)) { // Under aggressive denoising, use segmentation to turn off loop // filter below some qp thresh. The filter is reduced for all // blocks that have been encoded as ZEROMV LAST x frames in a row, // where x is set by cpi->denoiser.denoise_pars.consec_zerolast. // This is to avoid "dot" artifacts that can occur from repeated // loop filtering on noisy input source.
cpi->cyclic_refresh_q = Q; // lf_adjustment = -MAX_LOOP_FILTER;
lf_adjustment = -40; for (i = 0; i < mbs_in_frame; ++i) {
seg_map[i] = (cpi->consec_zero_last[i] >
cpi->denoiser.denoise_pars.consec_zerolast)
? 1
: 0;
}
}
} #endif
}
/* Set up the quant segment data */
feature_data[MB_LVL_ALT_Q][0] = 0;
feature_data[MB_LVL_ALT_Q][1] = (cpi->cyclic_refresh_q - Q);
feature_data[MB_LVL_ALT_Q][2] = 0;
feature_data[MB_LVL_ALT_Q][3] = 0;
/* Set up the loop segment data */
feature_data[MB_LVL_ALT_LF][0] = 0;
feature_data[MB_LVL_ALT_LF][1] = lf_adjustment;
feature_data[MB_LVL_ALT_LF][2] = 0;
feature_data[MB_LVL_ALT_LF][3] = 0;
/* Initialise the feature data structure */
set_segment_data(cpi, &feature_data[0][0], SEGMENT_DELTADATA);
}
void vp8_set_speed_features(VP8_COMP *cpi) {
SPEED_FEATURES *sf = &cpi->sf; int Mode = cpi->compressor_speed; int Speed = cpi->Speed; int Speed2; int i;
VP8_COMMON *cm = &cpi->common; int last_improved_quant = sf->improved_quant; int ref_frames;
/* Initialise default mode frequency sampling variables */ for (i = 0; i < MAX_MODES; ++i) {
cpi->mode_check_freq[i] = 0;
}
// Special case for temporal layers. // Reduce the thresholds for zero/nearest/near for GOLDEN, if GOLDEN is // used as second reference. We don't modify thresholds for ALTREF case // since ALTREF is usually used as long-term reference in temporal layers. if ((cpi->Speed <= 6) && (cpi->oxcf.number_of_layers > 1) &&
(cpi->ref_frame_flags & VP8_LAST_FRAME) &&
(cpi->ref_frame_flags & VP8_GOLD_FRAME)) { if (cpi->closest_reference_frame == GOLDEN_FRAME) {
sf->thresh_mult[THR_ZERO2] = sf->thresh_mult[THR_ZERO2] >> 3;
sf->thresh_mult[THR_NEAREST2] = sf->thresh_mult[THR_NEAREST2] >> 3;
sf->thresh_mult[THR_NEAR2] = sf->thresh_mult[THR_NEAR2] >> 3;
} else {
sf->thresh_mult[THR_ZERO2] = sf->thresh_mult[THR_ZERO2] >> 1;
sf->thresh_mult[THR_NEAREST2] = sf->thresh_mult[THR_NEAREST2] >> 1;
sf->thresh_mult[THR_NEAR2] = sf->thresh_mult[THR_NEAR2] >> 1;
}
}
// For real-time mode at speed 10 keep the mode_check_freq threshold // for NEW1 similar to that of speed 9.
Speed2 = Speed; if (cpi->Speed == 10 && Mode == 2) Speed2 = RT(9);
cpi->mode_check_freq[THR_NEW1] = speed_map(Speed2, mode_check_freq_map_new1);
/* Slow quant, dct and trellis not worthwhile for first pass * so make sure they are always turned off.
*/ if (cpi->pass == 1) {
sf->improved_quant = 0;
sf->optimize_coefficients = 0;
sf->improved_dct = 0;
}
if (cpi->sf.improved_dct) {
cpi->mb.short_fdct8x4 = vp8_short_fdct8x4;
cpi->mb.short_fdct4x4 = vp8_short_fdct4x4;
} else { /* No fast FDCT defined for any platform at this time. */
cpi->mb.short_fdct8x4 = vp8_short_fdct8x4;
cpi->mb.short_fdct4x4 = vp8_short_fdct4x4;
}
cpi->mb.short_walsh4x4 = vp8_short_walsh4x4;
if (cpi->sf.improved_quant) {
cpi->mb.quantize_b = vp8_regular_quantize_b;
} else {
cpi->mb.quantize_b = vp8_fast_quantize_b;
} if (cpi->sf.improved_quant != last_improved_quant) vp8cx_init_quantizer(cpi);
if (vp8_yv12_alloc_frame_buffer(&cpi->pick_lf_lvl_frame, width, height,
VP8BORDERINPIXELS)) {
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, "Failed to allocate last frame buffer");
}
if (vp8_yv12_alloc_frame_buffer(&cpi->scaled_source, width, height,
VP8BORDERINPIXELS)) {
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, "Failed to allocate scaled source buffer");
}
/* Frame rate is not available on the first frame, as it's derived from * the observed timestamps. The actual value used here doesn't matter * too much, as it will adapt quickly.
*/ if (oxcf->timebase.num > 0) {
cpi->framerate =
(double)(oxcf->timebase.den) / (double)(oxcf->timebase.num);
} else {
cpi->framerate = 30;
}
/* If the reciprocal of the timebase seems like a reasonable framerate, * then use that as a guess, otherwise use 30.
*/ if (cpi->framerate > 180) cpi->framerate = 30;
/* change includes all joint functionality */
vp8_change_config(cpi, oxcf);
/* Initialize active best and worst q and average q values. */
cpi->active_worst_quality = cpi->oxcf.worst_allowed_q;
cpi->active_best_quality = cpi->oxcf.best_allowed_q;
cpi->avg_frame_qindex = cpi->oxcf.worst_allowed_q;
for (i = 0; i < cpi->oxcf.number_of_layers; ++i) {
vp8_init_temporal_layer_context(cpi, oxcf, i, prev_layer_framerate);
prev_layer_framerate =
cpi->output_framerate / cpi->oxcf.rate_decimator[i];
}
}
#if VP8_TEMPORAL_ALT_REF
{ int i;
cpi->fixed_divide[0] = 0;
for (i = 1; i < 512; ++i) cpi->fixed_divide[i] = 0x80000 / i;
} #endif
}
/* Update snapshots of the layer contexts to reflect new parameters */ if (oxcf->number_of_layers > 1) { unsignedint i; double prev_layer_framerate = 0;
assert(oxcf->number_of_layers <= VPX_TS_MAX_LAYERS); for (i = 0; i < oxcf->number_of_layers && i < VPX_TS_MAX_LAYERS; ++i) {
LAYER_CONTEXT *lc = &cpi->layer_context[i];
/* Work out the average size of a frame within this layer */ if (i > 0) {
lc->avg_frame_size_for_layer =
(int)round((oxcf->target_bitrate[i] - oxcf->target_bitrate[i - 1]) *
1000 / (lc->framerate - prev_layer_framerate));
}
// GF behavior for 1 pass CBR, used when error_resilience is off. if (!cpi->oxcf.error_resilient_mode &&
cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER &&
cpi->oxcf.Mode == MODE_REALTIME)
cpi->baseline_gf_interval = cpi->gf_interval_onepass_cbr;
/* Set or reset optimal and maximum buffer levels. */ if (cpi->oxcf.optimal_buffer_level == 0) {
cpi->oxcf.optimal_buffer_level = cpi->oxcf.target_bandwidth / 8;
} else {
cpi->oxcf.optimal_buffer_level = rescale(
(int)cpi->oxcf.optimal_buffer_level, cpi->oxcf.target_bandwidth, 1000);
}
if (cpi->oxcf.maximum_buffer_size == 0) {
cpi->oxcf.maximum_buffer_size = cpi->oxcf.target_bandwidth / 8;
} else {
cpi->oxcf.maximum_buffer_size = rescale((int)cpi->oxcf.maximum_buffer_size,
cpi->oxcf.target_bandwidth, 1000);
} // Under a configuration change, where maximum_buffer_size may change, // keep buffer level clipped to the maximum allowed buffer size. if (cpi->bits_off_target > cpi->oxcf.maximum_buffer_size) {
cpi->bits_off_target = cpi->oxcf.maximum_buffer_size;
cpi->buffer_level = cpi->bits_off_target;
}
/* Set up frame rate and related parameters rate control values. */
vp8_new_framerate(cpi, cpi->framerate);
/* Set absolute upper and lower quality limits */
cpi->worst_quality = cpi->oxcf.worst_allowed_q;
cpi->best_quality = cpi->oxcf.best_allowed_q;
/* active values should only be modified if out of new range */ if (cpi->active_worst_quality > cpi->oxcf.worst_allowed_q) {
cpi->active_worst_quality = cpi->oxcf.worst_allowed_q;
} /* less likely */ elseif (cpi->active_worst_quality < cpi->oxcf.best_allowed_q) {
cpi->active_worst_quality = cpi->oxcf.best_allowed_q;
} if (cpi->active_best_quality < cpi->oxcf.best_allowed_q) {
cpi->active_best_quality = cpi->oxcf.best_allowed_q;
} /* less likely */ elseif (cpi->active_best_quality > cpi->oxcf.worst_allowed_q) {
cpi->active_best_quality = cpi->oxcf.worst_allowed_q;
}
// Check if the number of temporal layers has changed, and if so reset the // pattern counter and set/initialize the temporal layer context for the // new layer configuration. if (cpi->oxcf.number_of_layers != prev_number_of_layers) { // If the number of temporal layers are changed we must start at the // base of the pattern cycle, so set the layer id to 0 and reset // the temporal pattern counter. if (cpi->temporal_layer_id > 0) {
cpi->temporal_layer_id = 0;
}
cpi->temporal_pattern_counter = 0;
vp8_reset_temporal_layer_change(cpi, oxcf, prev_number_of_layers);
}
if (!cpi->initial_width) {
cpi->initial_width = cpi->oxcf.Width;
cpi->initial_height = cpi->oxcf.Height;
}
/* TODO(jkoleszar): if an internal spatial resampling is active, * and we downsize the input image, maybe we should clear the * internal scale immediately rather than waiting for it to * correct.
*/
/* VP8 sharpness level mapping 0-7 (vs 0-10 in general VPx dialogs) */ if (cpi->oxcf.Sharpness > 7) cpi->oxcf.Sharpness = 7;
cm->sharpness_level = cpi->oxcf.Sharpness;
if (cm->horiz_scale != VP8E_NORMAL || cm->vert_scale != VP8E_NORMAL) { int hr, hs, vr, vs;
/* force to allowlag to 0 if lag_in_frames is 0; */ if (cpi->oxcf.lag_in_frames == 0) {
cpi->oxcf.allow_lag = 0;
} /* Limit on lag buffers as these are not currently dynamically allocated */ elseif (cpi->oxcf.lag_in_frames > MAX_LAG_BUFFERS) {
cpi->oxcf.lag_in_frames = MAX_LAG_BUFFERS;
}
/* Prime the recent reference frame usage counters. * Hereafter they will be maintained as a sort of moving average
*/
cpi->recent_ref_frame_usage[INTRA_FRAME] = 1;
cpi->recent_ref_frame_usage[LAST_FRAME] = 1;
cpi->recent_ref_frame_usage[GOLDEN_FRAME] = 1;
cpi->recent_ref_frame_usage[ALTREF_FRAME] = 1;
/* Set reference frame sign bias for ALTREF frame to 1 (for now) */
cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 1;
/*Initialize the feed-forward activity masking.*/
cpi->activity_avg = 90 << 12;
/* Give a sensible default for the first frame. */
cpi->frames_since_key = 8;
cpi->key_frame_frequency = cpi->oxcf.key_freq;
cpi->this_key_frame_forced = 0;
cpi->next_key_frame_forced = 0;
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.