Improve bitrate checking to accommodate non-integer and less than 1 framerates

This commit is contained in:
Miika Metsoila 2017-12-01 17:20:12 +02:00
parent 57cf92d35f
commit f64d42169f

View file

@ -434,8 +434,8 @@ int main(int argc, char *argv[])
// how many bits have been written this second? used for checking if framerate exceeds level's limits // how many bits have been written this second? used for checking if framerate exceeds level's limits
uint64_t bits_this_second = 0; 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 // 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; unsigned frames_this_second = 0;
float framerate = ((float)encoder->cfg.framerate_num) / ((float)encoder->cfg.framerate_denom); const 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);
@ -535,15 +535,36 @@ int main(int argc, char *argv[])
bitstream_length += len_out; bitstream_length += len_out;
// the level's bitrate check // the level's bitrate check
bits_this_second += len_out; frames_this_second += 1;
frames_this_second += 1.0f;
if ((float)frames_this_second >= framerate) {
// if framerate <= 1 then we go here always
// how much of the bits of the last frame belonged to the next second
uint64_t leftover_bits = (uint64_t)((double)len_out * ((double)frames_this_second - framerate));
// the latest frame is counted for the amount that it contributed to this current second
bits_this_second += len_out - leftover_bits;
if (frames_this_second >= framerate) {
if (bits_this_second > encoder->cfg.max_bitrate) { 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.", fprintf(stderr, "Level warning: This %s's bitrate (%llu bits/s) reached the maximum bitrate (%u bits/s) of %s tier level %g.",
bits_this_second, encoder->cfg.max_bitrate, encoder->cfg.high_tier?"high":"main", ((float)encoder->cfg.level) / 10.0f); framerate >= 1.0f ? "second" : "frame",
bits_this_second,
encoder->cfg.max_bitrate,
encoder->cfg.high_tier ? "high" : "main",
(float)encoder->cfg.level / 10.0f );
} }
frames_this_second -= framerate;
if (framerate > 1.0f) {
// leftovers for the next second
bits_this_second = leftover_bits;
} else {
// one or more next seconds are from this frame and their bitrate is the same or less as this frame's
bits_this_second = 0;
}
frames_this_second = 0;
} else {
bits_this_second += len_out;
} }
// Compute and print stats. // Compute and print stats.