Overview
MServer is a C++ library that implements the VStreamer interface. It serves H.264 (RFC 6184), H.265 (RFC 7798) and MJPEG (RFC 2435) video over RTSP, RTSPS, RTSP over HTTP/HTTPS, UDP multicast, direct RTP push, WebRTC and HLS.
MServer 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.
This README calls each delivery path a leg: the served leg (clients that connect over RTSP, RTSPS or RTSP over HTTP/HTTPS, unicast or multicast), the push leg (direct RTP push), WebRTC and HLS.
MServer starts no external process. On Linux it links one external library: OpenSSL 3.0 or newer; the other libraries it links are built from source together with it (see Build and connect to your project). Through FormatConverter and ImageResizer the build also links the OpenMP runtime of the compiler when OpenMP is available, and libg2d (NXP i.MX) when it is installed. The FIPS 140-3 statements in this README depend on OpenSSL. On Windows MServer itself links no external library (with the default CNG backend of CryptoProvider, cryptography goes through the system’s CNG API), and the legs that need TLS or DTLS are not available; see Windows build with MSVC.
The caller supplies the frames: RAW pictures, or pictures already encoded as H.264, H.265 or JPEG. MServer does the rest itself: pixel-format conversion, letterbox/crop scaling, overlay, encoding (through the VCodec object the caller passes in), Annex-B parsing, parameter-set extraction, RTP packetization, MPEG-TS multiplexing, KLV carriage, RTCP, TLS, digest authentication, ICE, DTLS-SRTP, WHEP signalling, session management and pacing.
Documentation
Documentation: GO TO DOCUMENTATION
Video server interface
class MServer : public VStreamer
{
public:
/// Get library version.
static std::string getVersion();
/// Init video server.
bool initVStreamer(VStreamerParams& params, VCodec* codec = nullptr,
VOverlay* overlay = nullptr) override;
/// Check initialization status.
bool isVStreamerInit() override;
/// Close video server.
void closeVStreamer() override;
/// Send frame for streaming.
bool sendFrame(Frame& frame, uint8_t* userData = nullptr,
int userDataSize = 0) override;
/// Set parameter.
bool setParam(VStreamerParam id, float value) override;
/// Set parameter.
bool setParam(VStreamerParam id, std::string value) override;
/// Get all parameters.
void getParams(VStreamerParams& params) override;
/// Execute action command.
bool executeCommand(VStreamerCommand id) override;
/// Decode a command datagram and execute it (the interface's default).
bool decodeAndExecuteCommand(uint8_t* data, int size) override;
/// Get statistics.
struct Stats { /* ... */ };
void getStats(Stats& stats) const;
};
Simple example
#include <chrono>
#include <cstring>
#include <iostream>
#include <thread>
#include "MServer.h"
#include "VCodecLibav.h"
namespace
{
/// Frames in a row the server may refuse before the example gives up. A frame
/// is refused (FALSE) when the server is not initialised, the frame is
/// invalid or there is no memory for it; a stream nobody watches answers TRUE.
constexpr int MAX_REFUSED_FRAMES{100};
}
int main()
{
// Prepare video server params.
rapidpixel::VStreamerParams params;
params.codec = "H264"; // Codec type.
params.width = 640; // Output video width.
params.height = 480; // Output video height.
params.fps = 25.0f; // Output video FPS.
params.gop = 25; // Output video GOP size (key-frame interval).
params.rtspPort = 8554; // Output RTSP port.
params.suffix = "live"; // Stream name.
params.type = 1; // Software codec type for VCodecLibav.
// HLS is enabled by DEFAULT in the VStreamer interface, so this is a
// deliberate choice either way rather than an omission: leaving it alone
// opens a listener on the interface default port 8080, which web servers
// and containers often hold already, and initVStreamer() fails if the port
// is taken. The example uses 8088 instead. Said out loud here so the
// second URL below is no surprise.
params.hlsEnable = true;
params.hlsPort = 8088;
// The encoder is declared BEFORE the server and outlives it: MServer keeps
// using it until closeVStreamer(), and locals are destroyed in reverse
// order of construction.
rapidpixel::VCodecLibav encoder;
// Init video server.
rapidpixel::MServer server;
if (!server.initVStreamer(params, &encoder, nullptr))
{
return -1;
}
std::cout << "Streaming on rtsp://127.0.0.1:8554/live" << std::endl;
std::cout << " and http://127.0.0.1:8088/live/index.m3u8"
<< std::endl;
// Input video frame. It is 1280x720 while the stream above is 640x480:
// MServer scales, so the frame you send need not match the stream you
// publish.
rapidpixel::Frame frame(1280, 720, rapidpixel::Fourcc::YUV24);
// Stream loop, bounded by MAX_REFUSED_FRAMES.
uint8_t color = 0;
int refused = 0;
while (refused < MAX_REFUSED_FRAMES)
{
// Reset input frame with color.
memset(frame.data, color++, static_cast<size_t>(frame.size));
memset(frame.data + color * frame.width * 3, 255 - color,
static_cast<size_t>(frame.width) * 3);
// Send frame to video server.
if (server.sendFrame(frame))
{
refused = 0;
}
else
{
++refused;
}
// Wait for next frame.
std::this_thread::sleep_for(std::chrono::milliseconds(35));
}
std::cout << "The server refused " << MAX_REFUSED_FRAMES
<< " frames in a row, stopped" << std::endl;
server.closeVStreamer();
return -1;
}

