diff options
author | Adrian Grange <agrange@google.com> | 2013-04-15 09:46:16 -0700 |
---|---|---|
committer | Gerrit Code Review <gerrit@gerrit.golo.chromium.org> | 2013-04-15 09:46:16 -0700 |
commit | 4ee671a15c9674456cf447168beb0462278ee14b (patch) | |
tree | 35337527df0f367c8490366bdd69aabd771a4fc4 | |
parent | 8ae091823de3fc90451a6f67731687ca552ce99b (diff) | |
parent | c2876cf0fde6baf9cbdf3c7570adedfd1065f3db (diff) | |
download | libvpx-4ee671a15c9674456cf447168beb0462278ee14b.tar libvpx-4ee671a15c9674456cf447168beb0462278ee14b.tar.gz libvpx-4ee671a15c9674456cf447168beb0462278ee14b.tar.bz2 libvpx-4ee671a15c9674456cf447168beb0462278ee14b.zip |
Merge "Initial addition of multiple ARF frames" into experimental
-rwxr-xr-x | configure | 1 | ||||
-rw-r--r-- | vp8/encoder/onyx_if.c | 4 | ||||
-rw-r--r-- | vp9/common/vp9_onyxc_int.h | 8 | ||||
-rw-r--r-- | vp9/decoder/vp9_onyxd_if.c | 2 | ||||
-rw-r--r-- | vp9/encoder/vp9_bitstream.c | 20 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 321 | ||||
-rw-r--r-- | vp9/encoder/vp9_onyx_if.c | 312 | ||||
-rw-r--r-- | vp9/encoder/vp9_onyx_int.h | 41 | ||||
-rw-r--r-- | vp9/encoder/vp9_ratectrl.c | 11 | ||||
-rw-r--r-- | vp9/vp9_cx_iface.c | 7 |
10 files changed, 596 insertions, 131 deletions
@@ -253,6 +253,7 @@ EXPERIMENT_LIST=" scatterscan oneshotq sbsegment + multiple_arf " CONFIG_LIST=" external_build diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 916137b49..88cca7fa7 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -2685,7 +2685,7 @@ static void update_alt_ref_frame_stats(VP8_COMP *cpi) /* Clear the alternate reference update pending flag. */ cpi->source_alt_ref_pending = 0; - /* Set the alternate refernce frame active flag */ + /* Set the alternate reference frame active flag */ cpi->source_alt_ref_active = 1; @@ -3332,7 +3332,7 @@ static void encode_frame_to_data_rate else cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 0; - /* Check to see if a key frame is signalled + /* Check to see if a key frame is signaled * For two pass with auto key frame enabled cm->frame_type may already * be set, but not for one pass. */ diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index 6f928f5e0..c7ca67efe 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -18,6 +18,7 @@ #include "vp9/common/vp9_entropymv.h" #include "vp9/common/vp9_entropy.h" #include "vp9/common/vp9_entropymode.h" + #if CONFIG_POSTPROC #include "vp9/common/vp9_postproc.h" #endif @@ -37,8 +38,13 @@ void vp9_initialize_common(void); #define QINDEX_RANGE (MAXQ + 1) +#if CONFIG_MULTIPLE_ARF +#define NUM_REF_FRAMES 8 +#define NUM_REF_FRAMES_LG2 3 +#else #define NUM_REF_FRAMES 3 #define NUM_REF_FRAMES_LG2 2 +#endif #define ALLOWED_REFS_PER_FRAME 3 @@ -52,6 +58,8 @@ void vp9_initialize_common(void); #define COMP_PRED_CONTEXTS 2 +#define MAX_LAG_BUFFERS 25 + typedef struct frame_contexts { vp9_prob bmode_prob[VP9_NKF_BINTRAMODES - 1]; vp9_prob ymode_prob[VP9_YMODES - 1]; /* interframe intra mode probs */ diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c index 3c7ac0fcd..b64b7e4dc 100644 --- a/vp9/decoder/vp9_onyxd_if.c +++ b/vp9/decoder/vp9_onyxd_if.c @@ -249,7 +249,7 @@ int vp9_get_reference_dec(VP9D_PTR ptr, int index, YV12_BUFFER_CONFIG **fb) { return 0; } -/* If any buffer updating is signalled it should be done here. */ +/* If any buffer updating is signaled it should be done here. */ static void swap_frame_buffers(VP9D_COMP *pbi) { int ref_index = 0, mask; diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 9cb448a99..c2ae957c8 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -2617,7 +2617,12 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, int refresh_mask; // Should the GF or ARF be updated using the transmitted frame or buffer - if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) { +#if CONFIG_MULTIPLE_ARF + if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame && + !cpi->refresh_alt_ref_frame) { +#else + if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) { +#endif /* Preserve the previously existing golden frame and update the frame in * the alt ref slot instead. This is highly specific to the use of * alt-ref as a forward reference, and this needs to be generalized as @@ -2630,10 +2635,21 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) | (cpi->refresh_golden_frame << cpi->alt_fb_idx); } else { + int arf_idx = cpi->alt_fb_idx; +#if CONFIG_MULTIPLE_ARF + // Determine which ARF buffer to use to encode this ARF frame. + if (cpi->multi_arf_enabled) { + int sn = cpi->sequence_number; + arf_idx = (cpi->frame_coding_order[sn] < 0) ? + cpi->arf_buffer_idx[sn + 1] : + cpi->arf_buffer_idx[sn]; + } +#endif refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) | (cpi->refresh_golden_frame << cpi->gld_fb_idx) | - (cpi->refresh_alt_ref_frame << cpi->alt_fb_idx); + (cpi->refresh_alt_ref_frame << arf_idx); } + vp9_write_literal(&header_bc, refresh_mask, NUM_REF_FRAMES); vp9_write_literal(&header_bc, cpi->lst_fb_idx, NUM_REF_FRAMES_LG2); vp9_write_literal(&header_bc, cpi->gld_fb_idx, NUM_REF_FRAMES_LG2); diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 70f9e3153..1dd2a7dd8 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -317,15 +317,20 @@ static double simple_weight(YV12_BUFFER_CONFIG *source) { } -// This function returns the current per frame maximum bitrate target +// This function returns the current per frame maximum bitrate target. static int frame_max_bits(VP9_COMP *cpi) { - // Max allocation for a single frame based on the max section guidelines passed in and how many bits are left + // Max allocation for a single frame based on the max section guidelines + // passed in and how many bits are left. int max_bits; - // For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user - max_bits = (int)(((double)cpi->twopass.bits_left / (cpi->twopass.total_stats->count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0)); + // For VBR base this on the bits and frames left plus the + // two_pass_vbrmax_section rate passed in by the user. + max_bits = (int) (((double) cpi->twopass.bits_left + / (cpi->twopass.total_stats->count - (double) cpi->common + .current_video_frame)) + * ((double) cpi->oxcf.two_pass_vbrmax_section / 100.0)); - // Trap case where we are out of bits + // Trap case where we are out of bits. if (max_bits < 0) max_bits = 0; @@ -746,7 +751,7 @@ void vp9_first_pass(VP9_COMP *cpi) { } // TODO: handle the case when duration is set to 0, or something less - // than the full time between subsequent cpi->source_time_stamp s . + // than the full time between subsequent values of cpi->source_time_stamp. fps.duration = (double)(cpi->source->ts_end - cpi->source->ts_start); @@ -873,7 +878,7 @@ static double calc_correction_factor(double err_per_mb, // Given a current maxQ value sets a range for future values. // PGW TODO.. -// This code removes direct dependency on QIndex to determin the range +// This code removes direct dependency on QIndex to determine the range // (now uses the actual quantizer) but has not been tuned. static void adjust_maxq_qrange(VP9_COMP *cpi) { int i; @@ -991,7 +996,7 @@ static int estimate_max_q(VP9_COMP *cpi, } // Adjust maxq_min_limit and maxq_max_limit limits based on - // averaga q observed in clip for non kf/gf/arf frames + // average q observed in clip for non kf/gf/arf frames // Give average a chance to settle though. // PGW TODO.. This code is broken for the extended Q range if ((cpi->ni_frames > @@ -1379,7 +1384,7 @@ static int calc_arf_boost( &this_frame_mv_in_out, &mv_in_out_accumulator, &abs_mv_in_out_accumulator, &mv_ratio_accumulator); - // We want to discount the the flash frame itself and the recovery + // We want to discount the flash frame itself and the recovery // frame that follows as both will have poor scores. flash_detected = detect_flash(cpi, (i + offset)) || detect_flash(cpi, (i + offset + 1)); @@ -1442,9 +1447,8 @@ static int calc_arf_boost( return arf_boost; } -static void configure_arnr_filter(VP9_COMP *cpi, - FIRSTPASS_STATS *this_frame, - int group_boost) { +void configure_arnr_filter(VP9_COMP *cpi, const unsigned int this_frame, + int group_boost) { int half_gf_int; int frames_after_arf; int frames_bwd = cpi->oxcf.arnr_max_frames - 1; @@ -1458,8 +1462,7 @@ static void configure_arnr_filter(VP9_COMP *cpi, // Note: this_frame->frame has been updated in the loop // so it now points at the ARF frame. half_gf_int = cpi->baseline_gf_interval >> 1; - frames_after_arf = (int)(cpi->twopass.total_stats->count - - this_frame->frame - 1); + frames_after_arf = (int)(cpi->twopass.total_stats->count - this_frame - 1); switch (cpi->oxcf.arnr_type) { case 1: // Backward filter @@ -1515,7 +1518,144 @@ static void configure_arnr_filter(VP9_COMP *cpi, } } -// Analyse and define a gf/arf group . +#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. + // 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); + + // 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->twopass.frames_to_key <= (FIXED_ARF_GROUP_SIZE + 8)) { + // Setup a GF group close to the keyframe. + cpi->source_alt_ref_pending = FALSE; + cpi->baseline_gf_interval = cpi->twopass.frames_to_key; + schedule_frames(cpi, 0, (cpi->baseline_gf_interval - 1), 2, 0, 0); + } else { + // Setup a fixed period ARF group. + cpi->source_alt_ref_pending = TRUE; + cpi->baseline_gf_interval = FIXED_ARF_GROUP_SIZE; + schedule_frames(cpi, 0, -(cpi->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 + +// Analyse and define a gf/arf group. static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { FIRSTPASS_STATS next_frame; FIRSTPASS_STATS *start_pos; @@ -1619,7 +1759,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { } // Break clause to detect very still sections after motion - // (for example a staic image after a fade or other transition). + // (for example a static image after a fade or other transition). if (detect_transition_to_still(cpi, i, 5, loop_decay_rate, last_loop_decay_rate)) { allow_alt_ref = FALSE; @@ -1637,9 +1777,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Break at cpi->max_gf_interval unless almost totally static (i >= active_max_gf_interval && (zero_motion_accumulator < 0.995)) || ( - // Dont break out with a very short interval + // Don't break out with a very short interval (i > MIN_GF_INTERVAL) && - // Dont break out very close to a key frame + // Don't break out very close to a key frame ((cpi->twopass.frames_to_key - i) >= MIN_GF_INTERVAL) && ((boost_score > 125.0) || (next_frame.pcnt_inter < 0.75)) && (!flash_detected) && @@ -1657,7 +1797,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { old_boost_score = boost_score; } - // Dont allow a gf too near the next kf + // Don't allow a gf too near the next kf if ((cpi->twopass.frames_to_key - i) < MIN_GF_INTERVAL) { while (i < cpi->twopass.frames_to_key) { i++; @@ -1672,10 +1812,22 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { } } - // Set the interval till the next gf or arf. + // Set the interval until the next gf or arf. cpi->baseline_gf_interval = i; - // Should we use the alternate refernce frame +#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 + + // Should we use the alternate reference frame if (allow_alt_ref && (i < cpi->oxcf.lag_in_frames) && (i >= MIN_GF_INTERVAL) && @@ -1686,16 +1838,66 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ((mv_in_out_accumulator / (double)i > -0.2) || (mv_in_out_accumulator > -2.0)) && (boost_score > 100)) { - // Alterrnative boost calculation for alt ref + // Alternative boost calculation for alt ref cpi->gfu_boost = calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost, &b_boost); cpi->source_alt_ref_pending = TRUE; - configure_arnr_filter(cpi, this_frame, cpi->gfu_boost); +#if CONFIG_MULTIPLE_ARF + // Set the ARF schedule. + if (cpi->multi_arf_enabled) { + schedule_frames(cpi, 0, -(cpi->baseline_gf_interval - 1), 2, 1, 0); + } +#endif } else { cpi->gfu_boost = (int)boost_score; cpi->source_alt_ref_pending = FALSE; +#if CONFIG_MULTIPLE_ARF + // Set the GF schedule. + if (cpi->multi_arf_enabled) { + schedule_frames(cpi, 0, cpi->baseline_gf_interval - 1, 2, 0, 0); + assert(cpi->new_frame_coding_order_period == cpi->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 + // Now decide how many bits should be allocated to the GF group as a // proportion of those remaining in the kf group. // The final key frame group in the clip is treated as a special case @@ -1736,10 +1938,13 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { cpi->twopass.modified_error_used += gf_group_err; // Assign bits to the arf or gf. - for (i = 0; i <= (cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME); i++) { + for (i = 0; + i <= (cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME); + ++i) { int boost; int allocation_chunks; - int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q; + int Q = + (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q; int gf_bits; boost = (cpi->gfu_boost * vp9_gfboost_qadjust(Q)) / 100; @@ -1758,7 +1963,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { (cpi->baseline_gf_interval * 100) + (boost - 100); // Prevent overflow - if (boost > 1028) { + if (boost > 1028) { // TODO(agrange) Should this be 1024? int divisor = boost >> 10; boost /= divisor; allocation_chunks /= divisor; @@ -1807,18 +2012,21 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { if (gf_bits < 0) gf_bits = 0; - gf_bits += cpi->min_frame_bandwidth; // Add in minimum for a frame + // Add in minimum for a frame + gf_bits += cpi->min_frame_bandwidth; if (i == 0) { cpi->twopass.gf_bits = gf_bits; } - if (i == 1 || (!cpi->source_alt_ref_pending && (cpi->common.frame_type != KEY_FRAME))) { - cpi->per_frame_bandwidth = gf_bits; // Per frame bit target for this frame + if (i == 1 || (!cpi->source_alt_ref_pending + && (cpi->common.frame_type != KEY_FRAME))) { + // Per frame bit target for this frame + cpi->per_frame_bandwidth = gf_bits; } } { - // Adjust KF group bits and error remainin + // Adjust KF group bits and error remaining cpi->twopass.kf_group_error_left -= (int64_t)gf_group_err; cpi->twopass.kf_group_bits -= cpi->twopass.gf_group_bits; @@ -1835,13 +2043,14 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { else cpi->twopass.gf_group_error_left = (int64_t)gf_group_err; - cpi->twopass.gf_group_bits -= cpi->twopass.gf_bits - cpi->min_frame_bandwidth; + cpi->twopass.gf_group_bits -= cpi->twopass.gf_bits + - cpi->min_frame_bandwidth; if (cpi->twopass.gf_group_bits < 0) cpi->twopass.gf_group_bits = 0; // This condition could fail if there are two kfs very close together - // despite (MIN_GF_INTERVAL) and would cause a devide by 0 in the + // despite (MIN_GF_INTERVAL) and would cause a divide by 0 in the // calculation of cpi->twopass.alt_extra_bits. if (cpi->baseline_gf_interval >= 3) { int boost = (cpi->source_alt_ref_pending) @@ -1853,6 +2062,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { pct_extra = (boost - 100) / 50; pct_extra = (pct_extra > 20) ? 20 : pct_extra; + // TODO(agrange) Remove cpi->twopass.alt_extra_bits. cpi->twopass.alt_extra_bits = (int) ((cpi->twopass.gf_group_bits * pct_extra) / 100); cpi->twopass.gf_group_bits -= cpi->twopass.alt_extra_bits; @@ -1887,24 +2097,28 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Allocate bits to a normal frame that is neither a gf an arf or a key frame. static void assign_std_frame_bits(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { - int target_frame_size; // gf_group_error_left + int target_frame_size; double modified_err; - double err_fraction; // What portion of the remaining GF group error is used by this frame + double err_fraction; - int max_bits = frame_max_bits(cpi); // Max for a single frame + // Max for a single frame. + int max_bits = frame_max_bits(cpi); - // Calculate modified prediction error used in bit allocation + // Calculate modified prediction error used in bit allocation. modified_err = calculate_modified_err(cpi, this_frame); if (cpi->twopass.gf_group_error_left > 0) - err_fraction = modified_err / cpi->twopass.gf_group_error_left; // What portion of the remaining GF group error is used by this frame + // What portion of the remaining GF group error is used by this frame. + err_fraction = modified_err / cpi->twopass.gf_group_error_left; else err_fraction = 0.0; - target_frame_size = (int)((double)cpi->twopass.gf_group_bits * err_fraction); // How many of those bits available for allocation should we give it? + // How many of those bits available for allocation should we give it? + target_frame_size = (int)((double)cpi->twopass.gf_group_bits * err_fraction); - // Clip to target size to 0 - max_bits (or cpi->twopass.gf_group_bits) at the top end. + // Clip target size to 0 - max_bits (or cpi->twopass.gf_group_bits) at + // the top end. if (target_frame_size < 0) target_frame_size = 0; else { @@ -1915,17 +2129,18 @@ static void assign_std_frame_bits(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { target_frame_size = (int)cpi->twopass.gf_group_bits; } - // Adjust error remaining + // Adjust error and bits remaining. cpi->twopass.gf_group_error_left -= (int64_t)modified_err; - cpi->twopass.gf_group_bits -= target_frame_size; // Adjust bits remaining + cpi->twopass.gf_group_bits -= target_frame_size; if (cpi->twopass.gf_group_bits < 0) cpi->twopass.gf_group_bits = 0; - target_frame_size += cpi->min_frame_bandwidth; // Add in the minimum number of bits that is set aside for every frame. - + // Add in the minimum number of bits that is set aside for every frame. + target_frame_size += cpi->min_frame_bandwidth; - cpi->per_frame_bandwidth = target_frame_size; // Per frame bit target for this frame + // Per frame bit target for this frame. + cpi->per_frame_bandwidth = target_frame_size; } // Make a damped adjustment to the active max q. @@ -2059,7 +2274,16 @@ void vp9_second_pass(VP9_COMP *cpi) { if (cpi->frames_till_gf_update_due == 0) { // Define next gf group and assign bits to it vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame)); - define_gf_group(cpi, &this_frame_copy); + +#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 // If we are going to code an altref frame at the end of the group // and the current frame is not a key frame.... @@ -2101,7 +2325,7 @@ void vp9_second_pass(VP9_COMP *cpi) { cpi->twopass.frames_to_key--; - // Update the total stats remaining sturcture + // Update the total stats remaining structure subtract_stats(cpi->twopass.total_left_stats, &this_frame); } @@ -2178,7 +2402,8 @@ static int test_candidate_kf(VP9_COMP *cpi, break; } - // If there is tolerable prediction for at least the next 3 frames then break out else discard this pottential key frame and move on + // If there is tolerable prediction for at least the next 3 frames then + // break out else discard this potential key frame and move on if (boost_score > 30.0 && (i > 3)) is_viable_kf = TRUE; else { @@ -2231,7 +2456,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Take a copy of the initial frame details vpx_memcpy(&first_frame, this_frame, sizeof(*this_frame)); - cpi->twopass.kf_group_bits = 0; // Total bits avaialable to kf group + cpi->twopass.kf_group_bits = 0; // Total bits available to kf group cpi->twopass.kf_group_error_left = 0; // Group modified error score. kf_mod_err = calculate_modified_err(cpi, this_frame); diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 05977b3f5..890195204 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -82,6 +82,10 @@ extern double vp9_calc_ssimg(YV12_BUFFER_CONFIG *source, #endif +// TODO(agrange) Move this function. +extern void configure_arnr_filter(VP9_COMP *cpi, const unsigned int this_frame, + int group_boost); + // #define OUTPUT_YUV_REC #ifdef OUTPUT_YUV_SRC @@ -738,7 +742,12 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->optimize_coefficients = !cpi->oxcf.lossless; sf->first_step = 0; sf->max_step_search_steps = MAX_MVSEARCH_STEPS; +#if CONFIG_MULTIPLE_ARF + // Switch segmentation off. + sf->static_segmentation = 0; +#else sf->static_segmentation = 1; +#endif sf->splitmode_breakout = 0; sf->mb16_breakout = 0; @@ -748,7 +757,12 @@ void vp9_set_speed_features(VP9_COMP *cpi) { break; case 1: +#if CONFIG_MULTIPLE_ARF + // Switch segmentation off. + sf->static_segmentation = 0; +#else sf->static_segmentation = 1; +#endif sf->splitmode_breakout = 1; sf->mb16_breakout = 0; @@ -1265,7 +1279,11 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) { } // YX Temp +#if CONFIG_MULTIPLE_ARF + vp9_zero(cpi->alt_ref_source); +#else cpi->alt_ref_source = NULL; +#endif cpi->is_src_frame_alt_ref = 0; #if 0 @@ -1356,9 +1374,9 @@ VP9_PTR vp9_create_compressor(VP9_CONFIG *oxcf) { cpi->common.current_video_frame = 0; cpi->kf_overspend_bits = 0; cpi->kf_bitrate_adjustment = 0; - cpi->frames_till_gf_update_due = 0; + cpi->frames_till_gf_update_due = 0; cpi->gf_overspend_bits = 0; - cpi->non_gf_bitrate_adjustment = 0; + cpi->non_gf_bitrate_adjustment = 0; cm->prob_last_coded = 128; cm->prob_gf_coded = 128; cm->prob_intra_coded = 63; @@ -1369,7 +1387,7 @@ VP9_PTR vp9_create_compressor(VP9_CONFIG *oxcf) { for (i = 0; i < TX_SIZE_MAX_SB - 1; i++) cm->prob_tx[i] = 128; - // 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; @@ -1449,6 +1467,19 @@ VP9_PTR vp9_create_compressor(VP9_CONFIG *oxcf) { cpi->source_alt_ref_active = FALSE; cpi->refresh_alt_ref_frame = 0; +#if CONFIG_MULTIPLE_ARF + // Turn multiple ARF usage on/off. This is a quick hack for the initial test + // version. It should eventually be set via the codec API. + cpi->multi_arf_enabled = 1; + + if (cpi->multi_arf_enabled) { + cpi->sequence_number = 0; + cpi->frame_coding_order_period = 0; + vp9_zero(cpi->frame_coding_order); + vp9_zero(cpi->arf_buffer_idx); + } +#endif + cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS; #if CONFIG_INTERNAL_STATS cpi->b_calculate_ssimg = 0; @@ -2193,10 +2224,13 @@ static void update_alt_ref_frame_stats(VP9_COMP *cpi) { // this frame refreshes means next frames don't unless specified by user cpi->common.frames_since_golden = 0; - // Clear the alternate reference update pending flag. - cpi->source_alt_ref_pending = FALSE; +#if CONFIG_MULTIPLE_ARF + if (!cpi->multi_arf_enabled) +#endif + // Clear the alternate reference update pending flag. + cpi->source_alt_ref_pending = FALSE; - // Set the alternate refernce frame active flag + // Set the alternate reference frame active flag cpi->source_alt_ref_active = TRUE; @@ -2223,7 +2257,7 @@ static void update_golden_frame_stats(VP9_COMP *cpi) { // } // else // { - // // Carry a potrtion of count over to begining of next gf sequence + // // Carry a portion of count over to beginning of next gf sequence // cpi->recent_ref_frame_usage[INTRA_FRAME] >>= 5; // cpi->recent_ref_frame_usage[LAST_FRAME] >>= 5; // cpi->recent_ref_frame_usage[GOLDEN_FRAME] >>= 5; @@ -2362,7 +2396,7 @@ static int recode_loop_test(VP9_COMP *cpi, VP9_COMMON *cm = &cpi->common; // Is frame recode allowed at all - // Yes if either recode mode 1 is selected or mode two is selcted + // Yes if either recode mode 1 is selected or mode two is selected // and the frame is a key frame. golden frame or alt_ref_frame if ((cpi->sf.recode_loop == 1) || ((cpi->sf.recode_loop == 2) && @@ -2403,13 +2437,19 @@ static void update_reference_frames(VP9_COMP * const cpi) { &cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx); ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx); - } else if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) { + } +#if CONFIG_MULTIPLE_ARF + else if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame && + !cpi->refresh_alt_ref_frame) { +#else + else if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) { +#endif /* Preserve the previously existing golden frame and update the frame in * the alt ref slot instead. This is highly specific to the current use of * alt-ref as a forward reference, and this needs to be generalized as * other uses are implemented (like RTC/temporal scaling) * - * The update to the buffer in the alt ref slot was signalled in + * The update to the buffer in the alt ref slot was signaled in * vp9_pack_bitstream(), now swap the buffer pointers so that it's treated * as the golden frame next time. */ @@ -2421,10 +2461,16 @@ static void update_reference_frames(VP9_COMP * const cpi) { tmp = cpi->alt_fb_idx; cpi->alt_fb_idx = cpi->gld_fb_idx; cpi->gld_fb_idx = tmp; - } else { /* For non key/golden frames */ + } else { /* For non key/golden frames */ if (cpi->refresh_alt_ref_frame) { + int arf_idx = cpi->alt_fb_idx; +#if CONFIG_MULTIPLE_ARF + if (cpi->multi_arf_enabled) { + arf_idx = cpi->arf_buffer_idx[cpi->sequence_number + 1]; + } +#endif ref_cnt_fb(cm->fb_idx_ref_cnt, - &cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx); + &cm->ref_frame_map[arf_idx], cm->new_fb_idx); } if (cpi->refresh_golden_frame) { @@ -2615,7 +2661,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, // For an alt ref frame in 2 pass we skip the call to the second // pass function that sets the target bandwidth so must set it here if (cpi->refresh_alt_ref_frame) { - cpi->per_frame_bandwidth = cpi->twopass.gf_bits; // Per frame bit target for the alt ref frame + // Per frame bit target for the alt ref frame + cpi->per_frame_bandwidth = cpi->twopass.gf_bits; // per second target bitrate cpi->target_bandwidth = (int)(cpi->twopass.gf_bits * cpi->output_frame_rate); @@ -2637,7 +2684,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, // Current default encoder behaviour for the altref sign bias cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = cpi->source_alt_ref_active; - // Check to see if a key frame is signalled + // Check to see if a key frame is signaled // For two pass with auto key frame enabled cm->frame_type may already be set, but not for one pass. if ((cm->current_video_frame == 0) || (cm->frame_flags & FRAMEFLAGS_KEY) || @@ -2681,7 +2728,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, // Configure use of segmentation for enhanced coding of static regions. // Only allowed for now in second pass of two pass (as requires lagged coding) - // and if the relevent speed feature flag is set. + // and if the relevant speed feature flag is set. if ((cpi->pass == 2) && (cpi->sf.static_segmentation)) { configure_static_seg_features(cpi); } @@ -2695,6 +2742,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, q = cpi->active_worst_quality; if (cm->frame_type == KEY_FRAME) { +#if CONFIG_MULTIPLE_ARF + double current_q; +#endif int high = 2000; int low = 400; @@ -2711,7 +2761,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cpi->active_best_quality = kf_low_motion_minq[q] + adjustment; } - // Make an adjustment based on the %s static + // Make an adjustment based on the % static // The main impact of this is at lower Q to prevent overly large key // frames unless a lot of the image is static. if (cpi->kf_zeromotion_pct < 64) @@ -2728,9 +2778,14 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, delta_qindex = compute_qdelta(cpi, last_boosted_q, (last_boosted_q * 0.75)); - cpi->active_best_quality = MAX(qindex + delta_qindex, cpi->best_quality); } +#if CONFIG_MULTIPLE_ARF + // Force the KF quantizer to be 30% of the active_worst_quality. + current_q = vp9_convert_qindex_to_q(cpi->active_worst_quality); + cpi->active_best_quality = cpi->active_worst_quality + + compute_qdelta(cpi, current_q, current_q * 0.3); +#endif } else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) { int high = 2000; int low = 400; @@ -2776,7 +2831,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cpi->active_best_quality = inter_minq[q]; #endif - // For the constant/constrained quality mode we dont want + // For the constant/constrained quality mode we don't want // q to fall below the cq level. if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && (cpi->active_best_quality < cpi->cq_target_quality)) { @@ -2814,12 +2869,34 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, vp9_compute_frame_size_bounds(cpi, &frame_under_shoot_limit, &frame_over_shoot_limit); - // Limit Q range for the adaptive loop. - bottom_index = cpi->active_best_quality; - top_index = cpi->active_worst_quality; - q_low = cpi->active_best_quality; - q_high = cpi->active_worst_quality; +#if CONFIG_MULTIPLE_ARF + // Force the quantizer determined by the coding order pattern. + if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME)) { + double new_q; + double current_q = vp9_convert_qindex_to_q(cpi->active_worst_quality); + int level = cpi->this_frame_weight; + assert(level >= 0); + // Set quantizer steps at 10% increments. + new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level))); + q = cpi->active_worst_quality + compute_qdelta(cpi, current_q, new_q); + + bottom_index = q; + top_index = q; + q_low = q; + q_high = q; + + printf("frame:%d q:%d\n", cm->current_video_frame, q); + } else { +#endif + // Limit Q range for the adaptive loop. + bottom_index = cpi->active_best_quality; + top_index = cpi->active_worst_quality; + q_low = cpi->active_best_quality; + q_high = cpi->active_worst_quality; +#if CONFIG_MULTIPLE_ARF + } +#endif loop_count = 0; if (cm->frame_type != KEY_FRAME) { @@ -2936,8 +3013,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, if (cm->frame_type == KEY_FRAME) { /* Choose which entropy context to use. When using a forward reference * frame, it immediately follows the keyframe, and thus benefits from - * using the same entropy context established by the keyframe. Otherwise, - * use the default context 0. + * using the same entropy context established by the keyframe. + * Otherwise, use the default context 0. */ cm->frame_context_idx = cpi->oxcf.play_alternate; vp9_setup_key_frame(cpi); @@ -3191,7 +3268,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, } } - // Update the GF useage maps. + // Update the GF usage maps. // This is done after completing the compression of a frame when all modes // etc. are finalized but before loop filter vp9_update_gf_useage_maps(cpi, cm, &cpi->mb); @@ -3366,7 +3443,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, // in this frame. update_base_skip_probs(cpi); -#if 0 // 1 && CONFIG_INTERNAL_STATS +#if 0 && CONFIG_INTERNAL_STATS { FILE *f = fopen("tmp.stt", "a"); int recon_err; @@ -3513,10 +3590,33 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, // Tell the caller that the frame was coded as a key frame *frame_flags = cm->frame_flags | FRAMEFLAGS_KEY; - // As this frame is a key frame the next defaults to an inter frame. +#if CONFIG_MULTIPLE_ARF + // Reset the sequence number. + if (cpi->multi_arf_enabled) { + cpi->sequence_number = 0; + cpi->frame_coding_order_period = cpi->new_frame_coding_order_period; + cpi->new_frame_coding_order_period = -1; + } +#endif + + // As this frame is a key frame the next defaults to an inter frame. cm->frame_type = INTER_FRAME; } else { *frame_flags = cm->frame_flags&~FRAMEFLAGS_KEY; + +#if CONFIG_MULTIPLE_ARF + /* Increment position in the coded frame sequence. */ + if (cpi->multi_arf_enabled) { + ++cpi->sequence_number; + if (cpi->sequence_number >= cpi->frame_coding_order_period) { + cpi->sequence_number = 0; + cpi->frame_coding_order_period = cpi->new_frame_coding_order_period; + cpi->new_frame_coding_order_period = -1; + } + cpi->this_frame_weight = cpi->arf_weight[cpi->sequence_number]; + assert(cpi->this_frame_weight >= 0); + } +#endif } // Clear the one shot update flags for segmentation map and mode/ref loop filter deltas. @@ -3528,16 +3628,15 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cm->last_width = cm->width; cm->last_height = cm->height; - // Dont increment frame counters if this was an altref buffer update not a real frame + // Don't increment frame counters if this was an altref buffer + // update not a real frame if (cm->show_frame) { - cm->current_video_frame++; - cpi->frames_since_key++; + ++cm->current_video_frame; + ++cpi->frames_since_key; } // reset to normal state now that we are done. - - #if 0 { char filename[512]; @@ -3624,6 +3723,12 @@ static int frame_is_reference(const VP9_COMP *cpi) { mb->update_mb_segmentation_data; } +#if CONFIG_MULTIPLE_ARF +int is_next_frame_arf(VP9_COMP *cpi) { + // Negative entry in frame_coding_order indicates an ARF at this position. + return cpi->frame_coding_order[cpi->sequence_number + 1] < 0 ? 1 : 0; +} +#endif int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, unsigned long *size, unsigned char *dest, @@ -3633,6 +3738,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, struct vpx_usec_timer cmptimer; YV12_BUFFER_CONFIG *force_src_buffer = NULL; int i; + // FILE *fp_out = fopen("enc_frame_type.txt", "a"); if (!cpi) return -1; @@ -3644,37 +3750,90 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, cpi->mb.e_mbd.allow_high_precision_mv = ALTREF_HIGH_PRECISION_MV; set_mvcost(&cpi->mb); - // Should we code an alternate reference frame - if (cpi->oxcf.play_alternate && - cpi->source_alt_ref_pending) { - if ((cpi->source = vp9_lookahead_peek(cpi->lookahead, - cpi->frames_till_gf_update_due))) { + // Should we code an alternate reference frame. + if (cpi->oxcf.play_alternate && cpi->source_alt_ref_pending) { + int frames_to_arf; + +#if CONFIG_MULTIPLE_ARF + assert(!cpi->multi_arf_enabled || + cpi->frame_coding_order[cpi->sequence_number] < 0); + + if (cpi->multi_arf_enabled && (cpi->pass == 2)) + frames_to_arf = (-cpi->frame_coding_order[cpi->sequence_number]) + - cpi->next_frame_in_order; + else +#endif + frames_to_arf = cpi->frames_till_gf_update_due; + + assert(frames_to_arf < cpi->twopass.frames_to_key); + + if ((cpi->source = vp9_lookahead_peek(cpi->lookahead, frames_to_arf))) { +#if CONFIG_MULTIPLE_ARF + cpi->alt_ref_source[cpi->arf_buffered] = cpi->source; +#else cpi->alt_ref_source = cpi->source; +#endif + if (cpi->oxcf.arnr_max_frames > 0) { - vp9_temporal_filter_prepare(cpi, cpi->frames_till_gf_update_due); + // Produce the filtered ARF frame. + // TODO(agrange) merge these two functions. + configure_arnr_filter(cpi, cm->current_video_frame + frames_to_arf, + cpi->gfu_boost); + vp9_temporal_filter_prepare(cpi, frames_to_arf); force_src_buffer = &cpi->alt_ref_buffer; } - cm->frames_till_alt_ref_frame = cpi->frames_till_gf_update_due; + + cm->show_frame = 0; cpi->refresh_alt_ref_frame = 1; cpi->refresh_golden_frame = 0; cpi->refresh_last_frame = 0; - cm->show_frame = 0; - cpi->source_alt_ref_pending = FALSE; // Clear Pending altf Ref flag. cpi->is_src_frame_alt_ref = 0; + + // TODO(agrange) This needs to vary depending on where the next ARF is. + cm->frames_till_alt_ref_frame = frames_to_arf; + +#if CONFIG_MULTIPLE_ARF + if (!cpi->multi_arf_enabled) +#endif + cpi->source_alt_ref_pending = FALSE; // Clear Pending altf Ref flag. } } if (!cpi->source) { +#if CONFIG_MULTIPLE_ARF + int i; +#endif if ((cpi->source = vp9_lookahead_pop(cpi->lookahead, flush))) { cm->show_frame = 1; +#if CONFIG_MULTIPLE_ARF + // Is this frame the ARF overlay. + cpi->is_src_frame_alt_ref = FALSE; + for (i = 0; i < cpi->arf_buffered; ++i) { + if (cpi->source == cpi->alt_ref_source[i]) { + cpi->is_src_frame_alt_ref = TRUE; + cpi->refresh_golden_frame = TRUE; + break; + } + } +#else cpi->is_src_frame_alt_ref = cpi->alt_ref_source && (cpi->source == cpi->alt_ref_source); - +#endif if (cpi->is_src_frame_alt_ref) { - cpi->refresh_last_frame = 0; + // Current frame is an ARF overlay frame. +#if CONFIG_MULTIPLE_ARF + cpi->alt_ref_source[i] = NULL; +#else cpi->alt_ref_source = NULL; +#endif + // Don't refresh the last buffer for an ARF overlay frame. It will + // become the GF so preserve last as an alternative prediction option. + cpi->refresh_last_frame = 0; } +#if CONFIG_MULTIPLE_ARF + ++cpi->next_frame_in_order; +#endif } } @@ -3684,6 +3843,23 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, *time_stamp = cpi->source->ts_start; *time_end = cpi->source->ts_end; *frame_flags = cpi->source->flags; + + // fprintf(fp_out, " Frame:%d", cm->current_video_frame); +#if CONFIG_MULTIPLE_ARF + if (cpi->multi_arf_enabled) { + // fprintf(fp_out, " seq_no:%d this_frame_weight:%d", + // cpi->sequence_number, cpi->this_frame_weight); + } else { + // fprintf(fp_out, "\n"); + } +#else + // fprintf(fp_out, "\n"); +#endif + +#if CONFIG_MULTIPLE_ARF + if ((cm->frame_type != KEY_FRAME) && (cpi->pass == 2)) + cpi->source_alt_ref_pending = is_next_frame_arf(cpi); +#endif } else { *size = 0; if (flush && cpi->pass == 1 && !cpi->twopass.first_pass_done) { @@ -3691,6 +3867,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, cpi->twopass.first_pass_done = 1; } + // fclose(fp_out); return -1; } @@ -3745,33 +3922,44 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, // Clear down mmx registers vp9_clear_system_state(); // __asm emms; - cm->frame_type = INTER_FRAME; - cm->frame_flags = *frame_flags; - -#if 0 - - if (cpi->refresh_alt_ref_frame) { - // cpi->refresh_golden_frame = 1; - cpi->refresh_golden_frame = 0; - cpi->refresh_last_frame = 0; - } else { - cpi->refresh_golden_frame = 0; - cpi->refresh_last_frame = 1; - } - -#endif - /* find a free buffer for the new frame, releasing the reference previously * held. */ cm->fb_idx_ref_cnt[cm->new_fb_idx]--; cm->new_fb_idx = get_free_fb(cm); +#if CONFIG_MULTIPLE_ARF + /* Set up the correct ARF frame. */ + if (cpi->refresh_alt_ref_frame) { + ++cpi->arf_buffered; + } + if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) && + (cpi->pass == 2)) { + cpi->alt_fb_idx = cpi->arf_buffer_idx[cpi->sequence_number]; + } +#endif + /* Get the mapping of L/G/A to the reference buffer pool */ cm->active_ref_idx[0] = cm->ref_frame_map[cpi->lst_fb_idx]; cm->active_ref_idx[1] = cm->ref_frame_map[cpi->gld_fb_idx]; cm->active_ref_idx[2] = cm->ref_frame_map[cpi->alt_fb_idx]; +#if 0 // CONFIG_MULTIPLE_ARF + if (cpi->multi_arf_enabled) { + fprintf(fp_out, " idx(%d, %d, %d, %d) active(%d, %d, %d)", + cpi->lst_fb_idx, cpi->gld_fb_idx, cpi->alt_fb_idx, cm->new_fb_idx, + cm->active_ref_idx[0], cm->active_ref_idx[1], cm->active_ref_idx[2]); + if (cpi->refresh_alt_ref_frame) + fprintf(fp_out, " type:ARF"); + if (cpi->is_src_frame_alt_ref) + fprintf(fp_out, " type:OVERLAY[%d]", cpi->alt_fb_idx); + fprintf(fp_out, "\n"); + } +#endif + + cm->frame_type = INTER_FRAME; + cm->frame_flags = *frame_flags; + /* Reset the frame pointers to the current frame size */ vp8_yv12_realloc_frame_buffer(&cm->yv12_fb[cm->new_fb_idx], cm->width, cm->height, @@ -3814,7 +4002,6 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, cpi->refresh_golden_frame = 0; cpi->refresh_last_frame = 1; cm->frame_type = INTER_FRAME; - } vpx_usec_timer_mark(&cmptimer); @@ -3927,12 +4114,11 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, cpi->total_ssimg_v += v; cpi->total_ssimg_all += frame_all; } - } } #endif - + // fclose(fp_out); return 0; } diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index 15daa7e83..f3209a3f7 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -31,18 +31,22 @@ // Experimental rate control switches #if CONFIG_ONESHOTQ -#define ONE_SHOT_Q_ESTIMATE 1 -#define STRICT_ONE_SHOT_Q 1 -#define DISABLE_RC_LONG_TERM_MEM 1 +#define ONE_SHOT_Q_ESTIMATE 0 +#define STRICT_ONE_SHOT_Q 0 +#define DISABLE_RC_LONG_TERM_MEM 0 #endif + // #define SPEEDSTATS 1 +#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 DEFAULT_GF_INTERVAL 7 #define KEY_FRAME_CONTEXT 5 -#define MAX_LAG_BUFFERS 25 - #if CONFIG_COMP_INTERINTRA_PRED #define MAX_MODES 54 #else @@ -326,7 +330,11 @@ typedef struct VP9_COMP { struct lookahead_ctx *lookahead; struct lookahead_entry *source; +#if CONFIG_MULTIPLE_ARF + struct lookahead_entry *alt_ref_source[NUM_REF_FRAMES]; +#else struct lookahead_entry *alt_ref_source; +#endif YV12_BUFFER_CONFIG *Source; YV12_BUFFER_CONFIG *un_scaled_source; @@ -345,6 +353,9 @@ typedef struct VP9_COMP { int lst_fb_idx; int gld_fb_idx; int alt_fb_idx; +#if CONFIG_MULTIPLE_ARF + int alt_ref_fb_idx[NUM_REF_FRAMES - 3]; +#endif int refresh_last_frame; int refresh_golden_frame; int refresh_alt_ref_frame; @@ -358,6 +369,12 @@ typedef struct VP9_COMP { unsigned int key_frame_frequency; unsigned int this_key_frame_forced; unsigned int next_key_frame_forced; +#if CONFIG_MULTIPLE_ARF + // Position within a frame coding order (including any additional ARF frames). + unsigned int sequence_number; + // Next frame in naturally occurring order that has not yet been coded. + int next_frame_in_order; +#endif // Ambient reconstruction err target for force key frames int ambient_err; @@ -396,7 +413,6 @@ typedef struct VP9_COMP { double gf_rate_correction_factor; int frames_till_gf_update_due; // Count down till next GF - int current_gf_interval; // GF interval chosen when we coded the last GF int gf_overspend_bits; // Total bits overspent becasue of GF boost (cumulative) @@ -686,6 +702,19 @@ typedef struct VP9_COMP { int initial_width; int initial_height; + +#if CONFIG_MULTIPLE_ARF + // ARF tracking variables. + int multi_arf_enabled; + unsigned int frame_coding_order_period; + unsigned int new_frame_coding_order_period; + int frame_coding_order[MAX_LAG_BUFFERS * 2]; + int arf_buffer_idx[MAX_LAG_BUFFERS * 3 / 2]; + int arf_weight[MAX_LAG_BUFFERS]; + int arf_buffered; + int this_frame_weight; + int max_arf_level; +#endif } VP9_COMP; void vp9_encode_frame(VP9_COMP *cpi); diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index d26f5ec46..fc22146c3 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -112,7 +112,7 @@ int vp9_bits_per_mb(FRAME_TYPE frame_type, int qindex, const double q = vp9_convert_qindex_to_q(qindex); int enumerator = frame_type == KEY_FRAME ? 4000000 : 2500000; - // q based adjustment to baseline enumberator + // q based adjustment to baseline enumerator enumerator += (int)(enumerator * q) >> 12; return (int)(0.5 + (enumerator * correction_factor / q)); } @@ -300,7 +300,7 @@ static void calc_iframe_target_size(VP9_COMP *cpi) { } -// Do the best we can to define the parameteres for the next GF based +// Do the best we can to define the parameters for the next GF based // on what information we have available. // // In this experimental code only two pass is supported @@ -358,16 +358,13 @@ static void calc_pframe_target_size(VP9_COMP *cpi) { (estimate_bits_at_q(1, q, cpi->common.MBs, 1.0) * cpi->last_boost) / 100; } - } else { // If there is an active ARF at this location use the minimum - // bits on this frame even if it is a contructed arf. + // bits on this frame even if it is a constructed arf. // The active maximum quantizer insures that an appropriate - // number of bits will be spent if needed for contstructed ARFs. + // number of bits will be spent if needed for constructed ARFs. cpi->this_frame_target = 0; } - - cpi->current_gf_interval = cpi->frames_till_gf_update_due; } } diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 56453e249..1d95eed79 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -486,7 +486,10 @@ static vpx_codec_err_t vp8e_common_init(vpx_codec_ctx_t *ctx, priv->vp8_cfg.pkt_list = &priv->pkt_list.head; priv->vp8_cfg.experimental = experimental; - priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2; + // TODO(agrange) Check the limits set on this buffer, or the check that is + // applied in vp8e_encode. + priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 8; +// priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2; if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096; @@ -754,7 +757,7 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx, vpx_codec_cx_pkt_t pkt; VP9_COMP *cpi = (VP9_COMP *)ctx->cpi; - /* Pack invisible frames with the next visisble frame */ + /* Pack invisible frames with the next visible frame */ if (!cpi->common.show_frame) { if (!ctx->pending_cx_data) ctx->pending_cx_data = cx_data; |