mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 19:24:06 +00:00
Implement level's bitrate limit checking during encoding
This commit is contained in:
parent
021fb27787
commit
57cf92d35f
17
src/cfg.c
17
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
|
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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue