From 037ea2b1461b372d9104ed1aae91e96afd96be44 Mon Sep 17 00:00:00 2001 From: Aaro Altonen Date: Mon, 11 May 2020 11:18:18 +0300 Subject: [PATCH] Fix best effort FPS calculations --- benchmarks/ffmpeg/sender.cc | 37 ++++++++++++++++++++++++++++++++----- benchmarks/uvgrtp/sender.cc | 29 ++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/benchmarks/ffmpeg/sender.cc b/benchmarks/ffmpeg/sender.cc index 949bb9c..7f3d969 100644 --- a/benchmarks/ffmpeg/sender.cc +++ b/benchmarks/ffmpeg/sender.cc @@ -73,10 +73,11 @@ void thread_func(void *mem, size_t len, char *addr_, int thread_num, double fps, (void)avformat_write_header(avfctx, NULL); uint64_t chunk_size, total_size; - uint64_t fpt_ms = 0; - uint64_t fsize = 0; - uint32_t frames = 0; - uint64_t diff = 0; + uint64_t fpt_ms = 0; + uint64_t fsize = 0; + uint32_t frames = 0; + uint64_t diff = 0; + uint64_t overtime = 0; std::chrono::high_resolution_clock::time_point start, end, fpts, fpte; start = std::chrono::high_resolution_clock::now(); @@ -105,8 +106,34 @@ void thread_func(void *mem, size_t len, char *addr_, int thread_num, double fps, fprintf(stderr, "too slow (%lu vs %lu): aborting!\n", diff, sleep); goto end; } + + /* We used "overtime" microseconds more than we should have, + * the next frame must be sent faster so we don't fall behind + * + * Multiple frames might have been late so the "overtime" will hold + * the amount of microseconds we have been late in total */ + overtime += diff - sleep; } else { - std::this_thread::sleep_for(std::chrono::microseconds(sleep - diff)); + /* last frame did not use our time budget so + * just sleep the time denoted by fps and continue to next frame */ + if (!overtime) { + std::this_thread::sleep_for(std::chrono::microseconds(sleep - diff)); + } else { + /* the sending of previous frame(s) took more time than it should have, + * and we're punished for it. + * + * If we send this frame fast enough and there have not been too many frames late, + * we can just sleep for whatever is left after the "overtime" is subtracted from + * our sleep time and continue sending. + * + * Otherwise, we can just update the overtime counter with our sleep time and continue */ + if (sleep - diff > overtime) { + std::this_thread::sleep_for(std::chrono::microseconds(sleep - diff - overtime)); + overtime = 0; + } else { + overtime -= (sleep - diff); + } + } } i += chunk_size; diff --git a/benchmarks/uvgrtp/sender.cc b/benchmarks/uvgrtp/sender.cc index 623a6bc..8bc7113 100644 --- a/benchmarks/uvgrtp/sender.cc +++ b/benchmarks/uvgrtp/sender.cc @@ -15,6 +15,7 @@ void thread_func(void *mem, size_t len, char *addr, int thread_num, double fps, uint64_t chunk_size = 0; uint64_t total_size = 0; uint64_t diff = 0; + uint64_t overtime = 0; rtp_error_t ret = RTP_OK; std::string addr_("10.21.25.26"); @@ -54,8 +55,34 @@ void thread_func(void *mem, size_t len, char *addr, int thread_num, double fps, fprintf(stderr, "too slow (%lu vs %lu): aborting!\n", diff, sleep); goto end; } + + /* We used "overtime" microseconds more than we should have, + * the next frame must be sent faster so we don't fall behind + * + * Multiple frames might have been late so the "overtime" will hold + * the amount of microseconds we have been late in total */ + overtime += diff - sleep; } else { - std::this_thread::sleep_for(std::chrono::microseconds(sleep - diff)); + /* last frame did not use our time budget so + * just sleep the time denoted by fps and continue to next frame */ + if (!overtime) { + std::this_thread::sleep_for(std::chrono::microseconds(sleep - diff)); + } else { + /* the sending of previous frame(s) took more time than it should have, + * and we're punished for it. + * + * If we send this frame fast enough and there have not been too many frames late, + * we can just sleep for whatever is left after the "overtime" is subtracted from + * our sleep time and continue sending. + * + * Otherwise, we can just update the overtime counter with our sleep time and continue */ + if (sleep - diff > overtime) { + std::this_thread::sleep_for(std::chrono::microseconds(sleep - diff - overtime)); + overtime = 0; + } else { + overtime -= (sleep - diff); + } + } } offset += chunk_size;