From: Adrian Grange Date: Tue, 2 Apr 2013 22:08:50 +0000 (-0700) Subject: Initial addition of multiple ARF frames X-Git-Tag: v1.3.0~1106^2~227^2~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c2876cf0fde6baf9cbdf3c7570adedfd1065f3db;p=platform%2Fupstream%2Flibvpx.git Initial addition of multiple ARF frames This is work-in-progress, it implements multiple ARF encoding behind an experimental flag. It adds the ability to insert multiple ARF frames into a single ARF group. This patch implements the reordering of the coded frames, and implements a fixed-length coding pattern. It applies a fixed quantizer strategy based on where the frame is in the coding sequence. Further work to modify the rate control strategy is ongoing and will be submitted via a set of future patches. In this first step, each ARF group is recursively bisected and an ARF frame added at that position in the sequence. The recursion continues until ARF frames are within MIN_GF_INTERVAL frames. The code sits behind the "multiple-arf" experimental flag ("CONFIG_MULTIPLE_ARF"). The experimental flag "oneshotq" ("CONFIG_ONESHOTQ") also needs to be enabled for this patch to work correctly. Change-Id: Ie473b05ebb43ac473c0cfb659b2b8042823085e2 --- diff --git a/configure b/configure index acd4e70..69627c5 100755 --- a/configure +++ b/configure @@ -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 916137b..88cca7f 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 6f928f5..c7ca67e 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 3c7ac0f..b64b7e4 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 ba4c80b..8da17a6 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 70f9e31..1dd2a7d 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 05977b3..8901952 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 15daa7e..f3209a3 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 d26f5ec..fc22146 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 56453e2..1d95eed 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;