Implement level's bitrate limit checking during encoding

This commit is contained in:
Miika Metsoila 2017-11-28 16:19:44 +02:00
parent 021fb27787
commit 57cf92d35f
4 changed files with 28 additions and 10 deletions

View file

@ -1252,7 +1252,8 @@ void kvz_config_process_lp_gop(kvz_config *cfg)
cfg->gop[gop.g - 1].qp_factor = 0.578; // from HM 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. * \brief Check that configuration is sensible.
@ -1460,7 +1461,7 @@ int kvz_config_validate(const kvz_config *const cfg)
return !error; 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] = { static const struct { uint32_t lsr; uint32_t lps; uint32_t main_bitrate; } LEVEL_CONSTRAINTS[13] = {
{ 552'960, 36'864, 128 }, // 1 { 552'960, 36'864, 128 }, // 1
@ -1559,17 +1560,15 @@ static int validate_hevc_level(const kvz_config *const cfg) {
// max luma picture size // max luma picture size
uint32_t max_lps = LEVEL_CONSTRAINTS[lvl_idx].lps; uint32_t max_lps = LEVEL_CONSTRAINTS[lvl_idx].lps;
// max bitrate
uint32_t max_bitrate;
if (cfg->high_tier) { if (cfg->high_tier) {
max_bitrate = HIGH_TIER_BITRATES[lvl_idx - 5] * 1000; cfg->max_bitrate = HIGH_TIER_BITRATES[lvl_idx - 5] * 1000;
} else { } 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", 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; level_error = 1;
} }
@ -1614,7 +1613,7 @@ static int validate_hevc_level(const kvz_config *const cfg) {
} }
if (cfg->force_level) { 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; return 0;
} else { } else {
return level_error; return level_error;

View file

@ -30,7 +30,6 @@
#include "kvazaar.h" #include "kvazaar.h"
/* Function definitions */ /* Function definitions */
kvz_config *kvz_config_alloc(void); kvz_config *kvz_config_alloc(void);
int kvz_config_init(kvz_config *cfg); int kvz_config_init(kvz_config *cfg);

View file

@ -431,6 +431,12 @@ int main(int argc, char *argv[])
uint32_t frames_done = 0; uint32_t frames_done = 0;
double psnr_sum[3] = { 0.0, 0.0, 0.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_x = get_padding(opts->config->width);
uint8_t padding_y = get_padding(opts->config->height); uint8_t padding_y = get_padding(opts->config->height);
@ -528,6 +534,18 @@ int main(int argc, char *argv[])
bitstream_length += len_out; 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. // Compute and print stats.
double frame_psnr[3] = { 0.0, 0.0, 0.0 }; double frame_psnr[3] = { 0.0, 0.0, 0.0 };

View file

@ -358,6 +358,8 @@ typedef struct kvz_config
uint8_t force_level; uint8_t force_level;
/** \brief Whether we use the high tier bitrates. Requires the level to be 4 or higher. */ /** \brief Whether we use the high tier bitrates. Requires the level to be 4 or higher. */
uint8_t high_tier; uint8_t high_tier;
/** \brief The maximum allowed bitrate for this level and tier. */
uint32_t max_bitrate;
} kvz_config; } kvz_config;
/** /**