Update latency benchmarks to use command line parameters

This commit is contained in:
Joni Räsänen 2021-11-23 14:50:18 +02:00
parent fa99d5f697
commit a011bde424
7 changed files with 140 additions and 113 deletions

View File

@ -200,29 +200,29 @@ sub recv_generic {
print "End netcat receiver\n";
}
sub lat_send {
sub send_latency {
print "Latency send benchmark\n";
my ($lib, $file, $addr, $port) = @_;
my ($lib, $file, $saddr, $raddr, $port, $fps, $iter, $format, $srtp) = @_;
my ($socket, $remote, $data);
$socket = mk_ssock($addr, $port);
$socket = mk_ssock($saddr, $port);
$remote = $socket->accept();
for ((1 .. 100)) {
for ((1 .. $iter)) {
$remote->recv($data, 16);
system ("./$lib/latency_sender >> $lib/results/latencies 2>&1");
system ("./$lib/latency_sender $file $saddr $port $raddr $port $fps $format $srtp>> $lib/results/latencies 2>&1");
}
print "Latency send benchmark finished\n";
}
sub lat_recv {
sub recv_latency {
print "Latency receive benchmark\n";
my ($lib, $addr, $port) = @_;
my $socket = mk_rsock($addr, $port);
my ($lib, $saddr, $raddr, $port, $iter, $format, $srtp) = @_;
my $socket = mk_rsock($saddr, $port);
for ((1 .. 100)) {
for ((1 .. $iter)) {
$socket->send("start");
system ("./$lib/latency_receiver 2>&1 >/dev/null");
system ("./$lib/latency_receiver $raddr $port $saddr $port $format $srtp 2>&1 >/dev/null");
sleep 2;
}
print "Latency receive benchmark finished\n";
@ -236,7 +236,7 @@ sub print_help {
. "\t--file <test filename>\n"
. "\t--saddr <sender address>\n"
. "\t--raddr <receiver address>\n"
. "\t--port <server port>\n"
. "\t--port <used port>\n"
. "\t--threads <# of threads>\n"
. "\t--start <start fps>\n"
. "\t--end <end fps>\n\n";
@ -244,8 +244,10 @@ sub print_help {
print "usage (latency):\n ./benchmark.pl \n"
. "\t--latency\n"
. "\t--role <send|recv>\n"
. "\t--addr <server address>\n"
. "\t--port <server port>\n"
. "\t--saddr <sender address>\n"
. "\t--raddr <receiver address>\n"
. "\t--port <used port>\n"
. "\t--fps <the fps at which benchmarking is done>\n"
. "\t--lib <uvgrtp|ffmpeg|live555>\n\n" and exit;
}
@ -262,7 +264,7 @@ GetOptions(
"end|e=f" => \(my $end = 0),
"step=i" => \(my $step = 0),
"use-nc|use-netcat" => \(my $nc = 0),
"framerates|fps=s" => \(my $fps = ""),
"framerate|framerates|fps=s" => \(my $fps = ""),
"latency|lat" => \(my $lat = 0),
"srtp" => \(my $srtp = 0),
"exec=s" => \(my $exec = "default"),
@ -282,6 +284,7 @@ die "Please specify role with --role" if !$role;
die "library not supported\n" if !grep (/$lib/, ("uvgrtp", "ffmpeg", "live555"));
die "format not supported\n" if !grep (/$format/, ("hevc", "vvc", "h265", "h266"));
$fps = 30.0 if $lat and !$fps;
my @fps_vals = ();
@ -315,7 +318,7 @@ if ($role eq "send" or $role eq "sender") {
if ($lat) {
system "make $lib" . "_latency_sender";
lat_send($lib, $file, $raddr, $port);
send_latency($lib, $file, $saddr, $raddr, $port, $fps, $iter, $format, $srtp);
} else {
if ($exec eq "default") {
system "make $lib" . "_sender";
@ -328,7 +331,7 @@ if ($role eq "send" or $role eq "sender") {
if ($lat) {
system "make $lib" . "_latency_receiver";
lat_recv($lib, $saddr, $port);
recv_latency($lib, $saddr, $raddr, $port, $iter, $format, $srtp);
} elsif (!$nc) {
if ($exec eq "default") {
system "make $lib" . "_receiver";

View File

@ -129,4 +129,27 @@ void write_send_results_to_file(const std::string& filename,
result_file << bytes << " bytes, " << bytes / 1000 << " kB, " << bytes / 1000000 << " MB took "
<< diff << " ms " << diff / 1000 << " s" << std::endl;
result_file.close();
}
bool get_srtp_state(std::string srtp)
{
if (srtp == "1" || srtp == "yes" || srtp == "y" || srtp == "srtp")
{
return true;
}
return false;
}
bool get_vvc_state(std::string format)
{
if (format == "vvc" || format == "h266")
{
return true;
}
else if (format != "hevc" && format != "h265")
{
std::cerr << "Unsupported sender format: " << format << std::endl;
}
return false;
}

View File

@ -12,4 +12,8 @@ void* get_mem(std::string filename, size_t& len);
int get_next_frame_start(uint8_t* data, uint32_t offset, uint32_t data_len, uint8_t& start_len);
void write_send_results_to_file(const std::string& filename,
const size_t bytes, const uint64_t diff);
const size_t bytes, const uint64_t diff);
bool get_srtp_state(std::string srtp);
bool get_vvc_state(std::string format);

View File

@ -1,4 +1,5 @@
#include "uvgrtp_util.h"
#include "../util/util.hh"
#include <uvgrtp/lib.hh>
#include <uvgrtp/clock.hh>
@ -17,22 +18,23 @@ void hook_receiver(void *arg, uvg_rtp::frame::rtp_frame *frame)
nframes++;
}
int receiver(void)
int receiver(std::string local_address, int local_port, std::string remote_address, int remote_port,
bool vvc_enabled, bool srtp_enabled)
{
std::string addr("127.0.0.1");
uvgrtp::context rtp_ctx;
uvgrtp::session* session = nullptr;
uvgrtp::media_stream* receive = nullptr;
uint16_t send_port = SENDER_PORT;
uint16_t receive_port = RECEIVER_PORT;
intialize_uvgrtp(rtp_ctx, &session, &receive, addr_, addr_, receive_port, send_port, false);
intialize_uvgrtp(rtp_ctx, &session, &receive, remote_address, local_address,
local_port, remote_port, vvc_enabled, srtp_enabled);
receive->install_receive_hook(receive, hook_receiver);
// the reaceiving end is not measured in latency tests
while (nframes < EXPECTED_FRAMES)
{
std::this_thread::sleep_for(std::chrono::milliseconds(3));
}
cleanup_uvgrtp(rtp_ctx, session, receive);
@ -41,7 +43,18 @@ int receiver(void)
int main(int argc, char **argv)
{
(void)argc, (void)argv;
if (argc != 7) {
fprintf(stderr, "usage: ./%s <local address> <local port> <remote address> <remote port> \
<format> <srtp>\n", __FILE__);
return EXIT_FAILURE;
}
return receiver();
std::string local_address = argv[1];
int local_port = atoi(argv[2]);
std::string remote_address = argv[3];
int remote_port = atoi(argv[4]);
bool vvc_enabled = get_vvc_state(argv[5]);
bool srtp_enabled = get_srtp_state(argv[6]);
return receiver(local_address, local_port, remote_address, remote_port, vvc_enabled, srtp_enabled);
}

View File

@ -1,4 +1,5 @@
#include "uvgrtp_util.h"
#include "../util/util.hh"
#include <uvgrtp/lib.hh>
#include <uvgrtp/clock.hh>
@ -9,9 +10,7 @@
constexpr float LATENCY_TEST_FPS = 30.0f;
extern void* get_mem(std::string filename, size_t& len);
std::chrono::high_resolution_clock::time_point start2;
std::chrono::high_resolution_clock::time_point frame_send_time;
size_t frames = 0;
size_t ninters = 0;
@ -28,7 +27,7 @@ static void hook_sender(void *arg, uvg_rtp::frame::rtp_frame *frame)
if (frame) {
uint64_t diff = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now() - start2
std::chrono::high_resolution_clock::now() - frame_send_time
).count();
switch ((frame->payload[0] >> 1) & 0x3f) {
@ -47,64 +46,63 @@ static void hook_sender(void *arg, uvg_rtp::frame::rtp_frame *frame)
}
}
static int sender(void)
static int sender(std::string input_file, std::string local_address, int local_port,
std::string remote_address, int remote_port, float fps, bool vvc_enabled, bool srtp_enabled)
{
std::string addr("127.0.0.1");
uvgrtp::context rtp_ctx;
uvgrtp::session* session = nullptr;
uvgrtp::media_stream* send = nullptr;
uint16_t send_port = SENDER_PORT + thread_num * 2;
uint16_t receive_port = RECEIVER_PORT + thread_num * 2;
intialize_uvgrtp(rtp_ctx, session, send, addr_, addr_, send_port, receive_port, false);
uint16_t thread_local_port = local_port + thread_num * 2;
uint16_t thread_remote_port = remote_port + thread_num * 2;
intialize_uvgrtp(rtp_ctx, &session, &send, remote_address, local_address,
thread_local_port, thread_remote_port, vvc_enabled, srtp_enabled);
send->install_receive_hook(nullptr, hook_sender);
size_t len = 0;
void* mem = get_mem("test_file.hevc", len);
void* mem = get_mem(input_file, len);
if (mem == nullptr)
std::vector<uint64_t> chunk_sizes;
get_chunk_locations(get_chunk_filename(input_file), chunk_sizes);
if (mem == nullptr || chunk_sizes.empty())
{
return EXIT_FAILURE;
}
uint64_t csize = 0;
uint64_t diff = 0;
uint64_t current = 0;
uint64_t current_frame = 0;
uint64_t chunk_size = 0;
uint64_t period = (uint64_t)((1000 / LATENCY_TEST_FPS) * 1000);
uint64_t period = (uint64_t)((1000 / fps) * 1000);
size_t offset = 0;
rtp_error_t ret = RTP_OK;
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
for (int rounds = 0; rounds < 1; ++rounds) {
for (size_t offset = 0, k = 0; offset < len; ++k) {
memcpy(&chunk_size, (uint8_t *)mem + offset, sizeof(uint64_t));
offset += sizeof(uint64_t);
// record send time
start2 = std::chrono::high_resolution_clock::now();
if ((ret = send->push_frame((uint8_t *)mem + offset, chunk_size, 0)) != RTP_OK) {
fprintf(stderr, "push_frame() failed!\n");
cleanup_uvgrtp(rtp_ctx, session, send);
return EXIT_FAILURE;
}
// wait until is the time to send next latency test frame
auto runtime = (uint64_t)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now() - start
).count();
if (runtime < current * period)
std::this_thread::sleep_for(std::chrono::microseconds(current * period - runtime));
current += 1;
offset += chunk_size;
for (auto& chunk_size : chunk_sizes)
{
// record send time
frame_send_time = std::chrono::high_resolution_clock::now();
if ((ret = send->push_frame((uint8_t*)mem + offset, chunk_size, 0)) != RTP_OK) {
fprintf(stderr, "push_frame() failed!\n");
cleanup_uvgrtp(rtp_ctx, session, send);
return EXIT_FAILURE;
}
current_frame += 1;
offset += chunk_size;
// wait until is the time to send next latency test frame
auto runtime = (uint64_t)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now() - start).count();
if (runtime < current_frame * period)
std::this_thread::sleep_for(std::chrono::microseconds(current_frame * period - runtime));
}
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // just so we don't exit too soon
// just so we don't exit before last frame has arrived. Does not affect results
std::this_thread::sleep_for(std::chrono::milliseconds(100));
cleanup_uvgrtp(rtp_ctx, session, send);
@ -120,7 +118,22 @@ static int sender(void)
int main(int argc, char **argv)
{
(void)argc, (void)argv;
if (argc != 9) {
fprintf(stderr, "usage: ./%s <input file> <local address> <local port> <remote address> <remote port> \
<fps> <format> <srtp> \n", __FILE__);
return EXIT_FAILURE;
}
return sender();
}
std::string input_file = argv[1];
std::string local_address = argv[2];
int local_port = atoi(argv[3]);
std::string remote_address = argv[4];
int remote_port = atoi(argv[5]);
float fps = atof(argv[6]);
bool vvc_enabled = get_vvc_state(argv[7]);
bool srtp_enabled = get_srtp_state(argv[8]);
return sender(input_file, local_address, local_port, remote_address, remote_port, fps, vvc_enabled, srtp_enabled);
}

View File

@ -1,4 +1,5 @@
#include "uvgrtp_util.hh"
#include "../util/util.hh"
#include <uvgrtp/lib.hh>
#include <uvgrtp/clock.hh>
@ -33,28 +34,17 @@ int main(int argc, char** argv)
}
std::string local_address = argv[1];
int local_port = atoi(argv[2]);
int local_port = atoi(argv[2]);
std::string remote_address = argv[3];
int remote_port = atoi(argv[4]);
int remote_port = atoi(argv[4]);
std::cout << "Starting uvgRTP receiver tests. " << local_address << ":" << local_port
<< "<-" << remote_address << ":" << remote_port << std::endl;
int nthreads = atoi(argv[5]);
std::string format = argv[6];
bool vvc = false;
if (format == "vvc" || format == "h266")
{
vvc = true;
}
else if (format != "hevc" && format != "h265")
{
std::cerr << "Unsupported uvgRTP receiver format: " << format << std::endl;
return EXIT_FAILURE;
}
bool srtp = false; // TODO
bool vvc_enabled = get_vvc_state(argv[6]);
bool srtp_enabled = get_srtp_state(argv[7]);
thread_info = (struct thread_info*)calloc(nthreads, sizeof(*thread_info));
@ -62,7 +52,7 @@ int main(int argc, char** argv)
for (int i = 0; i < nthreads; ++i) {
threads.push_back(new std::thread(receiver_thread, i, nthreads, local_address, local_port,
remote_address, remote_port, vvc, srtp));
remote_address, remote_port, vvc_enabled, srtp_enabled));
}
// wait all the thread executions to end and delete them

View File

@ -23,37 +23,18 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
std::string input_file = argv[1];
std::string result_file = argv[2];
std::string input_file = argv[1];
std::string result_file = argv[2];
std::string local_address = argv[3];
int local_port = atoi(argv[4]);
std::string local_address = argv[3];
int local_port = atoi(argv[4]);
std::string remote_address = argv[5];
int remote_port = atoi(argv[6]);
int nthreads = atoi(argv[7]);
int fps = atoi(argv[8]);
std::string format = argv[9];
std::string srtp = argv[10];
bool vvc = false;
if (format == "vvc" || format == "h266")
{
vvc = true;
}
else if (format != "hevc" && format != "h265")
{
std::cerr << "Unsupported uvgRTP sender format: " << format << std::endl;
return EXIT_FAILURE;
}
bool srtp_enabled = false;
if (srtp == "1" || srtp == "yes" || srtp == "y" || srtp == "srtp")
{
srtp_enabled = true;
}
int nthreads = atoi(argv[7]);
int fps = atoi(argv[8]);
bool vvc_enabled = get_vvc_state(argv[9]);
bool srtp_enabled = get_srtp_state(argv[10]);
std::cout << "Starting uvgRTP sender tests. " << local_address << ":" << local_port
<< "->" << remote_address << ":" << remote_port << std::endl;
@ -75,7 +56,7 @@ int main(int argc, char **argv)
for (int i = 0; i < nthreads; ++i) {
threads.push_back(new std::thread(sender_thread, mem, local_address, local_port, remote_address,
remote_port, i, fps, vvc, srtp_enabled, result_file, chunk_sizes));
remote_port, i, fps, vvc_enabled, srtp_enabled, result_file, chunk_sizes));
}
for (unsigned int i = 0; i < threads.size(); ++i) {