diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 7c4ca637849e4326b69339a999ac98a3544b9518..adc1b793531fe428f48dc25633b387cd39c9b2f3 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -353,13 +353,14 @@ static double simple_weight(YV12_BUFFER_CONFIG *source) { // This function returns the maximum target rate per frame. static int frame_max_bits(VP9_COMP *cpi) { int64_t max_bits = - ((int64_t)cpi->rc.av_per_frame_bandwidth * - (int64_t)cpi->oxcf.two_pass_vbrmax_section) / 100; + ((int64_t)cpi->rc.av_per_frame_bandwidth * + (int64_t)cpi->oxcf.two_pass_vbrmax_section) / 100; if (max_bits < 0) - return 0; - if (max_bits >= INT_MAX) - return INT_MAX; + max_bits = 0; + else if (max_bits > cpi->rc.max_frame_bandwidth) + max_bits = cpi->rc.max_frame_bandwidth; + return (int)max_bits; } diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 8e60bc96d2c1ed76461110ae61092e8e4b9c13a7..2bcfcd4f07a52448639c31aeab77ce29d21bfff9 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -59,6 +59,11 @@ void vp9_coef_tree_initialize(); #define DISABLE_COMPOUND_SPLIT 0x18 #define LAST_AND_INTRA_SPLIT_ONLY 0x1E +// Max rate target for 1080P and below encodes under normal circumstances +// (1920 * 1080 / (16 * 16)) * MAX_MB_RATE bits per MB +#define MAX_MB_RATE 250 +#define MAXRATE_1080P 2025000 + #if CONFIG_INTERNAL_STATS extern double vp9_calc_ssim(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, int lumamask, @@ -1093,6 +1098,9 @@ int vp9_reverse_trans(int x) { }; void vp9_new_framerate(VP9_COMP *cpi, double framerate) { + VP9_COMMON *const cm = &cpi->common; + int64_t vbr_max_bits; + if (framerate < 0.1) framerate = 30; @@ -1109,6 +1117,19 @@ void vp9_new_framerate(VP9_COMP *cpi, double framerate) { cpi->rc.min_frame_bandwidth = MAX(cpi->rc.min_frame_bandwidth, FRAME_OVERHEAD_BITS); + // A maximum bitrate for a frame is defined. + // The baseline for this aligns with HW implementations that + // can support decode of 1080P content up to a bitrate of MAX_MB_RATE bits + // per 16x16 MB (averaged over a frame). However this limit is extended if + // a very high rate is given on the command line or the the rate cannnot + // be acheived because of a user specificed max q (e.g. when the user + // specifies lossless encode. + // + vbr_max_bits = ((int64_t)cpi->rc.av_per_frame_bandwidth * + (int64_t)cpi->oxcf.two_pass_vbrmax_section) / 100; + cpi->rc.max_frame_bandwidth = + MAX(MAX((cm->MBs * MAX_MB_RATE), MAXRATE_1080P), vbr_max_bits); + // Set Maximum gf/arf interval cpi->rc.max_gf_interval = 16; @@ -2449,10 +2470,14 @@ static int recode_loop_test(VP9_COMP *cpi, int force_recode = 0; VP9_COMMON *cm = &cpi->common; - // Is frame recode allowed at all - // 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) || + // Special case trap if maximum allowed frame size exceeded. + if (cpi->rc.projected_frame_size > cpi->rc.max_frame_bandwidth) { + force_recode = 1; + + // Is frame recode allowed. + // Yes if either recode mode 1 is selected or mode 2 is selected + // and the frame is a key frame, golden frame or alt_ref_frame + } else if ((cpi->sf.recode_loop == 1) || ((cpi->sf.recode_loop == 2) && ((cm->frame_type == KEY_FRAME) || cpi->refresh_golden_frame || @@ -2630,7 +2655,8 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { "%6d %6d %5d %5d %5d %10d %10.3f" "%10.3f %8d %10d %10d %10d\n", cpi->common.current_video_frame, cpi->rc.this_frame_target, - cpi->rc.projected_frame_size, 0, + cpi->rc.projected_frame_size, + cpi->rc.projected_frame_size / cpi->common.MBs, (cpi->rc.projected_frame_size - cpi->rc.this_frame_target), (int)cpi->rc.total_target_vs_actual, (int)(cpi->oxcf.starting_buffer_level - cpi->rc.bits_off_target), @@ -2740,8 +2766,9 @@ static void encode_with_recode_loop(VP9_COMP *cpi, if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) { loop = 0; } else { - // Special case handling for forced key frames - if ((cm->frame_type == KEY_FRAME) && cpi->rc.this_key_frame_forced) { + if ((cm->frame_type == KEY_FRAME) && + cpi->rc.this_key_frame_forced && + (cpi->rc.projected_frame_size < cpi->rc.max_frame_bandwidth)) { int last_q = *q; int kf_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm)); @@ -2780,7 +2807,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, loop = *q != last_q; } else if (recode_loop_test( cpi, frame_over_shoot_limit, frame_under_shoot_limit, - *q, top_index, bottom_index)) { + *q, MAX(q_high, top_index), bottom_index)) { // Is the projected frame size out of range and are we allowed // to attempt to recode. int last_q = *q; @@ -2791,6 +2818,10 @@ static void encode_with_recode_loop(VP9_COMP *cpi, // Frame is too large if (cpi->rc.projected_frame_size > cpi->rc.this_frame_target) { + // Special case if the projected size is > the max allowed. + if (cpi->rc.projected_frame_size >= cpi->rc.max_frame_bandwidth) + q_high = cpi->rc.worst_quality; + // Raise Qlow as to at least the current value q_low = *q < q_high ? *q + 1 : q_high; @@ -2804,12 +2835,12 @@ static void encode_with_recode_loop(VP9_COMP *cpi, vp9_rc_update_rate_correction_factors(cpi, 0); *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target, - bottom_index, top_index); + bottom_index, MAX(q_high, top_index)); while (*q < q_low && retries < 10) { vp9_rc_update_rate_correction_factors(cpi, 0); *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target, - bottom_index, top_index); + bottom_index, MAX(q_high, top_index)); retries++; } } @@ -2855,7 +2886,9 @@ static void encode_with_recode_loop(VP9_COMP *cpi, } } - if (cpi->rc.is_src_frame_alt_ref) + // Special case for overlay frame. + if (cpi->rc.is_src_frame_alt_ref && + (cpi->rc.projected_frame_size < cpi->rc.max_frame_bandwidth)) loop = 0; if (loop) { diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index a5be0f424734548ff66f1d0855deb5384004bbb0..be079d8596ca9af4eb6d8e71c835a545ae585fd4 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -442,9 +442,10 @@ typedef struct { unsigned int source_alt_ref_active; unsigned int is_src_frame_alt_ref; - int per_frame_bandwidth; // Current section per frame bandwidth target - int av_per_frame_bandwidth; // Average frame size target for clip - int min_frame_bandwidth; // Minimum allocation used for any frame + int per_frame_bandwidth; // Current section per frame bandwidth target + int av_per_frame_bandwidth; // Average frame size target for clip + int min_frame_bandwidth; // Minimum allocation used for any frame + int max_frame_bandwidth; // Maximum burst rate allowed for a frame. int ni_av_qi; int ni_tot_qi; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 939a7f9983e3864deaa5020ee36958626ea3d0dc..ae1aaa32ea0aaf43d84ea5c0f91e4312440eb727 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -746,8 +746,13 @@ int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi, } else { q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target, active_best_quality, active_worst_quality); - if (q > *top_index) - q = *top_index; + if (q > *top_index) { + // Special case when we are targeting the max allowed rate + if (cpi->rc.this_frame_target >= cpi->rc.max_frame_bandwidth) + *top_index = q; + else + q = *top_index; + } } #if CONFIG_MULTIPLE_ARF // Force the quantizer determined by the coding order pattern. @@ -810,6 +815,11 @@ void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi, *frame_under_shoot_limit -= 200; if (*frame_under_shoot_limit < 0) *frame_under_shoot_limit = 0; + + // Clip to maximum allowed rate for a frame. + if (*frame_over_shoot_limit > cpi->rc.max_frame_bandwidth) { + *frame_over_shoot_limit = cpi->rc.max_frame_bandwidth; + } } } @@ -822,6 +832,10 @@ int vp9_rc_pick_frame_size_target(VP9_COMP *cpi) { else calc_pframe_target_size(cpi); + // Clip the frame target to the maximum allowed value. + if (cpi->rc.this_frame_target > cpi->rc.max_frame_bandwidth) + cpi->rc.this_frame_target = cpi->rc.max_frame_bandwidth; + // Target rate per SB64 (including partial SB64s. cpi->rc.sb64_target_rate = ((int64_t)cpi->rc.this_frame_target * 64 * 64) / (cpi->common.width * cpi->common.height);