From: Paul Wilkins Date: Mon, 9 Jun 2014 15:25:31 +0000 (+0100) Subject: Experiment for mid group second arf. X-Git-Tag: v1.4.0~1353 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2e430cba616fcb6db8a92a94ba9fa4263a2121b0;p=platform%2Fupstream%2Flibvpx.git Experiment for mid group second arf. This patch implements a mechanism for inserting a second arf at the mid position of arf groups. It is currently disabled by default using the flag multi_arf_enabled. Results are currently down somewhat in initial testing if multi-arf is enabled. Most of the loss is attributable to the fact that code to preserve the previous golden frame (in the arf buffer) in cases where we are coding an overlay frame, is currently disabled in the multi-arf case. Change-Id: I1d777318ca09f147db2e8c86d7315fe86168c865 --- diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 76f5e7b..80787e5 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -895,8 +895,8 @@ static int get_refresh_mask(VP9_COMP *cpi) { 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 && - !cpi->use_svc) { + if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame && + cpi->rc.is_src_frame_alt_ref && !cpi->use_svc) { #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 @@ -919,6 +919,11 @@ static int get_refresh_mask(VP9_COMP *cpi) { cpi->arf_buffer_idx[sn]; } #endif + if ((cpi->pass == 2) && cpi->multi_arf_enabled) { + GF_GROUP *gf_group = &cpi->twopass.gf_group; + arf_idx = gf_group->arf_update_idx[gf_group->index]; + } + return (cpi->refresh_last_frame << cpi->lst_fb_idx) | (cpi->refresh_golden_frame << cpi->gld_fb_idx) | (cpi->refresh_alt_ref_frame << arf_idx); diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 7eeb644..6d2bdfe 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -766,6 +766,10 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) { cpi->refresh_alt_ref_frame = 0; + if (cpi->pass == 2) + cpi->multi_arf_enabled = 0; + else + cpi->multi_arf_enabled = 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. @@ -1492,8 +1496,8 @@ void vp9_update_reference_frames(VP9_COMP *cpi) { 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 && - !cpi->use_svc) { + else if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame && + cpi->rc.is_src_frame_alt_ref && !cpi->use_svc) { #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 @@ -1520,6 +1524,11 @@ void vp9_update_reference_frames(VP9_COMP *cpi) { arf_idx = cpi->arf_buffer_idx[cpi->sequence_number + 1]; } #endif + if ((cpi->pass == 2) && cpi->multi_arf_enabled) { + GF_GROUP *gf_group = &cpi->twopass.gf_group; + arf_idx = gf_group->arf_update_idx[gf_group->index]; + } + ref_cnt_fb(cm->frame_bufs, &cm->ref_frame_map[arf_idx], cm->new_fb_idx); } @@ -2397,6 +2406,66 @@ void adjust_frame_rate(VP9_COMP *cpi) { cpi->last_end_time_stamp_seen = cpi->source->ts_end; } +// Returns 0 if this is not an alt ref else the offset of the source frame +// used as the arf midpoint. +static int get_arf_src_index(VP9_COMP *cpi) { + RATE_CONTROL *const rc = &cpi->rc; + int arf_src_index = 0; + if (is_altref_enabled(&cpi->oxcf)) { + if (cpi->pass == 2) { + const GF_GROUP *const gf_group = &cpi->twopass.gf_group; + if (gf_group->update_type[gf_group->index] == ARF_UPDATE) { + arf_src_index = gf_group->arf_src_offset[gf_group->index]; + } + } else if (rc->source_alt_ref_pending) { + arf_src_index = rc->frames_till_gf_update_due; + } + } + return arf_src_index; +} + +static void is_src_altref(VP9_COMP *cpi) { + RATE_CONTROL *const rc = &cpi->rc; + +#if CONFIG_MULTIPLE_ARF + int i; + // Is this frame the ARF overlay. + rc->is_src_frame_alt_ref = 0; + for (i = 0; i < cpi->arf_buffered; ++i) { + if (cpi->source == cpi->alt_ref_source[i]) { + rc->is_src_frame_alt_ref = 1; + cpi->refresh_golden_frame = 1; + break; + } + } +#else + if (cpi->pass == 2) { + GF_GROUP *gf_group = &cpi->twopass.gf_group; + rc->is_src_frame_alt_ref = + (gf_group->update_type[gf_group->index] == OVERLAY_UPDATE); + } else { + rc->is_src_frame_alt_ref = cpi->alt_ref_source && + (cpi->source == cpi->alt_ref_source); + } +#endif + + if (rc->is_src_frame_alt_ref) { + // 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 +} + int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, size_t *size, uint8_t *dest, int64_t *time_stamp, int64_t *time_end, int flush) { @@ -2406,6 +2475,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, struct vpx_usec_timer cmptimer; YV12_BUFFER_CONFIG *force_src_buffer = NULL; MV_REFERENCE_FRAME ref_frame; + int arf_src_index; if (!cpi) return -1; @@ -2428,24 +2498,12 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, cpi->refresh_golden_frame = 0; cpi->refresh_alt_ref_frame = 0; - // Should we code an alternate reference frame. - if (is_altref_enabled(&cpi->oxcf) && rc->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 = rc->frames_till_gf_update_due; - - assert(frames_to_arf <= rc->frames_to_key); + // Should we encode an arf frame. + arf_src_index = get_arf_src_index(cpi); + if (arf_src_index) { + assert(arf_src_index <= rc->frames_to_key); - if ((cpi->source = vp9_lookahead_peek(cpi->lookahead, frames_to_arf))) { + if ((cpi->source = vp9_lookahead_peek(cpi->lookahead, arf_src_index))) { #if CONFIG_MULTIPLE_ARF cpi->alt_ref_source[cpi->arf_buffered] = cpi->source; #else @@ -2455,8 +2513,8 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, if (cpi->oxcf.arnr_max_frames > 0) { // Produce the filtered ARF frame. // TODO(agrange) merge these two functions. - vp9_configure_arnr_filter(cpi, frames_to_arf, rc->gfu_boost); - vp9_temporal_filter_prepare(cpi, frames_to_arf); + vp9_configure_arnr_filter(cpi, arf_src_index, rc->gfu_boost); + vp9_temporal_filter_prepare(cpi, arf_src_index); vp9_extend_frame_borders(&cpi->alt_ref_buffer); force_src_buffer = &cpi->alt_ref_buffer; } @@ -2466,59 +2524,28 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, cpi->refresh_golden_frame = 0; cpi->refresh_last_frame = 0; rc->is_src_frame_alt_ref = 0; - -#if CONFIG_MULTIPLE_ARF - if (!cpi->multi_arf_enabled) -#endif - rc->source_alt_ref_pending = 0; + rc->source_alt_ref_pending = 0; } else { rc->source_alt_ref_pending = 0; } } if (!cpi->source) { -#if CONFIG_MULTIPLE_ARF - int i; -#endif - // Get last frame source. if (cm->current_video_frame > 0) { if ((cpi->last_source = vp9_lookahead_peek(cpi->lookahead, -1)) == NULL) return -1; } + // Read in the source frame. if ((cpi->source = vp9_lookahead_pop(cpi->lookahead, flush))) { cm->show_frame = 1; cm->intra_only = 0; -#if CONFIG_MULTIPLE_ARF - // Is this frame the ARF overlay. - rc->is_src_frame_alt_ref = 0; - for (i = 0; i < cpi->arf_buffered; ++i) { - if (cpi->source == cpi->alt_ref_source[i]) { - rc->is_src_frame_alt_ref = 1; - cpi->refresh_golden_frame = 1; - break; - } - } -#else - rc->is_src_frame_alt_ref = cpi->alt_ref_source && - (cpi->source == cpi->alt_ref_source); -#endif - if (rc->is_src_frame_alt_ref) { - // 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 + // Check to see if the frame to be encoded is an overlay + // for a previous arf frame and if so configure it as such. + if (cpi->pass == 0) + is_src_altref(cpi); } } @@ -2587,6 +2614,11 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, cpi->alt_fb_idx = cpi->arf_buffer_idx[cpi->sequence_number]; } #endif + if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) && + (cpi->pass == 2)) { + const GF_GROUP *const gf_group = &cpi->twopass.gf_group; + cpi->alt_fb_idx = gf_group->arf_ref_idx[gf_group->index]; + } cpi->frame_flags = *frame_flags; diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index 185afad..5f37dd0 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -430,9 +430,9 @@ typedef struct VP9_COMP { PC_TREE *pc_root; int partition_cost[PARTITION_CONTEXTS][PARTITION_TYPES]; + int multi_arf_enabled; #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]; diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 54c3ec0..604bdb7 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -33,7 +33,6 @@ #include "vp9/encoder/vp9_firstpass.h" #include "vp9/encoder/vp9_mcomp.h" #include "vp9/encoder/vp9_quantize.h" -#include "vp9/encoder/vp9_ratectrl.h" #include "vp9/encoder/vp9_rdopt.h" #include "vp9/encoder/vp9_variance.h" @@ -1435,39 +1434,76 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits, TWO_PASS *twopass = &cpi->twopass; FIRSTPASS_STATS frame_stats; int i; - int group_frame_index = 1; + int frame_index = 1; int target_frame_size; int key_frame; const int max_bits = frame_max_bits(&cpi->rc, &cpi->oxcf); int64_t total_group_bits = gf_group_bits; double modified_err = 0.0; double err_fraction; + int mid_boost_bits = 0; + int middle_frame_idx; key_frame = cpi->common.frame_type == KEY_FRAME || vp9_is_upper_layer_key_frame(cpi); // For key frames the frame target rate is already set and it // is also the golden frame. - // NOTE: We dont bother to check for the special case of ARF overlay - // frames here, as there is clamping code for this in the function - // vp9_rc_clamp_pframe_target_size(), which applies to one and two pass - // encodes. if (!key_frame) { - twopass->gf_group_bit_allocation[0] = gf_arf_bits; + if (rc->source_alt_ref_active) { + twopass->gf_group.update_type[0] = OVERLAY_UPDATE; + twopass->gf_group.rf_level[0] = INTER_NORMAL; + twopass->gf_group.bit_allocation[0] = 0; + twopass->gf_group.arf_update_idx[0] = 2; + twopass->gf_group.arf_ref_idx[0] = 2; + } else { + twopass->gf_group.update_type[0] = GF_UPDATE; + twopass->gf_group.rf_level[0] = GF_ARF_STD; + twopass->gf_group.bit_allocation[0] = gf_arf_bits; + twopass->gf_group.arf_update_idx[0] = 2; + twopass->gf_group.arf_ref_idx[0] = 2; + } // Step over the golden frame / overlay frame if (EOF == input_stats(twopass, &frame_stats)) return; } + // Deduct the boost bits for arf (or gf if it is not a key frame) + // from the group total. + if (rc->source_alt_ref_pending || !key_frame) + total_group_bits -= gf_arf_bits; + // Store the bits to spend on the ARF if there is one. if (rc->source_alt_ref_pending) { - twopass->gf_group_bit_allocation[group_frame_index++] = gf_arf_bits; + // A portion of the gf / arf extra bits are set asside for lower level + // boosted frames in the middle of the group. + mid_boost_bits = gf_arf_bits >> 5; + gf_arf_bits -= (gf_arf_bits >> 5); + + twopass->gf_group.update_type[frame_index] = ARF_UPDATE; + twopass->gf_group.rf_level[frame_index] = GF_ARF_STD; + twopass->gf_group.bit_allocation[frame_index] = gf_arf_bits; + twopass->gf_group.arf_src_offset[frame_index] = + rc->baseline_gf_interval - 1; + twopass->gf_group.arf_update_idx[frame_index] = 2; + twopass->gf_group.arf_ref_idx[frame_index] = 2; + ++frame_index; + + if (cpi->multi_arf_enabled) { + // Set aside a slot for a level 1 arf. + twopass->gf_group.update_type[frame_index] = ARF_UPDATE; + twopass->gf_group.rf_level[frame_index] = GF_ARF_LOW; + twopass->gf_group.arf_src_offset[frame_index] = + ((rc->baseline_gf_interval - 1) >> 1); + twopass->gf_group.arf_update_idx[frame_index] = 3; + twopass->gf_group.arf_ref_idx[frame_index] = 2; + ++frame_index; + } } - // Deduct the boost bits for arf or gf if it is not a key frame. - if (rc->source_alt_ref_pending || !key_frame) - total_group_bits -= gf_arf_bits; + // Define middle frame + middle_frame_idx = frame_index + (rc->baseline_gf_interval >> 1) - 1; // Allocate bits to the other frames in the group. for (i = 0; i < rc->baseline_gf_interval - 1; ++i) { @@ -1482,10 +1518,35 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits, err_fraction = 0.0; target_frame_size = (int)((double)total_group_bits * err_fraction); + + if (rc->source_alt_ref_pending && cpi->multi_arf_enabled) { + mid_boost_bits += (target_frame_size >> 4); + target_frame_size -= (target_frame_size >> 4); + + if (frame_index <= middle_frame_idx) { + twopass->gf_group.arf_update_idx[frame_index] = 3; + twopass->gf_group.arf_ref_idx[frame_index] = 3; + } else { + twopass->gf_group.arf_update_idx[frame_index] = 2; + twopass->gf_group.arf_ref_idx[frame_index] = 2; + } + } + target_frame_size = clamp(target_frame_size, 0, MIN(max_bits, (int)total_group_bits)); - twopass->gf_group_bit_allocation[group_frame_index++] = target_frame_size; + twopass->gf_group.update_type[frame_index] = LF_UPDATE; + twopass->gf_group.rf_level[frame_index] = INTER_NORMAL; + + twopass->gf_group.bit_allocation[frame_index] = target_frame_size; + ++frame_index; + } + + if (rc->source_alt_ref_pending && cpi->multi_arf_enabled) { + twopass->gf_group.bit_allocation[2] = + twopass->gf_group.bit_allocation[middle_frame_idx] + mid_boost_bits; + twopass->gf_group.update_type[middle_frame_idx] = OVERLAY_UPDATE; + twopass->gf_group.bit_allocation[middle_frame_idx] = 0; } } @@ -1528,8 +1589,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Reset the GF group data structures unless this is a key // frame in which case it will already have been done. if (cpi->common.frame_type != KEY_FRAME) { - twopass->gf_group_index = 0; - vp9_zero(twopass->gf_group_bit_allocation); + vp9_zero(twopass->gf_group); } vp9_clear_system_state(); @@ -1669,6 +1729,8 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { else rc->baseline_gf_interval = i; + rc->frames_till_gf_update_due = rc->baseline_gf_interval; + // Should we use the alternate reference frame. if (allow_alt_ref && (i < cpi->oxcf.lag_in_frames) && @@ -1886,8 +1948,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { cpi->common.frame_type = KEY_FRAME; // Reset the GF group data structures. - twopass->gf_group_index = 0; - vp9_zero(twopass->gf_group_bit_allocation); + vp9_zero(twopass->gf_group); // Is this a forced key frame by interval. rc->this_key_frame_forced = rc->next_key_frame_forced; @@ -2078,7 +2139,9 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { twopass->kf_group_bits -= kf_bits; // Save the bits to spend on the key frame. - twopass->gf_group_bit_allocation[0] = kf_bits; + twopass->gf_group.bit_allocation[0] = kf_bits; + twopass->gf_group.update_type[0] = KF_UPDATE; + twopass->gf_group.rf_level[0] = KF_STD; // Note the total error score of the kf group minus the key frame itself. twopass->kf_group_error_left = (int)(kf_group_err - kf_mod_err); @@ -2106,6 +2169,44 @@ void vbr_rate_correction(int * this_frame_target, } } +// Define the reference buffers that will be updated post encode. +void configure_buffer_updates(VP9_COMP *cpi) { + TWO_PASS *const twopass = &cpi->twopass; + + cpi->rc.is_src_frame_alt_ref = 0; + switch (twopass->gf_group.update_type[twopass->gf_group.index]) { + case KF_UPDATE: + cpi->refresh_last_frame = 1; + cpi->refresh_golden_frame = 1; + cpi->refresh_alt_ref_frame = 1; + break; + case LF_UPDATE: + cpi->refresh_last_frame = 1; + cpi->refresh_golden_frame = 0; + cpi->refresh_alt_ref_frame = 0; + break; + case GF_UPDATE: + cpi->refresh_last_frame = 1; + cpi->refresh_golden_frame = 1; + cpi->refresh_alt_ref_frame = 0; + break; + case OVERLAY_UPDATE: + cpi->refresh_last_frame = 0; + cpi->refresh_golden_frame = 1; + cpi->refresh_alt_ref_frame = 0; + cpi->rc.is_src_frame_alt_ref = 1; + break; + case ARF_UPDATE: + cpi->refresh_last_frame = 0; + cpi->refresh_golden_frame = 0; + cpi->refresh_alt_ref_frame = 1; + break; + default: + assert(0); + } +} + + void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { VP9_COMMON *const cm = &cpi->common; RATE_CONTROL *const rc = &cpi->rc; @@ -2130,14 +2231,12 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { if (!twopass->stats_in) return; - // Increment the gf group index. - ++twopass->gf_group_index; - // If this is an arf frame then we dont want to read the stats file or // advance the input pointer as we already have what we need. - if (cpi->refresh_alt_ref_frame) { + if (twopass->gf_group.update_type[twopass->gf_group.index] == ARF_UPDATE) { int target_rate; - target_rate = twopass->gf_group_bit_allocation[twopass->gf_group_index]; + configure_buffer_updates(cpi); + target_rate = twopass->gf_group.bit_allocation[twopass->gf_group.index]; target_rate = vp9_rc_clamp_pframe_target_size(cpi, target_rate); rc->base_frame_target = target_rate; #ifdef LONG_TERM_VBR_CORRECTION @@ -2233,7 +2332,9 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { } } - target_rate = twopass->gf_group_bit_allocation[twopass->gf_group_index]; + configure_buffer_updates(cpi); + + target_rate = twopass->gf_group.bit_allocation[twopass->gf_group.index]; if (cpi->common.frame_type == KEY_FRAME) target_rate = vp9_rc_clamp_iframe_target_size(cpi, target_rate); else @@ -2296,4 +2397,7 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) { twopass->kf_group_bits -= bits_used; } twopass->kf_group_bits = MAX(twopass->kf_group_bits, 0); + + // Increment the gf group index ready for the next frame. + ++twopass->gf_group.index; } diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h index 8206521..61268ff 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h @@ -12,6 +12,7 @@ #define VP9_ENCODER_VP9_FIRSTPASS_H_ #include "vp9/encoder/vp9_lookahead.h" +#include "vp9/encoder/vp9_ratectrl.h" #ifdef __cplusplus extern "C" { @@ -39,6 +40,25 @@ typedef struct { int64_t spatial_layer_id; } FIRSTPASS_STATS; +typedef enum { + KF_UPDATE = 0, + LF_UPDATE = 1, + GF_UPDATE = 2, + ARF_UPDATE = 3, + OVERLAY_UPDATE = 4, + FRAME_UPDATE_TYPES = 5 +} FRAME_UPDATE_TYPE; + +typedef struct { + unsigned char index; + RATE_FACTOR_LEVEL rf_level[MAX_LAG_BUFFERS * 2]; + FRAME_UPDATE_TYPE update_type[MAX_LAG_BUFFERS * 2]; + unsigned char arf_src_offset[MAX_LAG_BUFFERS * 2]; + unsigned char arf_update_idx[MAX_LAG_BUFFERS * 2]; + unsigned char arf_ref_idx[MAX_LAG_BUFFERS * 2]; + int bit_allocation[MAX_LAG_BUFFERS * 2]; +} GF_GROUP; + typedef struct { unsigned int section_intra_rating; unsigned int next_iiratio; @@ -68,8 +88,7 @@ typedef struct { int active_worst_quality; - int gf_group_index; - int gf_group_bit_allocation[MAX_LAG_BUFFERS * 2]; + GF_GROUP gf_group; } TWO_PASS; struct VP9_COMP; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index f775003..4005044 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -186,6 +186,8 @@ static void update_buffer_level(VP9_COMP *cpi, int encoded_frame_size) { } void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) { + int i; + if (pass == 0 && oxcf->rc_mode == VPX_CBR) { rc->avg_frame_qindex[KEY_FRAME] = oxcf->worst_allowed_q; rc->avg_frame_qindex[INTER_FRAME] = oxcf->worst_allowed_q; @@ -227,9 +229,9 @@ void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) { rc->tot_q = 0.0; rc->avg_q = vp9_convert_qindex_to_q(oxcf->worst_allowed_q); - rc->rate_correction_factor = 1.0; - rc->key_frame_rate_correction_factor = 1.0; - rc->gf_rate_correction_factor = 1.0; + for (i = 0; i < RATE_FACTOR_LEVELS; ++i) { + rc->rate_correction_factors[i] = 1.0; + } } int vp9_rc_drop_frame(VP9_COMP *cpi) { @@ -271,28 +273,40 @@ int vp9_rc_drop_frame(VP9_COMP *cpi) { } static double get_rate_correction_factor(const VP9_COMP *cpi) { + const RATE_CONTROL *const rc = &cpi->rc; + if (cpi->common.frame_type == KEY_FRAME) { - return cpi->rc.key_frame_rate_correction_factor; + return rc->rate_correction_factors[KF_STD]; + } else if (cpi->pass == 2) { + RATE_FACTOR_LEVEL rf_lvl = + cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index]; + return rc->rate_correction_factors[rf_lvl]; } else { if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) && - !cpi->rc.is_src_frame_alt_ref && + !rc->is_src_frame_alt_ref && !(cpi->use_svc && cpi->oxcf.rc_mode == VPX_CBR)) - return cpi->rc.gf_rate_correction_factor; + return rc->rate_correction_factors[GF_ARF_STD]; else - return cpi->rc.rate_correction_factor; + return rc->rate_correction_factors[INTER_NORMAL]; } } static void set_rate_correction_factor(VP9_COMP *cpi, double factor) { + RATE_CONTROL *const rc = &cpi->rc; + if (cpi->common.frame_type == KEY_FRAME) { - cpi->rc.key_frame_rate_correction_factor = factor; + rc->rate_correction_factors[KF_STD] = factor; + } else if (cpi->pass == 2) { + RATE_FACTOR_LEVEL rf_lvl = + cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index]; + rc->rate_correction_factors[rf_lvl] = factor; } else { if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) && - !cpi->rc.is_src_frame_alt_ref && + !rc->is_src_frame_alt_ref && !(cpi->use_svc && cpi->oxcf.rc_mode == VPX_CBR)) - cpi->rc.gf_rate_correction_factor = factor; + rc->rate_correction_factors[GF_ARF_STD] = factor; else - cpi->rc.rate_correction_factor = factor; + rc->rate_correction_factors[INTER_NORMAL] = factor; } } @@ -920,7 +934,7 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi, active_worst_quality, 2.0); } else if (!rc->is_src_frame_alt_ref && (oxcf->rc_mode != VPX_CBR) && - (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) { + (cpi->refresh_alt_ref_frame)) { qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type, active_worst_quality, 1.75); } @@ -1026,11 +1040,8 @@ static void update_alt_ref_frame_stats(VP9_COMP *cpi) { RATE_CONTROL *const rc = &cpi->rc; rc->frames_since_golden = 0; -#if CONFIG_MULTIPLE_ARF - if (!cpi->multi_arf_enabled) -#endif - // Clear the alternate reference update pending flag. - rc->source_alt_ref_pending = 0; + // Mark the alt ref as done (setting to 0 means no further alt refs pending). + rc->source_alt_ref_pending = 0; // Set the alternate reference frame active flag rc->source_alt_ref_active = 1; @@ -1044,8 +1055,13 @@ static void update_golden_frame_stats(VP9_COMP *cpi) { // this frame refreshes means next frames don't unless specified by user rc->frames_since_golden = 0; - if (!rc->source_alt_ref_pending) + if (cpi->pass == 2) { + if (!rc->source_alt_ref_pending && + cpi->twopass.gf_group.rf_level[0] == GF_ARF_STD) + rc->source_alt_ref_active = 0; + } else if (!rc->source_alt_ref_pending) { rc->source_alt_ref_active = 0; + } // Decrement count down till next gf if (rc->frames_till_gf_update_due > 0) diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index f1a4a3f..a15235c 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -23,6 +23,15 @@ extern "C" { // Bits Per MB at different Q (Multiplied by 512) #define BPER_MB_NORMBITS 9 +typedef enum { + INTER_NORMAL = 0, + INTER_HIGH = 1, + GF_ARF_LOW = 2, + GF_ARF_STD = 3, + KF_STD = 4, + RATE_FACTOR_LEVELS = 5 +} RATE_FACTOR_LEVEL; + typedef struct { // Rate targetting variables int base_frame_target; // A baseline frame target before adjustment @@ -37,9 +46,7 @@ typedef struct { int last_boost; int kf_boost; - double rate_correction_factor; - double key_frame_rate_correction_factor; - double gf_rate_correction_factor; + double rate_correction_factors[RATE_FACTOR_LEVELS]; int frames_since_golden; int frames_till_gf_update_due; diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index 1b99575..84f3449 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -31,6 +31,7 @@ void vp9_init_layer_context(VP9_COMP *const cpi) { for (layer = 0; layer < layer_end; ++layer) { LAYER_CONTEXT *const lc = &svc->layer_context[layer]; RATE_CONTROL *const lrc = &lc->rc; + int i; lc->current_video_frame_in_layer = 0; lrc->avg_frame_qindex[INTER_FRAME] = oxcf->worst_allowed_q; lrc->ni_av_qi = oxcf->worst_allowed_q; @@ -42,8 +43,10 @@ void vp9_init_layer_context(VP9_COMP *const cpi) { lrc->ni_frames = 0; lrc->decimation_count = 0; lrc->decimation_factor = 0; - lrc->rate_correction_factor = 1.0; - lrc->key_frame_rate_correction_factor = 1.0; + + for (i = 0; i < RATE_FACTOR_LEVELS; ++i) { + lrc->rate_correction_factors[i] = 1.0; + } if (svc->number_temporal_layers > 1) { lc->target_bandwidth = oxcf->ts_target_bitrate[layer];