Index: source/libvpx/vp9/encoder/vp9_firstpass.c |
=================================================================== |
--- source/libvpx/vp9/encoder/vp9_firstpass.c (revision 281795) |
+++ source/libvpx/vp9/encoder/vp9_firstpass.c (working copy) |
@@ -33,8 +33,7 @@ |
#include "vp9/encoder/vp9_firstpass.h" |
#include "vp9/encoder/vp9_mcomp.h" |
#include "vp9/encoder/vp9_quantize.h" |
-#include "vp9/encoder/vp9_ratectrl.h" |
-#include "vp9/encoder/vp9_rdopt.h" |
+#include "vp9/encoder/vp9_rd.h" |
#include "vp9/encoder/vp9_variance.h" |
#define OUTPUT_FPF 0 |
@@ -56,14 +55,7 @@ |
#define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001) |
#define MIN_KF_BOOST 300 |
- |
-#if CONFIG_MULTIPLE_ARF |
-// Set MIN_GF_INTERVAL to 1 for the full decomposition. |
-#define MIN_GF_INTERVAL 2 |
-#else |
-#define MIN_GF_INTERVAL 4 |
-#endif |
- |
+#define MIN_GF_INTERVAL 4 |
#define LONG_TERM_VBR_CORRECTION |
static void swap_yv12(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) { |
@@ -97,23 +89,43 @@ |
// Read frame stats at an offset from the current position. |
-static int read_frame_stats(const TWO_PASS *p, |
- FIRSTPASS_STATS *frame_stats, int offset) { |
- const FIRSTPASS_STATS *fps_ptr = p->stats_in; |
- |
- // Check legality of offset. |
- if (offset >= 0) { |
- if (&fps_ptr[offset] >= p->stats_in_end) |
- return EOF; |
- } else if (offset < 0) { |
- if (&fps_ptr[offset] < p->stats_in_start) |
- return EOF; |
+static const FIRSTPASS_STATS *read_frame_stats(const TWO_PASS *p, int offset) { |
+ if ((offset >= 0 && p->stats_in + offset >= p->stats_in_end) || |
+ (offset < 0 && p->stats_in + offset < p->stats_in_start)) { |
+ return NULL; |
} |
- *frame_stats = fps_ptr[offset]; |
+ return &p->stats_in[offset]; |
+} |
+ |
+#if CONFIG_FP_MB_STATS |
+static int input_mb_stats(FIRSTPASS_FRAME_MB_STATS *fp_frame_stats, |
+ const VP9_COMMON *const cm) { |
+ FILE *fpfile; |
+ int ret; |
+ |
+ fpfile = fopen("firstpass_mb.stt", "r"); |
+ fseek(fpfile, cm->current_video_frame * cm->MBs * sizeof(FIRSTPASS_MB_STATS), |
+ SEEK_SET); |
+ ret = fread(fp_frame_stats->mb_stats, sizeof(FIRSTPASS_MB_STATS), cm->MBs, |
+ fpfile); |
+ fclose(fpfile); |
+ if (ret < cm->MBs) { |
+ return EOF; |
+ } |
return 1; |
} |
+static void output_mb_stats(FIRSTPASS_FRAME_MB_STATS *fp_frame_stats, |
+ const VP9_COMMON *const cm) { |
+ FILE *fpfile; |
+ |
+ fpfile = fopen("firstpass_mb.stt", "a"); |
+ fwrite(fp_frame_stats->mb_stats, sizeof(FIRSTPASS_MB_STATS), cm->MBs, fpfile); |
+ fclose(fpfile); |
+} |
+#endif |
+ |
static int input_stats(TWO_PASS *p, FIRSTPASS_STATS *fps) { |
if (p->stats_in >= p->stats_in_end) |
return EOF; |
@@ -460,6 +472,10 @@ |
const MV zero_mv = {0, 0}; |
const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12; |
+#if CONFIG_FP_MB_STATS |
+ FIRSTPASS_FRAME_MB_STATS *this_frame_mb_stats = &twopass->this_frame_mb_stats; |
+#endif |
+ |
vp9_clear_system_state(); |
set_first_pass_params(cpi); |
@@ -497,6 +513,8 @@ |
&cpi->scaled_source); |
} |
+ vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y); |
+ |
vp9_setup_src_planes(x, cpi->Source, 0, 0); |
vp9_setup_pre_planes(xd, 0, first_ref_buf, 0, 0, NULL); |
vp9_setup_dst_planes(xd->plane, new_yv12, 0, 0); |
@@ -504,8 +522,6 @@ |
xd->mi = cm->mi_grid_visible; |
xd->mi[0] = cm->mi; |
- vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y); |
- |
vp9_frame_init_quantizer(cpi); |
for (i = 0; i < MAX_MB_PLANE; ++i) { |
@@ -587,6 +603,17 @@ |
// Accumulate the intra error. |
intra_error += (int64_t)this_error; |
+#if CONFIG_FP_MB_STATS |
+ if (cpi->use_fp_mb_stats) { |
+ this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mode = |
+ DC_PRED; |
+ this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].err = |
+ this_error; |
+ this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mv.as_int |
+ = 0; |
+ } |
+#endif |
+ |
// Set up limit values for motion vectors to prevent them extending |
// outside the UMV borders. |
x->mv_col_min = -((mb_col * 16) + BORDER_MV_PIXELS_B16); |
@@ -615,7 +642,8 @@ |
&unscaled_last_source_buf_2d); |
// TODO(pengchong): Replace the hard-coded threshold |
- if (raw_motion_error > 25) { |
+ if (raw_motion_error > 25 || |
+ (cpi->use_svc && cpi->svc.number_temporal_layers == 1)) { |
// Test last reference frame using the previous best mv as the |
// starting point (best reference) for the search. |
first_pass_motion_search(cpi, x, &best_ref_mv.as_mv, &mv.as_mv, |
@@ -711,6 +739,17 @@ |
best_ref_mv.as_int = mv.as_int; |
+#if CONFIG_FP_MB_STATS |
+ if (cpi->use_fp_mb_stats) { |
+ this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mode = |
+ NEWMV; |
+ this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].err = |
+ motion_error; |
+ this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mv. |
+ as_int = mv.as_int; |
+ } |
+#endif |
+ |
if (mv.as_int) { |
++mvcount; |
@@ -815,6 +854,12 @@ |
twopass->this_frame_stats = fps; |
output_stats(&twopass->this_frame_stats, cpi->output_pkt_list); |
accumulate_stats(&twopass->total_stats, &fps); |
+ |
+#if CONFIG_FP_MB_STATS |
+ if (cpi->use_fp_mb_stats) { |
+ output_mb_stats(this_frame_mb_stats, cm); |
+ } |
+#endif |
} |
// Copy the previous Last Frame back into gf and and arf buffers if |
@@ -1060,24 +1105,16 @@ |
// score in the frame following a flash frame. The offset passed in should |
// reflect this. |
static int detect_flash(const TWO_PASS *twopass, int offset) { |
- FIRSTPASS_STATS next_frame; |
+ const FIRSTPASS_STATS *const next_frame = read_frame_stats(twopass, offset); |
- int flash_detected = 0; |
- |
- // Read the frame data. |
- // The return is FALSE (no flash detected) if not a valid frame |
- if (read_frame_stats(twopass, &next_frame, offset) != EOF) { |
- // What we are looking for here is a situation where there is a |
- // brief break in prediction (such as a flash) but subsequent frames |
- // are reasonably well predicted by an earlier (pre flash) frame. |
- // The recovery after a flash is indicated by a high pcnt_second_ref |
- // compared to pcnt_inter. |
- if (next_frame.pcnt_second_ref > next_frame.pcnt_inter && |
- next_frame.pcnt_second_ref >= 0.5) |
- flash_detected = 1; |
- } |
- |
- return flash_detected; |
+ // What we are looking for here is a situation where there is a |
+ // brief break in prediction (such as a flash) but subsequent frames |
+ // are reasonably well predicted by an earlier (pre flash) frame. |
+ // The recovery after a flash is indicated by a high pcnt_second_ref |
+ // compared to pcnt_inter. |
+ return next_frame != NULL && |
+ next_frame->pcnt_second_ref > next_frame->pcnt_inter && |
+ next_frame->pcnt_second_ref >= 0.5; |
} |
// Update the motion related elements to the GF arf boost calculation. |
@@ -1137,7 +1174,6 @@ |
static int calc_arf_boost(VP9_COMP *cpi, int offset, |
int f_frames, int b_frames, |
int *f_boost, int *b_boost) { |
- FIRSTPASS_STATS this_frame; |
TWO_PASS *const twopass = &cpi->twopass; |
int i; |
double boost_score = 0.0; |
@@ -1151,11 +1187,12 @@ |
// Search forward from the proposed arf/next gf position. |
for (i = 0; i < f_frames; ++i) { |
- if (read_frame_stats(twopass, &this_frame, (i + offset)) == EOF) |
+ const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset); |
+ if (this_frame == NULL) |
break; |
// Update the motion related elements to the boost calculation. |
- accumulate_frame_motion_stats(&this_frame, |
+ accumulate_frame_motion_stats(this_frame, |
&this_frame_mv_in_out, &mv_in_out_accumulator, |
&abs_mv_in_out_accumulator, |
&mv_ratio_accumulator); |
@@ -1167,12 +1204,12 @@ |
// Accumulate the effect of prediction quality decay. |
if (!flash_detected) { |
- decay_accumulator *= get_prediction_decay_rate(&cpi->common, &this_frame); |
+ decay_accumulator *= get_prediction_decay_rate(&cpi->common, this_frame); |
decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR |
? MIN_DECAY_FACTOR : decay_accumulator; |
} |
- boost_score += decay_accumulator * calc_frame_boost(twopass, &this_frame, |
+ boost_score += decay_accumulator * calc_frame_boost(twopass, this_frame, |
this_frame_mv_in_out); |
} |
@@ -1188,11 +1225,12 @@ |
// Search backward towards last gf position. |
for (i = -1; i >= -b_frames; --i) { |
- if (read_frame_stats(twopass, &this_frame, (i + offset)) == EOF) |
+ const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset); |
+ if (this_frame == NULL) |
break; |
// Update the motion related elements to the boost calculation. |
- accumulate_frame_motion_stats(&this_frame, |
+ accumulate_frame_motion_stats(this_frame, |
&this_frame_mv_in_out, &mv_in_out_accumulator, |
&abs_mv_in_out_accumulator, |
&mv_ratio_accumulator); |
@@ -1204,12 +1242,12 @@ |
// Cumulative effect of prediction quality decay. |
if (!flash_detected) { |
- decay_accumulator *= get_prediction_decay_rate(&cpi->common, &this_frame); |
+ decay_accumulator *= get_prediction_decay_rate(&cpi->common, this_frame); |
decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR |
? MIN_DECAY_FACTOR : decay_accumulator; |
} |
- boost_score += decay_accumulator * calc_frame_boost(twopass, &this_frame, |
+ boost_score += decay_accumulator * calc_frame_boost(twopass, this_frame, |
this_frame_mv_in_out); |
} |
*b_boost = (int)boost_score; |
@@ -1221,144 +1259,6 @@ |
return arf_boost; |
} |
-#if CONFIG_MULTIPLE_ARF |
-// Work out the frame coding order for a GF or an ARF group. |
-// The current implementation codes frames in their natural order for a |
-// GF group, and inserts additional ARFs into an ARF group using a |
-// binary split approach. |
-// NOTE: this function is currently implemented recursively. |
-static void schedule_frames(VP9_COMP *cpi, const int start, const int end, |
- const int arf_idx, const int gf_or_arf_group, |
- const int level) { |
- int i, abs_end, half_range; |
- int *cfo = cpi->frame_coding_order; |
- int idx = cpi->new_frame_coding_order_period; |
- |
- // If (end < 0) an ARF should be coded at position (-end). |
- assert(start >= 0); |
- |
- // printf("start:%d end:%d\n", start, end); |
- |
- // GF Group: code frames in logical order. |
- if (gf_or_arf_group == 0) { |
- assert(end >= start); |
- for (i = start; i <= end; ++i) { |
- cfo[idx] = i; |
- cpi->arf_buffer_idx[idx] = arf_idx; |
- cpi->arf_weight[idx] = -1; |
- ++idx; |
- } |
- cpi->new_frame_coding_order_period = idx; |
- return; |
- } |
- |
- // ARF Group: Work out the ARF schedule and mark ARF frames as negative. |
- if (end < 0) { |
- // printf("start:%d end:%d\n", -end, -end); |
- // ARF frame is at the end of the range. |
- cfo[idx] = end; |
- // What ARF buffer does this ARF use as predictor. |
- cpi->arf_buffer_idx[idx] = (arf_idx > 2) ? (arf_idx - 1) : 2; |
- cpi->arf_weight[idx] = level; |
- ++idx; |
- abs_end = -end; |
- } else { |
- abs_end = end; |
- } |
- |
- half_range = (abs_end - start) >> 1; |
- |
- // ARFs may not be adjacent, they must be separated by at least |
- // MIN_GF_INTERVAL non-ARF frames. |
- if ((start + MIN_GF_INTERVAL) >= (abs_end - MIN_GF_INTERVAL)) { |
- // printf("start:%d end:%d\n", start, abs_end); |
- // Update the coding order and active ARF. |
- for (i = start; i <= abs_end; ++i) { |
- cfo[idx] = i; |
- cpi->arf_buffer_idx[idx] = arf_idx; |
- cpi->arf_weight[idx] = -1; |
- ++idx; |
- } |
- cpi->new_frame_coding_order_period = idx; |
- } else { |
- // Place a new ARF at the mid-point of the range. |
- cpi->new_frame_coding_order_period = idx; |
- schedule_frames(cpi, start, -(start + half_range), arf_idx + 1, |
- gf_or_arf_group, level + 1); |
- schedule_frames(cpi, start + half_range + 1, abs_end, arf_idx, |
- gf_or_arf_group, level + 1); |
- } |
-} |
- |
-#define FIXED_ARF_GROUP_SIZE 16 |
- |
-void define_fixed_arf_period(VP9_COMP *cpi) { |
- int i; |
- int max_level = INT_MIN; |
- |
- assert(cpi->multi_arf_enabled); |
- assert(cpi->oxcf.lag_in_frames >= FIXED_ARF_GROUP_SIZE); |
- |
- // Save the weight of the last frame in the sequence before next |
- // sequence pattern overwrites it. |
- cpi->this_frame_weight = cpi->arf_weight[cpi->sequence_number]; |
- assert(cpi->this_frame_weight >= 0); |
- |
- cpi->twopass.gf_zeromotion_pct = 0; |
- |
- // Initialize frame coding order variables. |
- cpi->new_frame_coding_order_period = 0; |
- cpi->next_frame_in_order = 0; |
- cpi->arf_buffered = 0; |
- vp9_zero(cpi->frame_coding_order); |
- vp9_zero(cpi->arf_buffer_idx); |
- vpx_memset(cpi->arf_weight, -1, sizeof(cpi->arf_weight)); |
- |
- if (cpi->rc.frames_to_key <= (FIXED_ARF_GROUP_SIZE + 8)) { |
- // Setup a GF group close to the keyframe. |
- cpi->rc.source_alt_ref_pending = 0; |
- cpi->rc.baseline_gf_interval = cpi->rc.frames_to_key; |
- schedule_frames(cpi, 0, (cpi->rc.baseline_gf_interval - 1), 2, 0, 0); |
- } else { |
- // Setup a fixed period ARF group. |
- cpi->rc.source_alt_ref_pending = 1; |
- cpi->rc.baseline_gf_interval = FIXED_ARF_GROUP_SIZE; |
- schedule_frames(cpi, 0, -(cpi->rc.baseline_gf_interval - 1), 2, 1, 0); |
- } |
- |
- // Replace level indicator of -1 with correct level. |
- for (i = 0; i < cpi->new_frame_coding_order_period; ++i) { |
- if (cpi->arf_weight[i] > max_level) { |
- max_level = cpi->arf_weight[i]; |
- } |
- } |
- ++max_level; |
- for (i = 0; i < cpi->new_frame_coding_order_period; ++i) { |
- if (cpi->arf_weight[i] == -1) { |
- cpi->arf_weight[i] = max_level; |
- } |
- } |
- cpi->max_arf_level = max_level; |
-#if 0 |
- printf("\nSchedule: "); |
- for (i = 0; i < cpi->new_frame_coding_order_period; ++i) { |
- printf("%4d ", cpi->frame_coding_order[i]); |
- } |
- printf("\n"); |
- printf("ARFref: "); |
- for (i = 0; i < cpi->new_frame_coding_order_period; ++i) { |
- printf("%4d ", cpi->arf_buffer_idx[i]); |
- } |
- printf("\n"); |
- printf("Weight: "); |
- for (i = 0; i < cpi->new_frame_coding_order_period; ++i) { |
- printf("%4d ", cpi->arf_weight[i]); |
- } |
- printf("\n"); |
-#endif |
-} |
-#endif |
- |
// Calculate a section intra ratio used in setting max loop filter. |
static int calculate_section_intra_ratio(const FIRSTPASS_STATS *begin, |
const FIRSTPASS_STATS *end, |
@@ -1428,6 +1328,18 @@ |
return MAX((int)(((int64_t)boost * total_group_bits) / allocation_chunks), 0); |
} |
+// Current limit on maximum number of active arfs in a GF/ARF group. |
+#define MAX_ACTIVE_ARFS 2 |
+#define ARF_SLOT1 2 |
+#define ARF_SLOT2 3 |
+// This function indirects the choice of buffers for arfs. |
+// At the moment the values are fixed but this may change as part of |
+// the integration process with other codec features that swap buffers around. |
+static void get_arf_buffer_indices(unsigned char *arf_buffer_indices) { |
+ arf_buffer_indices[0] = ARF_SLOT1; |
+ arf_buffer_indices[1] = ARF_SLOT2; |
+} |
+ |
static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits, |
double group_error, int gf_arf_bits) { |
RATE_CONTROL *const rc = &cpi->rc; |
@@ -1435,42 +1347,80 @@ |
TWO_PASS *twopass = &cpi->twopass; |
FIRSTPASS_STATS frame_stats; |
int i; |
- int group_frame_index = 1; |
+ int frame_index = 1; |
int target_frame_size; |
int key_frame; |
const int max_bits = frame_max_bits(&cpi->rc, &cpi->oxcf); |
int64_t total_group_bits = gf_group_bits; |
double modified_err = 0.0; |
double err_fraction; |
+ int mid_boost_bits = 0; |
+ int mid_frame_idx; |
+ unsigned char arf_buffer_indices[MAX_ACTIVE_ARFS]; |
key_frame = cpi->common.frame_type == KEY_FRAME || |
vp9_is_upper_layer_key_frame(cpi); |
+ get_arf_buffer_indices(arf_buffer_indices); |
+ |
// For key frames the frame target rate is already set and it |
// is also the golden frame. |
- // NOTE: We dont bother to check for the special case of ARF overlay |
- // frames here, as there is clamping code for this in the function |
- // vp9_rc_clamp_pframe_target_size(), which applies to one and two pass |
- // encodes. |
if (!key_frame) { |
- twopass->gf_group_bit_allocation[0] = gf_arf_bits; |
+ if (rc->source_alt_ref_active) { |
+ twopass->gf_group.update_type[0] = OVERLAY_UPDATE; |
+ twopass->gf_group.rf_level[0] = INTER_NORMAL; |
+ twopass->gf_group.bit_allocation[0] = 0; |
+ twopass->gf_group.arf_update_idx[0] = arf_buffer_indices[0]; |
+ twopass->gf_group.arf_ref_idx[0] = arf_buffer_indices[0]; |
+ } else { |
+ twopass->gf_group.update_type[0] = GF_UPDATE; |
+ twopass->gf_group.rf_level[0] = GF_ARF_STD; |
+ twopass->gf_group.bit_allocation[0] = gf_arf_bits; |
+ twopass->gf_group.arf_update_idx[0] = arf_buffer_indices[0]; |
+ twopass->gf_group.arf_ref_idx[0] = arf_buffer_indices[0]; |
+ } |
// Step over the golden frame / overlay frame |
if (EOF == input_stats(twopass, &frame_stats)) |
return; |
} |
+ // Deduct the boost bits for arf (or gf if it is not a key frame) |
+ // from the group total. |
+ if (rc->source_alt_ref_pending || !key_frame) |
+ total_group_bits -= gf_arf_bits; |
+ |
// Store the bits to spend on the ARF if there is one. |
if (rc->source_alt_ref_pending) { |
- twopass->gf_group_bit_allocation[group_frame_index++] = gf_arf_bits; |
+ twopass->gf_group.update_type[frame_index] = ARF_UPDATE; |
+ twopass->gf_group.rf_level[frame_index] = GF_ARF_STD; |
+ twopass->gf_group.bit_allocation[frame_index] = gf_arf_bits; |
+ twopass->gf_group.arf_src_offset[frame_index] = |
+ (unsigned char)(rc->baseline_gf_interval - 1); |
+ twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[0]; |
+ twopass->gf_group.arf_ref_idx[frame_index] = |
+ arf_buffer_indices[cpi->multi_arf_last_grp_enabled && |
+ rc->source_alt_ref_active]; |
+ ++frame_index; |
+ |
+ if (cpi->multi_arf_enabled) { |
+ // Set aside a slot for a level 1 arf. |
+ twopass->gf_group.update_type[frame_index] = ARF_UPDATE; |
+ twopass->gf_group.rf_level[frame_index] = GF_ARF_LOW; |
+ twopass->gf_group.arf_src_offset[frame_index] = |
+ (unsigned char)((rc->baseline_gf_interval >> 1) - 1); |
+ twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[1]; |
+ twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[0]; |
+ ++frame_index; |
+ } |
} |
- // Deduct the boost bits for arf or gf if it is not a key frame. |
- if (rc->source_alt_ref_pending || !key_frame) |
- total_group_bits -= gf_arf_bits; |
+ // Define middle frame |
+ mid_frame_idx = frame_index + (rc->baseline_gf_interval >> 1) - 1; |
// Allocate bits to the other frames in the group. |
for (i = 0; i < rc->baseline_gf_interval - 1; ++i) { |
+ int arf_idx = 0; |
if (EOF == input_stats(twopass, &frame_stats)) |
break; |
@@ -1482,11 +1432,52 @@ |
err_fraction = 0.0; |
target_frame_size = (int)((double)total_group_bits * err_fraction); |
+ |
+ if (rc->source_alt_ref_pending && cpi->multi_arf_enabled) { |
+ mid_boost_bits += (target_frame_size >> 4); |
+ target_frame_size -= (target_frame_size >> 4); |
+ |
+ if (frame_index <= mid_frame_idx) |
+ arf_idx = 1; |
+ } |
+ twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[arf_idx]; |
+ twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[arf_idx]; |
+ |
target_frame_size = clamp(target_frame_size, 0, |
MIN(max_bits, (int)total_group_bits)); |
- twopass->gf_group_bit_allocation[group_frame_index++] = target_frame_size; |
+ twopass->gf_group.update_type[frame_index] = LF_UPDATE; |
+ twopass->gf_group.rf_level[frame_index] = INTER_NORMAL; |
+ |
+ twopass->gf_group.bit_allocation[frame_index] = target_frame_size; |
+ ++frame_index; |
} |
+ |
+ // Note: |
+ // We need to configure the frame at the end of the sequence + 1 that will be |
+ // the start frame for the next group. Otherwise prior to the call to |
+ // vp9_rc_get_second_pass_params() the data will be undefined. |
+ twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[0]; |
+ twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[0]; |
+ |
+ if (rc->source_alt_ref_pending) { |
+ twopass->gf_group.update_type[frame_index] = OVERLAY_UPDATE; |
+ twopass->gf_group.rf_level[frame_index] = INTER_NORMAL; |
+ |
+ // Final setup for second arf and its overlay. |
+ if (cpi->multi_arf_enabled) { |
+ twopass->gf_group.bit_allocation[2] = |
+ twopass->gf_group.bit_allocation[mid_frame_idx] + mid_boost_bits; |
+ twopass->gf_group.update_type[mid_frame_idx] = OVERLAY_UPDATE; |
+ twopass->gf_group.bit_allocation[mid_frame_idx] = 0; |
+ } |
+ } else { |
+ twopass->gf_group.update_type[frame_index] = GF_UPDATE; |
+ twopass->gf_group.rf_level[frame_index] = GF_ARF_STD; |
+ } |
+ |
+ // Note whether multi-arf was enabled this group for next time. |
+ cpi->multi_arf_last_grp_enabled = cpi->multi_arf_enabled; |
} |
// Analyse and define a gf/arf group. |
@@ -1528,8 +1519,7 @@ |
// Reset the GF group data structures unless this is a key |
// frame in which case it will already have been done. |
if (cpi->common.frame_type != KEY_FRAME) { |
- twopass->gf_group_index = 0; |
- vp9_zero(twopass->gf_group_bit_allocation); |
+ vp9_zero(twopass->gf_group); |
} |
vp9_clear_system_state(); |
@@ -1552,19 +1542,22 @@ |
// Motion breakout threshold for loop below depends on image size. |
mv_ratio_accumulator_thresh = (cpi->common.width + cpi->common.height) / 10.0; |
- // Work out a maximum interval for the GF. |
- // If the image appears completely static we can extend beyond this. |
- // The value chosen depends on the active Q range. At low Q we have |
- // bits to spare and are better with a smaller interval and smaller boost. |
- // At high Q when there are few bits to spare we are better with a longer |
- // interval to spread the cost of the GF. |
- // |
- active_max_gf_interval = |
- 12 + ((int)vp9_convert_qindex_to_q(rc->last_q[INTER_FRAME]) >> 5); |
- |
- if (active_max_gf_interval > rc->max_gf_interval) |
+ // Work out a maximum interval for the GF group. |
+ // If the image appears almost completely static we can extend beyond this. |
+ if (cpi->multi_arf_allowed) { |
active_max_gf_interval = rc->max_gf_interval; |
+ } else { |
+ // The value chosen depends on the active Q range. At low Q we have |
+ // bits to spare and are better with a smaller interval and smaller boost. |
+ // At high Q when there are few bits to spare we are better with a longer |
+ // interval to spread the cost of the GF. |
+ active_max_gf_interval = |
+ 12 + ((int)vp9_convert_qindex_to_q(rc->last_q[INTER_FRAME]) >> 5); |
+ if (active_max_gf_interval > rc->max_gf_interval) |
+ active_max_gf_interval = rc->max_gf_interval; |
+ } |
+ |
i = 0; |
while (i < rc->static_scene_max_gf_interval && i < rc->frames_to_key) { |
++i; |
@@ -1651,24 +1644,14 @@ |
} |
} |
-#if CONFIG_MULTIPLE_ARF |
- if (cpi->multi_arf_enabled) { |
- // Initialize frame coding order variables. |
- cpi->new_frame_coding_order_period = 0; |
- cpi->next_frame_in_order = 0; |
- cpi->arf_buffered = 0; |
- vp9_zero(cpi->frame_coding_order); |
- vp9_zero(cpi->arf_buffer_idx); |
- vpx_memset(cpi->arf_weight, -1, sizeof(cpi->arf_weight)); |
- } |
-#endif |
- |
// Set the interval until the next gf. |
if (cpi->common.frame_type == KEY_FRAME || rc->source_alt_ref_active) |
rc->baseline_gf_interval = i - 1; |
else |
rc->baseline_gf_interval = i; |
+ rc->frames_till_gf_update_due = rc->baseline_gf_interval; |
+ |
// Should we use the alternate reference frame. |
if (allow_alt_ref && |
(i < cpi->oxcf.lag_in_frames) && |
@@ -1681,62 +1664,15 @@ |
&b_boost); |
rc->source_alt_ref_pending = 1; |
-#if CONFIG_MULTIPLE_ARF |
- // Set the ARF schedule. |
- if (cpi->multi_arf_enabled) { |
- schedule_frames(cpi, 0, -(rc->baseline_gf_interval - 1), 2, 1, 0); |
- } |
-#endif |
+ // Test to see if multi arf is appropriate. |
+ cpi->multi_arf_enabled = |
+ (cpi->multi_arf_allowed && (rc->baseline_gf_interval >= 6) && |
+ (zero_motion_accumulator < 0.995)) ? 1 : 0; |
} else { |
rc->gfu_boost = (int)boost_score; |
rc->source_alt_ref_pending = 0; |
-#if CONFIG_MULTIPLE_ARF |
- // Set the GF schedule. |
- if (cpi->multi_arf_enabled) { |
- schedule_frames(cpi, 0, rc->baseline_gf_interval - 1, 2, 0, 0); |
- assert(cpi->new_frame_coding_order_period == |
- rc->baseline_gf_interval); |
- } |
-#endif |
} |
-#if CONFIG_MULTIPLE_ARF |
- if (cpi->multi_arf_enabled && (cpi->common.frame_type != KEY_FRAME)) { |
- int max_level = INT_MIN; |
- // Replace level indicator of -1 with correct level. |
- for (i = 0; i < cpi->frame_coding_order_period; ++i) { |
- if (cpi->arf_weight[i] > max_level) { |
- max_level = cpi->arf_weight[i]; |
- } |
- } |
- ++max_level; |
- for (i = 0; i < cpi->frame_coding_order_period; ++i) { |
- if (cpi->arf_weight[i] == -1) { |
- cpi->arf_weight[i] = max_level; |
- } |
- } |
- cpi->max_arf_level = max_level; |
- } |
-#if 0 |
- if (cpi->multi_arf_enabled) { |
- printf("\nSchedule: "); |
- for (i = 0; i < cpi->new_frame_coding_order_period; ++i) { |
- printf("%4d ", cpi->frame_coding_order[i]); |
- } |
- printf("\n"); |
- printf("ARFref: "); |
- for (i = 0; i < cpi->new_frame_coding_order_period; ++i) { |
- printf("%4d ", cpi->arf_buffer_idx[i]); |
- } |
- printf("\n"); |
- printf("Weight: "); |
- for (i = 0; i < cpi->new_frame_coding_order_period; ++i) { |
- printf("%4d ", cpi->arf_weight[i]); |
- } |
- printf("\n"); |
- } |
-#endif |
-#endif |
// Reset the file position. |
reset_fpf_position(twopass, start_pos); |
@@ -1886,14 +1822,15 @@ |
cpi->common.frame_type = KEY_FRAME; |
// Reset the GF group data structures. |
- twopass->gf_group_index = 0; |
- vp9_zero(twopass->gf_group_bit_allocation); |
+ vp9_zero(twopass->gf_group); |
// Is this a forced key frame by interval. |
rc->this_key_frame_forced = rc->next_key_frame_forced; |
- // Clear the alt ref active flag as this can never be active on a key frame. |
+ // Clear the alt ref active flag and last group multi arf flags as they |
+ // can never be set for a key frame. |
rc->source_alt_ref_active = 0; |
+ cpi->multi_arf_last_grp_enabled = 0; |
// KF is always a GF so clear frames till next gf counter. |
rc->frames_till_gf_update_due = 0; |
@@ -2078,7 +2015,9 @@ |
twopass->kf_group_bits -= kf_bits; |
// Save the bits to spend on the key frame. |
- twopass->gf_group_bit_allocation[0] = kf_bits; |
+ twopass->gf_group.bit_allocation[0] = kf_bits; |
+ twopass->gf_group.update_type[0] = KF_UPDATE; |
+ twopass->gf_group.rf_level[0] = KF_STD; |
// Note the total error score of the kf group minus the key frame itself. |
twopass->kf_group_error_left = (int)(kf_group_err - kf_mod_err); |
@@ -2106,6 +2045,44 @@ |
} |
} |
+// Define the reference buffers that will be updated post encode. |
+void configure_buffer_updates(VP9_COMP *cpi) { |
+ TWO_PASS *const twopass = &cpi->twopass; |
+ |
+ cpi->rc.is_src_frame_alt_ref = 0; |
+ switch (twopass->gf_group.update_type[twopass->gf_group.index]) { |
+ case KF_UPDATE: |
+ cpi->refresh_last_frame = 1; |
+ cpi->refresh_golden_frame = 1; |
+ cpi->refresh_alt_ref_frame = 1; |
+ break; |
+ case LF_UPDATE: |
+ cpi->refresh_last_frame = 1; |
+ cpi->refresh_golden_frame = 0; |
+ cpi->refresh_alt_ref_frame = 0; |
+ break; |
+ case GF_UPDATE: |
+ cpi->refresh_last_frame = 1; |
+ cpi->refresh_golden_frame = 1; |
+ cpi->refresh_alt_ref_frame = 0; |
+ break; |
+ case OVERLAY_UPDATE: |
+ cpi->refresh_last_frame = 0; |
+ cpi->refresh_golden_frame = 1; |
+ cpi->refresh_alt_ref_frame = 0; |
+ cpi->rc.is_src_frame_alt_ref = 1; |
+ break; |
+ case ARF_UPDATE: |
+ cpi->refresh_last_frame = 0; |
+ cpi->refresh_golden_frame = 0; |
+ cpi->refresh_alt_ref_frame = 1; |
+ break; |
+ default: |
+ assert(0); |
+ } |
+} |
+ |
+ |
void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { |
VP9_COMMON *const cm = &cpi->common; |
RATE_CONTROL *const rc = &cpi->rc; |
@@ -2130,14 +2107,12 @@ |
if (!twopass->stats_in) |
return; |
- // Increment the gf group index. |
- ++twopass->gf_group_index; |
- |
// If this is an arf frame then we dont want to read the stats file or |
// advance the input pointer as we already have what we need. |
- if (cpi->refresh_alt_ref_frame) { |
+ if (twopass->gf_group.update_type[twopass->gf_group.index] == ARF_UPDATE) { |
int target_rate; |
- target_rate = twopass->gf_group_bit_allocation[twopass->gf_group_index]; |
+ configure_buffer_updates(cpi); |
+ target_rate = twopass->gf_group.bit_allocation[twopass->gf_group.index]; |
target_rate = vp9_rc_clamp_pframe_target_size(cpi, target_rate); |
rc->base_frame_target = target_rate; |
#ifdef LONG_TERM_VBR_CORRECTION |
@@ -2201,15 +2176,7 @@ |
// Define a new GF/ARF group. (Should always enter here for key frames). |
if (rc->frames_till_gf_update_due == 0) { |
-#if CONFIG_MULTIPLE_ARF |
- if (cpi->multi_arf_enabled) { |
- define_fixed_arf_period(cpi); |
- } else { |
-#endif |
- define_gf_group(cpi, &this_frame_copy); |
-#if CONFIG_MULTIPLE_ARF |
- } |
-#endif |
+ define_gf_group(cpi, &this_frame_copy); |
if (twopass->gf_zeromotion_pct > 995) { |
// As long as max_thresh for encode breakout is small enough, it is ok |
@@ -2233,7 +2200,9 @@ |
} |
} |
- target_rate = twopass->gf_group_bit_allocation[twopass->gf_group_index]; |
+ configure_buffer_updates(cpi); |
+ |
+ target_rate = twopass->gf_group.bit_allocation[twopass->gf_group.index]; |
if (cpi->common.frame_type == KEY_FRAME) |
target_rate = vp9_rc_clamp_iframe_target_size(cpi, target_rate); |
else |
@@ -2249,6 +2218,12 @@ |
// Update the total stats remaining structure. |
subtract_stats(&twopass->total_left_stats, &this_frame); |
+ |
+#if CONFIG_FP_MB_STATS |
+ if (cpi->use_fp_mb_stats) { |
+ input_mb_stats(&twopass->this_frame_mb_stats, cm); |
+ } |
+#endif |
} |
void vp9_twopass_postencode_update(VP9_COMP *cpi) { |
@@ -2296,4 +2271,7 @@ |
twopass->kf_group_bits -= bits_used; |
} |
twopass->kf_group_bits = MAX(twopass->kf_group_bits, 0); |
+ |
+ // Increment the gf group index ready for the next frame. |
+ ++twopass->gf_group.index; |
} |