vp10 cleanup: remove svc code
Spatial/temporal svc code was removed. Verified using Borg test, and the results before and after the change are matching. Change-Id: I4c2ee5cd560428e3e50be02e57e5871ef4246390
This commit is contained in:
@@ -291,7 +291,7 @@ void vp10_cyclic_refresh_postencode(VP10_COMP *const cpi) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set golden frame update interval, for non-svc 1 pass CBR mode.
|
// Set golden frame update interval, for 1 pass CBR mode.
|
||||||
void vp10_cyclic_refresh_set_golden_update(VP10_COMP *const cpi) {
|
void vp10_cyclic_refresh_set_golden_update(VP10_COMP *const cpi) {
|
||||||
RATE_CONTROL *const rc = &cpi->rc;
|
RATE_CONTROL *const rc = &cpi->rc;
|
||||||
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
|
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
|
||||||
@@ -484,10 +484,7 @@ void vp10_cyclic_refresh_setup(VP10_COMP *const cpi) {
|
|||||||
if (cm->current_video_frame == 0)
|
if (cm->current_video_frame == 0)
|
||||||
cr->low_content_avg = 0.0;
|
cr->low_content_avg = 0.0;
|
||||||
// Don't apply refresh on key frame or enhancement layer frames.
|
// Don't apply refresh on key frame or enhancement layer frames.
|
||||||
if (!apply_cyclic_refresh ||
|
if (!apply_cyclic_refresh || cm->frame_type == KEY_FRAME) {
|
||||||
(cm->frame_type == KEY_FRAME) ||
|
|
||||||
(cpi->svc.temporal_layer_id > 0) ||
|
|
||||||
(cpi->svc.spatial_layer_id > 0)) {
|
|
||||||
// Set segmentation map to 0 and disable.
|
// Set segmentation map to 0 and disable.
|
||||||
unsigned char *const seg_map = cpi->segmentation_map;
|
unsigned char *const seg_map = cpi->segmentation_map;
|
||||||
memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
|
memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ void vp10_cyclic_refresh_update__map(struct VP10_COMP *const cpi);
|
|||||||
// Update the actual number of blocks that were applied the segment delta q.
|
// Update the actual number of blocks that were applied the segment delta q.
|
||||||
void vp10_cyclic_refresh_postencode(struct VP10_COMP *const cpi);
|
void vp10_cyclic_refresh_postencode(struct VP10_COMP *const cpi);
|
||||||
|
|
||||||
// Set golden frame update interval, for non-svc 1 pass CBR mode.
|
// Set golden frame update interval, for 1 pass CBR mode.
|
||||||
void vp10_cyclic_refresh_set_golden_update(struct VP10_COMP *const cpi);
|
void vp10_cyclic_refresh_set_golden_update(struct VP10_COMP *const cpi);
|
||||||
|
|
||||||
// Check if we should not update golden reference, based on past refresh stats.
|
// Check if we should not update golden reference, based on past refresh stats.
|
||||||
|
|||||||
@@ -996,18 +996,7 @@ static void write_frame_size_with_refs(VP10_COMP *cpi,
|
|||||||
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
|
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
|
||||||
YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, ref_frame);
|
YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, ref_frame);
|
||||||
|
|
||||||
// Set "found" to 0 for temporal svc and for spatial svc key frame
|
if (cfg != NULL) {
|
||||||
if (cpi->use_svc &&
|
|
||||||
((cpi->svc.number_temporal_layers > 1 &&
|
|
||||||
cpi->oxcf.rc_mode == VPX_CBR) ||
|
|
||||||
(cpi->svc.number_spatial_layers > 1 &&
|
|
||||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame) ||
|
|
||||||
(is_two_pass_svc(cpi) &&
|
|
||||||
cpi->svc.encode_empty_frame_state == ENCODING &&
|
|
||||||
cpi->svc.layer_context[0].frames_from_key_frame <
|
|
||||||
cpi->svc.number_temporal_layers + 1))) {
|
|
||||||
found = 0;
|
|
||||||
} else if (cfg != NULL) {
|
|
||||||
found = cm->width == cfg->y_crop_width &&
|
found = cm->width == cfg->y_crop_width &&
|
||||||
cm->height == cfg->y_crop_height;
|
cm->height == cfg->y_crop_height;
|
||||||
}
|
}
|
||||||
@@ -1093,14 +1082,6 @@ static void write_uncompressed_header(VP10_COMP *cpi,
|
|||||||
write_bitdepth_colorspace_sampling(cm, wb);
|
write_bitdepth_colorspace_sampling(cm, wb);
|
||||||
write_frame_size(cm, wb);
|
write_frame_size(cm, wb);
|
||||||
} else {
|
} else {
|
||||||
// In spatial svc if it's not error_resilient_mode then we need to code all
|
|
||||||
// visible frames as invisible. But we need to keep the show_frame flag so
|
|
||||||
// that the publisher could know whether it is supposed to be visible.
|
|
||||||
// So we will code the show_frame flag as it is. Then code the intra_only
|
|
||||||
// bit here. This will make the bitstream incompatible. In the player we
|
|
||||||
// will change to show_frame flag to 0, then add an one byte frame with
|
|
||||||
// show_existing_frame flag which tells the decoder which frame we want to
|
|
||||||
// show.
|
|
||||||
if (!cm->show_frame)
|
if (!cm->show_frame)
|
||||||
vpx_wb_write_bit(wb, cm->intra_only);
|
vpx_wb_write_bit(wb, cm->intra_only);
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,7 @@ void vp10_pack_bitstream(VP10_COMP *cpi, uint8_t *dest, size_t *size);
|
|||||||
|
|
||||||
static INLINE int vp10_preserve_existing_gf(VP10_COMP *cpi) {
|
static INLINE int vp10_preserve_existing_gf(VP10_COMP *cpi) {
|
||||||
return !cpi->multi_arf_allowed && cpi->refresh_golden_frame &&
|
return !cpi->multi_arf_allowed && cpi->refresh_golden_frame &&
|
||||||
cpi->rc.is_src_frame_alt_ref &&
|
cpi->rc.is_src_frame_alt_ref;
|
||||||
(!cpi->use_svc || // Add spatial svc base layer case here
|
|
||||||
(is_two_pass_svc(cpi) &&
|
|
||||||
cpi->svc.spatial_layer_id == 0 &&
|
|
||||||
cpi->svc.layer_context[0].gold_ref_idx >=0 &&
|
|
||||||
cpi->oxcf.ss_enable_auto_arf[0]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -695,11 +695,7 @@ static int choose_partitioning(VP10_COMP *cpi,
|
|||||||
s = x->plane[0].src.buf;
|
s = x->plane[0].src.buf;
|
||||||
sp = x->plane[0].src.stride;
|
sp = x->plane[0].src.stride;
|
||||||
|
|
||||||
if (!is_key_frame && !(is_one_pass_cbr_svc(cpi) &&
|
if (!is_key_frame) {
|
||||||
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame)) {
|
|
||||||
// In the case of spatial/temporal scalable coding, the assumption here is
|
|
||||||
// that the temporal reference frame will always be of type LAST_FRAME.
|
|
||||||
// TODO(marpan): If that assumption is broken, we need to revisit this code.
|
|
||||||
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
|
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
|
||||||
unsigned int uv_sad;
|
unsigned int uv_sad;
|
||||||
const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
|
const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
|
||||||
@@ -710,12 +706,7 @@ static int choose_partitioning(VP10_COMP *cpi,
|
|||||||
+ (mi_col + 4 < cm->mi_cols) * 2 + (mi_row + 4 < cm->mi_rows);
|
+ (mi_col + 4 < cm->mi_cols) * 2 + (mi_row + 4 < cm->mi_rows);
|
||||||
|
|
||||||
assert(yv12 != NULL);
|
assert(yv12 != NULL);
|
||||||
|
yv12_g = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
|
||||||
if (!(is_one_pass_cbr_svc(cpi) && cpi->svc.spatial_layer_id)) {
|
|
||||||
// For now, GOLDEN will not be used for non-zero spatial layers, since
|
|
||||||
// it may not be a temporal reference.
|
|
||||||
yv12_g = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (yv12_g && yv12_g != yv12) {
|
if (yv12_g && yv12_g != yv12) {
|
||||||
vp10_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
|
vp10_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
|
||||||
@@ -851,9 +842,7 @@ static int choose_partitioning(VP10_COMP *cpi,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO(marpan): There is an issue with variance based on 4x4 average in
|
if (is_key_frame || (low_res &&
|
||||||
// svc mode, don't allow it for now.
|
|
||||||
if (is_key_frame || (low_res && !cpi->use_svc &&
|
|
||||||
vt.split[i].split[j].part_variances.none.variance >
|
vt.split[i].split[j].part_variances.none.variance >
|
||||||
(thresholds[1] << 1))) {
|
(thresholds[1] << 1))) {
|
||||||
force_split[split_index] = 0;
|
force_split[split_index] = 0;
|
||||||
|
|||||||
@@ -42,7 +42,6 @@
|
|||||||
#include "vp10/encoder/segmentation.h"
|
#include "vp10/encoder/segmentation.h"
|
||||||
#include "vp10/encoder/skin_detection.h"
|
#include "vp10/encoder/skin_detection.h"
|
||||||
#include "vp10/encoder/speed_features.h"
|
#include "vp10/encoder/speed_features.h"
|
||||||
#include "vp10/encoder/svc_layercontext.h"
|
|
||||||
#include "vp10/encoder/temporal_filter.h"
|
#include "vp10/encoder/temporal_filter.h"
|
||||||
|
|
||||||
#include "./vp10_rtcd.h"
|
#include "./vp10_rtcd.h"
|
||||||
@@ -238,13 +237,11 @@ static void setup_frame(VP10_COMP *cpi) {
|
|||||||
if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
|
if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
|
||||||
vp10_setup_past_independence(cm);
|
vp10_setup_past_independence(cm);
|
||||||
} else {
|
} else {
|
||||||
if (!cpi->use_svc)
|
cm->frame_context_idx = cpi->refresh_alt_ref_frame;
|
||||||
cm->frame_context_idx = cpi->refresh_alt_ref_frame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cm->frame_type == KEY_FRAME) {
|
if (cm->frame_type == KEY_FRAME) {
|
||||||
if (!is_two_pass_svc(cpi))
|
cpi->refresh_golden_frame = 1;
|
||||||
cpi->refresh_golden_frame = 1;
|
|
||||||
cpi->refresh_alt_ref_frame = 1;
|
cpi->refresh_alt_ref_frame = 1;
|
||||||
vp10_zero(cpi->interp_filter_selected);
|
vp10_zero(cpi->interp_filter_selected);
|
||||||
} else {
|
} else {
|
||||||
@@ -336,7 +333,6 @@ void vp10_initialize_enc(void) {
|
|||||||
|
|
||||||
static void dealloc_compressor_data(VP10_COMP *cpi) {
|
static void dealloc_compressor_data(VP10_COMP *cpi) {
|
||||||
VP10_COMMON *const cm = &cpi->common;
|
VP10_COMMON *const cm = &cpi->common;
|
||||||
int i;
|
|
||||||
|
|
||||||
vpx_free(cpi->mbmi_ext_base);
|
vpx_free(cpi->mbmi_ext_base);
|
||||||
cpi->mbmi_ext_base = NULL;
|
cpi->mbmi_ext_base = NULL;
|
||||||
@@ -393,26 +389,10 @@ static void dealloc_compressor_data(VP10_COMP *cpi) {
|
|||||||
|
|
||||||
vp10_free_pc_tree(&cpi->td);
|
vp10_free_pc_tree(&cpi->td);
|
||||||
|
|
||||||
for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
|
|
||||||
LAYER_CONTEXT *const lc = &cpi->svc.layer_context[i];
|
|
||||||
vpx_free(lc->rc_twopass_stats_in.buf);
|
|
||||||
lc->rc_twopass_stats_in.buf = NULL;
|
|
||||||
lc->rc_twopass_stats_in.sz = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cpi->source_diff_var != NULL) {
|
if (cpi->source_diff_var != NULL) {
|
||||||
vpx_free(cpi->source_diff_var);
|
vpx_free(cpi->source_diff_var);
|
||||||
cpi->source_diff_var = NULL;
|
cpi->source_diff_var = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_LAG_BUFFERS; ++i) {
|
|
||||||
vpx_free_frame_buffer(&cpi->svc.scaled_frames[i]);
|
|
||||||
}
|
|
||||||
memset(&cpi->svc.scaled_frames[0], 0,
|
|
||||||
MAX_LAG_BUFFERS * sizeof(cpi->svc.scaled_frames[0]));
|
|
||||||
|
|
||||||
vpx_free_frame_buffer(&cpi->svc.empty_frame.img);
|
|
||||||
memset(&cpi->svc.empty_frame, 0, sizeof(cpi->svc.empty_frame));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void save_coding_context(VP10_COMP *cpi) {
|
static void save_coding_context(VP10_COMP *cpi) {
|
||||||
@@ -717,16 +697,9 @@ static void set_tile_limits(VP10_COMP *cpi) {
|
|||||||
int min_log2_tile_cols, max_log2_tile_cols;
|
int min_log2_tile_cols, max_log2_tile_cols;
|
||||||
vp10_get_tile_n_bits(cm->mi_cols, &min_log2_tile_cols, &max_log2_tile_cols);
|
vp10_get_tile_n_bits(cm->mi_cols, &min_log2_tile_cols, &max_log2_tile_cols);
|
||||||
|
|
||||||
if (is_two_pass_svc(cpi) &&
|
cm->log2_tile_cols = clamp(cpi->oxcf.tile_columns,
|
||||||
(cpi->svc.encode_empty_frame_state == ENCODING ||
|
min_log2_tile_cols, max_log2_tile_cols);
|
||||||
cpi->svc.number_spatial_layers > 1)) {
|
cm->log2_tile_rows = cpi->oxcf.tile_rows;
|
||||||
cm->log2_tile_cols = 0;
|
|
||||||
cm->log2_tile_rows = 0;
|
|
||||||
} else {
|
|
||||||
cm->log2_tile_cols = clamp(cpi->oxcf.tile_columns,
|
|
||||||
min_log2_tile_cols, max_log2_tile_cols);
|
|
||||||
cm->log2_tile_rows = cpi->oxcf.tile_rows;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_frame_size(VP10_COMP *cpi) {
|
static void update_frame_size(VP10_COMP *cpi) {
|
||||||
@@ -741,19 +714,6 @@ static void update_frame_size(VP10_COMP *cpi) {
|
|||||||
cm->mi_rows * cm->mi_cols * sizeof(*cpi->mbmi_ext_base));
|
cm->mi_rows * cm->mi_cols * sizeof(*cpi->mbmi_ext_base));
|
||||||
|
|
||||||
set_tile_limits(cpi);
|
set_tile_limits(cpi);
|
||||||
|
|
||||||
if (is_two_pass_svc(cpi)) {
|
|
||||||
if (vpx_realloc_frame_buffer(&cpi->alt_ref_buffer,
|
|
||||||
cm->width, cm->height,
|
|
||||||
cm->subsampling_x, cm->subsampling_y,
|
|
||||||
#if CONFIG_VP9_HIGHBITDEPTH
|
|
||||||
cm->use_highbitdepth,
|
|
||||||
#endif
|
|
||||||
VP9_ENC_BORDER_IN_PIXELS, cm->byte_alignment,
|
|
||||||
NULL, NULL, NULL))
|
|
||||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
|
||||||
"Failed to reallocate alt_ref_buffer");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_buffer_indices(VP10_COMP *cpi) {
|
static void init_buffer_indices(VP10_COMP *cpi) {
|
||||||
@@ -779,23 +739,9 @@ static void init_config(struct VP10_COMP *cpi, VP10EncoderConfig *oxcf) {
|
|||||||
cm->height = oxcf->height;
|
cm->height = oxcf->height;
|
||||||
vp10_alloc_compressor_data(cpi);
|
vp10_alloc_compressor_data(cpi);
|
||||||
|
|
||||||
cpi->svc.temporal_layering_mode = oxcf->temporal_layering_mode;
|
|
||||||
|
|
||||||
// Single thread case: use counts in common.
|
// Single thread case: use counts in common.
|
||||||
cpi->td.counts = &cm->counts;
|
cpi->td.counts = &cm->counts;
|
||||||
|
|
||||||
// Spatial scalability.
|
|
||||||
cpi->svc.number_spatial_layers = oxcf->ss_number_layers;
|
|
||||||
// Temporal scalability.
|
|
||||||
cpi->svc.number_temporal_layers = oxcf->ts_number_layers;
|
|
||||||
|
|
||||||
if ((cpi->svc.number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) ||
|
|
||||||
((cpi->svc.number_temporal_layers > 1 ||
|
|
||||||
cpi->svc.number_spatial_layers > 1) &&
|
|
||||||
cpi->oxcf.pass != 1)) {
|
|
||||||
vp10_init_layer_context(cpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
// change includes all joint functionality
|
// change includes all joint functionality
|
||||||
vp10_change_config(cpi, oxcf);
|
vp10_change_config(cpi, oxcf);
|
||||||
|
|
||||||
@@ -1519,15 +1465,6 @@ void vp10_change_config(struct VP10_COMP *cpi, const VP10EncoderConfig *oxcf) {
|
|||||||
}
|
}
|
||||||
update_frame_size(cpi);
|
update_frame_size(cpi);
|
||||||
|
|
||||||
if ((cpi->svc.number_temporal_layers > 1 &&
|
|
||||||
cpi->oxcf.rc_mode == VPX_CBR) ||
|
|
||||||
((cpi->svc.number_temporal_layers > 1 ||
|
|
||||||
cpi->svc.number_spatial_layers > 1) &&
|
|
||||||
cpi->oxcf.pass != 1)) {
|
|
||||||
vp10_update_layer_context_change_config(cpi,
|
|
||||||
(int)cpi->oxcf.target_bandwidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
cpi->alt_ref_source = NULL;
|
cpi->alt_ref_source = NULL;
|
||||||
rc->is_src_frame_alt_ref = 0;
|
rc->is_src_frame_alt_ref = 0;
|
||||||
|
|
||||||
@@ -1618,7 +1555,6 @@ VP10_COMP *vp10_create_compressor(VP10EncoderConfig *oxcf,
|
|||||||
(FRAME_CONTEXT *)vpx_calloc(FRAME_CONTEXTS,
|
(FRAME_CONTEXT *)vpx_calloc(FRAME_CONTEXTS,
|
||||||
sizeof(*cm->frame_contexts)));
|
sizeof(*cm->frame_contexts)));
|
||||||
|
|
||||||
cpi->use_svc = 0;
|
|
||||||
cpi->resize_state = 0;
|
cpi->resize_state = 0;
|
||||||
cpi->resize_avg_qp = 0;
|
cpi->resize_avg_qp = 0;
|
||||||
cpi->resize_buffer_underflow = 0;
|
cpi->resize_buffer_underflow = 0;
|
||||||
@@ -1757,63 +1693,24 @@ VP10_COMP *vp10_create_compressor(VP10EncoderConfig *oxcf,
|
|||||||
const size_t packet_sz = sizeof(FIRSTPASS_STATS);
|
const size_t packet_sz = sizeof(FIRSTPASS_STATS);
|
||||||
const int packets = (int)(oxcf->two_pass_stats_in.sz / packet_sz);
|
const int packets = (int)(oxcf->two_pass_stats_in.sz / packet_sz);
|
||||||
|
|
||||||
if (cpi->svc.number_spatial_layers > 1
|
|
||||||
|| cpi->svc.number_temporal_layers > 1) {
|
|
||||||
FIRSTPASS_STATS *const stats = oxcf->two_pass_stats_in.buf;
|
|
||||||
FIRSTPASS_STATS *stats_copy[VPX_SS_MAX_LAYERS] = {0};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < oxcf->ss_number_layers; ++i) {
|
|
||||||
FIRSTPASS_STATS *const last_packet_for_layer =
|
|
||||||
&stats[packets - oxcf->ss_number_layers + i];
|
|
||||||
const int layer_id = (int)last_packet_for_layer->spatial_layer_id;
|
|
||||||
const int packets_in_layer = (int)last_packet_for_layer->count + 1;
|
|
||||||
if (layer_id >= 0 && layer_id < oxcf->ss_number_layers) {
|
|
||||||
LAYER_CONTEXT *const lc = &cpi->svc.layer_context[layer_id];
|
|
||||||
|
|
||||||
vpx_free(lc->rc_twopass_stats_in.buf);
|
|
||||||
|
|
||||||
lc->rc_twopass_stats_in.sz = packets_in_layer * packet_sz;
|
|
||||||
CHECK_MEM_ERROR(cm, lc->rc_twopass_stats_in.buf,
|
|
||||||
vpx_malloc(lc->rc_twopass_stats_in.sz));
|
|
||||||
lc->twopass.stats_in_start = lc->rc_twopass_stats_in.buf;
|
|
||||||
lc->twopass.stats_in = lc->twopass.stats_in_start;
|
|
||||||
lc->twopass.stats_in_end = lc->twopass.stats_in_start
|
|
||||||
+ packets_in_layer - 1;
|
|
||||||
stats_copy[layer_id] = lc->rc_twopass_stats_in.buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < packets; ++i) {
|
|
||||||
const int layer_id = (int)stats[i].spatial_layer_id;
|
|
||||||
if (layer_id >= 0 && layer_id < oxcf->ss_number_layers
|
|
||||||
&& stats_copy[layer_id] != NULL) {
|
|
||||||
*stats_copy[layer_id] = stats[i];
|
|
||||||
++stats_copy[layer_id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vp10_init_second_pass_spatial_svc(cpi);
|
|
||||||
} else {
|
|
||||||
#if CONFIG_FP_MB_STATS
|
#if CONFIG_FP_MB_STATS
|
||||||
if (cpi->use_fp_mb_stats) {
|
if (cpi->use_fp_mb_stats) {
|
||||||
const size_t psz = cpi->common.MBs * sizeof(uint8_t);
|
const size_t psz = cpi->common.MBs * sizeof(uint8_t);
|
||||||
const int ps = (int)(oxcf->firstpass_mb_stats_in.sz / psz);
|
const int ps = (int)(oxcf->firstpass_mb_stats_in.sz / psz);
|
||||||
|
|
||||||
cpi->twopass.firstpass_mb_stats.mb_stats_start =
|
cpi->twopass.firstpass_mb_stats.mb_stats_start =
|
||||||
oxcf->firstpass_mb_stats_in.buf;
|
oxcf->firstpass_mb_stats_in.buf;
|
||||||
cpi->twopass.firstpass_mb_stats.mb_stats_end =
|
cpi->twopass.firstpass_mb_stats.mb_stats_end =
|
||||||
cpi->twopass.firstpass_mb_stats.mb_stats_start +
|
cpi->twopass.firstpass_mb_stats.mb_stats_start +
|
||||||
(ps - 1) * cpi->common.MBs * sizeof(uint8_t);
|
(ps - 1) * cpi->common.MBs * sizeof(uint8_t);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cpi->twopass.stats_in_start = oxcf->two_pass_stats_in.buf;
|
cpi->twopass.stats_in_start = oxcf->two_pass_stats_in.buf;
|
||||||
cpi->twopass.stats_in = cpi->twopass.stats_in_start;
|
cpi->twopass.stats_in = cpi->twopass.stats_in_start;
|
||||||
cpi->twopass.stats_in_end = &cpi->twopass.stats_in[packets - 1];
|
cpi->twopass.stats_in_end = &cpi->twopass.stats_in[packets - 1];
|
||||||
|
|
||||||
vp10_init_second_pass(cpi);
|
vp10_init_second_pass(cpi);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vp10_set_speed_features_framesize_independent(cpi);
|
vp10_set_speed_features_framesize_independent(cpi);
|
||||||
@@ -2354,11 +2251,7 @@ static void generate_psnr_packet(VP10_COMP *cpi) {
|
|||||||
pkt.data.psnr.psnr[i] = psnr.psnr[i];
|
pkt.data.psnr.psnr[i] = psnr.psnr[i];
|
||||||
}
|
}
|
||||||
pkt.kind = VPX_CODEC_PSNR_PKT;
|
pkt.kind = VPX_CODEC_PSNR_PKT;
|
||||||
if (cpi->use_svc)
|
vpx_codec_pkt_list_add(cpi->output_pkt_list, &pkt);
|
||||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
|
|
||||||
cpi->svc.number_temporal_layers].psnr_pkt = pkt.data.psnr;
|
|
||||||
else
|
|
||||||
vpx_codec_pkt_list_add(cpi->output_pkt_list, &pkt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int vp10_use_as_reference(VP10_COMP *cpi, int ref_frame_flags) {
|
int vp10_use_as_reference(VP10_COMP *cpi, int ref_frame_flags) {
|
||||||
@@ -2687,11 +2580,6 @@ void vp10_update_reference_frames(VP10_COMP *cpi) {
|
|||||||
tmp = cpi->alt_fb_idx;
|
tmp = cpi->alt_fb_idx;
|
||||||
cpi->alt_fb_idx = cpi->gld_fb_idx;
|
cpi->alt_fb_idx = cpi->gld_fb_idx;
|
||||||
cpi->gld_fb_idx = tmp;
|
cpi->gld_fb_idx = tmp;
|
||||||
|
|
||||||
if (is_two_pass_svc(cpi)) {
|
|
||||||
cpi->svc.layer_context[0].gold_ref_idx = cpi->gld_fb_idx;
|
|
||||||
cpi->svc.layer_context[0].alt_ref_idx = cpi->alt_fb_idx;
|
|
||||||
}
|
|
||||||
} else { /* For non key/golden frames */
|
} else { /* For non key/golden frames */
|
||||||
if (cpi->refresh_alt_ref_frame) {
|
if (cpi->refresh_alt_ref_frame) {
|
||||||
int arf_idx = cpi->alt_fb_idx;
|
int arf_idx = cpi->alt_fb_idx;
|
||||||
@@ -2863,7 +2751,7 @@ void vp10_scale_references(VP10_COMP *cpi) {
|
|||||||
++buf->ref_count;
|
++buf->ref_count;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (cpi->oxcf.pass != 0 || cpi->use_svc)
|
if (cpi->oxcf.pass != 0)
|
||||||
cpi->scaled_ref_idx[ref_frame - 1] = INVALID_IDX;
|
cpi->scaled_ref_idx[ref_frame - 1] = INVALID_IDX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2872,7 +2760,7 @@ void vp10_scale_references(VP10_COMP *cpi) {
|
|||||||
static void release_scaled_references(VP10_COMP *cpi) {
|
static void release_scaled_references(VP10_COMP *cpi) {
|
||||||
VP10_COMMON *cm = &cpi->common;
|
VP10_COMMON *cm = &cpi->common;
|
||||||
int i;
|
int i;
|
||||||
if (cpi->oxcf.pass == 0 && !cpi->use_svc) {
|
if (cpi->oxcf.pass == 0) {
|
||||||
// Only release scaled references under certain conditions:
|
// Only release scaled references under certain conditions:
|
||||||
// if reference will be updated, or if scaled reference has same resolution.
|
// if reference will be updated, or if scaled reference has same resolution.
|
||||||
int refresh[3];
|
int refresh[3];
|
||||||
@@ -3106,7 +2994,6 @@ static void set_frame_size(VP10_COMP *cpi) {
|
|||||||
|
|
||||||
if (oxcf->pass == 0 &&
|
if (oxcf->pass == 0 &&
|
||||||
oxcf->rc_mode == VPX_CBR &&
|
oxcf->rc_mode == VPX_CBR &&
|
||||||
!cpi->use_svc &&
|
|
||||||
oxcf->resize_mode == RESIZE_DYNAMIC) {
|
oxcf->resize_mode == RESIZE_DYNAMIC) {
|
||||||
if (cpi->resize_pending == 1) {
|
if (cpi->resize_pending == 1) {
|
||||||
oxcf->scaled_frame_width =
|
oxcf->scaled_frame_width =
|
||||||
@@ -3129,10 +3016,7 @@ static void set_frame_size(VP10_COMP *cpi) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((oxcf->pass == 2) &&
|
if (oxcf->pass == 2) {
|
||||||
(!cpi->use_svc ||
|
|
||||||
(is_two_pass_svc(cpi) &&
|
|
||||||
cpi->svc.encode_empty_frame_state != ENCODING))) {
|
|
||||||
vp10_set_target_rate(cpi);
|
vp10_set_target_rate(cpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3239,10 +3123,9 @@ static void encode_without_recode_loop(VP10_COMP *cpi) {
|
|||||||
vp10_encode_frame(cpi);
|
vp10_encode_frame(cpi);
|
||||||
|
|
||||||
// Update some stats from cyclic refresh, and check if we should not update
|
// Update some stats from cyclic refresh, and check if we should not update
|
||||||
// golden reference, for non-SVC 1 pass CBR.
|
// golden reference, for 1 pass CBR.
|
||||||
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
|
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
|
||||||
cm->frame_type != KEY_FRAME &&
|
cm->frame_type != KEY_FRAME &&
|
||||||
!cpi->use_svc &&
|
|
||||||
(cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR))
|
(cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR))
|
||||||
vp10_cyclic_refresh_check_golden_update(cpi);
|
vp10_cyclic_refresh_check_golden_update(cpi);
|
||||||
|
|
||||||
@@ -3523,9 +3406,7 @@ static int get_ref_frame_flags(const VP10_COMP *cpi) {
|
|||||||
if (gold_is_last)
|
if (gold_is_last)
|
||||||
flags &= ~VP9_GOLD_FLAG;
|
flags &= ~VP9_GOLD_FLAG;
|
||||||
|
|
||||||
if (cpi->rc.frames_till_gf_update_due == INT_MAX &&
|
if (cpi->rc.frames_till_gf_update_due == INT_MAX)
|
||||||
(cpi->svc.number_temporal_layers == 1 &&
|
|
||||||
cpi->svc.number_spatial_layers == 1))
|
|
||||||
flags &= ~VP9_GOLD_FLAG;
|
flags &= ~VP9_GOLD_FLAG;
|
||||||
|
|
||||||
if (alt_is_last)
|
if (alt_is_last)
|
||||||
@@ -3677,44 +3558,6 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
|
|||||||
cm->reset_frame_context = 2;
|
cm->reset_frame_context = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_two_pass_svc(cpi) && cm->error_resilient_mode == 0) {
|
|
||||||
// Use context 0 for intra only empty frame, but the last frame context
|
|
||||||
// for other empty frames.
|
|
||||||
if (cpi->svc.encode_empty_frame_state == ENCODING) {
|
|
||||||
if (cpi->svc.encode_intra_empty_frame != 0)
|
|
||||||
cm->frame_context_idx = 0;
|
|
||||||
else
|
|
||||||
cm->frame_context_idx = FRAME_CONTEXTS - 1;
|
|
||||||
} else {
|
|
||||||
cm->frame_context_idx =
|
|
||||||
cpi->svc.spatial_layer_id * cpi->svc.number_temporal_layers +
|
|
||||||
cpi->svc.temporal_layer_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
cm->frame_parallel_decoding_mode = oxcf->frame_parallel_decoding_mode;
|
|
||||||
|
|
||||||
// The probs will be updated based on the frame type of its previous
|
|
||||||
// frame if frame_parallel_decoding_mode is 0. The type may vary for
|
|
||||||
// the frame after a key frame in base layer since we may drop enhancement
|
|
||||||
// layers. So set frame_parallel_decoding_mode to 1 in this case.
|
|
||||||
if (cm->frame_parallel_decoding_mode == 0) {
|
|
||||||
if (cpi->svc.number_temporal_layers == 1) {
|
|
||||||
if (cpi->svc.spatial_layer_id == 0 &&
|
|
||||||
cpi->svc.layer_context[0].last_frame_type == KEY_FRAME)
|
|
||||||
cm->frame_parallel_decoding_mode = 1;
|
|
||||||
} else if (cpi->svc.spatial_layer_id == 0) {
|
|
||||||
// Find the 2nd frame in temporal base layer and 1st frame in temporal
|
|
||||||
// enhancement layers from the key frame.
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < cpi->svc.number_temporal_layers; ++i) {
|
|
||||||
if (cpi->svc.layer_context[0].frames_from_key_frame == 1 << i) {
|
|
||||||
cm->frame_parallel_decoding_mode = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For 1 pass CBR, check if we are dropping this frame.
|
// For 1 pass CBR, check if we are dropping this frame.
|
||||||
// Never drop on key frame.
|
// Never drop on key frame.
|
||||||
@@ -3819,8 +3662,7 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
|
|||||||
|
|
||||||
cm->last_frame_type = cm->frame_type;
|
cm->last_frame_type = cm->frame_type;
|
||||||
|
|
||||||
if (!(is_two_pass_svc(cpi) && cpi->svc.encode_empty_frame_state == ENCODING))
|
vp10_rc_postencode_update(cpi, *size);
|
||||||
vp10_rc_postencode_update(cpi, *size);
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
output_frame_level_debug_stats(cpi);
|
output_frame_level_debug_stats(cpi);
|
||||||
@@ -3852,22 +3694,8 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
|
|||||||
// Don't increment frame counters if this was an altref buffer
|
// Don't increment frame counters if this was an altref buffer
|
||||||
// update not a real frame
|
// update not a real frame
|
||||||
++cm->current_video_frame;
|
++cm->current_video_frame;
|
||||||
if (cpi->use_svc)
|
|
||||||
vp10_inc_frame_in_layer(cpi);
|
|
||||||
}
|
}
|
||||||
cm->prev_frame = cm->cur_frame;
|
cm->prev_frame = cm->cur_frame;
|
||||||
|
|
||||||
if (cpi->use_svc)
|
|
||||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
|
|
||||||
cpi->svc.number_temporal_layers +
|
|
||||||
cpi->svc.temporal_layer_id].last_frame_type =
|
|
||||||
cm->frame_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SvcEncode(VP10_COMP *cpi, size_t *size, uint8_t *dest,
|
|
||||||
unsigned int *frame_flags) {
|
|
||||||
vp10_rc_get_svc_params(cpi);
|
|
||||||
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Pass0Encode(VP10_COMP *cpi, size_t *size, uint8_t *dest,
|
static void Pass0Encode(VP10_COMP *cpi, size_t *size, uint8_t *dest,
|
||||||
@@ -3885,8 +3713,7 @@ static void Pass2Encode(VP10_COMP *cpi, size_t *size,
|
|||||||
cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
|
cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
|
||||||
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
|
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
|
||||||
|
|
||||||
if (!(is_two_pass_svc(cpi) && cpi->svc.encode_empty_frame_state == ENCODING))
|
vp10_twopass_postencode_update(cpi);
|
||||||
vp10_twopass_postencode_update(cpi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_ref_frame_bufs(VP10_COMMON *cm) {
|
static void init_ref_frame_bufs(VP10_COMMON *cm) {
|
||||||
@@ -4113,28 +3940,13 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
|
|||||||
int arf_src_index;
|
int arf_src_index;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (is_two_pass_svc(cpi)) {
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
|
||||||
vp10_svc_start_frame(cpi);
|
|
||||||
// Use a small empty frame instead of a real frame
|
|
||||||
if (cpi->svc.encode_empty_frame_state == ENCODING)
|
|
||||||
source = &cpi->svc.empty_frame;
|
|
||||||
#endif
|
|
||||||
if (oxcf->pass == 2)
|
|
||||||
vp10_restore_layer_context(cpi);
|
|
||||||
} else if (is_one_pass_cbr_svc(cpi)) {
|
|
||||||
vp10_one_pass_cbr_svc_start_layer(cpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
vpx_usec_timer_start(&cmptimer);
|
vpx_usec_timer_start(&cmptimer);
|
||||||
|
|
||||||
vp10_set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
|
vp10_set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
|
||||||
|
|
||||||
// Is multi-arf enabled.
|
// Is multi-arf enabled.
|
||||||
// Note that at the moment multi_arf is only configured for 2 pass VBR and
|
// Note that at the moment multi_arf is only configured for 2 pass VBR
|
||||||
// will not work properly with svc.
|
if ((oxcf->pass == 2) && (cpi->oxcf.enable_auto_arf > 1))
|
||||||
if ((oxcf->pass == 2) && !cpi->use_svc &&
|
|
||||||
(cpi->oxcf.enable_auto_arf > 1))
|
|
||||||
cpi->multi_arf_allowed = 1;
|
cpi->multi_arf_allowed = 1;
|
||||||
else
|
else
|
||||||
cpi->multi_arf_allowed = 0;
|
cpi->multi_arf_allowed = 0;
|
||||||
@@ -4142,39 +3954,20 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
|
|||||||
// Normal defaults
|
// Normal defaults
|
||||||
cm->reset_frame_context = 0;
|
cm->reset_frame_context = 0;
|
||||||
cm->refresh_frame_context = 1;
|
cm->refresh_frame_context = 1;
|
||||||
if (!is_one_pass_cbr_svc(cpi)) {
|
|
||||||
cpi->refresh_last_frame = 1;
|
cpi->refresh_last_frame = 1;
|
||||||
cpi->refresh_golden_frame = 0;
|
cpi->refresh_golden_frame = 0;
|
||||||
cpi->refresh_alt_ref_frame = 0;
|
cpi->refresh_alt_ref_frame = 0;
|
||||||
}
|
|
||||||
|
|
||||||
// Should we encode an arf frame.
|
// Should we encode an arf frame.
|
||||||
arf_src_index = get_arf_src_index(cpi);
|
arf_src_index = get_arf_src_index(cpi);
|
||||||
|
|
||||||
// Skip alt frame if we encode the empty frame
|
|
||||||
if (is_two_pass_svc(cpi) && source != NULL)
|
|
||||||
arf_src_index = 0;
|
|
||||||
|
|
||||||
if (arf_src_index) {
|
if (arf_src_index) {
|
||||||
assert(arf_src_index <= rc->frames_to_key);
|
assert(arf_src_index <= rc->frames_to_key);
|
||||||
|
|
||||||
if ((source = vp10_lookahead_peek(cpi->lookahead, arf_src_index)) != NULL) {
|
if ((source = vp10_lookahead_peek(cpi->lookahead, arf_src_index)) != NULL) {
|
||||||
cpi->alt_ref_source = source;
|
cpi->alt_ref_source = source;
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
|
||||||
if (is_two_pass_svc(cpi) && cpi->svc.spatial_layer_id > 0) {
|
|
||||||
int i;
|
|
||||||
// Reference a hidden frame from a lower layer
|
|
||||||
for (i = cpi->svc.spatial_layer_id - 1; i >= 0; --i) {
|
|
||||||
if (oxcf->ss_enable_auto_arf[i]) {
|
|
||||||
cpi->gld_fb_idx = cpi->svc.layer_context[i].alt_ref_idx;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id].has_alt_frame = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (oxcf->arnr_max_frames > 0) {
|
if (oxcf->arnr_max_frames > 0) {
|
||||||
// Produce the filtered ARF frame.
|
// Produce the filtered ARF frame.
|
||||||
vp10_temporal_filter(cpi, arf_src_index);
|
vp10_temporal_filter(cpi, arf_src_index);
|
||||||
@@ -4202,21 +3995,11 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read in the source frame.
|
// Read in the source frame.
|
||||||
if (cpi->use_svc)
|
source = vp10_lookahead_pop(cpi->lookahead, flush);
|
||||||
source = vp10_svc_lookahead_pop(cpi, cpi->lookahead, flush);
|
|
||||||
else
|
|
||||||
source = vp10_lookahead_pop(cpi->lookahead, flush);
|
|
||||||
|
|
||||||
if (source != NULL) {
|
if (source != NULL) {
|
||||||
cm->show_frame = 1;
|
cm->show_frame = 1;
|
||||||
cm->intra_only = 0;
|
cm->intra_only = 0;
|
||||||
// if the flags indicate intra frame, but if the current picture is for
|
|
||||||
// non-zero spatial layer, it should not be an intra picture.
|
|
||||||
// TODO(Won Kap): this needs to change if per-layer intra frame is
|
|
||||||
// allowed.
|
|
||||||
if ((source->flags & VPX_EFLAG_FORCE_KF) && cpi->svc.spatial_layer_id) {
|
|
||||||
source->flags &= ~(unsigned int)(VPX_EFLAG_FORCE_KF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if the frame should be encoded as an arf overlay.
|
// Check to see if the frame should be encoded as an arf overlay.
|
||||||
check_src_altref(cpi, source);
|
check_src_altref(cpi, source);
|
||||||
@@ -4255,11 +4038,6 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
|
|||||||
adjust_frame_rate(cpi, source);
|
adjust_frame_rate(cpi, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_one_pass_cbr_svc(cpi)) {
|
|
||||||
vp10_update_temporal_layer_framerate(cpi);
|
|
||||||
vp10_restore_layer_context(cpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a free buffer for the new frame, releasing the reference previously
|
// Find a free buffer for the new frame, releasing the reference previously
|
||||||
// held.
|
// held.
|
||||||
if (cm->new_fb_idx != INVALID_IDX) {
|
if (cm->new_fb_idx != INVALID_IDX) {
|
||||||
@@ -4272,7 +4050,7 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
|
|||||||
|
|
||||||
cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
|
cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
|
||||||
|
|
||||||
if (!cpi->use_svc && cpi->multi_arf_allowed) {
|
if (cpi->multi_arf_allowed) {
|
||||||
if (cm->frame_type == KEY_FRAME) {
|
if (cm->frame_type == KEY_FRAME) {
|
||||||
init_buffer_indices(cpi);
|
init_buffer_indices(cpi);
|
||||||
} else if (oxcf->pass == 2) {
|
} else if (oxcf->pass == 2) {
|
||||||
@@ -4286,24 +4064,18 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
|
|||||||
|
|
||||||
cpi->frame_flags = *frame_flags;
|
cpi->frame_flags = *frame_flags;
|
||||||
|
|
||||||
if ((oxcf->pass == 2) &&
|
if (oxcf->pass == 2) {
|
||||||
(!cpi->use_svc ||
|
|
||||||
(is_two_pass_svc(cpi) &&
|
|
||||||
cpi->svc.encode_empty_frame_state != ENCODING))) {
|
|
||||||
vp10_rc_get_second_pass_params(cpi);
|
vp10_rc_get_second_pass_params(cpi);
|
||||||
} else if (oxcf->pass == 1) {
|
} else if (oxcf->pass == 1) {
|
||||||
set_frame_size(cpi);
|
set_frame_size(cpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpi->oxcf.pass != 0 ||
|
if (cpi->oxcf.pass != 0 || frame_is_intra_only(cm) == 1) {
|
||||||
cpi->use_svc ||
|
|
||||||
frame_is_intra_only(cm) == 1) {
|
|
||||||
for (i = 0; i < MAX_REF_FRAMES; ++i)
|
for (i = 0; i < MAX_REF_FRAMES; ++i)
|
||||||
cpi->scaled_ref_idx[i] = INVALID_IDX;
|
cpi->scaled_ref_idx[i] = INVALID_IDX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oxcf->pass == 1 &&
|
if (oxcf->pass == 1) {
|
||||||
(!cpi->use_svc || is_two_pass_svc(cpi))) {
|
|
||||||
const int lossless = is_lossless_requested(oxcf);
|
const int lossless = is_lossless_requested(oxcf);
|
||||||
#if CONFIG_VP9_HIGHBITDEPTH
|
#if CONFIG_VP9_HIGHBITDEPTH
|
||||||
if (cpi->oxcf.use_highbitdepth)
|
if (cpi->oxcf.use_highbitdepth)
|
||||||
@@ -4318,11 +4090,8 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
|
|||||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||||
cpi->td.mb.itxm_add = lossless ? vp10_iwht4x4_add : vp10_idct4x4_add;
|
cpi->td.mb.itxm_add = lossless ? vp10_iwht4x4_add : vp10_idct4x4_add;
|
||||||
vp10_first_pass(cpi, source);
|
vp10_first_pass(cpi, source);
|
||||||
} else if (oxcf->pass == 2 &&
|
} else if (oxcf->pass == 2) {
|
||||||
(!cpi->use_svc || is_two_pass_svc(cpi))) {
|
|
||||||
Pass2Encode(cpi, size, dest, frame_flags);
|
Pass2Encode(cpi, size, dest, frame_flags);
|
||||||
} else if (cpi->use_svc) {
|
|
||||||
SvcEncode(cpi, size, dest, frame_flags);
|
|
||||||
} else {
|
} else {
|
||||||
// One pass encode
|
// One pass encode
|
||||||
Pass0Encode(cpi, size, dest, frame_flags);
|
Pass0Encode(cpi, size, dest, frame_flags);
|
||||||
@@ -4340,14 +4109,6 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
|
|||||||
cpi->droppable = !frame_is_reference(cpi);
|
cpi->droppable = !frame_is_reference(cpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save layer specific state.
|
|
||||||
if (is_one_pass_cbr_svc(cpi) ||
|
|
||||||
((cpi->svc.number_temporal_layers > 1 ||
|
|
||||||
cpi->svc.number_spatial_layers > 1) &&
|
|
||||||
oxcf->pass == 2)) {
|
|
||||||
vp10_save_layer_context(cpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
vpx_usec_timer_mark(&cmptimer);
|
vpx_usec_timer_mark(&cmptimer);
|
||||||
cpi->time_compress_data += vpx_usec_timer_elapsed(&cmptimer);
|
cpi->time_compress_data += vpx_usec_timer_elapsed(&cmptimer);
|
||||||
|
|
||||||
@@ -4526,27 +4287,6 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (is_two_pass_svc(cpi)) {
|
|
||||||
if (cpi->svc.encode_empty_frame_state == ENCODING) {
|
|
||||||
cpi->svc.encode_empty_frame_state = ENCODED;
|
|
||||||
cpi->svc.encode_intra_empty_frame = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cm->show_frame) {
|
|
||||||
++cpi->svc.spatial_layer_to_encode;
|
|
||||||
if (cpi->svc.spatial_layer_to_encode >= cpi->svc.number_spatial_layers)
|
|
||||||
cpi->svc.spatial_layer_to_encode = 0;
|
|
||||||
|
|
||||||
// May need the empty frame after an visible frame.
|
|
||||||
cpi->svc.encode_empty_frame_state = NEED_TO_ENCODE;
|
|
||||||
}
|
|
||||||
} else if (is_one_pass_cbr_svc(cpi)) {
|
|
||||||
if (cm->show_frame) {
|
|
||||||
++cpi->svc.spatial_layer_to_encode;
|
|
||||||
if (cpi->svc.spatial_layer_to_encode >= cpi->svc.number_spatial_layers)
|
|
||||||
cpi->svc.spatial_layer_to_encode = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vpx_clear_system_state();
|
vpx_clear_system_state();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -4639,11 +4379,6 @@ int vp10_set_size_literal(VP10_COMP *cpi, unsigned int width,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vp10_set_svc(VP10_COMP *cpi, int use_svc) {
|
|
||||||
cpi->use_svc = use_svc;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t vp10_get_y_sse(const YV12_BUFFER_CONFIG *a,
|
int64_t vp10_get_y_sse(const YV12_BUFFER_CONFIG *a,
|
||||||
const YV12_BUFFER_CONFIG *b) {
|
const YV12_BUFFER_CONFIG *b) {
|
||||||
assert(a->y_crop_width == b->y_crop_width);
|
assert(a->y_crop_width == b->y_crop_width);
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
#include "vp10/encoder/ratectrl.h"
|
#include "vp10/encoder/ratectrl.h"
|
||||||
#include "vp10/encoder/rd.h"
|
#include "vp10/encoder/rd.h"
|
||||||
#include "vp10/encoder/speed_features.h"
|
#include "vp10/encoder/speed_features.h"
|
||||||
#include "vp10/encoder/svc_layercontext.h"
|
|
||||||
#include "vp10/encoder/tokenize.h"
|
#include "vp10/encoder/tokenize.h"
|
||||||
|
|
||||||
#if CONFIG_VP9_TEMPORAL_DENOISING
|
#if CONFIG_VP9_TEMPORAL_DENOISING
|
||||||
@@ -116,7 +115,7 @@ typedef enum {
|
|||||||
} AQ_MODE;
|
} AQ_MODE;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RESIZE_NONE = 0, // No frame resizing allowed (except for SVC).
|
RESIZE_NONE = 0, // No frame resizing allowed.
|
||||||
RESIZE_FIXED = 1, // All frames are coded at the specified dimension.
|
RESIZE_FIXED = 1, // All frames are coded at the specified dimension.
|
||||||
RESIZE_DYNAMIC = 2 // Coded size of each frame is determined by the codec.
|
RESIZE_DYNAMIC = 2 // Coded size of each frame is determined by the codec.
|
||||||
} RESIZE_TYPE;
|
} RESIZE_TYPE;
|
||||||
@@ -189,16 +188,6 @@ typedef struct VP10EncoderConfig {
|
|||||||
// END DATARATE CONTROL OPTIONS
|
// END DATARATE CONTROL OPTIONS
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
// Spatial and temporal scalability.
|
|
||||||
int ss_number_layers; // Number of spatial layers.
|
|
||||||
int ts_number_layers; // Number of temporal layers.
|
|
||||||
// Bitrate allocation for spatial layers.
|
|
||||||
int layer_target_bitrate[VPX_MAX_LAYERS];
|
|
||||||
int ss_target_bitrate[VPX_SS_MAX_LAYERS];
|
|
||||||
int ss_enable_auto_arf[VPX_SS_MAX_LAYERS];
|
|
||||||
// Bitrate allocation (CBR mode) and framerate factor, for temporal layers.
|
|
||||||
int ts_rate_decimator[VPX_TS_MAX_LAYERS];
|
|
||||||
|
|
||||||
int enable_auto_arf;
|
int enable_auto_arf;
|
||||||
|
|
||||||
int encode_breakout; // early breakout : for video conf recommend 800
|
int encode_breakout; // early breakout : for video conf recommend 800
|
||||||
@@ -239,7 +228,6 @@ typedef struct VP10EncoderConfig {
|
|||||||
int use_highbitdepth;
|
int use_highbitdepth;
|
||||||
#endif
|
#endif
|
||||||
vpx_color_space_t color_space;
|
vpx_color_space_t color_space;
|
||||||
VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode;
|
|
||||||
} VP10EncoderConfig;
|
} VP10EncoderConfig;
|
||||||
|
|
||||||
static INLINE int is_lossless_requested(const VP10EncoderConfig *cfg) {
|
static INLINE int is_lossless_requested(const VP10EncoderConfig *cfg) {
|
||||||
@@ -451,10 +439,6 @@ typedef struct VP10_COMP {
|
|||||||
// number of MBs in the current frame when the frame is
|
// number of MBs in the current frame when the frame is
|
||||||
// scaled.
|
// scaled.
|
||||||
|
|
||||||
int use_svc;
|
|
||||||
|
|
||||||
SVC svc;
|
|
||||||
|
|
||||||
// Store frame variance info in SOURCE_VAR_BASED_PARTITION search type.
|
// Store frame variance info in SOURCE_VAR_BASED_PARTITION search type.
|
||||||
diff *source_diff_var;
|
diff *source_diff_var;
|
||||||
// The threshold used in SOURCE_VAR_BASED_PARTITION search type.
|
// The threshold used in SOURCE_VAR_BASED_PARTITION search type.
|
||||||
@@ -546,8 +530,6 @@ int vp10_set_internal_size(VP10_COMP *cpi,
|
|||||||
int vp10_set_size_literal(VP10_COMP *cpi, unsigned int width,
|
int vp10_set_size_literal(VP10_COMP *cpi, unsigned int width,
|
||||||
unsigned int height);
|
unsigned int height);
|
||||||
|
|
||||||
void vp10_set_svc(VP10_COMP *cpi, int use_svc);
|
|
||||||
|
|
||||||
int vp10_get_quantizer(struct VP10_COMP *cpi);
|
int vp10_get_quantizer(struct VP10_COMP *cpi);
|
||||||
|
|
||||||
static INLINE int frame_is_kf_gf_arf(const VP10_COMP *cpi) {
|
static INLINE int frame_is_kf_gf_arf(const VP10_COMP *cpi) {
|
||||||
@@ -624,19 +606,9 @@ YV12_BUFFER_CONFIG *vp10_scale_if_required(VP10_COMMON *cm,
|
|||||||
|
|
||||||
void vp10_apply_encoding_flags(VP10_COMP *cpi, vpx_enc_frame_flags_t flags);
|
void vp10_apply_encoding_flags(VP10_COMP *cpi, vpx_enc_frame_flags_t flags);
|
||||||
|
|
||||||
static INLINE int is_two_pass_svc(const struct VP10_COMP *const cpi) {
|
|
||||||
return cpi->use_svc && cpi->oxcf.pass != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static INLINE int is_one_pass_cbr_svc(const struct VP10_COMP *const cpi) {
|
|
||||||
return (cpi->use_svc && cpi->oxcf.pass == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static INLINE int is_altref_enabled(const VP10_COMP *const cpi) {
|
static INLINE int is_altref_enabled(const VP10_COMP *const cpi) {
|
||||||
return cpi->oxcf.mode != REALTIME && cpi->oxcf.lag_in_frames > 0 &&
|
return cpi->oxcf.mode != REALTIME && cpi->oxcf.lag_in_frames > 0 &&
|
||||||
(cpi->oxcf.enable_auto_arf &&
|
cpi->oxcf.enable_auto_arf;
|
||||||
(!is_two_pass_svc(cpi) ||
|
|
||||||
cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE void set_ref_ptrs(VP10_COMMON *cm, MACROBLOCKD *xd,
|
static INLINE void set_ref_ptrs(VP10_COMMON *cm, MACROBLOCKD *xd,
|
||||||
|
|||||||
@@ -76,13 +76,6 @@ void vp10_encode_tiles_mt(VP10_COMP *cpi) {
|
|||||||
if (cpi->num_workers == 0) {
|
if (cpi->num_workers == 0) {
|
||||||
int allocated_workers = num_workers;
|
int allocated_workers = num_workers;
|
||||||
|
|
||||||
// While using SVC, we need to allocate threads according to the highest
|
|
||||||
// resolution.
|
|
||||||
if (cpi->use_svc) {
|
|
||||||
int max_tile_cols = get_max_tile_cols(cpi);
|
|
||||||
allocated_workers = VPXMIN(cpi->oxcf.max_threads, max_tile_cols);
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_MEM_ERROR(cm, cpi->workers,
|
CHECK_MEM_ERROR(cm, cpi->workers,
|
||||||
vpx_malloc(allocated_workers * sizeof(*cpi->workers)));
|
vpx_malloc(allocated_workers * sizeof(*cpi->workers)));
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,6 @@
|
|||||||
#define MIN_DECAY_FACTOR 0.01
|
#define MIN_DECAY_FACTOR 0.01
|
||||||
#define MIN_KF_BOOST 300
|
#define MIN_KF_BOOST 300
|
||||||
#define NEW_MV_MODE_PENALTY 32
|
#define NEW_MV_MODE_PENALTY 32
|
||||||
#define SVC_FACTOR_PT_LOW 0.45
|
|
||||||
#define DARK_THRESH 64
|
#define DARK_THRESH 64
|
||||||
#define DEFAULT_GRP_WEIGHT 1.0
|
#define DEFAULT_GRP_WEIGHT 1.0
|
||||||
#define RC_FACTOR_MIN 0.75
|
#define RC_FACTOR_MIN 0.75
|
||||||
@@ -177,14 +176,12 @@ static void zero_stats(FIRSTPASS_STATS *section) {
|
|||||||
section->new_mv_count = 0.0;
|
section->new_mv_count = 0.0;
|
||||||
section->count = 0.0;
|
section->count = 0.0;
|
||||||
section->duration = 1.0;
|
section->duration = 1.0;
|
||||||
section->spatial_layer_id = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void accumulate_stats(FIRSTPASS_STATS *section,
|
static void accumulate_stats(FIRSTPASS_STATS *section,
|
||||||
const FIRSTPASS_STATS *frame) {
|
const FIRSTPASS_STATS *frame) {
|
||||||
section->frame += frame->frame;
|
section->frame += frame->frame;
|
||||||
section->weight += frame->weight;
|
section->weight += frame->weight;
|
||||||
section->spatial_layer_id = frame->spatial_layer_id;
|
|
||||||
section->intra_error += frame->intra_error;
|
section->intra_error += frame->intra_error;
|
||||||
section->coded_error += frame->coded_error;
|
section->coded_error += frame->coded_error;
|
||||||
section->sr_coded_error += frame->sr_coded_error;
|
section->sr_coded_error += frame->sr_coded_error;
|
||||||
@@ -292,15 +289,7 @@ void vp10_init_first_pass(VP10_COMP *cpi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void vp10_end_first_pass(VP10_COMP *cpi) {
|
void vp10_end_first_pass(VP10_COMP *cpi) {
|
||||||
if (is_two_pass_svc(cpi)) {
|
output_stats(&cpi->twopass.total_stats, cpi->output_pkt_list);
|
||||||
int i;
|
|
||||||
for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
|
|
||||||
output_stats(&cpi->svc.layer_context[i].twopass.total_stats,
|
|
||||||
cpi->output_pkt_list);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
output_stats(&cpi->twopass.total_stats, cpi->output_pkt_list);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static vpx_variance_fn_t get_block_variance_fn(BLOCK_SIZE bsize) {
|
static vpx_variance_fn_t get_block_variance_fn(BLOCK_SIZE bsize) {
|
||||||
@@ -530,16 +519,13 @@ void vp10_first_pass(VP10_COMP *cpi, const struct lookahead_entry *source) {
|
|||||||
YV12_BUFFER_CONFIG *gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
|
YV12_BUFFER_CONFIG *gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
|
||||||
YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
|
YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
|
||||||
const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12;
|
const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12;
|
||||||
|
|
||||||
LAYER_CONTEXT *const lc = is_two_pass_svc(cpi) ?
|
|
||||||
&cpi->svc.layer_context[cpi->svc.spatial_layer_id] : NULL;
|
|
||||||
double intra_factor;
|
double intra_factor;
|
||||||
double brightness_factor;
|
double brightness_factor;
|
||||||
BufferPool *const pool = cm->buffer_pool;
|
BufferPool *const pool = cm->buffer_pool;
|
||||||
|
|
||||||
// First pass code requires valid last and new frame buffers.
|
// First pass code requires valid last and new frame buffers.
|
||||||
assert(new_yv12 != NULL);
|
assert(new_yv12 != NULL);
|
||||||
assert((lc != NULL) || frame_is_intra_only(cm) || (lst_yv12 != NULL));
|
assert(frame_is_intra_only(cm) || (lst_yv12 != NULL));
|
||||||
|
|
||||||
#if CONFIG_FP_MB_STATS
|
#if CONFIG_FP_MB_STATS
|
||||||
if (cpi->use_fp_mb_stats) {
|
if (cpi->use_fp_mb_stats) {
|
||||||
@@ -556,51 +542,6 @@ void vp10_first_pass(VP10_COMP *cpi, const struct lookahead_entry *source) {
|
|||||||
set_first_pass_params(cpi);
|
set_first_pass_params(cpi);
|
||||||
vp10_set_quantizer(cm, find_fp_qindex(cm->bit_depth));
|
vp10_set_quantizer(cm, find_fp_qindex(cm->bit_depth));
|
||||||
|
|
||||||
if (lc != NULL) {
|
|
||||||
twopass = &lc->twopass;
|
|
||||||
|
|
||||||
cpi->lst_fb_idx = cpi->svc.spatial_layer_id;
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG;
|
|
||||||
|
|
||||||
if (cpi->svc.number_spatial_layers + cpi->svc.spatial_layer_id <
|
|
||||||
REF_FRAMES) {
|
|
||||||
cpi->gld_fb_idx =
|
|
||||||
cpi->svc.number_spatial_layers + cpi->svc.spatial_layer_id;
|
|
||||||
cpi->ref_frame_flags |= VP9_GOLD_FLAG;
|
|
||||||
cpi->refresh_golden_frame = (lc->current_video_frame_in_layer == 0);
|
|
||||||
} else {
|
|
||||||
cpi->refresh_golden_frame = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lc->current_video_frame_in_layer == 0)
|
|
||||||
cpi->ref_frame_flags = 0;
|
|
||||||
|
|
||||||
vp10_scale_references(cpi);
|
|
||||||
|
|
||||||
// Use either last frame or alt frame for motion search.
|
|
||||||
if (cpi->ref_frame_flags & VP9_LAST_FLAG) {
|
|
||||||
first_ref_buf = vp10_get_scaled_ref_frame(cpi, LAST_FRAME);
|
|
||||||
if (first_ref_buf == NULL)
|
|
||||||
first_ref_buf = get_ref_frame_buffer(cpi, LAST_FRAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cpi->ref_frame_flags & VP9_GOLD_FLAG) {
|
|
||||||
gld_yv12 = vp10_get_scaled_ref_frame(cpi, GOLDEN_FRAME);
|
|
||||||
if (gld_yv12 == NULL) {
|
|
||||||
gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gld_yv12 = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_ref_ptrs(cm, xd,
|
|
||||||
(cpi->ref_frame_flags & VP9_LAST_FLAG) ? LAST_FRAME: NONE,
|
|
||||||
(cpi->ref_frame_flags & VP9_GOLD_FLAG) ? GOLDEN_FRAME : NONE);
|
|
||||||
|
|
||||||
cpi->Source = vp10_scale_if_required(cm, cpi->un_scaled_source,
|
|
||||||
&cpi->scaled_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
vp10_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
|
vp10_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
|
||||||
|
|
||||||
vp10_setup_src_planes(x, cpi->Source, 0, 0);
|
vp10_setup_src_planes(x, cpi->Source, 0, 0);
|
||||||
@@ -754,8 +695,7 @@ void vp10_first_pass(VP10_COMP *cpi, const struct lookahead_entry *source) {
|
|||||||
x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + BORDER_MV_PIXELS_B16;
|
x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + BORDER_MV_PIXELS_B16;
|
||||||
|
|
||||||
// Other than for the first frame do a motion search.
|
// Other than for the first frame do a motion search.
|
||||||
if ((lc == NULL && cm->current_video_frame > 0) ||
|
if (cm->current_video_frame > 0) {
|
||||||
(lc != NULL && lc->current_video_frame_in_layer > 0)) {
|
|
||||||
int tmp_err, motion_error, raw_motion_error;
|
int tmp_err, motion_error, raw_motion_error;
|
||||||
// Assume 0,0 motion with no mv overhead.
|
// Assume 0,0 motion with no mv overhead.
|
||||||
MV mv = {0, 0} , tmp_mv = {0, 0};
|
MV mv = {0, 0} , tmp_mv = {0, 0};
|
||||||
@@ -796,7 +736,7 @@ void vp10_first_pass(VP10_COMP *cpi, const struct lookahead_entry *source) {
|
|||||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||||
|
|
||||||
// TODO(pengchong): Replace the hard-coded threshold
|
// TODO(pengchong): Replace the hard-coded threshold
|
||||||
if (raw_motion_error > 25 || lc != NULL) {
|
if (raw_motion_error > 25) {
|
||||||
// Test last reference frame using the previous best mv as the
|
// Test last reference frame using the previous best mv as the
|
||||||
// starting point (best reference) for the search.
|
// starting point (best reference) for the search.
|
||||||
first_pass_motion_search(cpi, x, &best_ref_mv, &mv, &motion_error);
|
first_pass_motion_search(cpi, x, &best_ref_mv, &mv, &motion_error);
|
||||||
@@ -814,9 +754,7 @@ void vp10_first_pass(VP10_COMP *cpi, const struct lookahead_entry *source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search in an older reference frame.
|
// Search in an older reference frame.
|
||||||
if (((lc == NULL && cm->current_video_frame > 1) ||
|
if ((cm->current_video_frame > 1) && gld_yv12 != NULL) {
|
||||||
(lc != NULL && lc->current_video_frame_in_layer > 1))
|
|
||||||
&& gld_yv12 != NULL) {
|
|
||||||
// Assume 0,0 motion with no mv overhead.
|
// Assume 0,0 motion with no mv overhead.
|
||||||
int gf_motion_error;
|
int gf_motion_error;
|
||||||
|
|
||||||
@@ -1045,7 +983,6 @@ void vp10_first_pass(VP10_COMP *cpi, const struct lookahead_entry *source) {
|
|||||||
fps.weight = intra_factor * brightness_factor;
|
fps.weight = intra_factor * brightness_factor;
|
||||||
|
|
||||||
fps.frame = cm->current_video_frame;
|
fps.frame = cm->current_video_frame;
|
||||||
fps.spatial_layer_id = cpi->svc.spatial_layer_id;
|
|
||||||
fps.coded_error = (double)(coded_error >> 8) + min_err;
|
fps.coded_error = (double)(coded_error >> 8) + min_err;
|
||||||
fps.sr_coded_error = (double)(sr_coded_error >> 8) + min_err;
|
fps.sr_coded_error = (double)(sr_coded_error >> 8) + min_err;
|
||||||
fps.intra_error = (double)(intra_error >> 8) + min_err;
|
fps.intra_error = (double)(intra_error >> 8) + min_err;
|
||||||
@@ -1116,18 +1053,13 @@ void vp10_first_pass(VP10_COMP *cpi, const struct lookahead_entry *source) {
|
|||||||
|
|
||||||
vpx_extend_frame_borders(new_yv12);
|
vpx_extend_frame_borders(new_yv12);
|
||||||
|
|
||||||
if (lc != NULL) {
|
// The frame we just compressed now becomes the last frame.
|
||||||
vp10_update_reference_frames(cpi);
|
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx],
|
||||||
} else {
|
cm->new_fb_idx);
|
||||||
// The frame we just compressed now becomes the last frame.
|
|
||||||
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx],
|
|
||||||
cm->new_fb_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special case for the first frame. Copy into the GF buffer as a second
|
// Special case for the first frame. Copy into the GF buffer as a second
|
||||||
// reference.
|
// reference.
|
||||||
if (cm->current_video_frame == 0 && cpi->gld_fb_idx != INVALID_IDX &&
|
if (cm->current_video_frame == 0 && cpi->gld_fb_idx != INVALID_IDX) {
|
||||||
lc == NULL) {
|
|
||||||
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
|
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
|
||||||
cm->ref_frame_map[cpi->lst_fb_idx]);
|
cm->ref_frame_map[cpi->lst_fb_idx]);
|
||||||
}
|
}
|
||||||
@@ -1149,8 +1081,6 @@ void vp10_first_pass(VP10_COMP *cpi, const struct lookahead_entry *source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
++cm->current_video_frame;
|
++cm->current_video_frame;
|
||||||
if (cpi->use_svc)
|
|
||||||
vp10_inc_frame_in_layer(cpi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static double calc_correction_factor(double err_per_mb,
|
static double calc_correction_factor(double err_per_mb,
|
||||||
@@ -1200,11 +1130,6 @@ static int get_twopass_worst_quality(const VP10_COMP *cpi,
|
|||||||
BPER_MB_NORMBITS) / active_mbs;
|
BPER_MB_NORMBITS) / active_mbs;
|
||||||
|
|
||||||
int q;
|
int q;
|
||||||
int is_svc_upper_layer = 0;
|
|
||||||
|
|
||||||
if (is_two_pass_svc(cpi) && cpi->svc.spatial_layer_id > 0)
|
|
||||||
is_svc_upper_layer = 1;
|
|
||||||
|
|
||||||
|
|
||||||
// Try and pick a max Q that will be high enough to encode the
|
// Try and pick a max Q that will be high enough to encode the
|
||||||
// content at the given rate.
|
// content at the given rate.
|
||||||
@@ -1212,7 +1137,6 @@ static int get_twopass_worst_quality(const VP10_COMP *cpi,
|
|||||||
const double factor =
|
const double factor =
|
||||||
calc_correction_factor(av_err_per_mb,
|
calc_correction_factor(av_err_per_mb,
|
||||||
ERR_DIVISOR - ediv_size_correction,
|
ERR_DIVISOR - ediv_size_correction,
|
||||||
is_svc_upper_layer ? SVC_FACTOR_PT_LOW :
|
|
||||||
FACTOR_PT_LOW, FACTOR_PT_HIGH, q,
|
FACTOR_PT_LOW, FACTOR_PT_HIGH, q,
|
||||||
cpi->common.bit_depth);
|
cpi->common.bit_depth);
|
||||||
const int bits_per_mb =
|
const int bits_per_mb =
|
||||||
@@ -1264,12 +1188,8 @@ void vp10_calculate_coded_size(VP10_COMP *cpi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void vp10_init_second_pass(VP10_COMP *cpi) {
|
void vp10_init_second_pass(VP10_COMP *cpi) {
|
||||||
SVC *const svc = &cpi->svc;
|
|
||||||
const VP10EncoderConfig *const oxcf = &cpi->oxcf;
|
const VP10EncoderConfig *const oxcf = &cpi->oxcf;
|
||||||
const int is_two_pass_svc = (svc->number_spatial_layers > 1) ||
|
TWO_PASS *const twopass = &cpi->twopass;
|
||||||
(svc->number_temporal_layers > 1);
|
|
||||||
TWO_PASS *const twopass = is_two_pass_svc ?
|
|
||||||
&svc->layer_context[svc->spatial_layer_id].twopass : &cpi->twopass;
|
|
||||||
double frame_rate;
|
double frame_rate;
|
||||||
FIRSTPASS_STATS *stats;
|
FIRSTPASS_STATS *stats;
|
||||||
|
|
||||||
@@ -1290,17 +1210,9 @@ void vp10_init_second_pass(VP10_COMP *cpi) {
|
|||||||
// encoded in the second pass is a guess. However, the sum duration is not.
|
// encoded in the second pass is a guess. However, the sum duration is not.
|
||||||
// It is calculated based on the actual durations of all frames from the
|
// It is calculated based on the actual durations of all frames from the
|
||||||
// first pass.
|
// first pass.
|
||||||
|
vp10_new_framerate(cpi, frame_rate);
|
||||||
if (is_two_pass_svc) {
|
twopass->bits_left = (int64_t)(stats->duration * oxcf->target_bandwidth /
|
||||||
vp10_update_spatial_layer_framerate(cpi, frame_rate);
|
10000000.0);
|
||||||
twopass->bits_left = (int64_t)(stats->duration *
|
|
||||||
svc->layer_context[svc->spatial_layer_id].target_bandwidth /
|
|
||||||
10000000.0);
|
|
||||||
} else {
|
|
||||||
vp10_new_framerate(cpi, frame_rate);
|
|
||||||
twopass->bits_left = (int64_t)(stats->duration * oxcf->target_bandwidth /
|
|
||||||
10000000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This variable monitors how far behind the second ref update is lagging.
|
// This variable monitors how far behind the second ref update is lagging.
|
||||||
twopass->sr_update_lag = 1;
|
twopass->sr_update_lag = 1;
|
||||||
@@ -1701,15 +1613,8 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
|
|||||||
int mid_frame_idx;
|
int mid_frame_idx;
|
||||||
unsigned char arf_buffer_indices[MAX_ACTIVE_ARFS];
|
unsigned char arf_buffer_indices[MAX_ACTIVE_ARFS];
|
||||||
int alt_frame_index = frame_index;
|
int alt_frame_index = frame_index;
|
||||||
int has_temporal_layers = is_two_pass_svc(cpi) &&
|
|
||||||
cpi->svc.number_temporal_layers > 1;
|
|
||||||
|
|
||||||
// Only encode alt reference frame in temporal base layer.
|
key_frame = cpi->common.frame_type == KEY_FRAME;
|
||||||
if (has_temporal_layers)
|
|
||||||
alt_frame_index = cpi->svc.number_temporal_layers;
|
|
||||||
|
|
||||||
key_frame = cpi->common.frame_type == KEY_FRAME ||
|
|
||||||
vp10_is_upper_layer_key_frame(cpi);
|
|
||||||
|
|
||||||
get_arf_buffer_indices(arf_buffer_indices);
|
get_arf_buffer_indices(arf_buffer_indices);
|
||||||
|
|
||||||
@@ -1746,20 +1651,14 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
|
|||||||
gf_group->rf_level[alt_frame_index] = GF_ARF_STD;
|
gf_group->rf_level[alt_frame_index] = GF_ARF_STD;
|
||||||
gf_group->bit_allocation[alt_frame_index] = gf_arf_bits;
|
gf_group->bit_allocation[alt_frame_index] = gf_arf_bits;
|
||||||
|
|
||||||
if (has_temporal_layers)
|
gf_group->arf_src_offset[alt_frame_index] =
|
||||||
gf_group->arf_src_offset[alt_frame_index] =
|
(unsigned char)(rc->baseline_gf_interval - 1);
|
||||||
(unsigned char)(rc->baseline_gf_interval -
|
|
||||||
cpi->svc.number_temporal_layers);
|
|
||||||
else
|
|
||||||
gf_group->arf_src_offset[alt_frame_index] =
|
|
||||||
(unsigned char)(rc->baseline_gf_interval - 1);
|
|
||||||
|
|
||||||
gf_group->arf_update_idx[alt_frame_index] = arf_buffer_indices[0];
|
gf_group->arf_update_idx[alt_frame_index] = arf_buffer_indices[0];
|
||||||
gf_group->arf_ref_idx[alt_frame_index] =
|
gf_group->arf_ref_idx[alt_frame_index] =
|
||||||
arf_buffer_indices[cpi->multi_arf_last_grp_enabled &&
|
arf_buffer_indices[cpi->multi_arf_last_grp_enabled &&
|
||||||
rc->source_alt_ref_active];
|
rc->source_alt_ref_active];
|
||||||
if (!has_temporal_layers)
|
++frame_index;
|
||||||
++frame_index;
|
|
||||||
|
|
||||||
if (cpi->multi_arf_enabled) {
|
if (cpi->multi_arf_enabled) {
|
||||||
// Set aside a slot for a level 1 arf.
|
// Set aside a slot for a level 1 arf.
|
||||||
@@ -1782,10 +1681,6 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
|
|||||||
if (EOF == input_stats(twopass, &frame_stats))
|
if (EOF == input_stats(twopass, &frame_stats))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (has_temporal_layers && frame_index == alt_frame_index) {
|
|
||||||
++frame_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
modified_err = calculate_modified_err(cpi, twopass, oxcf, &frame_stats);
|
modified_err = calculate_modified_err(cpi, twopass, oxcf, &frame_stats);
|
||||||
|
|
||||||
if (group_error > 0)
|
if (group_error > 0)
|
||||||
@@ -2047,26 +1942,6 @@ static void define_gf_group(VP10_COMP *cpi, FIRSTPASS_STATS *this_frame) {
|
|||||||
// Set the interval until the next gf.
|
// Set the interval until the next gf.
|
||||||
rc->baseline_gf_interval = i - (is_key_frame || rc->source_alt_ref_pending);
|
rc->baseline_gf_interval = i - (is_key_frame || rc->source_alt_ref_pending);
|
||||||
|
|
||||||
// Only encode alt reference frame in temporal base layer. So
|
|
||||||
// baseline_gf_interval should be multiple of a temporal layer group
|
|
||||||
// (typically the frame distance between two base layer frames)
|
|
||||||
if (is_two_pass_svc(cpi) && cpi->svc.number_temporal_layers > 1) {
|
|
||||||
int count = (1 << (cpi->svc.number_temporal_layers - 1)) - 1;
|
|
||||||
int new_gf_interval = (rc->baseline_gf_interval + count) & (~count);
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < new_gf_interval - rc->baseline_gf_interval; ++j) {
|
|
||||||
if (EOF == input_stats(twopass, this_frame))
|
|
||||||
break;
|
|
||||||
gf_group_err += calculate_modified_err(cpi, twopass, oxcf, this_frame);
|
|
||||||
#if GROUP_ADAPTIVE_MAXQ
|
|
||||||
gf_group_raw_error += this_frame->coded_error;
|
|
||||||
#endif
|
|
||||||
gf_group_skip_pct += this_frame->intra_skip_pct;
|
|
||||||
gf_group_inactive_zone_rows += this_frame->inactive_zone_rows;
|
|
||||||
}
|
|
||||||
rc->baseline_gf_interval = new_gf_interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
|
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
|
||||||
|
|
||||||
// Reset the file position.
|
// Reset the file position.
|
||||||
@@ -2386,18 +2261,6 @@ static void find_next_key_frame(VP10_COMP *cpi, FIRSTPASS_STATS *this_frame) {
|
|||||||
rc->next_key_frame_forced = 0;
|
rc->next_key_frame_forced = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_two_pass_svc(cpi) && cpi->svc.number_temporal_layers > 1) {
|
|
||||||
int count = (1 << (cpi->svc.number_temporal_layers - 1)) - 1;
|
|
||||||
int new_frame_to_key = (rc->frames_to_key + count) & (~count);
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < new_frame_to_key - rc->frames_to_key; ++j) {
|
|
||||||
if (EOF == input_stats(twopass, this_frame))
|
|
||||||
break;
|
|
||||||
kf_group_err += calculate_modified_err(cpi, twopass, oxcf, this_frame);
|
|
||||||
}
|
|
||||||
rc->frames_to_key = new_frame_to_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special case for the last key frame of the file.
|
// Special case for the last key frame of the file.
|
||||||
if (twopass->stats_in >= twopass->stats_in_end) {
|
if (twopass->stats_in >= twopass->stats_in_end) {
|
||||||
// Accumulate kf group error.
|
// Accumulate kf group error.
|
||||||
@@ -2547,16 +2410,6 @@ static void configure_buffer_updates(VP10_COMP *cpi) {
|
|||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (is_two_pass_svc(cpi)) {
|
|
||||||
if (cpi->svc.temporal_layer_id > 0) {
|
|
||||||
cpi->refresh_last_frame = 0;
|
|
||||||
cpi->refresh_golden_frame = 0;
|
|
||||||
}
|
|
||||||
if (cpi->svc.layer_context[cpi->svc.spatial_layer_id].gold_ref_idx < 0)
|
|
||||||
cpi->refresh_golden_frame = 0;
|
|
||||||
if (cpi->alt_ref_source == NULL)
|
|
||||||
cpi->refresh_alt_ref_frame = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_skippable_frame(const VP10_COMP *cpi) {
|
static int is_skippable_frame(const VP10_COMP *cpi) {
|
||||||
@@ -2564,9 +2417,7 @@ static int is_skippable_frame(const VP10_COMP *cpi) {
|
|||||||
// first pass, and so do its previous and forward frames, then this frame
|
// first pass, and so do its previous and forward frames, then this frame
|
||||||
// can be skipped for partition check, and the partition size is assigned
|
// can be skipped for partition check, and the partition size is assigned
|
||||||
// according to the variance
|
// according to the variance
|
||||||
const SVC *const svc = &cpi->svc;
|
const TWO_PASS *const twopass = &cpi->twopass;
|
||||||
const TWO_PASS *const twopass = is_two_pass_svc(cpi) ?
|
|
||||||
&svc->layer_context[svc->spatial_layer_id].twopass : &cpi->twopass;
|
|
||||||
|
|
||||||
return (!frame_is_intra_only(&cpi->common) &&
|
return (!frame_is_intra_only(&cpi->common) &&
|
||||||
twopass->stats_in - 2 > twopass->stats_in_start &&
|
twopass->stats_in - 2 > twopass->stats_in_start &&
|
||||||
@@ -2587,16 +2438,9 @@ void vp10_rc_get_second_pass_params(VP10_COMP *cpi) {
|
|||||||
FIRSTPASS_STATS this_frame;
|
FIRSTPASS_STATS this_frame;
|
||||||
|
|
||||||
int target_rate;
|
int target_rate;
|
||||||
LAYER_CONTEXT *const lc = is_two_pass_svc(cpi) ?
|
|
||||||
&cpi->svc.layer_context[cpi->svc.spatial_layer_id] : 0;
|
|
||||||
|
|
||||||
if (lc != NULL) {
|
frames_left = (int)(twopass->total_stats.count -
|
||||||
frames_left = (int)(twopass->total_stats.count -
|
cm->current_video_frame);
|
||||||
lc->current_video_frame_in_layer);
|
|
||||||
} else {
|
|
||||||
frames_left = (int)(twopass->total_stats.count -
|
|
||||||
cm->current_video_frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!twopass->stats_in)
|
if (!twopass->stats_in)
|
||||||
return;
|
return;
|
||||||
@@ -2612,21 +2456,9 @@ void vp10_rc_get_second_pass_params(VP10_COMP *cpi) {
|
|||||||
|
|
||||||
cm->frame_type = INTER_FRAME;
|
cm->frame_type = INTER_FRAME;
|
||||||
|
|
||||||
if (lc != NULL) {
|
|
||||||
if (cpi->svc.spatial_layer_id == 0) {
|
|
||||||
lc->is_key_frame = 0;
|
|
||||||
} else {
|
|
||||||
lc->is_key_frame = cpi->svc.layer_context[0].is_key_frame;
|
|
||||||
|
|
||||||
if (lc->is_key_frame)
|
|
||||||
cpi->ref_frame_flags &= (~VP9_LAST_FLAG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the firstpass stats indicate that this frame is skippable for the
|
// Do the firstpass stats indicate that this frame is skippable for the
|
||||||
// partition search?
|
// partition search?
|
||||||
if (cpi->sf.allow_partition_search_skip &&
|
if (cpi->sf.allow_partition_search_skip && cpi->oxcf.pass == 2) {
|
||||||
cpi->oxcf.pass == 2 && (!cpi->use_svc || is_two_pass_svc(cpi))) {
|
|
||||||
cpi->partition_search_skippable_frame = is_skippable_frame(cpi);
|
cpi->partition_search_skippable_frame = is_skippable_frame(cpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2637,8 +2469,7 @@ void vp10_rc_get_second_pass_params(VP10_COMP *cpi) {
|
|||||||
|
|
||||||
if (cpi->oxcf.rc_mode == VPX_Q) {
|
if (cpi->oxcf.rc_mode == VPX_Q) {
|
||||||
twopass->active_worst_quality = cpi->oxcf.cq_level;
|
twopass->active_worst_quality = cpi->oxcf.cq_level;
|
||||||
} else if (cm->current_video_frame == 0 ||
|
} else if (cm->current_video_frame == 0) {
|
||||||
(lc != NULL && lc->current_video_frame_in_layer == 0)) {
|
|
||||||
// Special case code for first frame.
|
// Special case code for first frame.
|
||||||
const int section_target_bandwidth = (int)(twopass->bits_left /
|
const int section_target_bandwidth = (int)(twopass->bits_left /
|
||||||
frames_left);
|
frames_left);
|
||||||
@@ -2685,34 +2516,11 @@ void vp10_rc_get_second_pass_params(VP10_COMP *cpi) {
|
|||||||
cm->frame_type = INTER_FRAME;
|
cm->frame_type = INTER_FRAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lc != NULL) {
|
|
||||||
if (cpi->svc.spatial_layer_id == 0) {
|
|
||||||
lc->is_key_frame = (cm->frame_type == KEY_FRAME);
|
|
||||||
if (lc->is_key_frame) {
|
|
||||||
cpi->ref_frame_flags &=
|
|
||||||
(~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
|
|
||||||
lc->frames_from_key_frame = 0;
|
|
||||||
// Encode an intra only empty frame since we have a key frame.
|
|
||||||
cpi->svc.encode_intra_empty_frame = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cm->frame_type = INTER_FRAME;
|
|
||||||
lc->is_key_frame = cpi->svc.layer_context[0].is_key_frame;
|
|
||||||
|
|
||||||
if (lc->is_key_frame) {
|
|
||||||
cpi->ref_frame_flags &= (~VP9_LAST_FLAG);
|
|
||||||
lc->frames_from_key_frame = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define a new GF/ARF group. (Should always enter here for key frames).
|
// Define a new GF/ARF group. (Should always enter here for key frames).
|
||||||
if (rc->frames_till_gf_update_due == 0) {
|
if (rc->frames_till_gf_update_due == 0) {
|
||||||
define_gf_group(cpi, &this_frame);
|
define_gf_group(cpi, &this_frame);
|
||||||
|
|
||||||
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
|
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
|
||||||
if (lc != NULL)
|
|
||||||
cpi->refresh_golden_frame = 1;
|
|
||||||
|
|
||||||
#if ARF_STATS_OUTPUT
|
#if ARF_STATS_OUTPUT
|
||||||
{
|
{
|
||||||
@@ -2732,8 +2540,7 @@ void vp10_rc_get_second_pass_params(VP10_COMP *cpi) {
|
|||||||
|
|
||||||
// Do the firstpass stats indicate that this frame is skippable for the
|
// Do the firstpass stats indicate that this frame is skippable for the
|
||||||
// partition search?
|
// partition search?
|
||||||
if (cpi->sf.allow_partition_search_skip && cpi->oxcf.pass == 2 &&
|
if (cpi->sf.allow_partition_search_skip && cpi->oxcf.pass == 2) {
|
||||||
(!cpi->use_svc || is_two_pass_svc(cpi))) {
|
|
||||||
cpi->partition_search_skippable_frame = is_skippable_frame(cpi);
|
cpi->partition_search_skippable_frame = is_skippable_frame(cpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2783,8 +2590,7 @@ void vp10_twopass_postencode_update(VP10_COMP *cpi) {
|
|||||||
rc->rate_error_estimate = 0;
|
rc->rate_error_estimate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpi->common.frame_type != KEY_FRAME &&
|
if (cpi->common.frame_type != KEY_FRAME) {
|
||||||
!vp10_is_upper_layer_key_frame(cpi)) {
|
|
||||||
twopass->kf_group_bits -= bits_used;
|
twopass->kf_group_bits -= bits_used;
|
||||||
twopass->last_kfgroup_zeromotion_pct = twopass->kf_zeromotion_pct;
|
twopass->last_kfgroup_zeromotion_pct = twopass->kf_zeromotion_pct;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ typedef struct {
|
|||||||
double new_mv_count;
|
double new_mv_count;
|
||||||
double duration;
|
double duration;
|
||||||
double count;
|
double count;
|
||||||
int64_t spatial_layer_id;
|
|
||||||
} FIRSTPASS_STATS;
|
} FIRSTPASS_STATS;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -14,11 +14,6 @@
|
|||||||
#include "vpx_scale/yv12config.h"
|
#include "vpx_scale/yv12config.h"
|
||||||
#include "vpx/vpx_integer.h"
|
#include "vpx/vpx_integer.h"
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
|
||||||
#include "vpx/vp8cx.h"
|
|
||||||
#include "vpx/vpx_encoder.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -233,28 +233,6 @@ int vp10_rc_clamp_iframe_target_size(const VP10_COMP *const cpi, int target) {
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the buffer level for higher temporal layers, given the encoded current
|
|
||||||
// temporal layer.
|
|
||||||
static void update_layer_buffer_level(SVC *svc, int encoded_frame_size) {
|
|
||||||
int i = 0;
|
|
||||||
int current_temporal_layer = svc->temporal_layer_id;
|
|
||||||
for (i = current_temporal_layer + 1;
|
|
||||||
i < svc->number_temporal_layers; ++i) {
|
|
||||||
const int layer = LAYER_IDS_TO_IDX(svc->spatial_layer_id, i,
|
|
||||||
svc->number_temporal_layers);
|
|
||||||
LAYER_CONTEXT *lc = &svc->layer_context[layer];
|
|
||||||
RATE_CONTROL *lrc = &lc->rc;
|
|
||||||
int bits_off_for_this_layer = (int)(lc->target_bandwidth / lc->framerate -
|
|
||||||
encoded_frame_size);
|
|
||||||
lrc->bits_off_target += bits_off_for_this_layer;
|
|
||||||
|
|
||||||
// Clip buffer level to maximum buffer size for the layer.
|
|
||||||
lrc->bits_off_target =
|
|
||||||
VPXMIN(lrc->bits_off_target, lrc->maximum_buffer_size);
|
|
||||||
lrc->buffer_level = lrc->bits_off_target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the buffer level: leaky bucket model.
|
// Update the buffer level: leaky bucket model.
|
||||||
static void update_buffer_level(VP10_COMP *cpi, int encoded_frame_size) {
|
static void update_buffer_level(VP10_COMP *cpi, int encoded_frame_size) {
|
||||||
const VP10_COMMON *const cm = &cpi->common;
|
const VP10_COMMON *const cm = &cpi->common;
|
||||||
@@ -270,10 +248,6 @@ static void update_buffer_level(VP10_COMP *cpi, int encoded_frame_size) {
|
|||||||
// Clip the buffer level to the maximum specified buffer size.
|
// Clip the buffer level to the maximum specified buffer size.
|
||||||
rc->bits_off_target = VPXMIN(rc->bits_off_target, rc->maximum_buffer_size);
|
rc->bits_off_target = VPXMIN(rc->bits_off_target, rc->maximum_buffer_size);
|
||||||
rc->buffer_level = rc->bits_off_target;
|
rc->buffer_level = rc->bits_off_target;
|
||||||
|
|
||||||
if (is_one_pass_cbr_svc(cpi)) {
|
|
||||||
update_layer_buffer_level(&cpi->svc, encoded_frame_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int vp10_rc_get_default_min_gf_interval(
|
int vp10_rc_get_default_min_gf_interval(
|
||||||
@@ -408,7 +382,7 @@ static double get_rate_correction_factor(const VP10_COMP *cpi) {
|
|||||||
rcf = rc->rate_correction_factors[rf_lvl];
|
rcf = rc->rate_correction_factors[rf_lvl];
|
||||||
} else {
|
} else {
|
||||||
if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) &&
|
if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) &&
|
||||||
!rc->is_src_frame_alt_ref && !cpi->use_svc &&
|
!rc->is_src_frame_alt_ref &&
|
||||||
(cpi->oxcf.rc_mode != VPX_CBR || cpi->oxcf.gf_cbr_boost_pct > 20))
|
(cpi->oxcf.rc_mode != VPX_CBR || cpi->oxcf.gf_cbr_boost_pct > 20))
|
||||||
rcf = rc->rate_correction_factors[GF_ARF_STD];
|
rcf = rc->rate_correction_factors[GF_ARF_STD];
|
||||||
else
|
else
|
||||||
@@ -434,7 +408,7 @@ static void set_rate_correction_factor(VP10_COMP *cpi, double factor) {
|
|||||||
rc->rate_correction_factors[rf_lvl] = factor;
|
rc->rate_correction_factors[rf_lvl] = factor;
|
||||||
} else {
|
} else {
|
||||||
if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) &&
|
if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) &&
|
||||||
!rc->is_src_frame_alt_ref && !cpi->use_svc &&
|
!rc->is_src_frame_alt_ref &&
|
||||||
(cpi->oxcf.rc_mode != VPX_CBR || cpi->oxcf.gf_cbr_boost_pct > 20))
|
(cpi->oxcf.rc_mode != VPX_CBR || cpi->oxcf.gf_cbr_boost_pct > 20))
|
||||||
rc->rate_correction_factors[GF_ARF_STD] = factor;
|
rc->rate_correction_factors[GF_ARF_STD] = factor;
|
||||||
else
|
else
|
||||||
@@ -529,10 +503,7 @@ int vp10_rc_regulate_q(const VP10_COMP *cpi, int target_bits_per_frame,
|
|||||||
i = active_best_quality;
|
i = active_best_quality;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
|
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled) {
|
||||||
cm->seg.enabled &&
|
|
||||||
cpi->svc.temporal_layer_id == 0 &&
|
|
||||||
cpi->svc.spatial_layer_id == 0) {
|
|
||||||
bits_per_mb_at_this_q =
|
bits_per_mb_at_this_q =
|
||||||
(int)vp10_cyclic_refresh_rc_bits_per_mb(cpi, i, correction_factor);
|
(int)vp10_cyclic_refresh_rc_bits_per_mb(cpi, i, correction_factor);
|
||||||
} else {
|
} else {
|
||||||
@@ -722,7 +693,6 @@ static int rc_pick_q_and_bounds_one_pass_cbr(const VP10_COMP *cpi,
|
|||||||
cm->bit_depth);
|
cm->bit_depth);
|
||||||
}
|
}
|
||||||
} else if (!rc->is_src_frame_alt_ref &&
|
} else if (!rc->is_src_frame_alt_ref &&
|
||||||
!cpi->use_svc &&
|
|
||||||
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
|
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
|
||||||
// Use the lower of active_worst_quality and recent
|
// Use the lower of active_worst_quality and recent
|
||||||
// average Q as basis for GF/ARF best Q limit unless last frame was
|
// average Q as basis for GF/ARF best Q limit unless last frame was
|
||||||
@@ -992,7 +962,7 @@ static int rc_pick_q_and_bounds_two_pass(const VP10_COMP *cpi,
|
|||||||
int *inter_minq;
|
int *inter_minq;
|
||||||
ASSIGN_MINQ_TABLE(cm->bit_depth, inter_minq);
|
ASSIGN_MINQ_TABLE(cm->bit_depth, inter_minq);
|
||||||
|
|
||||||
if (frame_is_intra_only(cm) || vp10_is_upper_layer_key_frame(cpi)) {
|
if (frame_is_intra_only(cm)) {
|
||||||
// Handle the special case for key frames forced when we have reached
|
// Handle the special case for key frames forced when we have reached
|
||||||
// the maximum key frame interval. Here force the Q to a range
|
// the maximum key frame interval. Here force the Q to a range
|
||||||
// based on the ambient Q to reduce the risk of popping.
|
// based on the ambient Q to reduce the risk of popping.
|
||||||
@@ -1111,7 +1081,7 @@ static int rc_pick_q_and_bounds_two_pass(const VP10_COMP *cpi,
|
|||||||
#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
|
#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
|
||||||
vpx_clear_system_state();
|
vpx_clear_system_state();
|
||||||
// Static forced key frames Q restrictions dealt with elsewhere.
|
// Static forced key frames Q restrictions dealt with elsewhere.
|
||||||
if (!((frame_is_intra_only(cm) || vp10_is_upper_layer_key_frame(cpi))) ||
|
if (!(frame_is_intra_only(cm)) ||
|
||||||
!rc->this_key_frame_forced ||
|
!rc->this_key_frame_forced ||
|
||||||
(cpi->twopass.last_kfgroup_zeromotion_pct < STATIC_MOTION_THRESH)) {
|
(cpi->twopass.last_kfgroup_zeromotion_pct < STATIC_MOTION_THRESH)) {
|
||||||
int qdelta = vp10_frame_type_qdelta(cpi, gf_group->rf_level[gf_group->index],
|
int qdelta = vp10_frame_type_qdelta(cpi, gf_group->rf_level[gf_group->index],
|
||||||
@@ -1138,8 +1108,7 @@ static int rc_pick_q_and_bounds_two_pass(const VP10_COMP *cpi,
|
|||||||
if (oxcf->rc_mode == VPX_Q) {
|
if (oxcf->rc_mode == VPX_Q) {
|
||||||
q = active_best_quality;
|
q = active_best_quality;
|
||||||
// Special case code to try and match quality with forced key frames.
|
// Special case code to try and match quality with forced key frames.
|
||||||
} else if ((frame_is_intra_only(cm) || vp10_is_upper_layer_key_frame(cpi)) &&
|
} else if (frame_is_intra_only(cm) && rc->this_key_frame_forced) {
|
||||||
rc->this_key_frame_forced) {
|
|
||||||
// If static since last kf use better of last boosted and last kf q.
|
// If static since last kf use better of last boosted and last kf q.
|
||||||
if (cpi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) {
|
if (cpi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) {
|
||||||
q = VPXMIN(rc->last_kf_qindex, rc->last_boosted_qindex);
|
q = VPXMIN(rc->last_kf_qindex, rc->last_boosted_qindex);
|
||||||
@@ -1281,8 +1250,7 @@ void vp10_rc_postencode_update(VP10_COMP *cpi, uint64_t bytes_used) {
|
|||||||
ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[KEY_FRAME] + qindex, 2);
|
ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[KEY_FRAME] + qindex, 2);
|
||||||
} else {
|
} else {
|
||||||
if (rc->is_src_frame_alt_ref ||
|
if (rc->is_src_frame_alt_ref ||
|
||||||
!(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) ||
|
!(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
|
||||||
(cpi->use_svc && oxcf->rc_mode == VPX_CBR)) {
|
|
||||||
rc->last_q[INTER_FRAME] = qindex;
|
rc->last_q[INTER_FRAME] = qindex;
|
||||||
rc->avg_frame_qindex[INTER_FRAME] =
|
rc->avg_frame_qindex[INTER_FRAME] =
|
||||||
ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[INTER_FRAME] + qindex, 2);
|
ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[INTER_FRAME] + qindex, 2);
|
||||||
@@ -1434,7 +1402,6 @@ void vp10_rc_get_one_pass_vbr_params(VP10_COMP *cpi) {
|
|||||||
static int calc_pframe_target_size_one_pass_cbr(const VP10_COMP *cpi) {
|
static int calc_pframe_target_size_one_pass_cbr(const VP10_COMP *cpi) {
|
||||||
const VP10EncoderConfig *oxcf = &cpi->oxcf;
|
const VP10EncoderConfig *oxcf = &cpi->oxcf;
|
||||||
const RATE_CONTROL *rc = &cpi->rc;
|
const RATE_CONTROL *rc = &cpi->rc;
|
||||||
const SVC *const svc = &cpi->svc;
|
|
||||||
const int64_t diff = rc->optimal_buffer_level - rc->buffer_level;
|
const int64_t diff = rc->optimal_buffer_level - rc->buffer_level;
|
||||||
const int64_t one_pct_bits = 1 + rc->optimal_buffer_level / 100;
|
const int64_t one_pct_bits = 1 + rc->optimal_buffer_level / 100;
|
||||||
int min_frame_target =
|
int min_frame_target =
|
||||||
@@ -1451,17 +1418,7 @@ static int calc_pframe_target_size_one_pass_cbr(const VP10_COMP *cpi) {
|
|||||||
} else {
|
} else {
|
||||||
target = rc->avg_frame_bandwidth;
|
target = rc->avg_frame_bandwidth;
|
||||||
}
|
}
|
||||||
if (is_one_pass_cbr_svc(cpi)) {
|
|
||||||
// Note that for layers, avg_frame_bandwidth is the cumulative
|
|
||||||
// per-frame-bandwidth. For the target size of this frame, use the
|
|
||||||
// layer average frame size (i.e., non-cumulative per-frame-bw).
|
|
||||||
int layer =
|
|
||||||
LAYER_IDS_TO_IDX(svc->spatial_layer_id,
|
|
||||||
svc->temporal_layer_id, svc->number_temporal_layers);
|
|
||||||
const LAYER_CONTEXT *lc = &svc->layer_context[layer];
|
|
||||||
target = lc->avg_frame_size;
|
|
||||||
min_frame_target = VPXMAX(lc->avg_frame_size >> 4, FRAME_OVERHEAD_BITS);
|
|
||||||
}
|
|
||||||
if (diff > 0) {
|
if (diff > 0) {
|
||||||
// Lower the target bandwidth for this frame.
|
// Lower the target bandwidth for this frame.
|
||||||
const int pct_low = (int)VPXMIN(diff / one_pct_bits, oxcf->under_shoot_pct);
|
const int pct_low = (int)VPXMIN(diff / one_pct_bits, oxcf->under_shoot_pct);
|
||||||
@@ -1482,8 +1439,6 @@ static int calc_pframe_target_size_one_pass_cbr(const VP10_COMP *cpi) {
|
|||||||
|
|
||||||
static int calc_iframe_target_size_one_pass_cbr(const VP10_COMP *cpi) {
|
static int calc_iframe_target_size_one_pass_cbr(const VP10_COMP *cpi) {
|
||||||
const RATE_CONTROL *rc = &cpi->rc;
|
const RATE_CONTROL *rc = &cpi->rc;
|
||||||
const VP10EncoderConfig *oxcf = &cpi->oxcf;
|
|
||||||
const SVC *const svc = &cpi->svc;
|
|
||||||
int target;
|
int target;
|
||||||
if (cpi->common.current_video_frame == 0) {
|
if (cpi->common.current_video_frame == 0) {
|
||||||
target = ((rc->starting_buffer_level / 2) > INT_MAX)
|
target = ((rc->starting_buffer_level / 2) > INT_MAX)
|
||||||
@@ -1491,14 +1446,7 @@ static int calc_iframe_target_size_one_pass_cbr(const VP10_COMP *cpi) {
|
|||||||
} else {
|
} else {
|
||||||
int kf_boost = 32;
|
int kf_boost = 32;
|
||||||
double framerate = cpi->framerate;
|
double framerate = cpi->framerate;
|
||||||
if (svc->number_temporal_layers > 1 &&
|
|
||||||
oxcf->rc_mode == VPX_CBR) {
|
|
||||||
// Use the layer framerate for temporal layers CBR mode.
|
|
||||||
const int layer = LAYER_IDS_TO_IDX(svc->spatial_layer_id,
|
|
||||||
svc->temporal_layer_id, svc->number_temporal_layers);
|
|
||||||
const LAYER_CONTEXT *lc = &svc->layer_context[layer];
|
|
||||||
framerate = lc->framerate;
|
|
||||||
}
|
|
||||||
kf_boost = VPXMAX(kf_boost, (int)(2 * framerate - 16));
|
kf_boost = VPXMAX(kf_boost, (int)(2 * framerate - 16));
|
||||||
if (rc->frames_since_key < framerate / 2) {
|
if (rc->frames_since_key < framerate / 2) {
|
||||||
kf_boost = (int)(kf_boost * rc->frames_since_key /
|
kf_boost = (int)(kf_boost * rc->frames_since_key /
|
||||||
@@ -1509,82 +1457,6 @@ static int calc_iframe_target_size_one_pass_cbr(const VP10_COMP *cpi) {
|
|||||||
return vp10_rc_clamp_iframe_target_size(cpi, target);
|
return vp10_rc_clamp_iframe_target_size(cpi, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset information needed to set proper reference frames and buffer updates
|
|
||||||
// for temporal layering. This is called when a key frame is encoded.
|
|
||||||
static void reset_temporal_layer_to_zero(VP10_COMP *cpi) {
|
|
||||||
int sl;
|
|
||||||
LAYER_CONTEXT *lc = NULL;
|
|
||||||
cpi->svc.temporal_layer_id = 0;
|
|
||||||
|
|
||||||
for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
|
|
||||||
lc = &cpi->svc.layer_context[sl * cpi->svc.number_temporal_layers];
|
|
||||||
lc->current_video_frame_in_layer = 0;
|
|
||||||
lc->frames_from_key_frame = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vp10_rc_get_svc_params(VP10_COMP *cpi) {
|
|
||||||
VP10_COMMON *const cm = &cpi->common;
|
|
||||||
RATE_CONTROL *const rc = &cpi->rc;
|
|
||||||
int target = rc->avg_frame_bandwidth;
|
|
||||||
const int layer = LAYER_IDS_TO_IDX(cpi->svc.spatial_layer_id,
|
|
||||||
cpi->svc.temporal_layer_id, cpi->svc.number_temporal_layers);
|
|
||||||
|
|
||||||
if ((cm->current_video_frame == 0) ||
|
|
||||||
(cpi->frame_flags & FRAMEFLAGS_KEY) ||
|
|
||||||
(cpi->oxcf.auto_key && (rc->frames_since_key %
|
|
||||||
cpi->oxcf.key_freq == 0))) {
|
|
||||||
cm->frame_type = KEY_FRAME;
|
|
||||||
rc->source_alt_ref_active = 0;
|
|
||||||
|
|
||||||
if (is_two_pass_svc(cpi)) {
|
|
||||||
cpi->svc.layer_context[layer].is_key_frame = 1;
|
|
||||||
cpi->ref_frame_flags &=
|
|
||||||
(~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
|
|
||||||
} else if (is_one_pass_cbr_svc(cpi)) {
|
|
||||||
cpi->svc.layer_context[layer].is_key_frame = 1;
|
|
||||||
reset_temporal_layer_to_zero(cpi);
|
|
||||||
cpi->ref_frame_flags &=
|
|
||||||
(~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
|
|
||||||
// Assumption here is that LAST_FRAME is being updated for a keyframe.
|
|
||||||
// Thus no change in update flags.
|
|
||||||
target = calc_iframe_target_size_one_pass_cbr(cpi);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cm->frame_type = INTER_FRAME;
|
|
||||||
if (is_two_pass_svc(cpi)) {
|
|
||||||
LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
|
|
||||||
if (cpi->svc.spatial_layer_id == 0) {
|
|
||||||
lc->is_key_frame = 0;
|
|
||||||
} else {
|
|
||||||
lc->is_key_frame =
|
|
||||||
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame;
|
|
||||||
if (lc->is_key_frame)
|
|
||||||
cpi->ref_frame_flags &= (~VP9_LAST_FLAG);
|
|
||||||
}
|
|
||||||
cpi->ref_frame_flags &= (~VP9_ALT_FLAG);
|
|
||||||
} else if (is_one_pass_cbr_svc(cpi)) {
|
|
||||||
LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
|
|
||||||
if (cpi->svc.spatial_layer_id == 0) {
|
|
||||||
lc->is_key_frame = 0;
|
|
||||||
} else {
|
|
||||||
lc->is_key_frame =
|
|
||||||
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame;
|
|
||||||
}
|
|
||||||
target = calc_pframe_target_size_one_pass_cbr(cpi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any update/change of global cyclic refresh parameters (amount/delta-qp)
|
|
||||||
// should be done here, before the frame qp is selected.
|
|
||||||
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
|
|
||||||
vp10_cyclic_refresh_update_parameters(cpi);
|
|
||||||
|
|
||||||
vp10_rc_set_frame_target(cpi, target);
|
|
||||||
rc->frames_till_gf_update_due = INT_MAX;
|
|
||||||
rc->baseline_gf_interval = INT_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vp10_rc_get_one_pass_cbr_params(VP10_COMP *cpi) {
|
void vp10_rc_get_one_pass_cbr_params(VP10_COMP *cpi) {
|
||||||
VP10_COMMON *const cm = &cpi->common;
|
VP10_COMMON *const cm = &cpi->common;
|
||||||
RATE_CONTROL *const rc = &cpi->rc;
|
RATE_CONTROL *const rc = &cpi->rc;
|
||||||
|
|||||||
@@ -169,7 +169,6 @@ int vp10_rc_get_default_max_gf_interval(double framerate, int min_frame_rate);
|
|||||||
// First call per frame, one of:
|
// First call per frame, one of:
|
||||||
// vp10_rc_get_one_pass_vbr_params()
|
// vp10_rc_get_one_pass_vbr_params()
|
||||||
// vp10_rc_get_one_pass_cbr_params()
|
// vp10_rc_get_one_pass_cbr_params()
|
||||||
// vp10_rc_get_svc_params()
|
|
||||||
// vp10_rc_get_first_pass_params()
|
// vp10_rc_get_first_pass_params()
|
||||||
// vp10_rc_get_second_pass_params()
|
// vp10_rc_get_second_pass_params()
|
||||||
// depending on the usage to set the rate control encode parameters desired.
|
// depending on the usage to set the rate control encode parameters desired.
|
||||||
@@ -190,7 +189,6 @@ int vp10_rc_get_default_max_gf_interval(double framerate, int min_frame_rate);
|
|||||||
// encode_frame_to_data_rate() function.
|
// encode_frame_to_data_rate() function.
|
||||||
void vp10_rc_get_one_pass_vbr_params(struct VP10_COMP *cpi);
|
void vp10_rc_get_one_pass_vbr_params(struct VP10_COMP *cpi);
|
||||||
void vp10_rc_get_one_pass_cbr_params(struct VP10_COMP *cpi);
|
void vp10_rc_get_one_pass_cbr_params(struct VP10_COMP *cpi);
|
||||||
void vp10_rc_get_svc_params(struct VP10_COMP *cpi);
|
|
||||||
|
|
||||||
// Post encode update of the rate control parameters based
|
// Post encode update of the rate control parameters based
|
||||||
// on bytes used
|
// on bytes used
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
// Intra only frames, golden frames (except alt ref overlays) and
|
// Intra only frames, golden frames (except alt ref overlays) and
|
||||||
// alt ref frames tend to be coded at a higher than ambient quality
|
// alt ref frames tend to be coded at a higher than ambient quality
|
||||||
static int frame_is_boosted(const VP10_COMP *cpi) {
|
static int frame_is_boosted(const VP10_COMP *cpi) {
|
||||||
return frame_is_kf_gf_arf(cpi) || vp10_is_upper_layer_key_frame(cpi);
|
return frame_is_kf_gf_arf(cpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets a partition size down to which the auto partition code will always
|
// Sets a partition size down to which the auto partition code will always
|
||||||
@@ -284,8 +284,7 @@ static void set_rt_speed_feature(VP10_COMP *cpi, SPEED_FEATURES *sf,
|
|||||||
// pred_mv_sad will not be set (since vp10_mv_pred will not
|
// pred_mv_sad will not be set (since vp10_mv_pred will not
|
||||||
// be called).
|
// be called).
|
||||||
// TODO(marpan/agrange): Fix this condition.
|
// TODO(marpan/agrange): Fix this condition.
|
||||||
sf->reference_masking = (cpi->oxcf.resize_mode != RESIZE_DYNAMIC &&
|
sf->reference_masking = (cpi->oxcf.resize_mode != RESIZE_DYNAMIC) ? 1 : 0;
|
||||||
cpi->svc.number_spatial_layers == 1) ? 1 : 0;
|
|
||||||
|
|
||||||
sf->disable_filter_search_var_thresh = 50;
|
sf->disable_filter_search_var_thresh = 50;
|
||||||
sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
|
sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
|
||||||
|
|||||||
@@ -1,646 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "vp10/encoder/encoder.h"
|
|
||||||
#include "vp10/encoder/svc_layercontext.h"
|
|
||||||
#include "vp10/encoder/extend.h"
|
|
||||||
|
|
||||||
#define SMALL_FRAME_FB_IDX 7
|
|
||||||
#define SMALL_FRAME_WIDTH 16
|
|
||||||
#define SMALL_FRAME_HEIGHT 16
|
|
||||||
|
|
||||||
void vp10_init_layer_context(VP10_COMP *const cpi) {
|
|
||||||
SVC *const svc = &cpi->svc;
|
|
||||||
const VP10EncoderConfig *const oxcf = &cpi->oxcf;
|
|
||||||
int sl, tl;
|
|
||||||
int alt_ref_idx = svc->number_spatial_layers;
|
|
||||||
|
|
||||||
svc->spatial_layer_id = 0;
|
|
||||||
svc->temporal_layer_id = 0;
|
|
||||||
|
|
||||||
if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
|
|
||||||
if (vpx_realloc_frame_buffer(&cpi->svc.empty_frame.img,
|
|
||||||
SMALL_FRAME_WIDTH, SMALL_FRAME_HEIGHT,
|
|
||||||
cpi->common.subsampling_x,
|
|
||||||
cpi->common.subsampling_y,
|
|
||||||
#if CONFIG_VP9_HIGHBITDEPTH
|
|
||||||
cpi->common.use_highbitdepth,
|
|
||||||
#endif
|
|
||||||
VP9_ENC_BORDER_IN_PIXELS,
|
|
||||||
cpi->common.byte_alignment,
|
|
||||||
NULL, NULL, NULL))
|
|
||||||
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
|
|
||||||
"Failed to allocate empty frame for multiple frame "
|
|
||||||
"contexts");
|
|
||||||
|
|
||||||
memset(cpi->svc.empty_frame.img.buffer_alloc, 0x80,
|
|
||||||
cpi->svc.empty_frame.img.buffer_alloc_sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
|
|
||||||
for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
|
|
||||||
int layer = LAYER_IDS_TO_IDX(sl, tl, oxcf->ts_number_layers);
|
|
||||||
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
|
|
||||||
RATE_CONTROL *const lrc = &lc->rc;
|
|
||||||
int i;
|
|
||||||
lc->current_video_frame_in_layer = 0;
|
|
||||||
lc->layer_size = 0;
|
|
||||||
lc->frames_from_key_frame = 0;
|
|
||||||
lc->last_frame_type = FRAME_TYPES;
|
|
||||||
lrc->ni_av_qi = oxcf->worst_allowed_q;
|
|
||||||
lrc->total_actual_bits = 0;
|
|
||||||
lrc->total_target_vs_actual = 0;
|
|
||||||
lrc->ni_tot_qi = 0;
|
|
||||||
lrc->tot_q = 0.0;
|
|
||||||
lrc->avg_q = 0.0;
|
|
||||||
lrc->ni_frames = 0;
|
|
||||||
lrc->decimation_count = 0;
|
|
||||||
lrc->decimation_factor = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < RATE_FACTOR_LEVELS; ++i) {
|
|
||||||
lrc->rate_correction_factors[i] = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cpi->oxcf.rc_mode == VPX_CBR) {
|
|
||||||
lc->target_bandwidth = oxcf->layer_target_bitrate[layer];
|
|
||||||
lrc->last_q[INTER_FRAME] = oxcf->worst_allowed_q;
|
|
||||||
lrc->avg_frame_qindex[INTER_FRAME] = oxcf->worst_allowed_q;
|
|
||||||
lrc->avg_frame_qindex[KEY_FRAME] = oxcf->worst_allowed_q;
|
|
||||||
} else {
|
|
||||||
lc->target_bandwidth = oxcf->layer_target_bitrate[layer];
|
|
||||||
lrc->last_q[KEY_FRAME] = oxcf->best_allowed_q;
|
|
||||||
lrc->last_q[INTER_FRAME] = oxcf->best_allowed_q;
|
|
||||||
lrc->avg_frame_qindex[KEY_FRAME] = (oxcf->worst_allowed_q +
|
|
||||||
oxcf->best_allowed_q) / 2;
|
|
||||||
lrc->avg_frame_qindex[INTER_FRAME] = (oxcf->worst_allowed_q +
|
|
||||||
oxcf->best_allowed_q) / 2;
|
|
||||||
if (oxcf->ss_enable_auto_arf[sl])
|
|
||||||
lc->alt_ref_idx = alt_ref_idx++;
|
|
||||||
else
|
|
||||||
lc->alt_ref_idx = INVALID_IDX;
|
|
||||||
lc->gold_ref_idx = INVALID_IDX;
|
|
||||||
}
|
|
||||||
|
|
||||||
lrc->buffer_level = oxcf->starting_buffer_level_ms *
|
|
||||||
lc->target_bandwidth / 1000;
|
|
||||||
lrc->bits_off_target = lrc->buffer_level;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 vp10_update_layer_context_change_config(VP10_COMP *const cpi,
|
|
||||||
const int target_bandwidth) {
|
|
||||||
SVC *const svc = &cpi->svc;
|
|
||||||
const VP10EncoderConfig *const oxcf = &cpi->oxcf;
|
|
||||||
const RATE_CONTROL *const rc = &cpi->rc;
|
|
||||||
int sl, tl, layer = 0, spatial_layer_target;
|
|
||||||
float bitrate_alloc = 1.0;
|
|
||||||
|
|
||||||
if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING) {
|
|
||||||
for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
|
|
||||||
spatial_layer_target = 0;
|
|
||||||
|
|
||||||
for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
|
|
||||||
layer = LAYER_IDS_TO_IDX(sl, tl, oxcf->ts_number_layers);
|
|
||||||
svc->layer_context[layer].target_bandwidth =
|
|
||||||
oxcf->layer_target_bitrate[layer];
|
|
||||||
}
|
|
||||||
|
|
||||||
layer = LAYER_IDS_TO_IDX(sl, ((oxcf->ts_number_layers - 1) < 0 ?
|
|
||||||
0 : (oxcf->ts_number_layers - 1)), oxcf->ts_number_layers);
|
|
||||||
spatial_layer_target =
|
|
||||||
svc->layer_context[layer].target_bandwidth =
|
|
||||||
oxcf->layer_target_bitrate[layer];
|
|
||||||
|
|
||||||
for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
|
|
||||||
LAYER_CONTEXT *const lc =
|
|
||||||
&svc->layer_context[sl * oxcf->ts_number_layers + tl];
|
|
||||||
RATE_CONTROL *const lrc = &lc->rc;
|
|
||||||
|
|
||||||
lc->spatial_layer_target_bandwidth = spatial_layer_target;
|
|
||||||
bitrate_alloc = (float)lc->target_bandwidth / spatial_layer_target;
|
|
||||||
lrc->starting_buffer_level =
|
|
||||||
(int64_t)(rc->starting_buffer_level * bitrate_alloc);
|
|
||||||
lrc->optimal_buffer_level =
|
|
||||||
(int64_t)(rc->optimal_buffer_level * bitrate_alloc);
|
|
||||||
lrc->maximum_buffer_size =
|
|
||||||
(int64_t)(rc->maximum_buffer_size * bitrate_alloc);
|
|
||||||
lrc->bits_off_target =
|
|
||||||
VPXMIN(lrc->bits_off_target, lrc->maximum_buffer_size);
|
|
||||||
lrc->buffer_level = VPXMIN(lrc->buffer_level, lrc->maximum_buffer_size);
|
|
||||||
lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[tl];
|
|
||||||
lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
|
|
||||||
lrc->max_frame_bandwidth = rc->max_frame_bandwidth;
|
|
||||||
lrc->worst_quality = rc->worst_quality;
|
|
||||||
lrc->best_quality = rc->best_quality;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int layer_end;
|
|
||||||
|
|
||||||
if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
|
|
||||||
layer_end = svc->number_temporal_layers;
|
|
||||||
} else {
|
|
||||||
layer_end = svc->number_spatial_layers;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (layer = 0; layer < layer_end; ++layer) {
|
|
||||||
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
|
|
||||||
RATE_CONTROL *const lrc = &lc->rc;
|
|
||||||
|
|
||||||
lc->target_bandwidth = oxcf->layer_target_bitrate[layer];
|
|
||||||
|
|
||||||
bitrate_alloc = (float)lc->target_bandwidth / target_bandwidth;
|
|
||||||
// Update buffer-related quantities.
|
|
||||||
lrc->starting_buffer_level =
|
|
||||||
(int64_t)(rc->starting_buffer_level * bitrate_alloc);
|
|
||||||
lrc->optimal_buffer_level =
|
|
||||||
(int64_t)(rc->optimal_buffer_level * bitrate_alloc);
|
|
||||||
lrc->maximum_buffer_size =
|
|
||||||
(int64_t)(rc->maximum_buffer_size * bitrate_alloc);
|
|
||||||
lrc->bits_off_target = VPXMIN(lrc->bits_off_target,
|
|
||||||
lrc->maximum_buffer_size);
|
|
||||||
lrc->buffer_level = VPXMIN(lrc->buffer_level, lrc->maximum_buffer_size);
|
|
||||||
// Update framerate-related quantities.
|
|
||||||
if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
|
|
||||||
lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[layer];
|
|
||||||
} else {
|
|
||||||
lc->framerate = cpi->framerate;
|
|
||||||
}
|
|
||||||
lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
|
|
||||||
lrc->max_frame_bandwidth = rc->max_frame_bandwidth;
|
|
||||||
// Update qp-related quantities.
|
|
||||||
lrc->worst_quality = rc->worst_quality;
|
|
||||||
lrc->best_quality = rc->best_quality;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static LAYER_CONTEXT *get_layer_context(VP10_COMP *const cpi) {
|
|
||||||
if (is_one_pass_cbr_svc(cpi))
|
|
||||||
return &cpi->svc.layer_context[cpi->svc.spatial_layer_id *
|
|
||||||
cpi->svc.number_temporal_layers + cpi->svc.temporal_layer_id];
|
|
||||||
else
|
|
||||||
return (cpi->svc.number_temporal_layers > 1 &&
|
|
||||||
cpi->oxcf.rc_mode == VPX_CBR) ?
|
|
||||||
&cpi->svc.layer_context[cpi->svc.temporal_layer_id] :
|
|
||||||
&cpi->svc.layer_context[cpi->svc.spatial_layer_id];
|
|
||||||
}
|
|
||||||
|
|
||||||
void vp10_update_temporal_layer_framerate(VP10_COMP *const cpi) {
|
|
||||||
SVC *const svc = &cpi->svc;
|
|
||||||
const VP10EncoderConfig *const oxcf = &cpi->oxcf;
|
|
||||||
LAYER_CONTEXT *const lc = get_layer_context(cpi);
|
|
||||||
RATE_CONTROL *const lrc = &lc->rc;
|
|
||||||
// Index into spatial+temporal arrays.
|
|
||||||
const int st_idx = svc->spatial_layer_id * svc->number_temporal_layers +
|
|
||||||
svc->temporal_layer_id;
|
|
||||||
const int tl = svc->temporal_layer_id;
|
|
||||||
|
|
||||||
lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[tl];
|
|
||||||
lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
|
|
||||||
lrc->max_frame_bandwidth = cpi->rc.max_frame_bandwidth;
|
|
||||||
// Update the average layer frame size (non-cumulative per-frame-bw).
|
|
||||||
if (tl == 0) {
|
|
||||||
lc->avg_frame_size = lrc->avg_frame_bandwidth;
|
|
||||||
} else {
|
|
||||||
const double prev_layer_framerate =
|
|
||||||
cpi->framerate / oxcf->ts_rate_decimator[tl - 1];
|
|
||||||
const int prev_layer_target_bandwidth =
|
|
||||||
oxcf->layer_target_bitrate[st_idx - 1];
|
|
||||||
lc->avg_frame_size =
|
|
||||||
(int)((lc->target_bandwidth - prev_layer_target_bandwidth) /
|
|
||||||
(lc->framerate - prev_layer_framerate));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vp10_update_spatial_layer_framerate(VP10_COMP *const cpi,
|
|
||||||
double framerate) {
|
|
||||||
const VP10EncoderConfig *const oxcf = &cpi->oxcf;
|
|
||||||
LAYER_CONTEXT *const lc = get_layer_context(cpi);
|
|
||||||
RATE_CONTROL *const lrc = &lc->rc;
|
|
||||||
|
|
||||||
lc->framerate = framerate;
|
|
||||||
lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
|
|
||||||
lrc->min_frame_bandwidth = (int)(lrc->avg_frame_bandwidth *
|
|
||||||
oxcf->two_pass_vbrmin_section / 100);
|
|
||||||
lrc->max_frame_bandwidth = (int)(((int64_t)lrc->avg_frame_bandwidth *
|
|
||||||
oxcf->two_pass_vbrmax_section) / 100);
|
|
||||||
vp10_rc_set_gf_interval_range(cpi, lrc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vp10_restore_layer_context(VP10_COMP *const cpi) {
|
|
||||||
LAYER_CONTEXT *const lc = get_layer_context(cpi);
|
|
||||||
const int old_frame_since_key = cpi->rc.frames_since_key;
|
|
||||||
const int old_frame_to_key = cpi->rc.frames_to_key;
|
|
||||||
|
|
||||||
cpi->rc = lc->rc;
|
|
||||||
cpi->twopass = lc->twopass;
|
|
||||||
cpi->oxcf.target_bandwidth = lc->target_bandwidth;
|
|
||||||
cpi->alt_ref_source = lc->alt_ref_source;
|
|
||||||
// Reset the frames_since_key and frames_to_key counters to their values
|
|
||||||
// before the layer restore. Keep these defined for the stream (not layer).
|
|
||||||
if (cpi->svc.number_temporal_layers > 1) {
|
|
||||||
cpi->rc.frames_since_key = old_frame_since_key;
|
|
||||||
cpi->rc.frames_to_key = old_frame_to_key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vp10_save_layer_context(VP10_COMP *const cpi) {
|
|
||||||
const VP10EncoderConfig *const oxcf = &cpi->oxcf;
|
|
||||||
LAYER_CONTEXT *const lc = get_layer_context(cpi);
|
|
||||||
|
|
||||||
lc->rc = cpi->rc;
|
|
||||||
lc->twopass = cpi->twopass;
|
|
||||||
lc->target_bandwidth = (int)oxcf->target_bandwidth;
|
|
||||||
lc->alt_ref_source = cpi->alt_ref_source;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vp10_init_second_pass_spatial_svc(VP10_COMP *cpi) {
|
|
||||||
SVC *const svc = &cpi->svc;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < svc->number_spatial_layers; ++i) {
|
|
||||||
TWO_PASS *const twopass = &svc->layer_context[i].twopass;
|
|
||||||
|
|
||||||
svc->spatial_layer_id = i;
|
|
||||||
vp10_init_second_pass(cpi);
|
|
||||||
|
|
||||||
twopass->total_stats.spatial_layer_id = i;
|
|
||||||
twopass->total_left_stats.spatial_layer_id = i;
|
|
||||||
}
|
|
||||||
svc->spatial_layer_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vp10_inc_frame_in_layer(VP10_COMP *const cpi) {
|
|
||||||
LAYER_CONTEXT *const lc =
|
|
||||||
&cpi->svc.layer_context[cpi->svc.spatial_layer_id *
|
|
||||||
cpi->svc.number_temporal_layers];
|
|
||||||
++lc->current_video_frame_in_layer;
|
|
||||||
++lc->frames_from_key_frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vp10_is_upper_layer_key_frame(const VP10_COMP *const cpi) {
|
|
||||||
return is_two_pass_svc(cpi) &&
|
|
||||||
cpi->svc.spatial_layer_id > 0 &&
|
|
||||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
|
|
||||||
cpi->svc.number_temporal_layers +
|
|
||||||
cpi->svc.temporal_layer_id].is_key_frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void get_layer_resolution(const int width_org, const int height_org,
|
|
||||||
const int num, const int den,
|
|
||||||
int *width_out, int *height_out) {
|
|
||||||
int w, h;
|
|
||||||
|
|
||||||
if (width_out == NULL || height_out == NULL || den == 0)
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The function sets proper ref_frame_flags, buffer indices, and buffer update
|
|
||||||
// variables for temporal layering mode 3 - that does 0-2-1-2 temporal layering
|
|
||||||
// scheme.
|
|
||||||
static void set_flags_and_fb_idx_for_temporal_mode3(VP10_COMP *const cpi) {
|
|
||||||
int frame_num_within_temporal_struct = 0;
|
|
||||||
int spatial_id, temporal_id;
|
|
||||||
spatial_id = cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
|
|
||||||
frame_num_within_temporal_struct =
|
|
||||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
|
|
||||||
cpi->svc.number_temporal_layers].current_video_frame_in_layer % 4;
|
|
||||||
temporal_id = cpi->svc.temporal_layer_id =
|
|
||||||
(frame_num_within_temporal_struct & 1) ? 2 :
|
|
||||||
(frame_num_within_temporal_struct >> 1);
|
|
||||||
cpi->ext_refresh_last_frame = cpi->ext_refresh_golden_frame =
|
|
||||||
cpi->ext_refresh_alt_ref_frame = 0;
|
|
||||||
if (!temporal_id) {
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 1;
|
|
||||||
cpi->ext_refresh_last_frame = 1;
|
|
||||||
if (!spatial_id) {
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG;
|
|
||||||
} else if (cpi->svc.layer_context[temporal_id].is_key_frame) {
|
|
||||||
// base layer is a key frame.
|
|
||||||
cpi->ref_frame_flags = VP9_GOLD_FLAG;
|
|
||||||
} else {
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
|
|
||||||
}
|
|
||||||
} else if (temporal_id == 1) {
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 1;
|
|
||||||
cpi->ext_refresh_alt_ref_frame = 1;
|
|
||||||
if (!spatial_id) {
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG;
|
|
||||||
} else {
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (frame_num_within_temporal_struct == 1) {
|
|
||||||
// the first tl2 picture
|
|
||||||
if (!spatial_id) {
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 1;
|
|
||||||
cpi->ext_refresh_alt_ref_frame = 1;
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG;
|
|
||||||
} else if (spatial_id < cpi->svc.number_spatial_layers - 1) {
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 1;
|
|
||||||
cpi->ext_refresh_alt_ref_frame = 1;
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
|
|
||||||
} else { // Top layer
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 0;
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The second tl2 picture
|
|
||||||
if (!spatial_id) {
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 1;
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG;
|
|
||||||
cpi->ext_refresh_last_frame = 1;
|
|
||||||
} else if (spatial_id < cpi->svc.number_spatial_layers - 1) {
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 1;
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
|
|
||||||
cpi->ext_refresh_last_frame = 1;
|
|
||||||
} else { // top layer
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 0;
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (temporal_id == 0) {
|
|
||||||
cpi->lst_fb_idx = spatial_id;
|
|
||||||
if (spatial_id)
|
|
||||||
cpi->gld_fb_idx = spatial_id - 1;
|
|
||||||
else
|
|
||||||
cpi->gld_fb_idx = 0;
|
|
||||||
cpi->alt_fb_idx = 0;
|
|
||||||
} else if (temporal_id == 1) {
|
|
||||||
cpi->lst_fb_idx = spatial_id;
|
|
||||||
cpi->gld_fb_idx = cpi->svc.number_spatial_layers + spatial_id - 1;
|
|
||||||
cpi->alt_fb_idx = cpi->svc.number_spatial_layers + spatial_id;
|
|
||||||
} else if (frame_num_within_temporal_struct == 1) {
|
|
||||||
cpi->lst_fb_idx = spatial_id;
|
|
||||||
cpi->gld_fb_idx = cpi->svc.number_spatial_layers + spatial_id - 1;
|
|
||||||
cpi->alt_fb_idx = cpi->svc.number_spatial_layers + spatial_id;
|
|
||||||
} else {
|
|
||||||
cpi->lst_fb_idx = cpi->svc.number_spatial_layers + spatial_id;
|
|
||||||
cpi->gld_fb_idx = cpi->svc.number_spatial_layers + spatial_id - 1;
|
|
||||||
cpi->alt_fb_idx = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The function sets proper ref_frame_flags, buffer indices, and buffer update
|
|
||||||
// variables for temporal layering mode 2 - that does 0-1-0-1 temporal layering
|
|
||||||
// scheme.
|
|
||||||
static void set_flags_and_fb_idx_for_temporal_mode2(VP10_COMP *const cpi) {
|
|
||||||
int spatial_id, temporal_id;
|
|
||||||
spatial_id = cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
|
|
||||||
temporal_id = cpi->svc.temporal_layer_id =
|
|
||||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
|
|
||||||
cpi->svc.number_temporal_layers].current_video_frame_in_layer & 1;
|
|
||||||
cpi->ext_refresh_last_frame = cpi->ext_refresh_golden_frame =
|
|
||||||
cpi->ext_refresh_alt_ref_frame = 0;
|
|
||||||
if (!temporal_id) {
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 1;
|
|
||||||
cpi->ext_refresh_last_frame = 1;
|
|
||||||
if (!spatial_id) {
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG;
|
|
||||||
} else if (cpi->svc.layer_context[temporal_id].is_key_frame) {
|
|
||||||
// base layer is a key frame.
|
|
||||||
cpi->ref_frame_flags = VP9_GOLD_FLAG;
|
|
||||||
} else {
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
|
|
||||||
}
|
|
||||||
} else if (temporal_id == 1) {
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 1;
|
|
||||||
cpi->ext_refresh_alt_ref_frame = 1;
|
|
||||||
if (!spatial_id) {
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG;
|
|
||||||
} else {
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (temporal_id == 0) {
|
|
||||||
cpi->lst_fb_idx = spatial_id;
|
|
||||||
if (spatial_id)
|
|
||||||
cpi->gld_fb_idx = spatial_id - 1;
|
|
||||||
else
|
|
||||||
cpi->gld_fb_idx = 0;
|
|
||||||
cpi->alt_fb_idx = 0;
|
|
||||||
} else if (temporal_id == 1) {
|
|
||||||
cpi->lst_fb_idx = spatial_id;
|
|
||||||
cpi->gld_fb_idx = cpi->svc.number_spatial_layers + spatial_id - 1;
|
|
||||||
cpi->alt_fb_idx = cpi->svc.number_spatial_layers + spatial_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The function sets proper ref_frame_flags, buffer indices, and buffer update
|
|
||||||
// variables for temporal layering mode 0 - that has no temporal layering.
|
|
||||||
static void set_flags_and_fb_idx_for_temporal_mode_noLayering(
|
|
||||||
VP10_COMP *const cpi) {
|
|
||||||
int spatial_id;
|
|
||||||
spatial_id = cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
|
|
||||||
cpi->ext_refresh_last_frame =
|
|
||||||
cpi->ext_refresh_golden_frame = cpi->ext_refresh_alt_ref_frame = 0;
|
|
||||||
cpi->ext_refresh_frame_flags_pending = 1;
|
|
||||||
cpi->ext_refresh_last_frame = 1;
|
|
||||||
if (!spatial_id) {
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG;
|
|
||||||
} else if (cpi->svc.layer_context[0].is_key_frame) {
|
|
||||||
cpi->ref_frame_flags = VP9_GOLD_FLAG;
|
|
||||||
} else {
|
|
||||||
cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
|
|
||||||
}
|
|
||||||
cpi->lst_fb_idx = spatial_id;
|
|
||||||
if (spatial_id)
|
|
||||||
cpi->gld_fb_idx = spatial_id - 1;
|
|
||||||
else
|
|
||||||
cpi->gld_fb_idx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vp10_one_pass_cbr_svc_start_layer(VP10_COMP *const cpi) {
|
|
||||||
int width = 0, height = 0;
|
|
||||||
LAYER_CONTEXT *lc = NULL;
|
|
||||||
|
|
||||||
if (cpi->svc.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_0212) {
|
|
||||||
set_flags_and_fb_idx_for_temporal_mode3(cpi);
|
|
||||||
} else if (cpi->svc.temporal_layering_mode ==
|
|
||||||
VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING) {
|
|
||||||
set_flags_and_fb_idx_for_temporal_mode_noLayering(cpi);
|
|
||||||
} else if (cpi->svc.temporal_layering_mode ==
|
|
||||||
VP9E_TEMPORAL_LAYERING_MODE_0101) {
|
|
||||||
set_flags_and_fb_idx_for_temporal_mode2(cpi);
|
|
||||||
} else if (cpi->svc.temporal_layering_mode ==
|
|
||||||
VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
|
|
||||||
// VP9E_TEMPORAL_LAYERING_MODE_BYPASS :
|
|
||||||
// if the code goes here, it means the encoder will be relying on the
|
|
||||||
// flags from outside for layering.
|
|
||||||
// However, since when spatial+temporal layering is used, the buffer indices
|
|
||||||
// cannot be derived automatically, the bypass mode will only work when the
|
|
||||||
// number of spatial layers equals 1.
|
|
||||||
assert(cpi->svc.number_spatial_layers == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id *
|
|
||||||
cpi->svc.number_temporal_layers +
|
|
||||||
cpi->svc.temporal_layer_id];
|
|
||||||
|
|
||||||
get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height,
|
|
||||||
lc->scaling_factor_num, lc->scaling_factor_den,
|
|
||||||
&width, &height);
|
|
||||||
|
|
||||||
if (vp10_set_size_literal(cpi, width, height) != 0)
|
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
|
||||||
int vp10_svc_start_frame(VP10_COMP *const cpi) {
|
|
||||||
int width = 0, height = 0;
|
|
||||||
LAYER_CONTEXT *lc;
|
|
||||||
struct lookahead_entry *buf;
|
|
||||||
int count = 1 << (cpi->svc.number_temporal_layers - 1);
|
|
||||||
|
|
||||||
cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
|
|
||||||
lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
|
|
||||||
|
|
||||||
cpi->svc.temporal_layer_id = 0;
|
|
||||||
while ((lc->current_video_frame_in_layer % count) != 0) {
|
|
||||||
++cpi->svc.temporal_layer_id;
|
|
||||||
count >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
|
|
||||||
|
|
||||||
cpi->lst_fb_idx = cpi->svc.spatial_layer_id;
|
|
||||||
|
|
||||||
if (cpi->svc.spatial_layer_id == 0)
|
|
||||||
cpi->gld_fb_idx = (lc->gold_ref_idx >= 0) ?
|
|
||||||
lc->gold_ref_idx : cpi->lst_fb_idx;
|
|
||||||
else
|
|
||||||
cpi->gld_fb_idx = cpi->svc.spatial_layer_id - 1;
|
|
||||||
|
|
||||||
if (lc->current_video_frame_in_layer == 0) {
|
|
||||||
if (cpi->svc.spatial_layer_id >= 2) {
|
|
||||||
cpi->alt_fb_idx = cpi->svc.spatial_layer_id - 2;
|
|
||||||
} else {
|
|
||||||
cpi->alt_fb_idx = cpi->lst_fb_idx;
|
|
||||||
cpi->ref_frame_flags &= (~VP9_LAST_FLAG & ~VP9_ALT_FLAG);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id]) {
|
|
||||||
cpi->alt_fb_idx = lc->alt_ref_idx;
|
|
||||||
if (!lc->has_alt_frame)
|
|
||||||
cpi->ref_frame_flags &= (~VP9_ALT_FLAG);
|
|
||||||
} else {
|
|
||||||
// Find a proper alt_fb_idx for layers that don't have alt ref frame
|
|
||||||
if (cpi->svc.spatial_layer_id == 0) {
|
|
||||||
cpi->alt_fb_idx = cpi->lst_fb_idx;
|
|
||||||
} else {
|
|
||||||
LAYER_CONTEXT *lc_lower =
|
|
||||||
&cpi->svc.layer_context[cpi->svc.spatial_layer_id - 1];
|
|
||||||
|
|
||||||
if (cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id - 1] &&
|
|
||||||
lc_lower->alt_ref_source != NULL)
|
|
||||||
cpi->alt_fb_idx = lc_lower->alt_ref_idx;
|
|
||||||
else if (cpi->svc.spatial_layer_id >= 2)
|
|
||||||
cpi->alt_fb_idx = cpi->svc.spatial_layer_id - 2;
|
|
||||||
else
|
|
||||||
cpi->alt_fb_idx = cpi->lst_fb_idx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height,
|
|
||||||
lc->scaling_factor_num, lc->scaling_factor_den,
|
|
||||||
&width, &height);
|
|
||||||
|
|
||||||
// Workaround for multiple frame contexts. In some frames we can't use prev_mi
|
|
||||||
// since its previous frame could be changed during decoding time. The idea is
|
|
||||||
// we put a empty invisible frame in front of them, then we will not use
|
|
||||||
// prev_mi when encoding these frames.
|
|
||||||
|
|
||||||
buf = vp10_lookahead_peek(cpi->lookahead, 0);
|
|
||||||
if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2 &&
|
|
||||||
cpi->svc.encode_empty_frame_state == NEED_TO_ENCODE &&
|
|
||||||
lc->rc.frames_to_key != 0 &&
|
|
||||||
!(buf != NULL && (buf->flags & VPX_EFLAG_FORCE_KF))) {
|
|
||||||
if ((cpi->svc.number_temporal_layers > 1 &&
|
|
||||||
cpi->svc.temporal_layer_id < cpi->svc.number_temporal_layers - 1) ||
|
|
||||||
(cpi->svc.number_spatial_layers > 1 &&
|
|
||||||
cpi->svc.spatial_layer_id == 0)) {
|
|
||||||
struct lookahead_entry *buf = vp10_lookahead_peek(cpi->lookahead, 0);
|
|
||||||
|
|
||||||
if (buf != NULL) {
|
|
||||||
cpi->svc.empty_frame.ts_start = buf->ts_start;
|
|
||||||
cpi->svc.empty_frame.ts_end = buf->ts_end;
|
|
||||||
cpi->svc.encode_empty_frame_state = ENCODING;
|
|
||||||
cpi->common.show_frame = 0;
|
|
||||||
cpi->ref_frame_flags = 0;
|
|
||||||
cpi->common.frame_type = INTER_FRAME;
|
|
||||||
cpi->lst_fb_idx =
|
|
||||||
cpi->gld_fb_idx = cpi->alt_fb_idx = SMALL_FRAME_FB_IDX;
|
|
||||||
|
|
||||||
if (cpi->svc.encode_intra_empty_frame != 0)
|
|
||||||
cpi->common.intra_only = 1;
|
|
||||||
|
|
||||||
width = SMALL_FRAME_WIDTH;
|
|
||||||
height = SMALL_FRAME_HEIGHT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cpi->oxcf.worst_allowed_q = vp10_quantizer_to_qindex(lc->max_q);
|
|
||||||
cpi->oxcf.best_allowed_q = vp10_quantizer_to_qindex(lc->min_q);
|
|
||||||
|
|
||||||
vp10_change_config(cpi, &cpi->oxcf);
|
|
||||||
|
|
||||||
if (vp10_set_size_literal(cpi, width, height) != 0)
|
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
|
||||||
|
|
||||||
vp10_set_high_precision_mv(cpi, 1);
|
|
||||||
|
|
||||||
cpi->alt_ref_source = get_layer_context(cpi)->alt_ref_source;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct lookahead_entry *vp10_svc_lookahead_pop(VP10_COMP *const cpi,
|
|
||||||
struct lookahead_ctx *ctx,
|
|
||||||
int drain) {
|
|
||||||
struct lookahead_entry *buf = NULL;
|
|
||||||
if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
|
|
||||||
buf = vp10_lookahead_peek(ctx, 0);
|
|
||||||
if (buf != NULL) {
|
|
||||||
// Only remove the buffer when pop the highest layer.
|
|
||||||
if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1) {
|
|
||||||
vp10_lookahead_pop(ctx, drain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef VP10_ENCODER_SVC_LAYERCONTEXT_H_
|
|
||||||
#define VP10_ENCODER_SVC_LAYERCONTEXT_H_
|
|
||||||
|
|
||||||
#include "vpx/vpx_encoder.h"
|
|
||||||
|
|
||||||
#include "vp10/encoder/ratectrl.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
RATE_CONTROL rc;
|
|
||||||
int target_bandwidth;
|
|
||||||
int spatial_layer_target_bandwidth; // Target for the spatial layer.
|
|
||||||
double framerate;
|
|
||||||
int avg_frame_size;
|
|
||||||
int max_q;
|
|
||||||
int min_q;
|
|
||||||
int scaling_factor_num;
|
|
||||||
int scaling_factor_den;
|
|
||||||
TWO_PASS twopass;
|
|
||||||
vpx_fixed_buf_t rc_twopass_stats_in;
|
|
||||||
unsigned int current_video_frame_in_layer;
|
|
||||||
int is_key_frame;
|
|
||||||
int frames_from_key_frame;
|
|
||||||
FRAME_TYPE last_frame_type;
|
|
||||||
struct lookahead_entry *alt_ref_source;
|
|
||||||
int alt_ref_idx;
|
|
||||||
int gold_ref_idx;
|
|
||||||
int has_alt_frame;
|
|
||||||
size_t layer_size;
|
|
||||||
struct vpx_psnr_pkt psnr_pkt;
|
|
||||||
} LAYER_CONTEXT;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int spatial_layer_id;
|
|
||||||
int temporal_layer_id;
|
|
||||||
int number_spatial_layers;
|
|
||||||
int number_temporal_layers;
|
|
||||||
|
|
||||||
int spatial_layer_to_encode;
|
|
||||||
|
|
||||||
// Workaround for multiple frame contexts
|
|
||||||
enum {
|
|
||||||
ENCODED = 0,
|
|
||||||
ENCODING,
|
|
||||||
NEED_TO_ENCODE
|
|
||||||
}encode_empty_frame_state;
|
|
||||||
struct lookahead_entry empty_frame;
|
|
||||||
int encode_intra_empty_frame;
|
|
||||||
|
|
||||||
// Store scaled source frames to be used for temporal filter to generate
|
|
||||||
// a alt ref frame.
|
|
||||||
YV12_BUFFER_CONFIG scaled_frames[MAX_LAG_BUFFERS];
|
|
||||||
|
|
||||||
// Layer context used for rate control in one pass temporal CBR mode or
|
|
||||||
// two pass spatial mode.
|
|
||||||
LAYER_CONTEXT layer_context[VPX_MAX_LAYERS];
|
|
||||||
// Indicates what sort of temporal layering is used.
|
|
||||||
// Currently, this only works for CBR mode.
|
|
||||||
VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode;
|
|
||||||
} SVC;
|
|
||||||
|
|
||||||
struct VP10_COMP;
|
|
||||||
|
|
||||||
// Initialize layer context data from init_config().
|
|
||||||
void vp10_init_layer_context(struct VP10_COMP *const cpi);
|
|
||||||
|
|
||||||
// Update the layer context from a change_config() call.
|
|
||||||
void vp10_update_layer_context_change_config(struct VP10_COMP *const cpi,
|
|
||||||
const int target_bandwidth);
|
|
||||||
|
|
||||||
// Prior to encoding the frame, update framerate-related quantities
|
|
||||||
// for the current temporal layer.
|
|
||||||
void vp10_update_temporal_layer_framerate(struct VP10_COMP *const cpi);
|
|
||||||
|
|
||||||
// Update framerate-related quantities for the current spatial layer.
|
|
||||||
void vp10_update_spatial_layer_framerate(struct VP10_COMP *const cpi,
|
|
||||||
double framerate);
|
|
||||||
|
|
||||||
// Prior to encoding the frame, set the layer context, for the current layer
|
|
||||||
// to be encoded, to the cpi struct.
|
|
||||||
void vp10_restore_layer_context(struct VP10_COMP *const cpi);
|
|
||||||
|
|
||||||
// Save the layer context after encoding the frame.
|
|
||||||
void vp10_save_layer_context(struct VP10_COMP *const cpi);
|
|
||||||
|
|
||||||
// Initialize second pass rc for spatial svc.
|
|
||||||
void vp10_init_second_pass_spatial_svc(struct VP10_COMP *cpi);
|
|
||||||
|
|
||||||
// Increment number of video frames in layer
|
|
||||||
void vp10_inc_frame_in_layer(struct VP10_COMP *const cpi);
|
|
||||||
|
|
||||||
// Check if current layer is key frame in spatial upper layer
|
|
||||||
int vp10_is_upper_layer_key_frame(const struct VP10_COMP *const cpi);
|
|
||||||
|
|
||||||
// Get the next source buffer to encode
|
|
||||||
struct lookahead_entry *vp10_svc_lookahead_pop(struct VP10_COMP *const cpi,
|
|
||||||
struct lookahead_ctx *ctx,
|
|
||||||
int drain);
|
|
||||||
|
|
||||||
// Start a frame and initialize svc parameters
|
|
||||||
int vp10_svc_start_frame(struct VP10_COMP *const cpi);
|
|
||||||
|
|
||||||
int vp10_one_pass_cbr_svc_start_layer(struct VP10_COMP *const cpi);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // VP10_ENCODER_SVC_LAYERCONTEXT_
|
|
||||||
@@ -652,9 +652,7 @@ static void adjust_arnr_filter(VP10_COMP *cpi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void vp10_temporal_filter(VP10_COMP *cpi, int distance) {
|
void vp10_temporal_filter(VP10_COMP *cpi, int distance) {
|
||||||
VP10_COMMON *const cm = &cpi->common;
|
|
||||||
RATE_CONTROL *const rc = &cpi->rc;
|
RATE_CONTROL *const rc = &cpi->rc;
|
||||||
MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
|
|
||||||
int frame;
|
int frame;
|
||||||
int frames_to_blur;
|
int frames_to_blur;
|
||||||
int start_frame;
|
int start_frame;
|
||||||
@@ -681,67 +679,21 @@ void vp10_temporal_filter(VP10_COMP *cpi, int distance) {
|
|||||||
if (frames_to_blur > 0) {
|
if (frames_to_blur > 0) {
|
||||||
// Setup scaling factors. Scaling on each of the arnr frames is not
|
// Setup scaling factors. Scaling on each of the arnr frames is not
|
||||||
// supported.
|
// supported.
|
||||||
if (cpi->use_svc) {
|
// ARF is produced at the native frame size and resized when coded.
|
||||||
// In spatial svc the scaling factors might be less then 1/2.
|
|
||||||
// So we will use non-normative scaling.
|
|
||||||
int frame_used = 0;
|
|
||||||
#if CONFIG_VP9_HIGHBITDEPTH
|
#if CONFIG_VP9_HIGHBITDEPTH
|
||||||
vp10_setup_scale_factors_for_frame(
|
vp10_setup_scale_factors_for_frame(&sf,
|
||||||
&sf,
|
frames[0]->y_crop_width,
|
||||||
get_frame_new_buffer(cm)->y_crop_width,
|
frames[0]->y_crop_height,
|
||||||
get_frame_new_buffer(cm)->y_crop_height,
|
frames[0]->y_crop_width,
|
||||||
get_frame_new_buffer(cm)->y_crop_width,
|
frames[0]->y_crop_height,
|
||||||
get_frame_new_buffer(cm)->y_crop_height,
|
cm->use_highbitdepth);
|
||||||
cm->use_highbitdepth);
|
|
||||||
#else
|
#else
|
||||||
vp10_setup_scale_factors_for_frame(
|
vp10_setup_scale_factors_for_frame(&sf,
|
||||||
&sf,
|
frames[0]->y_crop_width,
|
||||||
get_frame_new_buffer(cm)->y_crop_width,
|
frames[0]->y_crop_height,
|
||||||
get_frame_new_buffer(cm)->y_crop_height,
|
frames[0]->y_crop_width,
|
||||||
get_frame_new_buffer(cm)->y_crop_width,
|
frames[0]->y_crop_height);
|
||||||
get_frame_new_buffer(cm)->y_crop_height);
|
|
||||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||||
|
|
||||||
for (frame = 0; frame < frames_to_blur; ++frame) {
|
|
||||||
if (cm->mi_cols * MI_SIZE != frames[frame]->y_width ||
|
|
||||||
cm->mi_rows * MI_SIZE != frames[frame]->y_height) {
|
|
||||||
if (vpx_realloc_frame_buffer(&cpi->svc.scaled_frames[frame_used],
|
|
||||||
cm->width, cm->height,
|
|
||||||
cm->subsampling_x, cm->subsampling_y,
|
|
||||||
#if CONFIG_VP9_HIGHBITDEPTH
|
|
||||||
cm->use_highbitdepth,
|
|
||||||
#endif
|
|
||||||
VP9_ENC_BORDER_IN_PIXELS,
|
|
||||||
cm->byte_alignment,
|
|
||||||
NULL, NULL, NULL)) {
|
|
||||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
|
||||||
"Failed to reallocate alt_ref_buffer");
|
|
||||||
}
|
|
||||||
frames[frame] = vp10_scale_if_required(
|
|
||||||
cm, frames[frame], &cpi->svc.scaled_frames[frame_used]);
|
|
||||||
++frame_used;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cm->mi = cm->mip + cm->mi_stride + 1;
|
|
||||||
xd->mi = cm->mi_grid_visible;
|
|
||||||
xd->mi[0] = cm->mi;
|
|
||||||
} else {
|
|
||||||
// ARF is produced at the native frame size and resized when coded.
|
|
||||||
#if CONFIG_VP9_HIGHBITDEPTH
|
|
||||||
vp10_setup_scale_factors_for_frame(&sf,
|
|
||||||
frames[0]->y_crop_width,
|
|
||||||
frames[0]->y_crop_height,
|
|
||||||
frames[0]->y_crop_width,
|
|
||||||
frames[0]->y_crop_height,
|
|
||||||
cm->use_highbitdepth);
|
|
||||||
#else
|
|
||||||
vp10_setup_scale_factors_for_frame(&sf,
|
|
||||||
frames[0]->y_crop_width,
|
|
||||||
frames[0]->y_crop_height,
|
|
||||||
frames[0]->y_crop_width,
|
|
||||||
frames[0]->y_crop_height);
|
|
||||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
temporal_filter_iterate_c(cpi, frames, frames_to_blur,
|
temporal_filter_iterate_c(cpi, frames, frames_to_blur,
|
||||||
|
|||||||
@@ -186,46 +186,10 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
|
|||||||
RANGE_CHECK(cfg, rc_scaled_height, 0, cfg->g_h);
|
RANGE_CHECK(cfg, rc_scaled_height, 0, cfg->g_h);
|
||||||
}
|
}
|
||||||
|
|
||||||
RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS);
|
// Spatial/temporal scalability are not yet supported in VP10.
|
||||||
RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
|
// Only accept the default value for range checking.
|
||||||
|
RANGE_CHECK(cfg, ss_number_layers, 1, 1);
|
||||||
if (cfg->ss_number_layers * cfg->ts_number_layers > VPX_MAX_LAYERS)
|
RANGE_CHECK(cfg, ts_number_layers, 1, 1);
|
||||||
ERROR("ss_number_layers * ts_number_layers is out of range");
|
|
||||||
if (cfg->ts_number_layers > 1) {
|
|
||||||
unsigned int sl, tl;
|
|
||||||
for (sl = 1; sl < cfg->ss_number_layers; ++sl) {
|
|
||||||
for (tl = 1; tl < cfg->ts_number_layers; ++tl) {
|
|
||||||
const int layer =
|
|
||||||
LAYER_IDS_TO_IDX(sl, tl, cfg->ts_number_layers);
|
|
||||||
if (cfg->layer_target_bitrate[layer] <
|
|
||||||
cfg->layer_target_bitrate[layer - 1])
|
|
||||||
ERROR("ts_target_bitrate entries are not increasing");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1);
|
|
||||||
for (tl = cfg->ts_number_layers - 2; tl > 0; --tl)
|
|
||||||
if (cfg->ts_rate_decimator[tl - 1] != 2 * cfg->ts_rate_decimator[tl])
|
|
||||||
ERROR("ts_rate_decimator factors are not powers of 2");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
|
||||||
|
|
||||||
if ((cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) &&
|
|
||||||
cfg->g_pass == VPX_RC_LAST_PASS) {
|
|
||||||
unsigned int i, alt_ref_sum = 0;
|
|
||||||
for (i = 0; i < cfg->ss_number_layers; ++i) {
|
|
||||||
if (cfg->ss_enable_auto_alt_ref[i])
|
|
||||||
++alt_ref_sum;
|
|
||||||
}
|
|
||||||
if (alt_ref_sum > REF_FRAMES - cfg->ss_number_layers)
|
|
||||||
ERROR("Not enough ref buffers for svc alt ref frames");
|
|
||||||
if (cfg->ss_number_layers * cfg->ts_number_layers > 3 &&
|
|
||||||
cfg->g_error_resilient == 0)
|
|
||||||
ERROR("Multiple frame context are not supported for more than 3 layers");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// VP9 does not support a lower bound on the keyframe interval in
|
// VP9 does not support a lower bound on the keyframe interval in
|
||||||
// automatic keyframe placement mode.
|
// automatic keyframe placement mode.
|
||||||
if (cfg->kf_mode != VPX_KF_DISABLED &&
|
if (cfg->kf_mode != VPX_KF_DISABLED &&
|
||||||
@@ -263,44 +227,14 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
|
|||||||
if (cfg->rc_twopass_stats_in.sz % packet_sz)
|
if (cfg->rc_twopass_stats_in.sz % packet_sz)
|
||||||
ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
|
ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
|
||||||
|
|
||||||
if (cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) {
|
if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
|
||||||
int i;
|
ERROR("rc_twopass_stats_in requires at least two packets.");
|
||||||
unsigned int n_packets_per_layer[VPX_SS_MAX_LAYERS] = {0};
|
|
||||||
|
|
||||||
stats = cfg->rc_twopass_stats_in.buf;
|
stats =
|
||||||
for (i = 0; i < n_packets; ++i) {
|
(const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
|
||||||
const int layer_id = (int)stats[i].spatial_layer_id;
|
|
||||||
if (layer_id >= 0 && layer_id < (int)cfg->ss_number_layers) {
|
|
||||||
++n_packets_per_layer[layer_id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < (int)cfg->ss_number_layers; ++i) {
|
if ((int)(stats->count + 0.5) != n_packets - 1)
|
||||||
unsigned int layer_id;
|
ERROR("rc_twopass_stats_in missing EOS stats packet");
|
||||||
if (n_packets_per_layer[i] < 2) {
|
|
||||||
ERROR("rc_twopass_stats_in requires at least two packets for each "
|
|
||||||
"layer.");
|
|
||||||
}
|
|
||||||
|
|
||||||
stats = (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf +
|
|
||||||
n_packets - cfg->ss_number_layers + i;
|
|
||||||
layer_id = (int)stats->spatial_layer_id;
|
|
||||||
|
|
||||||
if (layer_id >= cfg->ss_number_layers
|
|
||||||
||(unsigned int)(stats->count + 0.5) !=
|
|
||||||
n_packets_per_layer[layer_id] - 1)
|
|
||||||
ERROR("rc_twopass_stats_in missing EOS stats packet");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
|
|
||||||
ERROR("rc_twopass_stats_in requires at least two packets.");
|
|
||||||
|
|
||||||
stats =
|
|
||||||
(const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
|
|
||||||
|
|
||||||
if ((int)(stats->count + 0.5) != n_packets - 1)
|
|
||||||
ERROR("rc_twopass_stats_in missing EOS stats packet");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !CONFIG_VP9_HIGHBITDEPTH
|
#if !CONFIG_VP9_HIGHBITDEPTH
|
||||||
@@ -381,7 +315,6 @@ static vpx_codec_err_t set_encoder_config(
|
|||||||
const vpx_codec_enc_cfg_t *cfg,
|
const vpx_codec_enc_cfg_t *cfg,
|
||||||
const struct vp10_extracfg *extra_cfg) {
|
const struct vp10_extracfg *extra_cfg) {
|
||||||
const int is_vbr = cfg->rc_end_usage == VPX_VBR;
|
const int is_vbr = cfg->rc_end_usage == VPX_VBR;
|
||||||
int sl, tl;
|
|
||||||
oxcf->profile = cfg->g_profile;
|
oxcf->profile = cfg->g_profile;
|
||||||
oxcf->max_threads = (int)cfg->g_threads;
|
oxcf->max_threads = (int)cfg->g_threads;
|
||||||
oxcf->width = cfg->g_w;
|
oxcf->width = cfg->g_w;
|
||||||
@@ -483,34 +416,6 @@ static vpx_codec_err_t set_encoder_config(
|
|||||||
|
|
||||||
oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
|
oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
|
||||||
|
|
||||||
oxcf->ss_number_layers = cfg->ss_number_layers;
|
|
||||||
oxcf->ts_number_layers = cfg->ts_number_layers;
|
|
||||||
oxcf->temporal_layering_mode = (enum vp9e_temporal_layering_mode)
|
|
||||||
cfg->temporal_layering_mode;
|
|
||||||
|
|
||||||
for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
|
||||||
oxcf->ss_enable_auto_arf[sl] = cfg->ss_enable_auto_alt_ref[sl];
|
|
||||||
#endif
|
|
||||||
for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
|
|
||||||
oxcf->layer_target_bitrate[sl * oxcf->ts_number_layers + tl] =
|
|
||||||
1000 * cfg->layer_target_bitrate[sl * oxcf->ts_number_layers + tl];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oxcf->ss_number_layers == 1 && oxcf->pass != 0) {
|
|
||||||
oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
|
||||||
oxcf->ss_enable_auto_arf[0] = extra_cfg->enable_auto_alt_ref;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (oxcf->ts_number_layers > 1) {
|
|
||||||
for (tl = 0; tl < VPX_TS_MAX_LAYERS; ++tl) {
|
|
||||||
oxcf->ts_rate_decimator[tl] = cfg->ts_rate_decimator[tl] ?
|
|
||||||
cfg->ts_rate_decimator[tl] : 1;
|
|
||||||
}
|
|
||||||
} else if (oxcf->ts_number_layers == 1) {
|
|
||||||
oxcf->ts_rate_decimator[0] = 1;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
printf("Current VP9 Settings: \n");
|
printf("Current VP9 Settings: \n");
|
||||||
printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
|
printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
|
||||||
@@ -938,12 +843,7 @@ static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP10_COMP *cpi,
|
|||||||
unsigned int lib_flags) {
|
unsigned int lib_flags) {
|
||||||
vpx_codec_frame_flags_t flags = lib_flags << 16;
|
vpx_codec_frame_flags_t flags = lib_flags << 16;
|
||||||
|
|
||||||
if (lib_flags & FRAMEFLAGS_KEY ||
|
if (lib_flags & FRAMEFLAGS_KEY)
|
||||||
(cpi->use_svc &&
|
|
||||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
|
|
||||||
cpi->svc.number_temporal_layers +
|
|
||||||
cpi->svc.temporal_layer_id].is_key_frame)
|
|
||||||
)
|
|
||||||
flags |= VPX_FRAME_IS_KEY;
|
flags |= VPX_FRAME_IS_KEY;
|
||||||
|
|
||||||
if (cpi->droppable)
|
if (cpi->droppable)
|
||||||
@@ -1058,17 +958,8 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx,
|
|||||||
if (size) {
|
if (size) {
|
||||||
vpx_codec_cx_pkt_t pkt;
|
vpx_codec_cx_pkt_t pkt;
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
|
||||||
if (cpi->use_svc)
|
|
||||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
|
|
||||||
cpi->svc.number_temporal_layers].layer_size += size;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Pack invisible frames with the next visible frame
|
// Pack invisible frames with the next visible frame
|
||||||
if (!cpi->common.show_frame ||
|
if (!cpi->common.show_frame) {
|
||||||
(cpi->use_svc &&
|
|
||||||
cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)
|
|
||||||
) {
|
|
||||||
if (ctx->pending_cx_data == 0)
|
if (ctx->pending_cx_data == 0)
|
||||||
ctx->pending_cx_data = cx_data;
|
ctx->pending_cx_data = cx_data;
|
||||||
ctx->pending_cx_data_sz += size;
|
ctx->pending_cx_data_sz += size;
|
||||||
@@ -1132,34 +1023,6 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx,
|
|||||||
|
|
||||||
cx_data += size;
|
cx_data += size;
|
||||||
cx_data_sz -= size;
|
cx_data_sz -= size;
|
||||||
#if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION)
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
|
||||||
if (cpi->use_svc && !ctx->output_cx_pkt_cb.output_cx_pkt) {
|
|
||||||
vpx_codec_cx_pkt_t pkt_sizes, pkt_psnr;
|
|
||||||
int sl;
|
|
||||||
vp10_zero(pkt_sizes);
|
|
||||||
vp10_zero(pkt_psnr);
|
|
||||||
pkt_sizes.kind = VPX_CODEC_SPATIAL_SVC_LAYER_SIZES;
|
|
||||||
pkt_psnr.kind = VPX_CODEC_SPATIAL_SVC_LAYER_PSNR;
|
|
||||||
for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
|
|
||||||
LAYER_CONTEXT *lc =
|
|
||||||
&cpi->svc.layer_context[sl * cpi->svc.number_temporal_layers];
|
|
||||||
pkt_sizes.data.layer_sizes[sl] = lc->layer_size;
|
|
||||||
pkt_psnr.data.layer_psnr[sl] = lc->psnr_pkt;
|
|
||||||
lc->layer_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_sizes);
|
|
||||||
|
|
||||||
vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_psnr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
if (is_one_pass_cbr_svc(cpi) &&
|
|
||||||
(cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1)) {
|
|
||||||
// Encoded all spatial layers; exit loop.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1334,84 +1197,6 @@ static vpx_codec_err_t ctrl_set_scale_mode(vpx_codec_alg_priv_t *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static vpx_codec_err_t ctrl_set_svc(vpx_codec_alg_priv_t *ctx, va_list args) {
|
|
||||||
int data = va_arg(args, int);
|
|
||||||
const vpx_codec_enc_cfg_t *cfg = &ctx->cfg;
|
|
||||||
// Both one-pass and two-pass RC are supported now.
|
|
||||||
// User setting this has to make sure of the following.
|
|
||||||
// In two-pass setting: either (but not both)
|
|
||||||
// cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
|
|
||||||
// In one-pass setting:
|
|
||||||
// either or both cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
|
|
||||||
|
|
||||||
vp10_set_svc(ctx->cpi, data);
|
|
||||||
|
|
||||||
if (data == 1 &&
|
|
||||||
(cfg->g_pass == VPX_RC_FIRST_PASS ||
|
|
||||||
cfg->g_pass == VPX_RC_LAST_PASS) &&
|
|
||||||
cfg->ss_number_layers > 1 &&
|
|
||||||
cfg->ts_number_layers > 1) {
|
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
return VPX_CODEC_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static vpx_codec_err_t ctrl_set_svc_layer_id(vpx_codec_alg_priv_t *ctx,
|
|
||||||
va_list args) {
|
|
||||||
vpx_svc_layer_id_t *const data = va_arg(args, vpx_svc_layer_id_t *);
|
|
||||||
VP10_COMP *const cpi = (VP10_COMP *)ctx->cpi;
|
|
||||||
SVC *const svc = &cpi->svc;
|
|
||||||
|
|
||||||
svc->spatial_layer_id = data->spatial_layer_id;
|
|
||||||
svc->temporal_layer_id = data->temporal_layer_id;
|
|
||||||
// Checks on valid layer_id input.
|
|
||||||
if (svc->temporal_layer_id < 0 ||
|
|
||||||
svc->temporal_layer_id >= (int)ctx->cfg.ts_number_layers) {
|
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
if (svc->spatial_layer_id < 0 ||
|
|
||||||
svc->spatial_layer_id >= (int)ctx->cfg.ss_number_layers) {
|
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
return VPX_CODEC_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static vpx_codec_err_t ctrl_get_svc_layer_id(vpx_codec_alg_priv_t *ctx,
|
|
||||||
va_list args) {
|
|
||||||
vpx_svc_layer_id_t *data = va_arg(args, vpx_svc_layer_id_t *);
|
|
||||||
VP10_COMP *const cpi = (VP10_COMP *)ctx->cpi;
|
|
||||||
SVC *const svc = &cpi->svc;
|
|
||||||
|
|
||||||
data->spatial_layer_id = svc->spatial_layer_id;
|
|
||||||
data->temporal_layer_id = svc->temporal_layer_id;
|
|
||||||
|
|
||||||
return VPX_CODEC_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
|
|
||||||
va_list args) {
|
|
||||||
VP10_COMP *const cpi = ctx->cpi;
|
|
||||||
vpx_svc_extra_cfg_t *const params = va_arg(args, vpx_svc_extra_cfg_t *);
|
|
||||||
int sl, tl;
|
|
||||||
|
|
||||||
// Number of temporal layers and number of spatial layers have to be set
|
|
||||||
// properly before calling this control function.
|
|
||||||
for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
|
|
||||||
for (tl = 0; tl < cpi->svc.number_temporal_layers; ++tl) {
|
|
||||||
const int layer =
|
|
||||||
LAYER_IDS_TO_IDX(sl, tl, cpi->svc.number_temporal_layers);
|
|
||||||
LAYER_CONTEXT *lc =
|
|
||||||
&cpi->svc.layer_context[layer];
|
|
||||||
lc->max_q = params->max_quantizers[sl];
|
|
||||||
lc->min_q = params->min_quantizers[sl];
|
|
||||||
lc->scaling_factor_num = params->scaling_factor_num[sl];
|
|
||||||
lc->scaling_factor_den = params->scaling_factor_den[sl];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return VPX_CODEC_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx,
|
static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx,
|
||||||
va_list args) {
|
va_list args) {
|
||||||
vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp =
|
vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp =
|
||||||
@@ -1466,10 +1251,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
|
|||||||
{VP9E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode},
|
{VP9E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode},
|
||||||
{VP9E_SET_AQ_MODE, ctrl_set_aq_mode},
|
{VP9E_SET_AQ_MODE, ctrl_set_aq_mode},
|
||||||
{VP9E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost},
|
{VP9E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost},
|
||||||
{VP9E_SET_SVC, ctrl_set_svc},
|
|
||||||
{VP9E_SET_SVC_PARAMETERS, ctrl_set_svc_parameters},
|
|
||||||
{VP9E_REGISTER_CX_CALLBACK, ctrl_register_cx_callback},
|
{VP9E_REGISTER_CX_CALLBACK, ctrl_register_cx_callback},
|
||||||
{VP9E_SET_SVC_LAYER_ID, ctrl_set_svc_layer_id},
|
|
||||||
{VP9E_SET_TUNE_CONTENT, ctrl_set_tune_content},
|
{VP9E_SET_TUNE_CONTENT, ctrl_set_tune_content},
|
||||||
{VP9E_SET_COLOR_SPACE, ctrl_set_color_space},
|
{VP9E_SET_COLOR_SPACE, ctrl_set_color_space},
|
||||||
{VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity},
|
{VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity},
|
||||||
@@ -1480,7 +1262,6 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
|
|||||||
{VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer},
|
{VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer},
|
||||||
{VP8E_GET_LAST_QUANTIZER_64, ctrl_get_quantizer64},
|
{VP8E_GET_LAST_QUANTIZER_64, ctrl_get_quantizer64},
|
||||||
{VP9_GET_REFERENCE, ctrl_get_reference},
|
{VP9_GET_REFERENCE, ctrl_get_reference},
|
||||||
{VP9E_GET_SVC_LAYER_ID, ctrl_get_svc_layer_id},
|
|
||||||
{VP9E_GET_ACTIVEMAP, ctrl_get_active_map},
|
{VP9E_GET_ACTIVEMAP, ctrl_get_active_map},
|
||||||
|
|
||||||
{ -1, NULL},
|
{ -1, NULL},
|
||||||
@@ -1536,7 +1317,10 @@ static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
|
|||||||
0, // kf_min_dist
|
0, // kf_min_dist
|
||||||
9999, // kf_max_dist
|
9999, // kf_max_dist
|
||||||
|
|
||||||
VPX_SS_DEFAULT_LAYERS, // ss_number_layers
|
// TODO(yunqingwang): Spatial/temporal scalability are not supported
|
||||||
|
// in VP10. The following 10 parameters are not used, which should
|
||||||
|
// be removed later.
|
||||||
|
1, // ss_number_layers
|
||||||
{0},
|
{0},
|
||||||
{0}, // ss_target_bitrate
|
{0}, // ss_target_bitrate
|
||||||
1, // ts_number_layers
|
1, // ts_number_layers
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ VP10_CX_SRCS-yes += encoder/quantize.h
|
|||||||
VP10_CX_SRCS-yes += encoder/ratectrl.h
|
VP10_CX_SRCS-yes += encoder/ratectrl.h
|
||||||
VP10_CX_SRCS-yes += encoder/rd.h
|
VP10_CX_SRCS-yes += encoder/rd.h
|
||||||
VP10_CX_SRCS-yes += encoder/rdopt.h
|
VP10_CX_SRCS-yes += encoder/rdopt.h
|
||||||
VP10_CX_SRCS-yes += encoder/svc_layercontext.h
|
|
||||||
VP10_CX_SRCS-yes += encoder/tokenize.h
|
VP10_CX_SRCS-yes += encoder/tokenize.h
|
||||||
VP10_CX_SRCS-yes += encoder/treewriter.h
|
VP10_CX_SRCS-yes += encoder/treewriter.h
|
||||||
VP10_CX_SRCS-yes += encoder/mcomp.c
|
VP10_CX_SRCS-yes += encoder/mcomp.c
|
||||||
@@ -65,7 +64,6 @@ VP10_CX_SRCS-yes += encoder/speed_features.c
|
|||||||
VP10_CX_SRCS-yes += encoder/speed_features.h
|
VP10_CX_SRCS-yes += encoder/speed_features.h
|
||||||
VP10_CX_SRCS-yes += encoder/subexp.c
|
VP10_CX_SRCS-yes += encoder/subexp.c
|
||||||
VP10_CX_SRCS-yes += encoder/subexp.h
|
VP10_CX_SRCS-yes += encoder/subexp.h
|
||||||
VP10_CX_SRCS-yes += encoder/svc_layercontext.c
|
|
||||||
VP10_CX_SRCS-yes += encoder/resize.c
|
VP10_CX_SRCS-yes += encoder/resize.c
|
||||||
VP10_CX_SRCS-yes += encoder/resize.h
|
VP10_CX_SRCS-yes += encoder/resize.h
|
||||||
VP10_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/blockiness.c
|
VP10_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/blockiness.c
|
||||||
|
|||||||
Reference in New Issue
Block a user