
RtpPusher C++ library
v1.4.1
Table of contents
- Overview
- Versions
- Library files
- RtpPusher class description
- Build and connect to your project
- Example
- How to play RTP stream
- How to extract KLV data from RTP stream
Overview
RtpPusher is a C++ library that provides H264 RTP, H265 RTP, and JPEG RTP packet sending to the network. The library internally handles extracting NAL units and fragmenting them into UDP packets. The library depends on: Frame library (provides declaration of video frame object, source code included, Apache 2.0 license) and UdpSocket library (provides methods to work with UDP sockets). Also, the example application depends on VSourceFile library to read H264/H265/JPEG frames from files (source code included). The library controls the time interval between RTP packets to prevent network overload (the network bandwidth is set by the user). The library doesn’t have third-party dependencies to be installed in the OS. The library is compatible with Linux and Windows.
Versions
Table 1 - Library versions.
| Version | Release date | What’s new |
|---|---|---|
| 1.0.0 | 15.07.2024 | - First version. |
| 1.1.0 | 12.12.2024 | - Fix bugs for Windows OS. - Update code structure. - Update example. |
| 1.1.1 | 03.04.2025 | - VSourceFile submodule update for example application. |
| 1.1.2 | 22.06.2025 | - UdpSocket update. |
| 1.2.0 | 25.07.2025 | - Add H265 support. |
| 1.3.0 | 03.10.2025 | - Fix h264 streaming issues. - Add user data streaming support. |
| 1.4.0 | 17.10.2025 | - Add JPEG support. - Fix user data insertion to H265. |
| 1.4.1 | 24.10.2025 | - Fix documentaion mistake about sdp file of H265. |
Library files
The library is supplied as source code only. The user will be given a set of files in the form of a CMake project (repository). The repository structure is shown below:
CMakeLists.txt ------------- Main CMake file of the library.
3rdparty ------------------- Folder with third-party libraries.
CMakeLists.txt --------- CMake file to include third-party libraries.
Frame ------------------ Folder with Frame library source code.
UdpSocket -------------- Folder with UdpSocket library source code.
src ------------------------ Folder with library source code.
CMakeLists.txt --------- CMake file of the library.
RtpPusher.h ------------ Main library header file.
RtpPusher.cpp ---------- C++ implementation file.
RtpPusherVersion.h ----- Header file with library version.
RtpPusherVersion.h.in -- CMake service file to generate version header.
example -------------------- Folder with test application files.
CMakeLists.txt --------- CMake file for example application.
main.cpp --------------- Source C++ file of example application.
3rdparty --------------- Folder with third-party libraries.
CMakeLists.txt ----- CMake file to include third-party libraries.
VSourceFile -------- Folder with VSourceFile library source code.
RtpPusher class description
RtpPusher class declaration
The RtpPusher.h file contains the RtpPusher class declaration:
namespace cr
{
namespace rtp
{
/// RTP pusher class.
class RtpPusher
{
public:
/// Get string of current library version.
static std::string getVersion();
/// Class constructor.
RtpPusher();
/// Class destructor.
~RtpPusher();
/// Init video streamer by set of parameters.
bool init(std::string ip,
uint16_t port,
int bandwidthKbps = 1000000,
int maxPayloadSize = 1420,
uint16_t metadataPort = 0);
/// Get init status.
bool isInit();
/// Close video streamer.
void close();
/// Send frame to video streamer.
bool sendFrame(cr::video::Frame &frame, uint8_t *userData = nullptr, size_t userDataSize = 0);
};
}
}
getVersion method
The getVersion() method returns a string of the current version of the RtpPusher class. Method declaration:
static std::string getVersion();
The method can be used without an RtpPusher class instance. Example:
std::cout << "RtpPusher version: " << RtpPusher::getVersion() << std::endl;
Console output:
RtpPusher version: 1.4.1
init method
The init(…) method initializes the RTP pusher. The method sets the IP address, port of the destination, channel bandwidth (optionally) in Kbps, and maximum RTP packet payload size (optionally). After initialization, the library runs an internal thread which is responsible for video streaming. Method declaration:
bool init(std::string ip, uint16_t port, int bandwidthKbps = 1000000, int maxPayloadSize = 1420, uint16_t metadataPort = 0);
| Parameter | Value |
|---|---|
| ip | Destination IP address. |
| port | Destination UDP port. |
| bandwidthKbps | Bandwidth of the network in Kbps. Default value is 1000000 Kbps (1 Gbps). This parameter is used to calculate the time gap between RTP packets. |
| maxPayloadSize | Maximum RTP payload size in bytes. Default is 1420. This parameter is used to adjust RTP packet size for different networks (make it lower to prevent filtering by routers). |
| metadataPort | Port for metadata (KLV etc). Default 0 - means user data will be embedded into SEI NAL unit of video stream. Otherwise, if port is different than 0 and different than the video port, user data will be sent over a separate RTP stream. In case of JPEG stream, user data should be sent over a separate RTP stream since JPEG does not support any mechanism to embed metadata into the video stream. |
Returns: TRUE if the RTP pusher is initialized or FALSE if not.
isInit method
The isInit() method returns the RTP pusher initialization status. Method declaration:
bool isInit();
Returns: TRUE if the RTP pusher is initialized or FALSE if not.
close method
The close() method closes the RTP pusher. The library will stop the internal streaming thread. Method declaration:
void close();
sendFrame method
The sendFrame(…) method sends a video frame. The method sends H264/H265/JPEG frames to the destination IP and port via RTP packets. The method is non-blocking which means that the method returns immediately after the frame is sent and the internal thread handles the frame sending. The library copies frame data to the internal buffer and returns control. If user data is provided, it will be sent to the same destination with the same timestamp as the frame. Thus, the receiver can synchronize user data with the video frame. Method declaration:
bool sendFrame(cr::video::Frame &frame, uint8_t *userData = nullptr, size_t userDataSize = 0);
| Parameter | Description |
|---|---|
| frame | Frame object with H264, H265, or JPEG fourcc. |
| userData | Pointer to user data to be sent with the frame (optional). NOTE: the size of user data can’t be more than maximum MTU size - 12 bytes in separate RTP packets and 255 bytes in the same RTP packet as SEI nals. |
| userDataSize | If user data pointer is not null, this parameter sets the size of user data in bytes (optional). NOTE: the size of user data can’t be more than maximum MTU size - 12 bytes in separate RTP packets and 255 bytes in the same RTP packet as SEI nals. |
Returns: TRUE if the frame was sent or FALSE if not.
Build and connect to your project
Typical commands to build RtpPusher library:
cd RtpPusher
mkdir build
cd build
cmake ..
make
If you want to connect RtpPusher library to your CMake project as source code, you can do the following. For example, if your repository has structure:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
Create a 3rdparty folder and copy the RtpPusher repository folder there. New structure of your repository:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
RtpPusher
Create a CMakeLists.txt file in the 3rdparty folder. CMakeLists.txt should contain:
cmake_minimum_required(VERSION 3.13)
################################################################################
## 3RD-PARTY
## dependencies for the project
################################################################################
project(3rdparty LANGUAGES CXX)
################################################################################
## SETTINGS
## basic 3rd-party settings before use
################################################################################
# To inherit the top-level architecture when the project is used as a submodule.
SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
# Disable self-overwriting of parameters inside included subdirectories.
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)
################################################################################
## CONFIGURATION
## 3rd-party submodules configuration
################################################################################
SET(${PARENT}_SUBMODULE_RTP_PUSHER ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_RTP_PUSHER)
SET(${PARENT}_RTP_PUSHER ON CACHE BOOL "" FORCE)
SET(${PARENT}_RTP_PUSHER_EXAMPLE OFF CACHE BOOL "" FORCE)
endif()
################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
if (${PARENT}_SUBMODULE_RTP_PUSHER)
add_subdirectory(RtpPusher)
endif()
The 3rdparty/CMakeLists.txt file adds the RtpPusher folder to your project and excludes the example from compiling (by default the example is excluded from compiling if RtpPusher is included as a sub-repository). The new structure of your repository will be:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
CMakeLists.txt
RtpPusher
Next, you need to include the 3rdparty folder in the main CMakeLists.txt file of your repository. Add the following string at the end of your main CMakeLists.txt:
add_subdirectory(3rdparty)
Next, you have to include the RtpPusher library in your src/CMakeLists.txt file:
target_link_libraries(${PROJECT_NAME} RtpPusher)
Done!
Example
A simple application shows how to use the RtpPusher library. The example includes the VSourceFile library to read H264 files.
#include <iostream>
#include <thread>
#include <chrono>
#include "VSourceFile.h"
#include "RtpPusher.h"
int main()
{
// Init video source.
cr::video::VSourceFile source;
std::string initString = "test.h264";
if (!source.openVSource(initString)) // Default 1280x720, 30 FPS
return -1;
std::cout << "Enter IP address: ";
std::string ip = "127.0.0.1";
std::cin >> ip;
std::cout << "Enter port number: ";
int port = 7032;
std::cin >> port;
// Init streamer.
cr::rtp::RtpPusher rtpPusher;
if (!rtpPusher.init(ip, port))
return -1;
// Main loop.
cr::video::Frame sourceFrame;
while (true)
{
// Get H264 frame from video source. We wait for a new frame for 1 sec.
if (!source.getFrame(sourceFrame, 1000))
continue;
// Send frame.
if (!rtpPusher.sendFrame(sourceFrame))
continue;
std::cout << "Frame : " << sourceFrame.frameId << std::endl;
// Wait to control frame rate (30 FPS = ~33ms between frames)
std::this_thread::sleep_for(std::chrono::milliseconds(33));
}
return 1;
}
How to play RTP stream
To play an RTP stream with ffmpeg or VLC, the user has to create an SDP file (examples for H264 and H265 are in the /static folder). Important: Replace the IP address and port in the SDP file with the values used in your application.
for H264 :
s=RTP H264 Stream
c=IN IP4 127.0.0.1
m=video 7032 RTP/AVP 96
a=rtpmap:96 H264/90000
for H265 :
s=RTP H265 Stream
c=IN IP4 127.0.0.1
m=video 7032 RTP/AVP 96
a=rtpmap:96 H265/90000
for JPEG :
s=RTP JPEG Stream
c=IN IP4 127.0.0.1
m=video 7032 RTP/AVP 26
a=rtpmap:26 JPEG/90000
Please ensure that the IP address and port number in the SDP file match the ones used in your application.
Play stream with ffplay:
ffplay -protocol_whitelist file,udp,rtp -i h264.sdp
To play an RTP stream in VLC, open h264.sdp in VLC.
How to extract KLV data from RTP stream
If KLV data is embedded into the SEI NAL unit of video stream (metadataPort = 0 in init method), extraction depends on the video codec. However, if KLV data is sent over a separate RTP stream (metadataPort is different than 0 and different than the video port in init method), KLV data can be extracted by gstreamer. For example:
gst-launch-1.0 udpsrc port=7034 caps="application/x-rtp, media=application, encoding-name=SMPTE336M, clock-rate=90000, payload=98" ! rtpjitterbuffer ! rtpklvdepay ! fakesink dump=true
Where 7034 is the port for KLV data (metadataPort in init method), 98 is the payload type for KLV data (can be changed in RtpPusher.cpp file, default is 98).
Output example:
00000000 (0x7f9f24014d44): 06 0e 2b 34 01 01 01 01 01 05 02 00 00 00 00 00 ..+4............
00000010 (0x7f9f24014d54): 10 59 65 73 74 65 72 64 61 79 73 20 57 6f 72 6c .Yesterdays Worl
00000020 (0x7f9f24014d64): 64 d