From 57cf92d35f5992c3acd733b39949bc930a3ea958 Mon Sep 17 00:00:00 2001 From: Miika Metsoila Date: Tue, 28 Nov 2017 16:19:44 +0200 Subject: [PATCH] Implement level's bitrate limit checking during encoding --- src/cfg.c | 17 ++++++++--------- src/cfg.h | 1 - src/encmain.c | 18 ++++++++++++++++++ src/kvazaar.h | 2 ++ 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/cfg.c b/src/cfg.c index 22a14a5d..e3ba2654 100644 --- a/src/cfg.c +++ b/src/cfg.c @@ -1252,7 +1252,8 @@ void kvz_config_process_lp_gop(kvz_config *cfg) cfg->gop[gop.g - 1].qp_factor = 0.578; // from HM } -static int validate_hevc_level(const kvz_config *const cfg); +// forward declaration +static int validate_hevc_level(kvz_config *const cfg); /** * \brief Check that configuration is sensible. @@ -1460,7 +1461,7 @@ int kvz_config_validate(const kvz_config *const cfg) return !error; } -static int validate_hevc_level(const kvz_config *const cfg) { +static int validate_hevc_level(kvz_config *const cfg) { static const struct { uint32_t lsr; uint32_t lps; uint32_t main_bitrate; } LEVEL_CONSTRAINTS[13] = { { 552'960, 36'864, 128 }, // 1 @@ -1559,17 +1560,15 @@ static int validate_hevc_level(const kvz_config *const cfg) { // max luma picture size uint32_t max_lps = LEVEL_CONSTRAINTS[lvl_idx].lps; - // max bitrate - uint32_t max_bitrate; if (cfg->high_tier) { - max_bitrate = HIGH_TIER_BITRATES[lvl_idx - 5] * 1000; + cfg->max_bitrate = HIGH_TIER_BITRATES[lvl_idx - 5] * 1000; } else { - max_bitrate = LEVEL_CONSTRAINTS[lvl_idx].main_bitrate * 1000; + cfg->max_bitrate = LEVEL_CONSTRAINTS[lvl_idx].main_bitrate * 1000; } - if (cfg->target_bitrate > max_bitrate) { + if (cfg->target_bitrate > cfg->max_bitrate) { fprintf(stderr, "%s: target bitrate exceeds %i, which is the maximum %s tier level %g bitrate\n", - level_err_prefix, max_bitrate, cfg->high_tier?"high":"main", lvl); + level_err_prefix, cfg->max_bitrate, cfg->high_tier?"high":"main", lvl); level_error = 1; } @@ -1614,7 +1613,7 @@ static int validate_hevc_level(const kvz_config *const cfg) { } if (cfg->force_level) { - // we just wanted to print warnings, and to check the level parameter's validity + // we wanted to print warnings, not get errors return 0; } else { return level_error; diff --git a/src/cfg.h b/src/cfg.h index c719ea4a..ee2604a9 100644 --- a/src/cfg.h +++ b/src/cfg.h @@ -30,7 +30,6 @@ #include "kvazaar.h" - /* Function definitions */ kvz_config *kvz_config_alloc(void); int kvz_config_init(kvz_config *cfg); diff --git a/src/encmain.c b/src/encmain.c index 130bd198..98ed1731 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -431,6 +431,12 @@ int main(int argc, char *argv[]) uint32_t frames_done = 0; double psnr_sum[3] = { 0.0, 0.0, 0.0 }; + // how many bits have been written this second? used for checking if framerate exceeds level's limits + uint64_t bits_this_second = 0; + // the amount of frames have been encoded in this second of video. can be non-integer value if framerate is non-integer value + float frames_this_second = 0; + float framerate = ((float)encoder->cfg.framerate_num) / ((float)encoder->cfg.framerate_denom); + uint8_t padding_x = get_padding(opts->config->width); uint8_t padding_y = get_padding(opts->config->height); @@ -527,6 +533,18 @@ int main(int argc, char *argv[]) fflush(output); bitstream_length += len_out; + + // the level's bitrate check + bits_this_second += len_out; + frames_this_second += 1.0f; + + if (frames_this_second >= framerate) { + if (bits_this_second > encoder->cfg.max_bitrate) { + fprintf(stderr, "Level warning: This second's bitrate (%llu) reached the maximum bitrate (%u) of %s tier level %g.", + bits_this_second, encoder->cfg.max_bitrate, encoder->cfg.high_tier?"high":"main", ((float)encoder->cfg.level) / 10.0f); + } + frames_this_second -= framerate; + } // Compute and print stats. diff --git a/src/kvazaar.h b/src/kvazaar.h index 05ad0bf5..8dd61ce2 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -358,6 +358,8 @@ typedef struct kvz_config uint8_t force_level; /** \brief Whether we use the high tier bitrates. Requires the level to be 4 or higher. */ uint8_t high_tier; + /** \brief The maximum allowed bitrate for this level and tier. */ + uint32_t max_bitrate; } kvz_config; /**