Skip to content

Commit 3de3132

Browse files
author
Louis Fréneau
committed
Add possible input frame limiter and fps log for each gof bitstream generation
1 parent 4c8d14c commit 3de3132

File tree

6 files changed

+60
-2
lines changed

6 files changed

+60
-2
lines changed

src/app/cli.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ namespace {
5252

5353
// NOLINTNEXTLINE(cert-err58-cpp)
5454
const std::string short_options = "i:g:l:n:o:s:t:b:d:";
55-
const std::array<struct option, 14> long_options{{{"input", required_argument, nullptr, 'i'},
55+
const std::array<struct option, 15> long_options{{{"input", required_argument, nullptr, 'i'},
5656
{"output", required_argument, nullptr, 'o'},
5757
{"frames", required_argument, nullptr, 'n'},
5858
{"start-frame", required_argument, nullptr, 's'},
@@ -65,7 +65,8 @@ const std::array<struct option, 14> long_options{{{"input", required_argument, n
6565
{"version", no_argument, nullptr, 0},
6666
{"dst-address", required_argument, nullptr, 0},
6767
{"dst-port", required_argument, nullptr, 0},
68-
{"sdp-outdir", required_argument, nullptr, 0}
68+
{"sdp-outdir", required_argument, nullptr, 0},
69+
{"input-frame-per-second-limiter", required_argument, nullptr, 0}
6970
}};
7071

7172
/**
@@ -205,6 +206,10 @@ bool opts_parse(cli::opts_t& opts, const int& argc, const std::span<const char*
205206
}
206207
} else if (name == "sdp-outdir") {
207208
opts.sdpOutdir = optarg;
209+
} else if (name == "input-frame-per-second-limiter") {
210+
opts.inputFramePerSecondLimiter = std::stoi(optarg);
211+
} else {
212+
//TODO(lf): throw error ?
208213
}
209214
}
210215

src/app/cli.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ struct opts_t {
7373
std::vector<uint16_t> dstPort{};
7474
/** \brief Output directory for SDP files */
7575
std::string sdpOutdir{};
76+
/** \brief FPS limit for reading input frames */
77+
size_t inputFramePerSecondLimiter = 0; // 0 means no input frame limiter (maxConcurrentFrames can still be a limiter)
78+
7679
};
7780

7881
bool opts_parse(cli::opts_t& opts, const int& argc, const std::span<const char* const>& args);

src/app/uvgVPCCencAppExample.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ void inputReadThread(const std::shared_ptr<input_handler_args>& args) {
197197
bool run = true;
198198
const size_t totalNbFrames = appParameters.nbFrames * appParameters.nbLoops;
199199
Retval returnValue = Retval::Running;
200+
201+
// For input frame limiter
202+
double lastFrameTimeStamp = 0;
203+
200204
// Producer thread that reads input frames.
201205
while (run) {
202206
// Signal that all input frames has been load
@@ -230,6 +234,20 @@ void inputReadThread(const std::shared_ptr<input_handler_args>& args) {
230234
returnValue = Retval::Failure;
231235
}
232236

237+
if(appParameters.inputFramePerSecondLimiter != 0) {
238+
const double targetDelayMs = 1000.0 / static_cast<double>(appParameters.inputFramePerSecondLimiter);
239+
const double currentFrameStamp = uvgvpcc_enc::global_timer.elapsed(); //TODO(lf,gg): is it okay to access such library objects from the application?
240+
const double delay = currentFrameStamp - lastFrameTimeStamp;
241+
if(delay < targetDelayMs) {
242+
const double waitMs = targetDelayMs - delay;
243+
std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int>(waitMs)));
244+
lastFrameTimeStamp = currentFrameStamp + waitMs;
245+
} else {
246+
lastFrameTimeStamp = currentFrameStamp;
247+
}
248+
}
249+
250+
233251
// Signal that an item has been produced
234252
available_input_slot.acquire();
235253
args->frame_in = frame;

src/lib/bitstreamGeneration/bitstreamGeneration.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#include <string>
4141
#include <utility>
4242
#include <vector>
43+
#include <sstream>
44+
#include <iomanip>
4345

4446
#include "atlas_context.hpp"
4547
#include "bitstream_common.hpp"
@@ -58,6 +60,11 @@ void BitstreamGeneration::createV3CGOFBitstream(const std::shared_ptr<uvgvpcc_en
5860
uvgvpcc_enc::API::v3c_unit_stream* output) {
5961
uvgvpcc_enc::Logger::log<uvgvpcc_enc::LogLevel::INFO>(
6062
"BITSTREAM GENERATION", "GOF " + std::to_string(gofUVG->gofId) + " : Create V3C GOF bitstream using uvgVPCC.\n");
63+
64+
65+
66+
67+
6168

6269
v3c_gof gof(gofUVG->gofId);
6370
gof.set_n_frames(gofUVG->nbFrames);
@@ -142,4 +149,22 @@ void BitstreamGeneration::createV3CGOFBitstream(const std::shared_ptr<uvgvpcc_en
142149
}
143150

144151
output->available_chunks.release();
152+
153+
if (paramUVG.displayBitstreamGenerationFps) {
154+
static double lastStampJobCreateV3CGOFBitstream = 0.0;
155+
const double currentStampJobCreateV3CGOFBitstream = global_timer.elapsed();
156+
const double ms = currentStampJobCreateV3CGOFBitstream - lastStampJobCreateV3CGOFBitstream;
157+
double fps = (static_cast<double>(gofUVG->nbFrames) * 1000.0) / ms;
158+
std::ostringstream msStream;
159+
msStream << std::fixed << std::setprecision(1) << ms;
160+
std::string msStr = msStream.str();
161+
fps = std::round(fps * 10.0) / 10.0;
162+
std::ostringstream fpsStream;
163+
fpsStream << std::fixed << std::setprecision(1) << fps;
164+
std::string fpsStr = fpsStream.str();
165+
lastStampJobCreateV3CGOFBitstream = currentStampJobCreateV3CGOFBitstream;
166+
uvgvpcc_enc::Logger::log<uvgvpcc_enc::LogLevel::INFO>(
167+
"BITSTREAM GENERATION", "GOF " + std::to_string(gofUVG->gofId) + " : Delay since last createV3CGOFBitstream: " + msStr + "ms, GOF with " + std::to_string(gofUVG->nbFrames) + " frames => " + fpsStr + "fps\n");
168+
}
169+
145170
}

src/lib/utils/parameters.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ void initializeParameterMap(Parameters& param) {
246246
{"attributeEncodingQp", {UINT, "", &param.attributeEncodingQp}},
247247
{"attributeEncodingPreset",
248248
{STRING, "ultrafast,superfast,veryfast,faster,fast,medium,slow,slower,veryslow", &param.attributeEncodingPreset}},
249+
250+
// ___ Bitstream generation ___ //
251+
{"displayBitstreamGenerationFps", {BOOL, "", &param.displayBitstreamGenerationFps}},
252+
249253
};
250254
}
251255

src/lib/utils/parameters.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ struct Parameters {
161161
size_t attributeEncodingQp;
162162
std::string attributeEncodingPreset;
163163

164+
// ___ Bitstream generation ___ //
165+
bool displayBitstreamGenerationFps = false;
166+
164167
// ___ Miscellaneous ___ //
165168
// bool useEncoderCommand = false; // lf : All mention of this parameter has been commented. This might be usefull to support command line
166169
// 2D encoder in the futur.

0 commit comments

Comments
 (0)