tests: Add functions usable by all tests

This makes the tests much, much easier to modify and add new tests.
This commit is contained in:
Joni Räsänen 2022-03-04 10:18:14 +02:00
parent c3c16731ba
commit 227da23d34
6 changed files with 201 additions and 369 deletions

View File

@ -12,6 +12,7 @@ target_sources(${PROJECT_NAME}
test_3_rtcp.cpp
test_4_formats.cpp
test_5_srtp_zrtp.cpp
test_common.hh
)
if(MSVC)

View File

@ -1,7 +1,9 @@
#include "uvgrtp/lib.hh"
#include <gtest/gtest.h>
#include "test_common.hh"
// TODO: 1) Test only sending, 2) test sending with different configuration, 3) test receiving with different configurations, and
// 4) test sending and receiving within same test while checking frame size
// parameters for this test. You can change these to suit your network environment
constexpr uint16_t LOCAL_PORT = 9300;
@ -9,7 +11,6 @@ constexpr char REMOTE_ADDRESS[] = "127.0.0.1";
constexpr uint16_t REMOTE_PORT = 9302;
void rtp_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame);
void cleanup(uvgrtp::context& ctx, uvgrtp::session* sess, uvgrtp::media_stream* ms);
void process_rtp_frame(uvgrtp::frame::rtp_frame* frame);
void test_wait(int time_ms, uvgrtp::media_stream* receiver)
@ -17,7 +18,8 @@ void test_wait(int time_ms, uvgrtp::media_stream* receiver)
uvgrtp::frame::rtp_frame* frame = nullptr;
auto start = std::chrono::high_resolution_clock::now();
frame = receiver->pull_frame(time_ms);
int actual_difference = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count();
int actual_difference =
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count();
EXPECT_EQ(RTP_OK, rtp_errno);
EXPECT_GE(actual_difference, time_ms);
@ -27,91 +29,6 @@ void test_wait(int time_ms, uvgrtp::media_stream* receiver)
process_rtp_frame(frame);
}
class Test_receiver
{
public:
Test_receiver(int expectedPackets):
receivedPackets_(0),
expectedPackets_(expectedPackets)
{}
void receive()
{
++receivedPackets_;
}
bool gotAll()
{
return receivedPackets_ == expectedPackets_;
}
private:
int receivedPackets_;
int expectedPackets_;
};
// TODO: 1) Test only sending, 2) test sending with different configuration, 3) test receiving with different configurations, and
// 4) test sending and receiving within same test while checking frame size
TEST(RTPTests, send_too_much)
{
// Tests sending large amounts of data to make sure nothing breaks because of it
// TODO: Everything should actually be received even in this case but it probably isn't at the moment
std::cout << "Starting RTP send too much test" << std::endl;
uvgrtp::context ctx;
uvgrtp::session* sess = ctx.create_session(REMOTE_ADDRESS);
uvgrtp::media_stream* sender = nullptr;
uvgrtp::media_stream* receiver = nullptr;
int flags = RTP_NO_FLAGS;
EXPECT_NE(nullptr, sess);
if (sess)
{
sender = sess->create_stream(LOCAL_PORT, REMOTE_PORT, RTP_FORMAT_H265, flags);
receiver = sess->create_stream(REMOTE_PORT, LOCAL_PORT, RTP_FORMAT_H265, flags);
}
EXPECT_NE(nullptr, receiver);
if (receiver)
{
std::cout << "Installing hook" << std::endl;
EXPECT_EQ(RTP_OK, receiver->install_receive_hook(nullptr, rtp_receive_hook));
}
EXPECT_NE(nullptr, sender);
if (sender)
{
std::cout << "Starting to send data" << std::endl;
int packets = 4000;
for (unsigned int i = 0; i < packets; ++i)
{
const int frame_size = 200000;
std::unique_ptr<uint8_t[]> dummy_frame = std::unique_ptr<uint8_t[]>(new uint8_t[frame_size]);
if (sender->push_frame(std::move(dummy_frame), frame_size, RTP_NO_FLAGS) != RTP_OK)
{
std::cout << "Failed to send RTP frame!" << std::endl;
}
if (i % (packets/10) == packets/10 - 1)
{
std::cout << "Sent " << (i + 1) * 100 / packets << " % of data" << std::endl;
}
}
sess->destroy_stream(sender);
sender = nullptr;
}
cleanup(ctx, sess, receiver);
}
TEST(RTPTests, rtp_hook)
{
// Tests installing a hook to uvgRTP
@ -127,16 +44,10 @@ TEST(RTPTests, rtp_hook)
receiver = sess->create_stream(LOCAL_PORT, REMOTE_PORT, RTP_FORMAT_H265, flags);
}
if (receiver)
{
std::cout << "Installing hook" << std::endl;
EXPECT_EQ(RTP_OK, receiver->install_receive_hook(nullptr, rtp_receive_hook));
}
add_hook(receiver, rtp_receive_hook);
EXPECT_NE(nullptr, sess);
EXPECT_NE(nullptr, receiver);
cleanup(ctx, sess, receiver);
cleanup_ms(sess, receiver);
cleanup_sess(ctx, sess);
}
TEST(RTPTests, rtp_poll)
@ -148,7 +59,7 @@ TEST(RTPTests, rtp_poll)
uvgrtp::media_stream* sender = nullptr;
uvgrtp::media_stream* receiver = nullptr;
int flags = RTP_NO_FLAGS;
int flags = RCE_NO_FLAGS;
EXPECT_NE(nullptr, sess);
if (sess)
@ -164,19 +75,8 @@ TEST(RTPTests, rtp_poll)
EXPECT_NE(nullptr, sender);
if (sender)
{
// TODO: This could be prettier by using functions
const int frame_size = 1500;
std::cout << "Sending " << test_packets << " test packets" << std::endl;
for (unsigned int i = 0; i < test_packets; ++i)
{
std::unique_ptr<uint8_t[]> dummy_frame = std::unique_ptr<uint8_t[]>(new uint8_t[frame_size]);
if (sender->push_frame(std::move(dummy_frame), frame_size, RTP_NO_FLAGS) != RTP_OK)
{
std::cout << "Failed to send RTP frame!" << std::endl;
}
}
send_packets(sess, sender, test_packets, frame_size, 0);
uvgrtp::frame::rtp_frame* received_frame = nullptr;
@ -204,17 +104,7 @@ TEST(RTPTests, rtp_poll)
EXPECT_EQ(received_packets_no_timeout, test_packets);
int received_packets_timout = 0;
std::cout << "Sending " << test_packets << " test packets" << std::endl;
for (unsigned int i = 0; i < test_packets; ++i)
{
std::unique_ptr<uint8_t[]> dummy_frame = std::unique_ptr<uint8_t[]>(new uint8_t[frame_size]);
if (sender->push_frame(std::move(dummy_frame), frame_size, RTP_NO_FLAGS) != RTP_OK)
{
std::cout << "Failed to send RTP frame!" << std::endl;
}
}
send_packets(sess, sender, test_packets, frame_size, 0);
std::cout << "Start pulling data with 3 ms timout" << std::endl;
@ -241,17 +131,44 @@ TEST(RTPTests, rtp_poll)
if (received_frame)
process_rtp_frame(received_frame);
sess->destroy_stream(sender);
sender = nullptr;
}
std::cout << "Finished pulling data" << std::endl;
cleanup(ctx, sess, receiver);
cleanup_ms(sess, sender);
cleanup_ms(sess, receiver);
cleanup_sess(ctx, sess);
}
TEST(RTPTests, send_too_much)
{
// Tests sending large amounts of data to make sure nothing breaks because of it
// TODO: Everything should actually be received even in this case but it probably isn't at the moment
std::cout << "Starting RTP send too much test" << std::endl;
uvgrtp::context ctx;
uvgrtp::session* sess = ctx.create_session(REMOTE_ADDRESS);
uvgrtp::media_stream* sender = nullptr;
uvgrtp::media_stream* receiver = nullptr;
int flags = RTP_NO_FLAGS;
EXPECT_NE(nullptr, sess);
if (sess)
{
sender = sess->create_stream(LOCAL_PORT, REMOTE_PORT, RTP_FORMAT_H265, flags);
receiver = sess->create_stream(REMOTE_PORT, LOCAL_PORT, RTP_FORMAT_H265, flags);
}
add_hook(receiver, rtp_receive_hook);
send_packets(sess, sender, 4000, 10000, 0);
cleanup_ms(sess, sender);
cleanup_ms(sess, receiver);
cleanup_sess(ctx, sess);
}
void rtp_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame)
@ -265,19 +182,6 @@ void rtp_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame)
process_rtp_frame(frame);
}
void cleanup(uvgrtp::context& ctx, uvgrtp::session* sess, uvgrtp::media_stream* ms)
{
if (ms)
{
sess->destroy_stream(ms);
}
if (sess)
{
ctx.destroy_session(sess);
}
}
void process_rtp_frame(uvgrtp::frame::rtp_frame* frame)
{

View File

@ -1,5 +1,4 @@
#include "uvgrtp/lib.hh"
#include <gtest/gtest.h>
#include "test_common.hh"
constexpr char LOCAL_INTERFACE[] = "127.0.0.1";
constexpr uint16_t LOCAL_PORT = 9200;
@ -15,13 +14,9 @@ constexpr int PACKET_INTERVAL_MS = 1000 / FRAME_RATE;
void receiver_hook(uvgrtp::frame::rtcp_receiver_report* frame);
void sender_hook(uvgrtp::frame::rtcp_sender_report* frame);
void wait_until_next_frame(std::chrono::steady_clock::time_point& start, int frame_index);
void cleanup(uvgrtp::context& ctx, uvgrtp::session* local_session, uvgrtp::session* remote_session,
uvgrtp::media_stream* send, uvgrtp::media_stream* receive);
TEST(RTCPTests, rtcp) {
std::cout << "Starting uvgRTP RTCP tests" << std::endl;
@ -44,9 +39,6 @@ TEST(RTCPTests, rtcp) {
remote_stream = remote_session->create_stream(REMOTE_PORT, LOCAL_PORT, RTP_FORMAT_GENERIC, flags);
}
EXPECT_NE(nullptr, local_session);
EXPECT_NE(nullptr, remote_session);
EXPECT_NE(nullptr, local_stream);
EXPECT_NE(nullptr, remote_stream);
if (local_stream)
@ -59,31 +51,13 @@ TEST(RTCPTests, rtcp) {
EXPECT_EQ(RTP_OK, remote_stream->get_rtcp()->install_sender_hook(sender_hook));
}
if (local_stream)
{
uint8_t buffer[PAYLOAD_LEN] = { 0 };
memset(buffer, 'a', PAYLOAD_LEN);
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
for (unsigned int i = 0; i < SEND_TEST_PACKETS; ++i)
{
EXPECT_EQ(RTP_OK, local_stream->push_frame((uint8_t*)buffer, PAYLOAD_LEN, RTP_NO_FLAGS));
if (i % (SEND_TEST_PACKETS/10) == SEND_TEST_PACKETS/10 - 1)
{
std::cout << "Sent " << (i + 1) * 100 / SEND_TEST_PACKETS << " % of data" << std::endl;
}
wait_until_next_frame(start, i);
}
}
send_packets(local_session, local_stream, SEND_TEST_PACKETS, PAYLOAD_LEN, PACKET_INTERVAL_MS);
cleanup(ctx, local_session, remote_session, local_stream, remote_stream);
}
TEST(RTCP_reopen_receiver, rtcp) {
std::cout << "Starting uvgRTP RTCP tests" << std::endl;
std::cout << "Starting uvgRTP RTCP reopen receiver test" << std::endl;
// Creation of RTP stream. See sending example for more details
uvgrtp::context ctx;
@ -104,9 +78,6 @@ TEST(RTCP_reopen_receiver, rtcp) {
remote_stream = remote_session->create_stream(REMOTE_PORT, LOCAL_PORT, RTP_FORMAT_GENERIC, flags);
}
EXPECT_NE(nullptr, local_session);
EXPECT_NE(nullptr, remote_session);
EXPECT_NE(nullptr, local_stream);
EXPECT_NE(nullptr, remote_stream);
if (local_stream)
@ -121,25 +92,8 @@ TEST(RTCP_reopen_receiver, rtcp) {
if (local_stream)
{
uint8_t buffer[PAYLOAD_LEN] = { 0 };
memset(buffer, 'a', PAYLOAD_LEN);
send_packets(local_session, local_stream, SEND_TEST_PACKETS/2, PAYLOAD_LEN, PACKET_INTERVAL_MS);
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
for (unsigned int i = 0; i < SEND_TEST_PACKETS; ++i)
{
EXPECT_EQ(RTP_OK, local_stream->push_frame((uint8_t*)buffer, PAYLOAD_LEN, RTP_NO_FLAGS));
wait_until_next_frame(start, i);
if (i % (SEND_TEST_PACKETS/10) == SEND_TEST_PACKETS/10 - 1)
{
std::cout << "Sent " << (i + 1) * 100 / SEND_TEST_PACKETS << " % of data" << std::endl;
}
if (i == SEND_TEST_PACKETS/2)
{
if (remote_stream)
{
std::cout << "Closing and reopening receiver for testing purposes" << std::endl;
@ -147,8 +101,8 @@ TEST(RTCP_reopen_receiver, rtcp) {
remote_stream = remote_session->create_stream(REMOTE_PORT, LOCAL_PORT, RTP_FORMAT_GENERIC, flags);
EXPECT_NE(nullptr, remote_stream);
}
}
}
send_packets(local_session, local_stream, SEND_TEST_PACKETS / 2, PAYLOAD_LEN, PACKET_INTERVAL_MS);
}
cleanup(ctx, local_session, remote_session, local_stream, remote_stream);
@ -179,9 +133,6 @@ TEST(RTCP_double_bind_test, rtcp) {
remote_stream = remote_session->create_stream(LOCAL_PORT, REMOTE_PORT, RTP_FORMAT_GENERIC, flags);
}
EXPECT_NE(nullptr, local_session);
EXPECT_NE(nullptr, remote_session);
EXPECT_NE(nullptr, local_stream);
EXPECT_EQ(nullptr, remote_stream);
cleanup(ctx, local_session, remote_session, local_stream, remote_stream);
@ -232,41 +183,13 @@ void sender_hook(uvgrtp::frame::rtcp_sender_report* frame)
delete frame;
}
void wait_until_next_frame(std::chrono::steady_clock::time_point& start, int frame_index)
{
// wait until it is time to send the next frame. Simulates a steady sending pace
// and included only for demostration purposes since you can use uvgRTP to send
// packets as fast as desired
auto time_since_start = std::chrono::steady_clock::now() - start;
auto next_frame_time = (frame_index + 1) * std::chrono::milliseconds(PACKET_INTERVAL_MS);
if (next_frame_time > time_since_start)
{
std::this_thread::sleep_for(next_frame_time - time_since_start);
}
}
void cleanup(uvgrtp::context& ctx, uvgrtp::session* local_session, uvgrtp::session* remote_session,
uvgrtp::media_stream* send, uvgrtp::media_stream* receive)
{
if (send)
{
local_session->destroy_stream(send);
}
if (receive)
{
remote_session->destroy_stream(receive);
}
if (local_session)
{
// Session must be destroyed manually
ctx.destroy_session(local_session);
}
if (remote_session)
{
// Session must be destroyed manually
ctx.destroy_session(remote_session);
cleanup_ms(local_session, send);
if (receive) {
cleanup_ms(remote_session, receive);
}
cleanup_sess(ctx, local_session);
cleanup_sess(ctx, remote_session);
}

View File

@ -1,5 +1,4 @@
#include "uvgrtp/lib.hh"
#include <gtest/gtest.h>
#include "test_common.hh"
constexpr uint16_t SEND_PORT = 9100;
constexpr char LOCAL_ADDRESS[] = "127.0.0.1";
@ -10,7 +9,6 @@ constexpr size_t PAYLOAD_LEN = 100;
void format_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame);
void cleanup_formats(uvgrtp::context& ctx, uvgrtp::session* sess, uvgrtp::media_stream* ms);
void process_format_frame(uvgrtp::frame::rtp_frame* frame);
@ -32,36 +30,12 @@ TEST(FormatTests, h264)
receiver = sess->create_stream(RECEIVE_PORT, SEND_PORT, RTP_FORMAT_H264, flags);
}
if (receiver)
{
std::cout << "Installing hook" << std::endl;
EXPECT_EQ(RTP_OK, receiver->install_receive_hook(nullptr, format_receive_hook));
}
add_hook(receiver, format_receive_hook);
send_packets(sess, sender, AMOUNT_OF_TEST_PACKETS, PAYLOAD_LEN, 0);
if (sender)
{
for (int i = 0; i < AMOUNT_OF_TEST_PACKETS; ++i)
{
std::unique_ptr<uint8_t[]> dummy_frame = std::unique_ptr<uint8_t[]>(new uint8_t[PAYLOAD_LEN]);
if ((i + 1) % 10 == 0 || i == 0) // print every 10 frames and first
std::cout << "Sending frame " << i + 1 << '/' << AMOUNT_OF_TEST_PACKETS << std::endl;
if (sender->push_frame(std::move(dummy_frame), PAYLOAD_LEN, RTP_NO_FLAGS) != RTP_OK)
{
std::cout << "Failed to send RTP frame!" << std::endl;
}
}
EXPECT_NE(nullptr, sender);
sess->destroy_stream(sender);
sender = nullptr;
}
EXPECT_NE(nullptr, sess);
EXPECT_NE(nullptr, receiver);
cleanup_formats(ctx, sess, receiver);
cleanup_ms(sess, sender);
cleanup_ms(sess, receiver);
cleanup_sess(ctx, sess);
}
TEST(FormatTests, h265)
@ -80,36 +54,12 @@ TEST(FormatTests, h265)
receiver = sess->create_stream(RECEIVE_PORT, SEND_PORT, RTP_FORMAT_H265, flags);
}
if (receiver)
{
std::cout << "Installing hook" << std::endl;
EXPECT_EQ(RTP_OK, receiver->install_receive_hook(nullptr, format_receive_hook));
}
add_hook(receiver, format_receive_hook);
send_packets(sess, sender, AMOUNT_OF_TEST_PACKETS, PAYLOAD_LEN, 0);
if (sender)
{
for (int i = 0; i < AMOUNT_OF_TEST_PACKETS; ++i)
{
std::unique_ptr<uint8_t[]> dummy_frame = std::unique_ptr<uint8_t[]>(new uint8_t[PAYLOAD_LEN]);
if ((i + 1) % 10 == 0 || i == 0) // print every 10 frames and first
std::cout << "Sending frame " << i + 1 << '/' << AMOUNT_OF_TEST_PACKETS << std::endl;
if (sender->push_frame(std::move(dummy_frame), PAYLOAD_LEN, RTP_NO_FLAGS) != RTP_OK)
{
std::cout << "Failed to send RTP frame!" << std::endl;
}
}
EXPECT_NE(nullptr, sender);
sess->destroy_stream(sender);
sender = nullptr;
}
EXPECT_NE(nullptr, sess);
EXPECT_NE(nullptr, receiver);
cleanup_formats(ctx, sess, receiver);
cleanup_ms(sess, sender);
cleanup_ms(sess, receiver);
cleanup_sess(ctx, sess);
}
TEST(FormatTests, h266)
@ -128,36 +78,12 @@ TEST(FormatTests, h266)
receiver = sess->create_stream(RECEIVE_PORT, SEND_PORT, RTP_FORMAT_H266, flags);
}
if (receiver)
{
std::cout << "Installing hook" << std::endl;
EXPECT_EQ(RTP_OK, receiver->install_receive_hook(nullptr, format_receive_hook));
}
add_hook(receiver, format_receive_hook);
send_packets(sess, sender, AMOUNT_OF_TEST_PACKETS, PAYLOAD_LEN, 0);
if (sender)
{
for (int i = 0; i < AMOUNT_OF_TEST_PACKETS; ++i)
{
std::unique_ptr<uint8_t[]> dummy_frame = std::unique_ptr<uint8_t[]>(new uint8_t[PAYLOAD_LEN]);
if ((i + 1) % 10 == 0 || i == 0) // print every 10 frames and first
std::cout << "Sending frame " << i + 1 << '/' << AMOUNT_OF_TEST_PACKETS << std::endl;
if (sender->push_frame(std::move(dummy_frame), PAYLOAD_LEN, RTP_NO_FLAGS) != RTP_OK)
{
std::cout << "Failed to send RTP frame!" << std::endl;
}
}
EXPECT_NE(nullptr, sender);
sess->destroy_stream(sender);
sender = nullptr;
}
EXPECT_NE(nullptr, sess);
EXPECT_NE(nullptr, receiver);
cleanup_formats(ctx, sess, receiver);
cleanup_ms(sess, sender);
cleanup_ms(sess, receiver);
cleanup_sess(ctx, sess);
}
void format_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame)
@ -165,19 +91,6 @@ void format_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame)
process_format_frame(frame);
}
void cleanup_formats(uvgrtp::context& ctx, uvgrtp::session* sess, uvgrtp::media_stream* ms)
{
if (ms)
{
sess->destroy_stream(ms);
}
if (sess)
{
ctx.destroy_session(sess);
}
}
void process_format_frame(uvgrtp::frame::rtp_frame* frame)
{
std::cout << "Receiving frame with seq: " << frame->header.seq

View File

@ -1,5 +1,4 @@
#include "uvgrtp/lib.hh"
#include <gtest/gtest.h>
#include "test_common.hh"
// network parameters of example
@ -35,29 +34,15 @@ TEST(EncryptionTests, no_send_user)
receiver = user_initialization(ctx, SRTP_256, sender_session, send);
// All media is now encrypted/decrypted automatically
char* message = (char*)"Hello, world!";
size_t msg_len = strlen(message);
if (send)
{
auto start = std::chrono::steady_clock::now();
for (unsigned int i = 0; i < 10; ++i)
{
EXPECT_EQ(RTP_OK, send->push_frame((uint8_t*)message, msg_len, RTP_NO_FLAGS));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
sender_session->destroy_stream(send);
send_packets(sender_session, send, 10, strlen((char*)"Hello, world!"), 10);
cleanup_ms(sender_session, send);
if (receiver && receiver->joinable())
{
receiver->join();
}
if (sender_session)
ctx.destroy_session(sender_session);
cleanup_sess(ctx, sender_session);
}
std::unique_ptr<std::thread> user_initialization(uvgrtp::context& ctx, Key_length sha,
@ -111,9 +96,6 @@ void receive_func(uint8_t key[KEY_SIZE_BYTES], uint8_t salt[SALT_SIZE_BYTES])
recv = receiver_session->create_stream(REMOTE_PORT, LOCAL_PORT, RTP_FORMAT_GENERIC, flags);
}
EXPECT_NE(nullptr, receiver_session);
EXPECT_NE(nullptr, recv);
if (recv)
{
recv->add_srtp_ctx(key, salt);
@ -135,15 +117,8 @@ void receive_func(uint8_t key[KEY_SIZE_BYTES], uint8_t salt[SALT_SIZE_BYTES])
}
}
if (recv)
{
receiver_session->destroy_stream(recv);
}
if (receiver_session)
{
ctx.destroy_session(receiver_session);
}
cleanup_ms(receiver_session, recv);
cleanup_sess(ctx, receiver_session);
}
void process_frame(uvgrtp::frame::rtp_frame* frame)

116
test/test_common.hh Normal file
View File

@ -0,0 +1,116 @@
#pragma once
#include <gtest/gtest.h>
#include "uvgrtp/lib.hh"
void wait_until_next_frame(std::chrono::steady_clock::time_point& start,
int frame_index, int packet_interval_ms);
inline void send_packets(uvgrtp::session* sess, uvgrtp::media_stream* sender,
int packets, size_t size, int packet_interval_ms);
inline void add_hook(uvgrtp::media_stream* receiver, void (*hook)(void*, uvgrtp::frame::rtp_frame*));
inline void cleanup_sess(uvgrtp::context& ctx, uvgrtp::session* sess);
inline void cleanup_ms(uvgrtp::session* sess, uvgrtp::media_stream* ms);
class Test_receiver
{
public:
Test_receiver(int expectedPackets) :
receivedPackets_(0),
expectedPackets_(expectedPackets)
{}
void receive()
{
++receivedPackets_;
}
bool gotAll()
{
return receivedPackets_ == expectedPackets_;
}
private:
int receivedPackets_;
int expectedPackets_;
};
inline void send_packets(uvgrtp::session* sess, uvgrtp::media_stream* sender,
int packets, size_t size, int packet_interval_ms)
{
EXPECT_NE(nullptr, sess);
EXPECT_NE(nullptr, sender);
if (sess && sender)
{
std::cout << "Sending " << packets << " test packets with size " << size << std::endl;
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
for (unsigned int i = 0; i < packets; ++i)
{
std::unique_ptr<uint8_t[]> dummy_frame = std::unique_ptr<uint8_t[]>(new uint8_t[size]);
memset(dummy_frame.get(), 'a', size);
if (sender->push_frame(std::move(dummy_frame), size, RTP_NO_FLAGS) != RTP_OK)
{
std::cout << "Failed to send test packet!" << std::endl;
}
if (i % (packets / 10) == packets / 10 - 1)
{
std::cout << "Sent " << (i + 1) * 100 / packets << " % of data" << std::endl;
}
if (packet_interval_ms > 0)
{
wait_until_next_frame(start, i, packet_interval_ms);
}
}
}
}
inline void wait_until_next_frame(std::chrono::steady_clock::time_point& start, int frame_index, int packet_interval_ms)
{
// wait until it is time to send the next frame. Simulates a steady sending pace
// and included only for demostration purposes since you can use uvgRTP to send
// packets as fast as desired
auto time_since_start = std::chrono::steady_clock::now() - start;
auto next_frame_time = (frame_index + 1) * std::chrono::milliseconds(packet_interval_ms);
if (next_frame_time > time_since_start)
{
std::this_thread::sleep_for(next_frame_time - time_since_start);
}
}
inline void cleanup_sess(uvgrtp::context& ctx, uvgrtp::session* sess)
{
EXPECT_NE(nullptr, sess);
if (sess)
{
// Session must be destroyed manually
ctx.destroy_session(sess);
}
}
inline void cleanup_ms(uvgrtp::session* sess, uvgrtp::media_stream* ms)
{
EXPECT_NE(nullptr, ms);
EXPECT_NE(nullptr, sess);
if (sess && ms)
{
sess->destroy_stream(ms);
}
}
inline void add_hook(uvgrtp::media_stream* receiver,
void (*hook)(void*, uvgrtp::frame::rtp_frame*))
{
EXPECT_NE(nullptr, receiver);
if (receiver)
{
std::cout << "Installing hook" << std::endl;
EXPECT_EQ(RTP_OK, receiver->install_receive_hook(nullptr, hook));
}
}