#include #include #include /* This example demonstrates using the configuration options of uvgRTP. * There are three types of configuration flags: RCE, RCC and RTP flags * RCE (RTP Context Enable) flags are used to enable different features * of uvgRTP and are passed when a new media_stream is created. * * RCC (RTP Context Configuration) flags can be used to modify the behavior of media * stream. They are used by calling configure_ctx-function of media_stream * and using the flag and value as parameters. * * Lastly, RTP flags can be added to modify the sending process of uvgRTP. */ /* This example implements one sender and one receiver. * These are their used interfaces and ports. You may * edit these if you wish to test this example on different machines */ constexpr char LOCAL_ADDRESS[] = "127.0.0.1"; constexpr uint16_t LOCAL_PORT = 8888; constexpr char REMOTE_ADDRESS[] = "127.0.0.1"; constexpr uint16_t REMOTE_PORT = 8890; // parameters for this example constexpr int BUFFER_SIZE_MB = 40 * 1000 * 1000; constexpr int MAX_PACKET_INTERVAL_MS = 150; constexpr size_t PAYLOAD_LEN = 4096; constexpr int SEND_TEST_PACKETS = 1000; void receive_process_hook(void *arg, uvgrtp::frame::rtp_frame *frame); void cleanup(uvgrtp::context& ctx, uvgrtp::session *local_session, uvgrtp::session *remote_session, uvgrtp::media_stream *send, uvgrtp::media_stream *receive); int main(void) { std::cout << "Starting uvgRTP configuration example" << std::endl; /* Some of the functionality of uvgRTP can be enabled or disabled using RCE_* flags. * * For example, here the created MediaStream object has RTCP enabled, * does not utilize system call clustering to reduce the possibility of packet dropping */ int send_flags = RCE_RTCP | /* enable RTCP */ RCE_SYSTEM_CALL_CLUSTERING | /* Enable system call clustering (only Linux) */ RCE_SEND_ONLY; /* interpret address/port as destination address/port */ /* Prepends a 4-byte HEVC start code (0x00000001) before each NAL unit. * This way the stream can be saved into a file and played by a media player */ int receive_flags = RCE_RTCP | /* enable RTCP */ RCE_RECEIVE_ONLY; /* interpret address/port as binding interface */ uvgrtp::context ctx; uvgrtp::session *local_session = ctx.create_session(REMOTE_ADDRESS); uvgrtp::media_stream *send = local_session->create_stream(REMOTE_PORT, RTP_FORMAT_H265, send_flags); uvgrtp::session *remote_session = ctx.create_session(REMOTE_ADDRESS); uvgrtp::media_stream *receive = remote_session->create_stream(REMOTE_PORT, RTP_FORMAT_H265, receive_flags); if (receive) { /* uvgRTP context can also be configured using RCC_* flags * These flags do not enable/disable functionality but alter default behaviour of uvgRTP * * For example, here UDP receive buffer is increased to BUFFER_SIZE_MB * and frame delay is set PACKET_MAX_DELAY_MS to allow frames to arrive a little late */ receive->configure_ctx(RCC_UDP_RCV_BUF_SIZE, BUFFER_SIZE_MB); receive->configure_ctx(RCC_RING_BUFFER_SIZE, BUFFER_SIZE_MB); receive->configure_ctx(RCC_PKT_MAX_DELAY, MAX_PACKET_INTERVAL_MS); // set the MTU size of expected packets receive->configure_ctx(RCC_MTU_SIZE, 1400); // Change the payload number used in RTP header receive->configure_ctx(RCC_DYN_PAYLOAD_TYPE, 120); // install receive hook for asynchronous reception receive->install_receive_hook(nullptr, receive_process_hook); } else { std::cerr << "Failed to create the receiver!" << std::endl; cleanup(ctx, local_session, remote_session, send, receive); return EXIT_FAILURE; } if (send) { /* Here, the UDP send buffer is increased to BUFFER_SIZE_MB */ send->configure_ctx(RCC_UDP_SND_BUF_SIZE, BUFFER_SIZE_MB); receive->configure_ctx(RCC_DYN_PAYLOAD_TYPE, 120); /* Set the MTU size to what you expect the network to support (uvgRTP substracts UDP and IP headers from this number) */ send->configure_ctx(RCC_MTU_SIZE, 1400); for (int i = 0; i < SEND_TEST_PACKETS; ++i) { auto buffer = std::unique_ptr(new uint8_t[PAYLOAD_LEN]); memset(buffer.get(), 'a', PAYLOAD_LEN); memset(buffer.get(), 0, 3); memset(buffer.get() + 3, 1, 1); memset(buffer.get() + 4, 1, (19 << 1)); // Intra frame if ((i+1)%10 == 0 || i == 0) // print every 10 frames and first std::cout << "Sending frame " << i + 1 << '/' << SEND_TEST_PACKETS << std::endl; if (send->push_frame(std::move(buffer), PAYLOAD_LEN, RTP_NO_FLAGS) != RTP_OK) { std::cerr << "Failed to send RTP frame!" << std::endl; cleanup(ctx, local_session, remote_session, send, receive); return EXIT_FAILURE; } } } cleanup(ctx, local_session, remote_session, send, receive); return EXIT_SUCCESS; } void receive_process_hook(void *arg, uvgrtp::frame::rtp_frame *frame) { std::cout << "Received frame. Payload size: " << frame->payload_len << std::endl; uvgrtp::frame::dealloc_frame(frame); } 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); } }