From f64d42169f97ffb6b805b57d7d857c9777df3b80 Mon Sep 17 00:00:00 2001 From: Miika Metsoila Date: Fri, 1 Dec 2017 17:20:12 +0200 Subject: [PATCH] Improve bitrate checking to accommodate non-integer and less than 1 framerates --- src/encmain.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/encmain.c b/src/encmain.c index 98ed1731..e30f876a 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -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 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); + unsigned frames_this_second = 0; + 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_y = get_padding(opts->config->height); @@ -535,15 +535,36 @@ int main(int argc, char *argv[]) bitstream_length += len_out; // the level's bitrate check - bits_this_second += len_out; - frames_this_second += 1.0f; + frames_this_second += 1; + + 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) { - 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); + fprintf(stderr, "Level warning: This %s's bitrate (%llu bits/s) reached the maximum bitrate (%u bits/s) of %s tier level %g.", + 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.