multirtspserver_web_logo

Multiple RTSP servers application template

v1.4.0

Table of contents

Application versions

Table 1 - Application versions.

Version Release date What’s new
1.0.0 22.05.2024 First version.
1.0.1 06.08.2024 - Submodules updated.
1.0.2 03.12.2024 - Submodules updated.
1.0.3 03.04.2025 - Multiple submodules update.
1.0.4 27.07.2025 - RtspServer submodules update.
1.1.0 16.08.2025 - CMake structure changed.
1.2.0 28.03.2026 - Codec was changed to software implementation.
1.2.1 20.06.2026 - Fixed RTSP server parameters initialization according to new VStreamer interface.
1.3.0 28.08.2026 - RtspServer replaced by MServer.
- Streamer preprocessing thread count set to 2 (VStreamerParams::custom1).
- Documentation updated.
1.3.1 13.10.2026 - VSourceOpenCv replaced by VSourceFile.
1.4.0 22.10.2026 - OpenCV dependency removed: the application does not display video, the custom video overlay is removed.
- VCodecLibav replaced by VEncoderJPEG: the default configuration is three JPEG streams, 1920 x 1080 at 30 FPS, 1280 x 720 at 20 FPS and 640 x 480 at 15 FPS, only the RTSP protocol is enabled.
- The application prints the RTSP URLs of the streams after starting.
- SimpleFileDialog removed: the video file is set by the videoFile parameter of the configuration file.
- Added check of the stream sizes, bind address in the printed URLs, handling of SIGINT and SIGTERM.
- Compiler warnings, hardening flags and standard C++ mode added to CMake.
- Documentation updated.

Overview

The MultiRtspServer application is an example of streaming video from a video file to three RTSP streams. The application shows how to use the VSourceFile and MServer libraries. The application is for Linux and depends on the libraries: VSourceFile (video capture from a video file), MServer (RTSP server), VEncoderJPEG (software JPEG encoder) and ConfigReader (reading and writing of the configuration file). On Linux the MServer library needs OpenSSL 3.0 or newer. The application is for Linux only because the function which gets the IP address of the host (HostAddress.cpp) uses the Linux network API (getifaddrs). The application does not display video.

MultiRtspServer is general-purpose software: it is not tied to any sector or application, and the developer of a program decides what the program does with it.

The application works as follows: after starting, it reads the configuration file MultiRtspServer.json (if the file does not exist or is not valid, the application creates a new one with the default parameters), opens the video file with VSourceFile, starts three MServer objects, prints three RTSP URLs and then sends every video frame to all three servers. Each server scales the frame to the resolution of its stream and keeps the frame rate of its stream, so the source frame rate and resolution do not have to match the streams. The video file is played in a loop.

By default the application creates three streams. All streams use the JPEG codec (Motion JPEG over RTP) and only the RTSP protocol (WebRTC, HLS, SRT, RTMP, metadata and the direct stream of MServer are switched off). All servers of one process share one RTSP port (7000): the streams are distinguished by the suffix of the URL, and the rtspPort of the first stream is the port of all streams.

Table 2 - Default streams.

Stream URL Resolution FPS Codec
Stream1 rtsp://IP:7000/stream1 1920 x 1080 30 JPEG
Stream2 rtsp://IP:7000/stream2 1280 x 720 20 JPEG
Stream3 rtsp://IP:7000/stream3 640 x 480 15 JPEG

Every stream has its own VEncoderJPEG encoder object and its own MServer object. The application passes the encoder to MServer when it initializes the server. The width and height of a JPEG stream must be multiples of 8 and must not be above 2040 pixels (limits of the RTP payload format of JPEG): the application checks the sizes after reading the configuration file. The JPEG encoder does not use the bitrate, but the server limits the sending rate to the doubled larger value of bitrateKbps and maxBitrateKbps. So these parameters must be above the data rate of the stream, which is about 1.25 bit per pixel at the default JPEG quality 80 (for example, 1920 x 1080 at 30 FPS needs about 78 Mbit/s). The default values are 60000, 20000 and 6000 kbps.

Application source code:

#include <csignal>
#include <iostream>
#include <string>
#include "ConfigReader.h"
#include "Frame.h"
#include "HostAddress.h"
#include "MServer.h"
#include "VEncoderJPEG.h"
#include "VSourceFile.h"
#include "VStreamer.h"

/// Number of video streams.
constexpr int NUM_STREAMS{3};
/// Name of the configuration file.
constexpr const char* CONFIG_FILE{"MultiRtspServer.json"};
/// RTSP port of all streams.
constexpr int RTSP_PORT{7000};
/// Time to wait for a video frame, milliseconds.
constexpr int FRAME_TIMEOUT_MSEC{1000};
/// Maximum width and height of a JPEG stream, pixels (limit of RTP/JPEG).
constexpr int JPEG_MAX_SIZE{2040};
/// Width and height of a JPEG stream must be multiples of this number.
constexpr int JPEG_SIZE_STEP{8};



/// Resolution, frame rate and bitrate of a video stream.
struct StreamSettings
{
    /// Frame width, pixels.
    int width;
    /// Frame height, pixels.
    int height;
    /// Frame rate, frames per second.
    float fps;
    /// Bitrate, kbps. The JPEG encoder does not use it, but the server limits
    /// the sending rate to the double of it. It must be above the data rate of
    /// the JPEG stream (about 1.25 bit per pixel at the quality 80).
    int bitrateKbps;
};

/// Default settings of the video streams: Stream1, Stream2 and Stream3.
constexpr StreamSettings STREAM_SETTINGS[NUM_STREAMS]{
    {1920, 1080, 30.0f, 60000},
    {1280, 720, 20.0f, 20000},
    {640, 480, 15.0f, 6000}};



/// Application parameters. The constructor sets the default values.
struct Params
{
    /// Path to the video file.
    std::string videoFile{"test.mp4"};
    /// Parameters of the video streams.
    rapidpixel::VStreamerParams stream[NUM_STREAMS];

    Params()
    {
        for (int i = 0; i < NUM_STREAMS; ++i)
        {
            rapidpixel::VStreamerParams& params = stream[i];
            params.codec = "JPEG";
            params.width = STREAM_SETTINGS[i].width;
            params.height = STREAM_SETTINGS[i].height;
            params.fps = STREAM_SETTINGS[i].fps;
            params.bitrateKbps = STREAM_SETTINGS[i].bitrateKbps;
            params.maxBitrateKbps = STREAM_SETTINGS[i].bitrateKbps;

            // All streams use one RTSP port and differ by the suffix.
            params.rtspPort = RTSP_PORT;
            params.suffix = "stream" + std::to_string(i + 1);

            // Only RTSP is used: all other protocols are switched off.
            params.directStreamEnable = false;
            params.webRtcEnable = false;
            params.hlsEnable = false;
            params.srtEnable = false;
            params.rtmpEnable = false;
            params.metadataEnable = false;
            params.overlayEnable = false;
        }
    }

    JSON_READABLE(Params, videoFile, stream)
};



namespace
{
/// Set by the signal handler to stop the main loop.
volatile std::sig_atomic_t g_stop{0};



/// Signal handler of SIGINT and SIGTERM.
void onSignal(int)
{
    g_stop = 1;
}



/// Check the width or the height of a JPEG stream.
bool isJpegSizeValid(int size)
{
    return size > 0 && size <= JPEG_MAX_SIZE && size % JPEG_SIZE_STEP == 0;
}
}



int main()
{
    if (std::signal(SIGINT, onSignal) == SIG_ERR ||
        std::signal(SIGTERM, onSignal) == SIG_ERR)
    {
        std::cerr << "Can't set the signal handlers" << std::endl;
        return 1;
    }

    // Read the parameters. If the file is absent or invalid, the default
    // parameters are used and the file is created.
    Params params;
    rapidpixel::ConfigReader config;
    if (!config.readFromFile(CONFIG_FILE) || !config.get(params, "Params"))
    {
        params = Params();
        config.set(params, "Params");
        if (!config.writeToFile(CONFIG_FILE))
        {
            std::cerr << "Can't write " << CONFIG_FILE << std::endl;
            return 1;
        }
    }

    // The server publishes a JPEG stream only if its size is valid.
    for (const rapidpixel::VStreamerParams& streamParams : params.stream)
    {
        if (!isJpegSizeValid(streamParams.width) ||
            !isJpegSizeValid(streamParams.height))
        {
            std::cerr << "Width and height of a stream must be multiples of "
                      << JPEG_SIZE_STEP << " and not above " << JPEG_MAX_SIZE
                      << std::endl;
            return 1;
        }
    }

    // Open the video file. The file is played in a loop.
    rapidpixel::VSourceFile source;
    if (!source.openVSource(params.videoFile))
    {
        std::cerr << "Can't open video file " << params.videoFile << std::endl;
        return 1;
    }

    // Start the streams. Every stream has its own JPEG encoder and its own
    // RTSP server. The encoders are declared first, so they are destroyed
    // after the servers which use them.
    rapidpixel::VEncoderJPEG encoder[NUM_STREAMS];
    rapidpixel::MServer server[NUM_STREAMS];
    for (int i = 0; i < NUM_STREAMS; ++i)
    {
        if (!server[i].initVStreamer(params.stream[i], &encoder[i]))
        {
            std::cerr << "Can't start stream " << i + 1 << std::endl;
            return 1;
        }
    }

    // Show the URLs of the streams. If the servers are bound to one address,
    // the streams are available only on this address.
    std::string host = params.stream[0].bindAddress;
    if (host.empty() || host == "0.0.0.0")
    {
        host = getHostAddress();
    }
    for (const rapidpixel::VStreamerParams& streamParams : params.stream)
    {
        std::cout << "rtsp://" << host << ":" << params.stream[0].rtspPort
                  << "/" << streamParams.suffix << std::endl;
    }

    // Send every video frame to all streams. Each server scales the frame to
    // the resolution of its stream and keeps the frame rate of its stream.
    rapidpixel::Frame frame;
    frame.fourcc = rapidpixel::Fourcc::NV12;
    while (g_stop == 0)
    {
        if (!source.getFrame(frame, FRAME_TIMEOUT_MSEC))
        {
            continue;
        }
        for (rapidpixel::MServer& streamer : server)
        {
            if (!streamer.sendFrame(frame))
            {
                std::cerr << "Can't send frame to the stream" << std::endl;
                return 1;
            }
        }
    }

    return 0;
}

Application files

The MultiRtspServer is provided as source code. Users are given a set of files in the form of a CMake project (repository). The repository structure is outlined below:

CMakeLists.txt ----------- Main CMake file of the application.
src ---------------------- Folder with source code of the application.
    CMakeLists.txt ------- CMake file of the application.
    HostAddress.h -------- Header file of the function which gets the IP address of the host.
    HostAddress.cpp ------ C++ implementation file.
    main.cpp ------------- Source code file of the application.
static ------------------- Folder with the test video file and the images of the documentation.

Build application

The MultiRtspServer is a complete repository in the form of a CMake project. Before compiling, the user has to install CMake, a C++17 compiler and the development files of OpenSSL 3.0 or newer (needed by the MServer library on Linux). To install them in Linux (Ubuntu), use the command:

sudo apt-get install build-essential cmake libssl-dev

Ubuntu 20.04 and Debian 11 have OpenSSL 1.1.1 only: there the MServer library is excluded from the SDK build (unless OpenSSL 3 is installed separately), so the application is excluded too (its configuration log says “MServer not found”).

Typical commands to build MultiRtspServer application (Release mode):

cd /path/to/RapidPixelSdk
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release --target MultiRtspServer

Launch

After compiling, you will get the MultiRtspServer executable file in the bin folder of the build folder. The application opens the video file which is set by the videoFile parameter of the configuration file (the default value is test.mp4, the path is relative to the current folder). Copy the test.mp4 file from the static folder to the folder from which the application is started and run the command:

./MultiRtspServer

After starting, the application creates the configuration file (if it doesn’t exist) and prints three lines, the RTSP URLs of the streams:

rtsp://192.168.1.10:7000/stream1
rtsp://192.168.1.10:7000/stream2
rtsp://192.168.1.10:7000/stream3

The address in the URLs is the IPv4 address of the first working network interface of the computer except the loopback one (or the value of the bindAddress parameter if the servers are bound to one address). Open the URLs in any RTSP client (for example, VLC, FFplay or FFmpeg), or check a stream with the command:

ffprobe rtsp://192.168.1.10:7000/stream1

To stop the application press Ctrl+C (SIGINT) or send SIGTERM. If the video file can’t be opened, the sizes of the streams are not valid or a stream can’t be started, the application prints a message to the error output and returns 1.

The configuration file MultiRtspServer.json contains the object Params with two parameters (Table 3). The streams are not protected by default and the servers listen on all network interfaces: set the user and password parameters of a stream to require a user name and a password, and the bindAddress parameter to listen on one address only.

Table 3 - Configuration file parameters.

Parameter Description
videoFile Path to the video file. Supported extensions: .h264, .264, .h265, .hevc, .jpg, .jpeg, .mjpg, .mjpeg, .mp4, .mov, .m4v and .avi. Default: test.mp4.
stream Array of three objects with the parameters of the streams (the VStreamerParams class, see the description of the MServer library). The default values of the parameters which are set by the application are given in Table 4.

Table 4 - Default parameters of the streams.

Parameter Stream1 Stream2 Stream3 Description
codec JPEG JPEG JPEG Codec of the stream.
width 1920 1280 640 Stream width, pixels. A multiple of 8, not above 2040.
height 1080 720 480 Stream height, pixels. A multiple of 8, not above 2040.
fps 30 20 15 Stream frame rate.
bitrateKbps, maxBitrateKbps 60000 20000 6000 Limit of the sending rate (see the Overview).
rtspPort 7000 7000 7000 RTSP port. The value of the first stream is used for all streams.
suffix stream1 stream2 stream3 Stream name, the last part of the URL.
directStreamEnable, webRtcEnable, hlsEnable, srtEnable, rtmpEnable, metadataEnable, overlayEnable false false false Protocols and functions which are not used.

Table of contents