summaryrefslogtreecommitdiff
path: root/vp8/encoder
diff options
context:
space:
mode:
Diffstat (limited to 'vp8/encoder')
-rw-r--r--vp8/encoder/encodeframe.c34
-rw-r--r--vp8/encoder/onyx_if.c511
-rw-r--r--vp8/encoder/onyx_int.h67
-rw-r--r--vp8/encoder/pickinter.c3
-rw-r--r--vp8/encoder/ratectrl.c44
5 files changed, 554 insertions, 105 deletions
diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c
index 510e4cc98..7f2b46daa 100644
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -456,7 +456,7 @@ void encode_mb_row(VP8_COMP *cpi,
vp8_activity_masking(cpi, x);
// Is segmentation enabled
- // MB level adjutment to quantizer
+ // MB level adjustment to quantizer
if (xd->segmentation_enabled)
{
// Code to set segment id in xd->mbmi.segment_id for current MB (with range checking)
@@ -505,7 +505,8 @@ void encode_mb_row(VP8_COMP *cpi,
// Special case code for cyclic refresh
// If cyclic update enabled then copy xd->mbmi.segment_id; (which may have been updated based on mode
// during vp8cx_encode_inter_macroblock()) back into the global sgmentation map
- if (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled)
+ if ((cpi->current_layer == 0) &&
+ (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled))
{
cpi->segmentation_map[map_index+mb_col] = xd->mode_info_context->mbmi.segment_id;
@@ -648,6 +649,30 @@ void init_encode_frame_mb_context(VP8_COMP *cpi)
+ vp8_cost_one(255)
+ vp8_cost_one(128);
}
+ else if ((cpi->oxcf.number_of_layers > 1) &&
+ (cpi->ref_frame_flags == VP8_GOLD_FLAG))
+ {
+ xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ + vp8_cost_zero(1);
+ xd->ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ + vp8_cost_one(1)
+ + vp8_cost_zero(255);
+ xd->ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ + vp8_cost_one(1)
+ + vp8_cost_one(255);
+ }
+ else if ((cpi->oxcf.number_of_layers > 1) &&
+ (cpi->ref_frame_flags == VP8_ALT_FLAG))
+ {
+ xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ + vp8_cost_zero(1);
+ xd->ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ + vp8_cost_one(1)
+ + vp8_cost_zero(1);
+ xd->ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ + vp8_cost_one(1)
+ + vp8_cost_one(1);
+ }
else
{
xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
@@ -937,7 +962,8 @@ void vp8_encode_frame(VP8_COMP *cpi)
// Adjust the projected reference frame useage probability numbers to reflect
// what we have just seen. This may be usefull when we make multiple itterations
// of the recode loop rather than continuing to use values from the previous frame.
- if ((cm->frame_type != KEY_FRAME) && !cm->refresh_alt_ref_frame && !cm->refresh_golden_frame)
+ if ((cm->frame_type != KEY_FRAME) && ((cpi->oxcf.number_of_layers > 1) ||
+ (!cm->refresh_alt_ref_frame && !cm->refresh_golden_frame)))
{
const int *const rfct = cpi->count_mb_ref_frame_usage;
const int rf_intra = rfct[INTRA_FRAME];
@@ -1220,7 +1246,7 @@ int vp8cx_encode_inter_macroblock
if (xd->segmentation_enabled)
{
// If cyclic update enabled
- if (cpi->cyclic_refresh_mode_enabled)
+ if (cpi->current_layer == 0 && cpi->cyclic_refresh_mode_enabled)
{
// Clear segment_id back to 0 if not coded (last frame 0,0)
if ((xd->mode_info_context->mbmi.segment_id == 1) &&
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index cac92057c..43c971480 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -237,6 +237,79 @@ void vp8_initialize()
extern FILE *vpxlogc;
#endif
+static void save_layer_context(VP8_COMP *cpi)
+{
+ LAYER_CONTEXT *lc = &cpi->layer_context[cpi->current_layer];
+
+ // Save layer dependent coding state
+ lc->target_bandwidth = cpi->target_bandwidth;
+ //lc->target_bandwidth = cpi->oxcf.target_bandwidth;
+ lc->starting_buffer_level = cpi->oxcf.starting_buffer_level;
+ lc->optimal_buffer_level = cpi->oxcf.optimal_buffer_level;
+ lc->maximum_buffer_size = cpi->oxcf.maximum_buffer_size;
+ lc->buffer_level = cpi->buffer_level;
+ lc->bits_off_target = cpi->bits_off_target;
+ lc->total_actual_bits = cpi->total_actual_bits;
+ lc->worst_quality = cpi->worst_quality;
+ lc->active_worst_quality = cpi->active_worst_quality;
+ lc->best_quality = cpi->best_quality;
+ lc->active_best_quality = cpi->active_best_quality;
+ lc->ni_av_qi = cpi->ni_av_qi;
+ lc->ni_tot_qi = cpi->ni_tot_qi;
+ lc->ni_frames = cpi->ni_frames;
+ lc->avg_frame_qindex = cpi->avg_frame_qindex;
+ lc->rate_correction_factor = cpi->rate_correction_factor;
+ lc->key_frame_rate_correction_factor = cpi->key_frame_rate_correction_factor;
+ lc->gf_rate_correction_factor = cpi->gf_rate_correction_factor;
+ lc->zbin_over_quant = cpi->zbin_over_quant;
+ lc->inter_frame_target = cpi->inter_frame_target;
+ lc->total_byte_count = cpi->total_byte_count;
+ lc->filter_level = cpi->common.filter_level;
+
+ lc->last_frame_percent_intra = cpi->last_frame_percent_intra;
+
+ memcpy (lc->count_mb_ref_frame_usage,
+ cpi->count_mb_ref_frame_usage,
+ sizeof(cpi->count_mb_ref_frame_usage));
+}
+
+static void restore_layer_context(VP8_COMP *cpi, const int layer)
+{
+ LAYER_CONTEXT *lc = &cpi->layer_context[layer];
+
+ // Restore layer dependent coding state
+ cpi->current_layer = layer;
+ cpi->target_bandwidth = lc->target_bandwidth;
+ cpi->oxcf.target_bandwidth = lc->target_bandwidth;
+ cpi->oxcf.starting_buffer_level = lc->starting_buffer_level;
+ cpi->oxcf.optimal_buffer_level = lc->optimal_buffer_level;
+ cpi->oxcf.maximum_buffer_size = lc->maximum_buffer_size;
+ cpi->buffer_level = lc->buffer_level;
+ cpi->bits_off_target = lc->bits_off_target;
+ cpi->total_actual_bits = lc->total_actual_bits;
+ //cpi->worst_quality = lc->worst_quality;
+ cpi->active_worst_quality = lc->active_worst_quality;
+ //cpi->best_quality = lc->best_quality;
+ cpi->active_best_quality = lc->active_best_quality;
+ cpi->ni_av_qi = lc->ni_av_qi;
+ cpi->ni_tot_qi = lc->ni_tot_qi;
+ cpi->ni_frames = lc->ni_frames;
+ cpi->avg_frame_qindex = lc->avg_frame_qindex;
+ cpi->rate_correction_factor = lc->rate_correction_factor;
+ cpi->key_frame_rate_correction_factor = lc->key_frame_rate_correction_factor;
+ cpi->gf_rate_correction_factor = lc->gf_rate_correction_factor;
+ cpi->zbin_over_quant = lc->zbin_over_quant;
+ cpi->inter_frame_target = lc->inter_frame_target;
+ cpi->total_byte_count = lc->total_byte_count;
+ cpi->common.filter_level = lc->filter_level;
+
+ cpi->last_frame_percent_intra = lc->last_frame_percent_intra;
+
+ memcpy (cpi->count_mb_ref_frame_usage,
+ lc->count_mb_ref_frame_usage,
+ sizeof(cpi->count_mb_ref_frame_usage));
+}
+
static void setup_features(VP8_COMP *cpi)
{
// Set up default state for MB feature flags
@@ -510,7 +583,7 @@ static void cyclic_background_refresh(VP8_COMP *cpi, int Q, int lf_adjustment)
set_segment_data((VP8_PTR)cpi, &feature_data[0][0], SEGMENT_DELTADATA);
// Delete sementation map
- vpx_free(seg_map);
+ vpx_free(seg_map);
seg_map = 0;
@@ -1397,11 +1470,13 @@ void vp8_new_frame_rate(VP8_COMP *cpi, double framerate)
if(framerate < .1)
framerate = 30;
- cpi->oxcf.frame_rate = framerate;
- cpi->output_frame_rate = cpi->oxcf.frame_rate;
- cpi->per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth / cpi->output_frame_rate);
- cpi->av_per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth / cpi->output_frame_rate);
- cpi->min_frame_bandwidth = (int)(cpi->av_per_frame_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+ cpi->oxcf.frame_rate = framerate;
+ cpi->output_frame_rate = cpi->oxcf.frame_rate;
+ cpi->per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth /
+ cpi->output_frame_rate);
+ cpi->av_per_frame_bandwidth = cpi->per_frame_bandwidth;
+ cpi->min_frame_bandwidth = (int)(cpi->av_per_frame_bandwidth *
+ cpi->oxcf.two_pass_vbrmin_section / 100);
// Set Maximum gf/arf interval
cpi->max_gf_interval = ((int)(cpi->output_frame_rate / 2.0) + 2);
@@ -1472,6 +1547,65 @@ static void init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->total_actual_bits = 0;
cpi->total_target_vs_actual = 0;
+ // Temporal scalabilty
+ if (cpi->oxcf.number_of_layers > 1)
+ {
+ int i;
+ int prev_layer_frame_rate=0;
+
+ for (i=0; i<cpi->oxcf.number_of_layers; i++)
+ {
+ LAYER_CONTEXT *lc = &cpi->layer_context[i];
+
+ // Layer configuration
+ lc->frame_rate =
+ cpi->output_frame_rate / cpi->oxcf.rate_decimator[i];
+ lc->target_bandwidth = cpi->oxcf.target_bitrate[i] * 1000;
+
+ lc->starting_buffer_level =
+ rescale(oxcf->starting_buffer_level,
+ lc->target_bandwidth, 1000);
+
+ if (oxcf->optimal_buffer_level == 0)
+ lc->optimal_buffer_level = lc->target_bandwidth / 8;
+ else
+ lc->optimal_buffer_level =
+ rescale(oxcf->optimal_buffer_level,
+ lc->target_bandwidth, 1000);
+
+ if (oxcf->maximum_buffer_size == 0)
+ lc->maximum_buffer_size = lc->target_bandwidth / 8;
+ else
+ lc->maximum_buffer_size =
+ rescale(oxcf->maximum_buffer_size,
+ lc->target_bandwidth, 1000);
+
+ // Work out the average size of a frame within this layer
+ if (i > 0)
+ lc->avg_frame_size_for_layer = (cpi->oxcf.target_bitrate[i] -
+ cpi->oxcf.target_bitrate[i-1]) * 1000 /
+ (lc->frame_rate - prev_layer_frame_rate);
+
+ lc->active_worst_quality = cpi->oxcf.worst_allowed_q;
+ lc->active_best_quality = cpi->oxcf.best_allowed_q;
+ lc->avg_frame_qindex = cpi->oxcf.worst_allowed_q;
+
+ lc->buffer_level = lc->starting_buffer_level;
+ lc->bits_off_target = lc->starting_buffer_level;
+
+ lc->total_actual_bits = 0;
+ lc->ni_av_qi = 0;
+ lc->ni_tot_qi = 0;
+ lc->ni_frames = 0;
+ lc->rate_correction_factor = 1.0;
+ lc->key_frame_rate_correction_factor = 1.0;
+ lc->gf_rate_correction_factor = 1.0;
+ lc->inter_frame_target = 0.0;
+
+ prev_layer_frame_rate = lc->frame_rate;
+ }
+ }
+
#if VP8_TEMPORAL_ALT_REF
{
int i;
@@ -1693,11 +1827,11 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->target_bandwidth = cpi->oxcf.target_bandwidth;
- cm->Width = cpi->oxcf.Width ;
- cm->Height = cpi->oxcf.Height ;
+ cm->Width = cpi->oxcf.Width;
+ cm->Height = cpi->oxcf.Height;
cm->horiz_scale = cpi->horiz_scale;
- cm->vert_scale = cpi->vert_scale ;
+ cm->vert_scale = cpi->vert_scale;
// VP8 sharpness level mapping 0-7 (vs 0-10 in general VPx dialogs)
if (cpi->oxcf.Sharpness > 7)
@@ -1828,7 +1962,7 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
cpi->prob_gf_coded = 128;
cpi->prob_intra_coded = 63;
- // Prime the recent reference frame useage counters.
+ // Prime the recent reference frame usage counters.
// Hereafter they will be maintained as a sort of moving average
cpi->recent_ref_frame_usage[INTRA_FRAME] = 1;
cpi->recent_ref_frame_usage[LAST_FRAME] = 1;
@@ -2143,35 +2277,106 @@ void vp8_remove_compressor(VP8_PTR *ptr)
FILE *f = fopen("opsnr.stt", "a");
double time_encoded = (cpi->last_end_time_stamp_seen
- cpi->first_time_stamp_ever) / 10000000.000;
- double total_encode_time = (cpi->time_receive_data + cpi->time_compress_data) / 1000.000;
- double dr = (double)cpi->bytes * (double) 8 / (double)1000 / time_encoded;
+ double total_encode_time = (cpi->time_receive_data +
+ cpi->time_compress_data) / 1000.000;
+ double dr = (double)cpi->bytes * 8.0 / 1000.0 / time_encoded;
if (cpi->b_calculate_psnr)
{
- YV12_BUFFER_CONFIG *lst_yv12 = &cpi->common.yv12_fb[cpi->common.lst_fb_idx];
- double samples = 3.0 / 2 * cpi->count * lst_yv12->y_width * lst_yv12->y_height;
- double total_psnr = vp8_mse2psnr(samples, 255.0, cpi->total_sq_error);
- double total_psnr2 = vp8_mse2psnr(samples, 255.0, cpi->total_sq_error2);
- double total_ssim = 100 * pow(cpi->summed_quality / cpi->summed_weights, 8.0);
-
- fprintf(f, "Bitrate\tAVGPsnr\tGLBPsnr\tAVPsnrP\tGLPsnrP\tVPXSSIM\t Time(us)\n");
- fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%8.0f\n",
- dr, cpi->total / cpi->count, total_psnr, cpi->totalp / cpi->count, total_psnr2, total_ssim,
- total_encode_time);
+ YV12_BUFFER_CONFIG *lst_yv12 =
+ &cpi->common.yv12_fb[cpi->common.lst_fb_idx];
+
+ if (cpi->oxcf.number_of_layers > 1)
+ {
+ int i;
+
+ fprintf(f, "Layer\tBitrate\tAVGPsnr\tGLBPsnr\tAVPsnrP\t"
+ "GLPsnrP\tVPXSSIM\t\n");
+ for (i=0; i<cpi->oxcf.number_of_layers; i++)
+ {
+ double dr = (double)cpi->bytes_in_layer[i] *
+ 8.0 / 1000.0 / time_encoded;
+ double samples = 3.0 / 2 * cpi->frames_in_layer[i] *
+ lst_yv12->y_width * lst_yv12->y_height;
+ double total_psnr = vp8_mse2psnr(samples, 255.0,
+ cpi->total_error2[i]);
+ double total_psnr2 = vp8_mse2psnr(samples, 255.0,
+ cpi->total_error2_p[i]);
+ double total_ssim = 100 * pow(cpi->sum_ssim[i] /
+ cpi->sum_weights[i], 8.0);
+
+ fprintf(f, "%5d\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t"
+ "%7.3f\t%7.3f\n",
+ i, dr,
+ cpi->sum_psnr[i] / cpi->frames_in_layer[i],
+ total_psnr,
+ cpi->sum_psnr_p[i] / cpi->frames_in_layer[i],
+ total_psnr2, total_ssim);
+ }
+ }
+ else
+ {
+ double samples = 3.0 / 2 * cpi->count *
+ lst_yv12->y_width * lst_yv12->y_height;
+ double total_psnr = vp8_mse2psnr(samples, 255.0,
+ cpi->total_sq_error);
+ double total_psnr2 = vp8_mse2psnr(samples, 255.0,
+ cpi->total_sq_error2);
+ double total_ssim = 100 * pow(cpi->summed_quality /
+ cpi->summed_weights, 8.0);
+
+ fprintf(f, "Bitrate\tAVGPsnr\tGLBPsnr\tAVPsnrP\t"
+ "GLPsnrP\tVPXSSIM\t Time(us)\n");
+ fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t"
+ "%7.3f\t%8.0f\n",
+ dr, cpi->total / cpi->count, total_psnr,
+ cpi->totalp / cpi->count, total_psnr2,
+ total_ssim, total_encode_time);
+ }
}
if (cpi->b_calculate_ssimg)
{
- fprintf(f, "BitRate\tSSIM_Y\tSSIM_U\tSSIM_V\tSSIM_A\t Time(us)\n");
- fprintf(f, "%7.3f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f\n", dr,
- cpi->total_ssimg_y / cpi->count, cpi->total_ssimg_u / cpi->count,
- cpi->total_ssimg_v / cpi->count, cpi->total_ssimg_all / cpi->count, total_encode_time);
+ if (cpi->oxcf.number_of_layers > 1)
+ {
+ int i;
+
+ fprintf(f, "Layer\tBitRate\tSSIM_Y\tSSIM_U\tSSIM_V\tSSIM_A\t"
+ "Time(us)\n");
+ for (i=0; i<cpi->oxcf.number_of_layers; i++)
+ {
+ double dr = (double)cpi->bytes_in_layer[i] *
+ 8.0 / 1000.0 / time_encoded;
+ fprintf(f, "%5d\t%7.3f\t%6.4f\t"
+ "%6.4f\t%6.4f\t%6.4f\t%8.0f\n",
+ i, dr,
+ cpi->total_ssimg_y_in_layer[i] /
+ cpi->frames_in_layer[i],
+ cpi->total_ssimg_u_in_layer[i] /
+ cpi->frames_in_layer[i],
+ cpi->total_ssimg_v_in_layer[i] /
+ cpi->frames_in_layer[i],
+ cpi->total_ssimg_all_in_layer[i] /
+ cpi->frames_in_layer[i],
+ total_encode_time);
+ }
+ }
+ else
+ {
+ fprintf(f, "BitRate\tSSIM_Y\tSSIM_U\tSSIM_V\tSSIM_A\t"
+ "Time(us)\n");
+ fprintf(f, "%7.3f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f\n", dr,
+ cpi->total_ssimg_y / cpi->count,
+ cpi->total_ssimg_u / cpi->count,
+ cpi->total_ssimg_v / cpi->count,
+ cpi->total_ssimg_all / cpi->count, total_encode_time);
+ }
}
fclose(f);
#if 0
f = fopen("qskip.stt", "a");
- fprintf(f, "minq:%d -maxq:%d skipture:skipfalse = %d:%d\n", cpi->oxcf.best_allowed_q, cpi->oxcf.worst_allowed_q, skiptruecount, skipfalsecount);
+ fprintf(f, "minq:%d -maxq:%d skiptrue:skipfalse = %d:%d\n", cpi->oxcf.best_allowed_q, cpi->oxcf.worst_allowed_q, skiptruecount, skipfalsecount);
fclose(f);
#endif
@@ -2841,10 +3046,41 @@ static void update_rd_ref_frame_probs(VP8_COMP *cpi)
}
else if (!(rf_intra + rf_inter))
{
- // This is a trap in case this function is called with cpi->recent_ref_frame_usage[] blank.
- cpi->prob_intra_coded = 63;
- cpi->prob_last_coded = 128;
- cpi->prob_gf_coded = 128;
+ if (cpi->oxcf.number_of_layers > 1)
+ {
+ if (cpi->ref_frame_flags == VP8_LAST_FLAG)
+ {
+ cpi->prob_intra_coded = 63;
+ cpi->prob_last_coded = 255;
+ cpi->prob_gf_coded = 128;
+ }
+ else if (cpi->ref_frame_flags == VP8_GOLD_FLAG)
+ {
+ cpi->prob_intra_coded = 63;
+ cpi->prob_last_coded = 1;
+ cpi->prob_gf_coded = 255;
+ }
+ else if (cpi->ref_frame_flags == VP8_ALT_FLAG)
+ {
+ cpi->prob_intra_coded = 63;
+ cpi->prob_last_coded = 1;
+ cpi->prob_gf_coded = 1;
+ }
+ else
+ {
+ cpi->prob_intra_coded = 63;
+ cpi->prob_last_coded = 128;
+ cpi->prob_gf_coded = 128;
+ }
+ }
+ else
+ {
+ // This is a trap in case this function is called with
+ // cpi->recent_ref_frame_usage[] blank.
+ cpi->prob_intra_coded = 63;
+ cpi->prob_last_coded = 128;
+ cpi->prob_gf_coded = 128;
+ }
}
else
{
@@ -2866,32 +3102,33 @@ static void update_rd_ref_frame_probs(VP8_COMP *cpi)
}
// update reference frame costs since we can do better than what we got last frame.
-
- if (cpi->common.refresh_alt_ref_frame)
- {
- cpi->prob_intra_coded += 40;
- cpi->prob_last_coded = 200;
- cpi->prob_gf_coded = 1;
- }
- else if (cpi->common.frames_since_golden == 0)
+ if (cpi->oxcf.number_of_layers == 1)
{
- cpi->prob_last_coded = 214;
- cpi->prob_gf_coded = 1;
- }
- else if (cpi->common.frames_since_golden == 1)
- {
- cpi->prob_last_coded = 192;
- cpi->prob_gf_coded = 220;
- }
- else if (cpi->source_alt_ref_active)
- {
- //int dist = cpi->common.frames_till_alt_ref_frame + cpi->common.frames_since_golden;
- cpi->prob_gf_coded -= 20;
+ if (cpi->common.refresh_alt_ref_frame)
+ {
+ cpi->prob_intra_coded += 40;
+ cpi->prob_last_coded = 200;
+ cpi->prob_gf_coded = 1;
+ }
+ else if (cpi->common.frames_since_golden == 0)
+ {
+ cpi->prob_last_coded = 214;
+ cpi->prob_gf_coded = 1;
+ }
+ else if (cpi->common.frames_since_golden == 1)
+ {
+ cpi->prob_last_coded = 192;
+ cpi->prob_gf_coded = 220;
+ }
+ else if (cpi->source_alt_ref_active)
+ {
+ //int dist = cpi->common.frames_till_alt_ref_frame + cpi->common.frames_since_golden;
+ cpi->prob_gf_coded -= 20;
- if (cpi->prob_gf_coded < 10)
- cpi->prob_gf_coded = 10;
+ if (cpi->prob_gf_coded < 10)
+ cpi->prob_gf_coded = 10;
+ }
}
-
#endif
}
@@ -3283,7 +3520,6 @@ static void encode_frame_to_data_rate
// Enable or disable mode based tweaking of the zbin
// For 2 Pass Only used where GF/ARF prediction quality
// is above a threshold
- cpi->zbin_mode_boost = 0;
cpi->zbin_mode_boost_enabled = TRUE;
if (cpi->pass == 2)
{
@@ -3432,6 +3668,19 @@ static void encode_frame_to_data_rate
cpi->buffer_level = cpi->bits_off_target;
+ if (cpi->oxcf.number_of_layers > 1)
+ {
+ int i;
+
+ // Propagate bits saved by dropping the frame to higher layers
+ for (i=cpi->current_layer+1; i<cpi->oxcf.number_of_layers; i++)
+ {
+ cpi->layer_context[i].bits_off_target
+ += cpi->av_per_frame_bandwidth;
+ cpi->layer_context[i].buffer_level = cpi->bits_off_target;
+ }
+ }
+
return;
}
else
@@ -3478,7 +3727,7 @@ static void encode_frame_to_data_rate
}
// Set an active best quality and if necessary active worst quality
- // There is some odd behaviour for one pass here that needs attention.
+ // There is some odd behavior for one pass here that needs attention.
if ( (cpi->pass == 2) || (cpi->ni_frames > 150))
{
vp8_clear_system_state();
@@ -3510,13 +3759,14 @@ static void encode_frame_to_data_rate
cpi->active_best_quality = kf_high_motion_minq[Q];
}
- else if (cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame)
+ else if (cpi->oxcf.number_of_layers==1 &&
+ (cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame))
{
// Use the lower of cpi->active_worst_quality and recent
// average Q as basis for GF/ARF Q limit unless last frame was
// a key frame.
if ( (cpi->frames_since_key > 1) &&
- (cpi->avg_frame_qindex < cpi->active_worst_quality) )
+ (cpi->avg_frame_qindex < cpi->active_worst_quality) )
{
Q = cpi->avg_frame_qindex;
}
@@ -3617,13 +3867,17 @@ static void encode_frame_to_data_rate
// Set highest allowed value for Zbin over quant
if (cm->frame_type == KEY_FRAME)
zbin_oq_high = 0; //ZBIN_OQ_MAX/16
- else if (cm->refresh_alt_ref_frame || (cm->refresh_golden_frame && !cpi->source_alt_ref_active))
- zbin_oq_high = 16;
+ else if ((cpi->oxcf.number_of_layers == 1) && ((cm->refresh_alt_ref_frame ||
+ (cm->refresh_golden_frame && !cpi->source_alt_ref_active))))
+ {
+ zbin_oq_high = 16;
+ }
else
zbin_oq_high = ZBIN_OQ_MAX;
- // Setup background Q adjustment for error resilliant mode
- if (cpi->cyclic_refresh_mode_enabled)
+ // Setup background Q adjustment for error resilient mode.
+ // For multi-layer encodes only enable this for the base layer.
+ if (cpi->cyclic_refresh_mode_enabled && (cpi->current_layer==0))
cyclic_background_refresh(cpi, Q, 0);
vp8_compute_frame_size_bounds(cpi, &frame_under_shoot_limit, &frame_over_shoot_limit);
@@ -3756,10 +4010,8 @@ static void encode_frame_to_data_rate
if (cpi->prob_skip_false > 250)
cpi->prob_skip_false = 250;
- if (cpi->is_src_frame_alt_ref)
+ if (cpi->oxcf.number_of_layers == 1 && cpi->is_src_frame_alt_ref)
cpi->prob_skip_false = 1;
-
-
}
#if 0
@@ -4111,9 +4363,10 @@ static void encode_frame_to_data_rate
}
// Update the GF useage maps.
- // This is done after completing the compression of a frame when all modes etc. are finalized but before loop filter
- // This is done after completing the compression of a frame when all modes etc. are finalized but before loop filter
- vp8_update_gf_useage_maps(cpi, cm, &cpi->mb);
+ // This is done after completing the compression of a frame when all
+ // modes etc. are finalized but before loop filter
+ if (cpi->oxcf.number_of_layers == 1)
+ vp8_update_gf_useage_maps(cpi, cm, &cpi->mb);
if (cm->frame_type == KEY_FRAME)
cm->refresh_last_frame = 1;
@@ -4179,6 +4432,13 @@ static void encode_frame_to_data_rate
cpi->total_byte_count += (*size);
cpi->projected_frame_size = (*size) << 3;
+ if (cpi->oxcf.number_of_layers > 1)
+ {
+ int i;
+ for (i=cpi->current_layer+1; i<cpi->oxcf.number_of_layers; i++)
+ cpi->layer_context[i].total_byte_count += (*size);
+ }
+
if (!active_worst_qchanged)
vp8_update_rate_correction_factors(cpi, 2);
@@ -4194,7 +4454,8 @@ static void encode_frame_to_data_rate
cpi->avg_frame_qindex = (2 + 3 * cpi->avg_frame_qindex + cm->base_qindex) >> 2;
// Keep a record from which we can calculate the average Q excluding GF updates and key frames
- if ((cm->frame_type != KEY_FRAME) && !cm->refresh_golden_frame && !cm->refresh_alt_ref_frame)
+ if ((cm->frame_type != KEY_FRAME) && ((cpi->oxcf.number_of_layers > 1) ||
+ (!cm->refresh_golden_frame && !cm->refresh_alt_ref_frame)))
{
cpi->ni_frames++;
@@ -4245,7 +4506,7 @@ static void encode_frame_to_data_rate
#endif
- // Set the count for maximum consequative dropped frames based upon the ratio of
+ // Set the count for maximum consecutive dropped frames based upon the ratio of
// this frame size to the target average per frame bandwidth.
// (cpi->av_per_frame_bandwidth > 0) is just a sanity check to prevent / 0.
if (cpi->drop_frames_allowed && (cpi->av_per_frame_bandwidth > 0))
@@ -4270,13 +4531,32 @@ static void encode_frame_to_data_rate
cpi->long_rolling_actual_bits = ((cpi->long_rolling_actual_bits * 31) + cpi->projected_frame_size + 16) / 32;
// Actual bits spent
- cpi->total_actual_bits += cpi->projected_frame_size;
+ cpi->total_actual_bits += cpi->projected_frame_size;
// Debug stats
cpi->total_target_vs_actual += (cpi->this_frame_target - cpi->projected_frame_size);
cpi->buffer_level = cpi->bits_off_target;
+ // Propagate values to higher temporal layers
+ if (cpi->oxcf.number_of_layers > 1)
+ {
+ int i;
+
+ for (i=cpi->current_layer+1; i<cpi->oxcf.number_of_layers; i++)
+ {
+ LAYER_CONTEXT *lc = &cpi->layer_context[i];
+ int bits_off_for_this_layer = lc->target_bandwidth / lc->frame_rate
+ - cpi->projected_frame_size;
+
+ lc->bits_off_target += bits_off_for_this_layer;
+
+ lc->total_actual_bits += cpi->projected_frame_size;
+ lc->total_target_vs_actual += bits_off_for_this_layer;
+ lc->buffer_level = lc->bits_off_target;
+ }
+ }
+
// Update bits left to the kf and gf groups to account for overshoot or undershoot on these frames
if (cm->frame_type == KEY_FRAME)
{
@@ -4322,7 +4602,7 @@ static void encode_frame_to_data_rate
vp8_clear_system_state(); //__asm emms;
- if (cpi->twopass.total_left_stats.coded_error != 0.0)
+ if (cpi->twopass.total_left_stats->coded_error != 0.0)
fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %6d %6d"
"%6d %6d %6d %5d %5d %5d %8d %8.2f %10d %10.3f"
"%10.3f %8d\n",
@@ -4340,9 +4620,9 @@ static void encode_frame_to_data_rate
cm->frame_type, cpi->gfu_boost,
cpi->twopass.est_max_qcorrection_factor,
(int)cpi->twopass.bits_left,
- cpi->twopass.total_left_stats.coded_error,
+ cpi->twopass.total_left_stats->coded_error,
(double)cpi->twopass.bits_left /
- cpi->twopass.total_left_stats.coded_error,
+ cpi->twopass.total_left_stats->coded_error,
cpi->tot_recode_hits);
else
fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %6d %6d"
@@ -4362,7 +4642,7 @@ static void encode_frame_to_data_rate
cm->frame_type, cpi->gfu_boost,
cpi->twopass.est_max_qcorrection_factor,
(int)cpi->twopass.bits_left,
- cpi->twopass.total_left_stats.coded_error,
+ cpi->twopass.total_left_stats->coded_error,
cpi->tot_recode_hits);
fclose(f);
@@ -4675,7 +4955,7 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
cm->refresh_golden_frame = 0;
cm->refresh_last_frame = 0;
cm->show_frame = 0;
- cpi->source_alt_ref_pending = FALSE; // Clear Pending altf Ref flag.
+ cpi->source_alt_ref_pending = FALSE; // Clear Pending alt Ref flag.
cpi->is_src_frame_alt_ref = 0;
}
}
@@ -4727,6 +5007,13 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
return -1;
}
+ // Restore layer specific context if necessary
+ if (cpi->oxcf.number_of_layers > 1)
+ {
+ restore_layer_context (cpi,
+ cpi->oxcf.layer_id[cm->current_video_frame % cpi->oxcf.periodicity]);
+ }
+
if (cpi->source->ts_start < cpi->first_time_stamp_ever)
{
cpi->first_time_stamp_ever = cpi->source->ts_start;
@@ -4734,7 +5021,16 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
}
// adjust frame rates based on timestamps given
- if (!cm->refresh_alt_ref_frame)
+ if (cpi->oxcf.number_of_layers > 1 )
+ {
+ vp8_new_frame_rate (
+ cpi, cpi->layer_context[cpi->current_layer].frame_rate);
+
+ cpi->last_time_stamp_seen = cpi->source->ts_start;
+ cpi->last_end_time_stamp_seen = cpi->source->ts_end;
+
+ }
+ else if (!cm->refresh_alt_ref_frame)
{
int64_t this_duration;
int step = 0;
@@ -4786,7 +5082,8 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
if (cpi->compressor_speed == 2)
{
- check_gf_quality(cpi);
+ if (cpi->oxcf.number_of_layers == 1)
+ check_gf_quality(cpi);
vpx_usec_timer_start(&tsctimer);
vpx_usec_timer_start(&ticktimer);
}
@@ -4893,6 +5190,10 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
}
+ // Save layer specific state
+ if (cpi->oxcf.number_of_layers > 1)
+ save_layer_context (cpi);
+
vpx_usec_timer_mark(&cmptimer);
cpi->time_compress_data += vpx_usec_timer_elapsed(&cmptimer);
@@ -4922,7 +5223,7 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
int y_samples = orig->y_height * orig->y_width ;
int uv_samples = orig->uv_height * orig->uv_width ;
int t_samples = y_samples + 2 * uv_samples;
- int64_t sq_error;
+ int64_t sq_error, sq_error2;
ye = calc_plane_error(orig->y_buffer, orig->y_stride,
recon->y_buffer, recon->y_stride, orig->y_width, orig->y_height,
@@ -4964,14 +5265,14 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
pp->v_buffer, pp->uv_stride, orig->uv_width, orig->uv_height,
IF_RTCD(&cpi->rtcd.variance));
- sq_error = ye + ue + ve;
+ sq_error2 = ye + ue + ve;
- frame_psnr2 = vp8_mse2psnr(t_samples, 255.0, sq_error);
+ frame_psnr2 = vp8_mse2psnr(t_samples, 255.0, sq_error2);
cpi->totalp_y += vp8_mse2psnr(y_samples, 255.0, ye);
cpi->totalp_u += vp8_mse2psnr(uv_samples, 255.0, ue);
cpi->totalp_v += vp8_mse2psnr(uv_samples, 255.0, ve);
- cpi->total_sq_error2 += sq_error;
+ cpi->total_sq_error2 += sq_error2;
cpi->totalp += frame_psnr2;
frame_ssim2 = vp8_calc_ssim(cpi->Source,
@@ -4981,6 +5282,24 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
cpi->summed_quality += frame_ssim2 * weight;
cpi->summed_weights += weight;
+ if (cpi->oxcf.number_of_layers > 1)
+ {
+ int i;
+
+ for (i=cpi->current_layer;
+ i<cpi->oxcf.number_of_layers; i++)
+ {
+ cpi->frames_in_layer[i]++;
+
+ cpi->bytes_in_layer[i] += *size;
+ cpi->sum_psnr[i] += frame_psnr;
+ cpi->sum_psnr_p[i] += frame_psnr2;
+ cpi->total_error2[i] += sq_error;
+ cpi->total_error2_p[i] += sq_error2;
+ cpi->sum_ssim[i] += frame_ssim2 * weight;
+ cpi->sum_weights[i] += weight;
+ }
+ }
}
}
@@ -4989,10 +5308,30 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
double y, u, v, frame_all;
frame_all = vp8_calc_ssimg(cpi->Source, cm->frame_to_show,
&y, &u, &v, IF_RTCD(&cpi->rtcd.variance));
- cpi->total_ssimg_y += y;
- cpi->total_ssimg_u += u;
- cpi->total_ssimg_v += v;
- cpi->total_ssimg_all += frame_all;
+
+ if (cpi->oxcf.number_of_layers > 1)
+ {
+ int i;
+
+ for (i=cpi->current_layer;
+ i<cpi->oxcf.number_of_layers; i++)
+ {
+ if (!cpi->b_calculate_psnr)
+ cpi->frames_in_layer[i]++;
+
+ cpi->total_ssimg_y_in_layer[i] += y;
+ cpi->total_ssimg_u_in_layer[i] += u;
+ cpi->total_ssimg_v_in_layer[i] += v;
+ cpi->total_ssimg_all_in_layer[i] += frame_all;
+ }
+ }
+ else
+ {
+ cpi->total_ssimg_y += y;
+ cpi->total_ssimg_u += u;
+ cpi->total_ssimg_v += v;
+ cpi->total_ssimg_all += frame_all;
+ }
}
}
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
index f9657c5a6..6678c15fb 100644
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -56,6 +56,8 @@
#define VP8_TEMPORAL_ALT_REF 1
#endif
+#define MAX_PERIODICITY 16
+
typedef struct
{
int kf_indicated;
@@ -238,6 +240,52 @@ enum
BLOCK_MAX_SEGMENTS
};
+typedef struct
+{
+ // Layer configuration
+ double frame_rate;
+ int target_bandwidth;
+
+ // Layer specific coding parameters
+ int starting_buffer_level;
+ int optimal_buffer_level;
+ int maximum_buffer_size;
+
+ int avg_frame_size_for_layer;
+
+ int buffer_level;
+ int bits_off_target;
+
+ long long total_actual_bits;
+ int total_target_vs_actual;
+
+ int worst_quality;
+ int active_worst_quality;
+ int best_quality;
+ int active_best_quality;
+
+ int ni_av_qi;
+ int ni_tot_qi;
+ int ni_frames;
+ int avg_frame_qindex;
+
+ double rate_correction_factor;
+ double key_frame_rate_correction_factor;
+ double gf_rate_correction_factor;
+
+ int zbin_over_quant;
+
+ int inter_frame_target;
+ INT64 total_byte_count;
+
+ int filter_level;
+
+ int last_frame_percent_intra;
+
+ int count_mb_ref_frame_usage[MAX_REF_FRAMES];
+
+} LAYER_CONTEXT;
+
typedef struct VP8_COMP
{
@@ -610,6 +658,25 @@ typedef struct VP8_COMP
int force_next_frame_intra; /* force next frame to intra when kf_auto says so */
int droppable;
+
+ // Coding layer state variables
+ unsigned int current_layer;
+ LAYER_CONTEXT layer_context[MAX_LAYERS];
+
+ long long frames_in_layer[MAX_LAYERS];
+ long long bytes_in_layer[MAX_LAYERS];
+ double sum_psnr[MAX_LAYERS];
+ double sum_psnr_p[MAX_LAYERS];
+ double total_error2[MAX_LAYERS];
+ double total_error2_p[MAX_LAYERS];
+ double sum_ssim[MAX_LAYERS];
+ double sum_weights[MAX_LAYERS];
+
+ double total_ssimg_y_in_layer[MAX_LAYERS];
+ double total_ssimg_u_in_layer[MAX_LAYERS];
+ double total_ssimg_v_in_layer[MAX_LAYERS];
+ double total_ssimg_all_in_layer[MAX_LAYERS];
+
} VP8_COMP;
void control_data_rate(VP8_COMP *cpi);
diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c
index 1e602138f..4a8258170 100644
--- a/vp8/encoder/pickinter.c
+++ b/vp8/encoder/pickinter.c
@@ -471,7 +471,8 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
else
skip_mode[GOLDEN_FRAME] = 1;
- if (cpi->ref_frame_flags & VP8_ALT_FLAG && cpi->source_alt_ref_active)
+ if ((cpi->ref_frame_flags & VP8_ALT_FLAG) &&
+ (cpi->source_alt_ref_active || cpi->oxcf.number_of_layers > 1))
{
YV12_BUFFER_CONFIG *alt_yv12 = &cpi->common.yv12_fb[cpi->common.alt_fb_idx];
y_buffer[ALTREF_FRAME] = alt_yv12->y_buffer + recon_yoffset;
diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c
index 46e1d9dd9..1ac905021 100644
--- a/vp8/encoder/ratectrl.c
+++ b/vp8/encoder/ratectrl.c
@@ -436,7 +436,8 @@ static void calc_iframe_target_size(VP8_COMP *cpi)
}
-// Do the best we can to define the parameteres for the next GF based on what information we have available.
+// Do the best we can to define the parameters for the next GF based on what
+// information we have available.
static void calc_gf_params(VP8_COMP *cpi)
{
int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
@@ -607,6 +608,11 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
{
int min_frame_target;
int Adjustment;
+ int old_per_frame_bandwidth = cpi->per_frame_bandwidth;
+
+ if ( cpi->current_layer > 0)
+ cpi->per_frame_bandwidth =
+ cpi->layer_context[cpi->current_layer].avg_frame_size_for_layer;
min_frame_target = 0;
@@ -622,7 +628,7 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
// Special alt reference frame case
- if (cpi->common.refresh_alt_ref_frame)
+ if((cpi->common.refresh_alt_ref_frame) && (cpi->oxcf.number_of_layers == 1))
{
if (cpi->pass == 2)
{
@@ -789,7 +795,7 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
// Decide whether or not we need to adjust the frame data rate target.
//
// If we are are below the optimal buffer fullness level and adherence
- // to buffering contraints is important to the end useage then adjust
+ // to buffering constraints is important to the end usage then adjust
// the per frame target.
if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
(cpi->buffer_level < cpi->oxcf.optimal_buffer_level))
@@ -812,12 +818,12 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
percent_low = 0;
// lower the target bandwidth for this frame.
- cpi->this_frame_target -= (cpi->this_frame_target * percent_low)
- / 200;
+ cpi->this_frame_target -=
+ (cpi->this_frame_target * percent_low) / 200;
// Are we using allowing control of active_worst_allowed_q
// according to buffer level.
- if (cpi->auto_worst_q)
+ if (cpi->auto_worst_q && cpi->ni_frames > 150)
{
int critical_buffer_level;
@@ -834,7 +840,7 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
(cpi->buffer_level < cpi->bits_off_target)
? cpi->buffer_level : cpi->bits_off_target;
}
- // For local file playback short term buffering contraints
+ // For local file playback short term buffering constraints
// are less of an issue
else
{
@@ -905,11 +911,11 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
percent_high = 0;
cpi->this_frame_target += (cpi->this_frame_target *
- percent_high) / 200;
-
+ percent_high) / 200;
- // Are we allowing control of active_worst_allowed_q according to bufferl level.
- if (cpi->auto_worst_q)
+ // Are we allowing control of active_worst_allowed_q according
+ // to buffer level.
+ if (cpi->auto_worst_q && cpi->ni_frames > 150)
{
// When using the relaxed buffer model stick to the user specified value
cpi->active_worst_quality = cpi->ni_av_qi;
@@ -1112,6 +1118,8 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
}
}
+
+ cpi->per_frame_bandwidth = old_per_frame_bandwidth;
}
@@ -1421,8 +1429,14 @@ void vp8_adjust_key_frame_context(VP8_COMP *cpi)
* bits allocated than those following other gfs.
*/
overspend = (cpi->projected_frame_size - cpi->per_frame_bandwidth);
- cpi->kf_overspend_bits += overspend * 7 / 8;
- cpi->gf_overspend_bits += overspend * 1 / 8;
+
+ if (cpi->oxcf.number_of_layers > 1)
+ cpi->kf_overspend_bits += overspend;
+ else
+ {
+ cpi->kf_overspend_bits += overspend * 7 / 8;
+ cpi->gf_overspend_bits += overspend * 1 / 8;
+ }
/* Work out how much to try and recover per frame. */
cpi->kf_bitrate_adjustment = cpi->kf_overspend_bits
@@ -1452,7 +1466,9 @@ void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_limit,
}
else
{
- if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
+ if (cpi->oxcf.number_of_layers > 1 ||
+ cpi->common.refresh_alt_ref_frame ||
+ cpi->common.refresh_golden_frame)
{
*frame_over_shoot_limit = cpi->this_frame_target * 9 / 8;
*frame_under_shoot_limit = cpi->this_frame_target * 7 / 8;