139 lines
4.2 KiB
C++
139 lines
4.2 KiB
C++
#include "uvgrtp_util.h"
|
|
#include "../util/util.hh"
|
|
|
|
#include <uvgrtp/lib.hh>
|
|
#include <uvgrtp/clock.hh>
|
|
|
|
#include <cstring>
|
|
#include <algorithm>
|
|
#include <string>
|
|
|
|
constexpr float LATENCY_TEST_FPS = 30.0f;
|
|
|
|
std::chrono::high_resolution_clock::time_point frame_send_time;
|
|
|
|
size_t frames = 0;
|
|
size_t ninters = 0;
|
|
size_t nintras = 0;
|
|
|
|
size_t total = 0;
|
|
size_t total_intra = 0;
|
|
size_t total_inter = 0;
|
|
|
|
static void hook_sender(void *arg, uvg_rtp::frame::rtp_frame *frame)
|
|
{
|
|
(void)arg, (void)frame;
|
|
|
|
if (frame) {
|
|
|
|
uint64_t diff = std::chrono::duration_cast<std::chrono::microseconds>(
|
|
std::chrono::high_resolution_clock::now() - frame_send_time
|
|
).count();
|
|
|
|
switch ((frame->payload[0] >> 1) & 0x3f) {
|
|
case 19:
|
|
total += (diff / 1000);
|
|
total_intra += (diff / 1000);
|
|
nintras++, frames++;
|
|
break;
|
|
|
|
case 1:
|
|
total += (diff / 1000);
|
|
total_inter += (diff / 1000);
|
|
ninters++, frames++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
uvgrtp::context rtp_ctx;
|
|
uvgrtp::session* session = nullptr;
|
|
uvgrtp::media_stream* send = nullptr;
|
|
|
|
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(input_file, len);
|
|
|
|
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 current_frame = 0;
|
|
uint64_t chunk_size = 0;
|
|
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 (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));
|
|
}
|
|
|
|
// 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);
|
|
|
|
fprintf(stderr, "%zu: intra %lf, inter %lf, avg %lf\n",
|
|
frames,
|
|
total_intra / (float)nintras,
|
|
total_inter / (float)ninters,
|
|
total / (float)frames
|
|
);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
int main(int argc, char **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;
|
|
}
|
|
|
|
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);
|
|
} |