C++ API Reference

Core C++ API for MediaX video streaming.

Stream Information

The StreamInformation structure defines stream parameters:

#include "rtp/rtp.h"

struct mediax::rtp::StreamInformation {
    std::string session_name;     // Stream name for SAP
    std::string hostname;         // Multicast address or IP
    uint16_t port;                // UDP port
    uint32_t width;               // Frame width in pixels
    uint32_t height;              // Frame height in pixels
    uint32_t framerate;           // Frames per second
    ColourspaceType encoding;     // Colorspace/codec type
};

Colorspace Types

enum class mediax::rtp::ColourspaceType {
    kColourspaceRgb24,      // 24-bit RGB
    kColourspaceYuv422,     // YCbCr 4:2:2 (UYVY)
    kColourspaceMono8,      // 8-bit grayscale
    kColourspaceMono16,     // 16-bit grayscale
    kColourspaceH264Part10, // H.264/AVC
    kColourspaceH265,       // H.265/HEVC
    kColourspaceAv1,        // AV1
    kColourspaceJpeg2000,   // JPEG 2000
    kColourspaceJpeg,       // JPEG (RFC 2435)
};

Payloader Classes

Uncompressed Payloader

#include "uncompressed/rtp_uncompressed_payloader.h"

class mediax::rtp::uncompressed::RtpUncompressedPayloader {
public:
    void SetStreamInfo(const StreamInformation& info);
    bool Open();
    void Close();
    bool Transmit(const uint8_t* data, bool blocking = true);
};

H.264 VAAPI Payloader

#include "h264/vaapi/rtp_h264_vaapi_payloader.h"

class mediax::rtp::h264::vaapi::RtpH264VaapiPayloader {
public:
    void SetStreamInfo(const StreamInformation& info);
    bool Open();
    void Close();
    bool Transmit(const uint8_t* data, bool blocking = true);
};

H.265 VAAPI Payloader

#include "h265/vaapi/rtp_h265_vaapi_payloader.h"

class mediax::rtp::h265::vaapi::RtpH265VaapiPayloader {
public:
    void SetStreamInfo(const StreamInformation& info);
    bool Open();
    void Close();
    bool Transmit(const uint8_t* data, bool blocking = true);
};

AV1 Payloader

#include "av1/vaapi/rtp_av1_vaapi_payloader.h"

class mediax::rtp::av1::vaapi::RtpAv1VaapiPayloader {
public:
    void SetStreamInfo(const StreamInformation& info);
    bool Open();
    void Close();
    bool Transmit(const uint8_t* data, bool blocking = true);
};

JPEG Classes

RTP JPEG (RFC 2435) through libjpeg, built when BUILD_JPEG=ON and libjpeg is found. See JPEG Video.

JPEG Payloader

#include "jpeg/libjpeg/rtp_jpeg_payloader.h"

class mediax::rtp::jpeg::RtpJpegPayloader : public mediax::rtp::RtpPayloader {
public:
    void SetStreamInfo(const StreamInformation& info);
    void SetEncoderConfig(const EncoderConfig& config);  // quality 1-100, JpegSubsampling::k422 / k420
    void SetMtu(uint32_t mtu);                           // 256 to 65000, default 1400
    bool Open();
    void Start();
    void Stop();
    void Close();
    int Transmit(uint8_t* rgb_frame, bool blocking = true);  // RGB24, up to 2040x2040
    uint64_t GetBytesSent() const;
    uint64_t GetFrameCount() const;
};

JPEG Depayloader

#include "jpeg/libjpeg/rtp_jpeg_depayloader.h"

class mediax::rtp::jpeg::RtpJpegDepayloader : public mediax::rtp::RtpDepayloader {
public:
    void SetStreamInfo(const StreamInformation& info);
    bool Open();
    void Start();
    void Stop();
    void Close();
    bool Receive(RtpFrameData* data, int32_t timeout_ms = 0);  // RGB24
    void RegisterCallback(const RtpCallback& callback);
    void RegisterEncodedFrameCallback(const EncodedFrameCallback& callback);  // the JPEG file of each frame
    uint64_t GetDroppedFrames() const;
    bool PushRtpPacket(const uint8_t* data, size_t size);  // external transport such as RTSP
};

JPEG VAAPI Payloader and Depayloader

#include "jpeg/vaapi/rtp_jpeg_vaapi_depayloader.h"
#include "jpeg/vaapi/rtp_jpeg_vaapi_payloader.h"

// Derive from RtpJpegPayloader / RtpJpegDepayloader, built when libva is found. The GPU compresses and decodes,
// libjpeg takes over when the hardware is missing or refuses a frame.
class mediax::rtp::jpeg::vaapi::RtpJpegVaapiPayloader : public mediax::rtp::jpeg::RtpJpegPayloader {
public:
    static bool IsVaapiAvailable();       // the GPU encodes baseline JPEG
    bool IsHardwareActive() const;
    uint64_t GetHardwareFrames() const;
};

class mediax::rtp::jpeg::vaapi::RtpJpegVaapiDepayloader : public mediax::rtp::jpeg::RtpJpegDepayloader {
public:
    static bool IsVaapiAvailable();       // the GPU decodes baseline JPEG
    bool IsHardwareActive() const;
    uint64_t GetHardwareFrames() const;
};

Depayloader Classes

Uncompressed Depayloader

#include "uncompressed/rtp_uncompressed_depayloader.h"

class mediax::rtp::uncompressed::RtpUncompressedDepayloader {
public:
    void SetStreamInfo(const StreamInformation& info);
    bool Open();
    void Close();
    void Start();
    void Stop();
    bool Receive(uint8_t* data, int timeout_ms = 0);
    void RegisterCallback(std::function<void(const RtpFrameData&)> callback);
};

H.264 VAAPI Depayloader

#include "h264/vaapi/rtp_h264_vaapi_depayloader.h"

class mediax::rtp::h264::vaapi::RtpH264VaapiDepayloader {
public:
    void SetStreamInfo(const StreamInformation& info);
    bool Open();
    void Close();
    void Start();
    void Stop();
    bool Receive(uint8_t* data, int timeout_ms = 0);
    void RegisterCallback(std::function<void(const RtpFrameData&)> callback);
};

H.265 VAAPI Depayloader

#include "h265/vaapi/rtp_h265_vaapi_depayloader.h"

class mediax::rtp::h265::vaapi::RtpH265VaapiDepayloader {
public:
    void SetStreamInfo(const StreamInformation& info);
    bool Open();
    void Close();
    void Start();
    void Stop();
    bool Receive(uint8_t* data, int timeout_ms = 0);
    void RegisterCallback(std::function<void(const RtpFrameData&)> callback);
};

AV1 Depayloader

#include "av1/vaapi/rtp_av1_vaapi_depayloader.h"

class mediax::rtp::av1::vaapi::RtpAv1VaapiDepayloader {
public:
    void SetStreamInfo(const StreamInformation& info);
    bool Open();
    void Close();
    void Start();
    void Stop();
    bool Receive(uint8_t* data, int timeout_ms = 0);
    void RegisterCallback(std::function<void(const RtpFrameData&)> callback);
};

Other H.264 and AV1 Backends

Every H.264 backend derives from mediax::rtp::RtpPayloader / RtpDepayloader, so they are used exactly like the VAAPI classes above. Which ones exist in a build depends on the CMake options and detected libraries (see Hardware Acceleration).

Backend Payloader Depayloader Header directory Namespace Availability check
OpenH264 (software) RtpH264OpenH264Payloader RtpH264OpenH264Depayloader h264/openh264/ mediax::rtp::h264::openh264 Always when built
NVIDIA NVENC / NVDEC RtpH264NvencPayloader RtpH264NvdecDepayloader h264/nvenc/ mediax::rtp::h264::nvenc IsNvencAvailable() / IsNvdecAvailable()
Jetson Multimedia API RtpH264JetsonPayloader RtpH264JetsonDepayloader h264/jetson/ mediax::rtp::h264::jetson IsAvailable()
V4L2 M2M RtpH264V4l2m2mPayloader RtpH264V4l2m2mDepayloader h264/v4l2_m2m/ mediax::rtp::h264::v4l2_m2m V4L2M2mProbe
Android AMediaCodec RtpH264AndroidPayloader RtpH264AndroidDepayloader h264/android/ mediax::rtp::h264::android IsAndroidMediaCodecAvailable()
Jetson AV1 (decode only) - RtpAv1JetsonDepayloader av1/jetson/ mediax::rtp::av1::jetson IsAvailable()
#include "h264/openh264/rtp_h264_openh264_payloader.h"
#include "h264/nvenc/rtp_h264_nvenc_payloader.h"

mediax::rtp::h264::openh264::RtpH264OpenH264Payloader software;

if (mediax::rtp::h264::nvenc::RtpH264NvencPayloader::IsNvencAvailable()) {
  mediax::rtp::h264::nvenc::RtpH264NvencPayloader hardware;
}

H.264 encoder factory

mediax::rtp::h264::EncoderFactory (h264/encoder_factory.h) probes the machine and returns the best H.264 payloader. Priority is NVENC, VAAPI, V4L2 M2M, Jetson, Android MediaCodec, then OpenH264.

#include "h264/encoder_factory.h"

using mediax::rtp::h264::EncoderFactory;
using mediax::rtp::h264::EncoderType;

for (const auto& info : EncoderFactory::DetectEncoders()) {
  std::cout << info.name << (info.is_hardware ? " (hardware)" : " (software)")
            << (info.available ? " available\n" : " not available\n");
}

std::unique_ptr<mediax::rtp::RtpPayloader> best = EncoderFactory::CreateBest();
auto vaapi = EncoderFactory::Create(EncoderType::kVaapi);  // nullptr if unavailable

EncoderType is kNvenc, kVaapi, kV4L2M2m, kJetson, kAndroidMediaCodec or kOpenH264. IsAvailable(type) and GetEncoderName(type) are also provided.

Frame Data Structure

struct mediax::rtp::RtpFrameData {
    uint8_t* cpu_buffer;          // Pointer to frame data
    struct {
        uint32_t width;
        uint32_t height;
    } resolution;
    ColourspaceType encoding;
    uint32_t timestamp;
};

RTSP Classes

See the RTSP Receiver guide for details. All classes are in mediax::rtsp.

RTSP Depayloader

RtspDepayloader derives from mediax::rtp::RtpDepayloader, so Receive(), RegisterCallback(), recording and the Open()/Start()/Stop()/Close() lifecycle work as for any other depayloader.

#include "rtsp/rtsp_depayloader.h"

mediax::rtsp::RtspDepayloader rx;
rx.SetUrl("rtsp://camera/stream");
rx.SetCredentials("user", "password");
if (rx.Open()) {
  rx.Start();
  mediax::rtp::RtpFrameData frame;
  while (rx.Receive(&frame, 1000)) { /* RGB24 in frame.cpu_buffer */ }
  rx.Close();
}
Member Purpose
SetUrl(), SetCredentials() Stream URL (credentials may be in the URL) and authentication
SetClientConfig(RtspClientConfig) Transport, timeouts, RTCP and reconnect policy
SetTrackSelector(), SetDecoderFactory() Choose the track, or supply your own decoder
RegisterStateCallback(), RegisterErrorCallback() Follow session state and errors
RegisterEncodedFrameCallback() Receive compressed access units before decoding
GetLastStatus(), GetLastError(), GetTrack(), GetTracks(), GetStatistics() Results and statistics

RTSP Client

RtspClient is the control plane on its own: Connect(), Describe(), Setup(), Play(), Pause(), Teardown() (or Open() to do the first three), with RegisterRtpHandler() delivering each RTP packet.

Stream probe

#include "rtsp/rtsp_probe.h"

mediax::rtsp::RtspProbeOptions options;
options.level = mediax::rtsp::RtspProbeLevel::kMedia;   // kDescribe by default
mediax::rtsp::RtspProbeResult result = mediax::rtsp::ProbeRtspStream("rtsp://camera/stream", options);
bool live = result.IsLive();

RtspProbeResult has status, error, reachable, described, media_flowing, tracks, transport and the timings describe_ms, first_packet_ms and total_ms.

Decoder factory

#include "rtp/depayloader_factory.h"

auto decoders = mediax::rtp::DepayloaderFactory::DetectDecoders(mediax::rtp::ColourspaceType::kColourspaceH264Part10);
auto depayloader = mediax::rtp::DepayloaderFactory::CreateBest(mediax::rtp::ColourspaceType::kColourspaceH264Part10);

Only backends that return true from RtpDepayloader::SupportsExternalTransport() are offered (currently OpenH264).

SRT Classes

See the SRT guide for details. All classes are in mediax::srt.

SRT Depayloader

SrtDepayloader derives from mediax::rtp::RtpDepayloader, like the RTSP and HLS receivers. It finds the codec (H.264, H.265 or AV1) in the MPEG-TS stream, creates the decoder and delivers RGB24 frames.

#include "srt/srt_depayloader.h"

mediax::srt::SrtDepayloader rx;
rx.SetUrl("srt://:9000?mode=listener&latency=250&passphrase=correct-horse-battery");
rx.Open();
rx.Start();                       // Connects (and reconnects) in the background

mediax::rtp::RtpFrameData frame;
while (rx.Receive(&frame, 5000)) {
  // frame.cpu_buffer holds RGB24 data
}
rx.Close();
Method Description
SetUrl(url) / SetConfig(SrtConfig) Connection settings, see ParseSrtUrl() for the URL options
SetReconnect(enable, delay_ms) Automatic reconnection (default on)
SetWaitForKeyFrameAfterLoss(enable) Hold the decoder until the next key frame after an unrecoverable loss (default on)
RegisterErrorCallback(cb) Connection errors, from a worker thread
WaitForConnection(timeout_ms) Wait until the SRT connection is up
GetStatistics() RTT, loss, recoveries, drops, rates, frames and reconnects

SRT Transmitter

SrtTransmitter muxes H.264, H.265 or AV1 access units into MPEG-TS and sends them. For AV1 the access unit is a temporal unit, a sequence of OBUs.

#include "srt/srt_transmitter.h"

mediax::srt::SrtTransmitter tx;
tx.SetUrl("srt://gcs.example:9000?latency=250");
tx.SetCodec(mediax::rtp::ColourspaceType::kColourspaceH264Part10);   // Or kColourspaceH265 or kColourspaceAv1
tx.Open();
tx.Start();
tx.SendAccessUnit(annex_b, size, pts_90khz, is_key_frame);

Attach(RtpPayloader*) sends the output of the OpenH264, VAAPI H.264/H.265 and VAAPI AV1 encoders over SRT instead of RTP, and RegisterKeyFrameRequestCallback() lets a new peer ask the encoder for a key frame.

SRT Socket and configuration

SrtSocket is one connection (handshake, retransmission, encryption) and can be used directly. SrtConfig holds the settings, SrtConfig::ForDroneLink(expected_rtt_ms) returns a preset for a radio link, and SrtStatistics reports the counters.

RTP to SRT gateway

These classes convert H.264 and H.265 (not AV1) between RTP and SRT without decoding or re-encoding. See the SRT user guide for what they do and their limits.

#include "gateway/srt_gateway.h"

mediax::gateway::SrtGateway gateway;

mediax::gateway::RtpToSrtRouteConfig camera;      // SAP announced RTP -> SRT
camera.session_name = "Camera 1";
camera.srt_url = "srt://ground-station.example:9000?latency=200";
const auto camera_id = gateway.AddRtpToSrt(camera);

mediax::gateway::SrtToRtpRouteConfig drone;       // SRT -> RTP announced with SAP
drone.session_name = "Drone 7";
drone.srt_url = "srt://:9100?mode=listener&latency=300";
drone.rtp_address = "239.192.10.7";
drone.rtp_port = 5004;
gateway.AddSrtToRtp(drone);

gateway.Start();
mediax::gateway::GatewayRouteStatus status;
gateway.GetRouteStatus(camera_id, &status);
Class Description
SrtGateway AddRtpToSrt(), AddSrtToRtp(), Remove(), Start(), Stop(), GetStatus(), GetRouteStatus()
RtpSapToSrtRoute One SAP announced RTP stream to SRT: Start(), Stop(), OnAnnouncement(), GetStatus()
SrtToRtpSapRoute One SRT source to RTP and SAP: Start(), Stop(), GetStatus()
RtpToSrt SetUrl(), SetCodec(), PushRtpPacket(), RegisterKeyFrameRequestCallback(), GetStatistics()
SrtToRtp SetUrl(), SetOptions(), RegisterRtpPacketCallback(), RegisterStreamCallback(), GetStatistics()
RtpUdpReceiver / RtpUdpSender UDP unicast and multicast transport of RTP packets (rtp/rtp_udp.h)
H264RtpDepacketizer / H265RtpDepacketizer RTP packets to Annex B access units (mpegts/rtp_depacketizer.h)

HLS Classes

Built with BUILD_HLS=ON (the default, needs libcurl, not on Windows). See the HLS Receiver guide.

HLS Depayloader

#include "hls/hls_depayloader.h"

mediax::hls::HlsClientConfig config;
config.preferred_height = 720;

mediax::hls::HlsDepayloader rx;
rx.SetClientConfig(config);
rx.SetUrl("https://example.com/live/stream.m3u8");
if (rx.Open()) {
  rx.Start();
  mediax::rtp::RtpFrameData frame;
  while (rx.Receive(&frame, 5000)) { /* decoded RGB24 */ }
  rx.Close();
}

HlsDepayloader derives from mediax::rtp::RtpDepayloader, like the RTSP and SRT receivers. Segments encrypted with AES-128 (EXT-X-KEY) are decrypted when MediaX is built with OpenSSL (hls/hls_aes.h: HasAesDecryption(), DecryptAes128()).

Audio is received with RegisterAudioCallback(), which gets an mediax::hls::HlsAudioFrame (hls/hls_audio.h): decoded 16 bit PCM (format == HlsAudioFormat::kPcmS16, pcm, sample_rate, channels) or the encoded AAC, MPEG audio, AC-3 or E-AC-3 bytes (encoded), with the 90 kHz pts. PCM needs a decoder: the libavcodec one built in with BUILD_HLS_AUDIO_DECODE=ON (CreateAvcodecAudioDecoder(), HasBuiltInAudioDecoder()) or an HlsAudioDecoder returned by the factory given to SetAudioDecoderFactory(). The application plays the audio.

Member Description
SetUrl(url) The .m3u8 playlist, master or media. Returns an HlsStatus
SetClientConfig(HlsClientConfig) Timeouts, variant choice, live start offset, buffering, pacing, User-Agent
SetFetcher(std::shared_ptr<HlsHttpFetcher>) Replace the libcurl HTTP client, for tests
RegisterErrorCallback() Errors, possibly from a worker thread
GetLastStatus(), GetLastError() kOk, kInvalidArgument, kInvalidState, kNetworkError, kHttpError, kTimeout, kParseError, kUnsupported, kCancelled
GetStatistics() HlsStatistics: playlist requests, segments and bytes downloaded, frames delivered, RTP packets, errors
GetVariant() The HlsVariant playing: URI, bandwidth, size, codecs, frame rate
HasEnded() A finished (EXT-X-ENDLIST) stream was played out, or the stream was abandoned

HlsClientConfig fields: connect_timeout_ms, request_timeout_ms, max_redirects, preferred_height, max_bandwidth, live_start_segments, max_consecutive_errors, max_buffer_ms, realtime_pacing, user_agent.

Chromecast Classes

Built with BUILD_CAST=ON (the default, needs OpenSSL, not on Windows). See the Chromecast guide. All classes are in mediax::cast.

Discovery

CastDiscovery finds the Chromecasts and other Google Cast devices on the network with multicast DNS.

#include "cast/cast_discovery.h"

mediax::cast::CastDiscovery discovery;
discovery.RegisterDeviceFoundCallback([](const mediax::cast::CastDevice& d) { /* ... */ });
discovery.Start();
mediax::cast::CastDevice tv;
if (discovery.WaitForDevice("Living Room TV", 5000, &tv)) { /* ... */ }
Member Description
Start(), Stop(), Refresh() Begin, end and repeat the search
SetInterfaceAddress(address) Search on one interface only (default all multicast capable ones)
RegisterDeviceFoundCallback(), RegisterDeviceLostCallback() New or changed devices, and devices that left or timed out, from the discovery thread
GetDevices(), FindDevice(name_or_id, &device), WaitForDevice(name_or_id, timeout_ms, &device) The detected devices, found by name (any case), id or address
GetLastError() Description of the last failure

CastDevice has id, friendly_name, model, address, port, capabilities and SupportsVideo().

Sender

CastSender casts H.264 access units to a device. It serves them as live HLS from an HTTP server in the process and tells the device over CASTv2 to play them.

#include "cast/cast_sender.h"

mediax::cast::CastSender sender;
sender.SetDevice(tv);
sender.Open();
sender.Start();
sender.SendAccessUnit(annex_b, size, pts_90khz, is_key_frame);
sender.WaitForStreaming(30000);
Member Description
SetDevice(), SetConfig(CastConfig) The device and the settings: segment length, playlist size, timeouts, interface, port, title
SetReconnect(enable, delay_ms) Automatic reconnection (default on)
Open(), Start(), Stop(), Close() Open() starts the HTTP server, Start() connects in the background
SendAccessUnit() One Annex B access unit, with or without a time stamp
Attach(RtpPayloader*), Detach() Cast the output of the OpenH264 or VAAPI H.264 encoders instead of sending RTP
RegisterKeyFrameRequestCallback() Ask the encoder for a key frame when a segment is due to end
RegisterErrorCallback(), RegisterStateCallback() Errors and CastState changes, from a worker thread
WaitForStreaming(timeout_ms), GetState(), IsStreaming(), PlaylistUrl() Follow the connection
GetStatistics(), GetLastStatus(), GetLastError() Counters and failures

RTP to Chromecast

Class Description
RtpToCast H.264 RTP packets to a Chromecast without decoding: SetConfig(), PushRtpPacket(), RegisterKeyFrameRequestCallback(), GetStatistics()
RtpSapToCastRoute One SAP announced H.264 RTP stream cast to a device: SetDiscovery(), SetDevice(), Start(), Stop(), OnAnnouncement(), GetStatus()

Building blocks

Class Header Purpose
CastSession cast/cast_session.h One CASTv2 session: Connect(), Launch(), Load(), StopApplication(), Close()
CastTransport, CreateTlsTransport() cast/cast_transport.h The connection to the device, TLS over TCP. Replaceable, for tests
CastMessage, EncodeCastMessage(), DecodeCastMessage() cast/cast_protobuf.h The CASTv2 message and its protocol buffer encoding
HlsSegmenter cast/hls_segmenter.h H.264 access units to MPEG-TS segments and a live playlist
HttpServer cast/http_server.h Serves the playlist and segments from memory to one peer
ParseDnsMessage(), BuildDnsQuery() cast/dns_message.h The multicast DNS codec

MPEG-TS Classes

mediax::mpegts (mpegts/) is the transport stream layer shared by the HLS and SRT receivers, the SRT transmitter and the Chromecast sender. It is part of libmediax when BUILD_HLS, BUILD_SRT or BUILD_CAST is on.

Class Header Purpose
TsDemuxer mpegts/ts_demux.h MPEG-2 transport stream to video access units (H.264, H.265, AV1) with PTS/DTS and continuity checks. Optionally also the first audio stream (AAC, MPEG audio, AC-3, E-AC-3) through SetAudioCallback()
TsMuxer mpegts/ts_mux.h Video access units to transport stream packets
H264RtpPacketizer, H265RtpPacketizer, Av1RtpPacketizer mpegts/rtp_packetizer.h Annex B / OBU access units to RTP (RFC 6184, RFC 7798, AV1 payload)
H264RtpDepacketizer, H265RtpDepacketizer mpegts/rtp_depacketizer.h RTP packets back to Annex B access units

Capture, Tracking and Display Helpers

Class Header Notes
V4L2Capture v4l2/v4l2_source.h Video4Linux2 capture: V4L2Capture(device, width, height), Initalise(), CaptureFrame(buffer). Used by the v4l2 example
cvtrack::Tracker cvtrack/tracker.h FFT correlation object tracker: AddObject(BoundingBox), Update(frame, width, height, channels), GetTrackedObjects(). Used by the qt6-tracker example
mediax::DisplayManagerBase, mediax::sdl::DisplayManager renderer/ SDL2 renderer for the examples only (built with EXAMPLES=ON), not installed

SAP Classes

SAP Announcer

#include "sap/sap_announcer.h"

class mediax::sap::SapAnnouncer {
public:
    void AddSapAnnouncement(const rtp::StreamInformation& info);
    void DeleteSapAnnouncement(const std::string& session_name);
    void DeleteAllSapAnnouncements();
    void Start();
    void Stop();
};

SAP Listener

#include "sap/sap_listener.h"

class mediax::sap::SapListener {
public:
    void Start();
    void Stop();
    const std::map<std::string, rtp::StreamInformation>& GetSapAnnouncements();
    void RegisterCallback(std::function<void(const rtp::StreamInformation&)> callback);
};

Codec Query Interface

Discover which codecs are compiled into the library and available at runtime.

CodecInfo Structure

#include "rtp/codec_query.h"

struct mediax::rtp::CodecInfo {
    std::string name;               // e.g. "H.264 VAAPI"
    std::string backend;            // e.g. "vaapi", "openh264", "nvenc"
    ColourspaceType colourspace;    // Codec type enum
    CodecDirection direction;       // kEncoder, kDecoder, or kBidirectional
    AccelerationType acceleration;  // kSoftware or kHardware
    bool compiled;                  // Compiled into this build
    bool available;                 // Hardware available at runtime
    std::string description;        // Human-readable description
};

Enumerations

enum class mediax::rtp::CodecDirection {
    kEncoder,       // Encode (payloader) only
    kDecoder,       // Decode (depayloader) only
    kBidirectional  // Both encode and decode
};

enum class mediax::rtp::AccelerationType {
    kSoftware,  // CPU / software-only codec
    kHardware   // Hardware-accelerated (GPU, ASIC, V4L2 M2M)
};

CodecQuery Class

#include "rtp/codec_query.h"

class mediax::rtp::CodecQuery {
public:
    // List all known backends (compiled and uncompiled)
    static std::vector<CodecInfo> GetCodecs();

    // Filter by direction
    static std::vector<CodecInfo> GetEncoders();
    static std::vector<CodecInfo> GetDecoders();

    // Filter by acceleration type
    static std::vector<CodecInfo> GetHardwareCodecs();
    static std::vector<CodecInfo> GetSoftwareCodecs();

    // Only compiled AND runtime-available backends
    static std::vector<CodecInfo> GetAvailableCodecs();

    // Filter by colourspace type
    static std::vector<CodecInfo> GetCodecsByColourspace(ColourspaceType type);

    // Quick check: is a named backend usable?
    static bool IsBackendAvailable(const std::string& backend);

    // Print formatted summary table
    static void PrintCodecSummary(std::ostream& os = std::cout);
};

Codec Query Examples

Print all available codecs:

#include "rtp/codec_query.h"

int main() {
    mediax::rtp::CodecQuery::PrintCodecSummary();
    return 0;
}

Output:

Codec                   Backend     Direction   Accel       Compiled  Available
--------------------------------------------------------------------------------
Uncompressed RGB24      uncompressed Both       Software    Yes       Yes
Uncompressed YUV422     uncompressed Both       Software    Yes       Yes
Uncompressed Mono8      uncompressed Both       Software    Yes       Yes
Uncompressed Mono16     uncompressed Both       Software    Yes       Yes
H.264 OpenH264          openh264    Both        Software    Yes       Yes
H.264 VAAPI             vaapi       Both        Hardware    Yes       Yes
H.265 VAAPI             vaapi       Both        Hardware    Yes       Yes
AV1 VAAPI               vaapi       Both        Hardware    Yes       Yes
H.264 NVENC Encoder     nvenc       Encoder     Hardware    No        No
H.264 NVDEC Decoder     nvenc       Decoder     Hardware    No        No

Choose a backend at runtime:

#include "rtp/codec_query.h"
#include <iostream>

void select_h264_encoder() {
    using namespace mediax::rtp;

    // Prefer hardware, fall back to software
    if (CodecQuery::IsBackendAvailable("vaapi")) {
        std::cout << "Using VAAPI hardware encoder\n";
        // Use RtpH264VaapiPayloader
    } else if (CodecQuery::IsBackendAvailable("nvenc")) {
        std::cout << "Using NVENC hardware encoder\n";
        // Use RtpH264NvencPayloader
    } else if (CodecQuery::IsBackendAvailable("openh264")) {
        std::cout << "Using OpenH264 software encoder\n";
        // Use RtpH264OpenH264Payloader
    } else {
        std::cerr << "No H.264 encoder available\n";
    }
}

List only hardware codecs:

auto hw = mediax::rtp::CodecQuery::GetHardwareCodecs();
for (const auto& c : hw) {
    std::cout << c.name << " - " << c.description
              << " [" << (c.available ? "ready" : "not available") << "]\n";
}

Find all H.264 backends:

auto h264 = mediax::rtp::CodecQuery::GetCodecsByColourspace(
    mediax::rtp::ColourspaceType::kColourspaceH264Part10);
for (const auto& c : h264) {
    std::cout << c.name << " (" << c.backend << ") "
              << (c.acceleration == mediax::rtp::AccelerationType::kHardware
                  ? "[HW]" : "[SW]")
              << "\n";
}

Complete Example

#include <iostream>
#include <vector>
#include "rtp/rtp.h"
#include "uncompressed/rtp_uncompressed_payloader.h"
#include "sap/sap_announcer.h"

int main() {
    // Configure stream
    mediax::rtp::StreamInformation stream_info;
    stream_info.session_name = "example-stream";
    stream_info.hostname = "239.192.1.1";
    stream_info.port = 5004;
    stream_info.width = 1920;
    stream_info.height = 1080;
    stream_info.framerate = 30;
    stream_info.encoding = mediax::rtp::ColourspaceType::kColourspaceRgb24;

    // Setup SAP announcer
    mediax::sap::SapAnnouncer announcer;
    announcer.AddSapAnnouncement(stream_info);
    announcer.Start();

    // Setup payloader
    mediax::rtp::uncompressed::RtpUncompressedPayloader payloader;
    payloader.SetStreamInfo(stream_info);
    payloader.Open();

    // Transmit frames
    std::vector<uint8_t> buffer(1920 * 1080 * 3);
    for (int i = 0; i < 100; ++i) {
        // Fill buffer with frame data...
        payloader.Transmit(buffer.data(), true);
    }

    // Cleanup
    payloader.Close();
    announcer.Stop();
    announcer.DeleteAllSapAnnouncements();

    return 0;
}

Linking

find_package(mediax REQUIRED)
target_link_libraries(your_app PRIVATE mediax::mediax)

GigE Vision API

Requires -DBUILD_GIGE=ON.

GigEDevice — camera emulation

#include "gige/gige_device.h"

class mediax::gige::GigEDevice {
public:
  /// Set manufacturer/model strings written into the GenICam XML
  void SetDeviceInfo(std::string_view manufacturer, std::string_view model,
                     std::string_view version, std::string_view serial,
                     std::string_view user_name);

  /// Set pixel format, resolution and frame rate
  void SetImageParams(uint32_t width, uint32_t height,
                      GvspPixelFormat pixel_format, uint32_t framerate);

  /// Register callbacks fired on AcquisitionStart / AcquisitionStop commands
  void SetAcquisitionStartCallback(std::function<void()> cb);
  void SetAcquisitionStopCallback(std::function<void()> cb);

  /// Open GVCP port (UDP 3956) — returns false if port unavailable
  bool Open();
  void Close();

  /// Returns true once the host has sent AcquisitionStart
  bool IsStreaming() const;

  /// Send one frame. Pixels must match the configured pixel format and dimensions.
  bool SendFrame(const uint8_t* pixels);
};

GigEReceiver — host-side receiver

#include "gige/gige_receiver.h"
#include "gige/gvsp/gvsp_receiver.h"

class mediax::gige::GigEReceiver {
public:
  /// Set the local UDP port for GVSP streaming (default 55100)
  void SetReceivePort(uint16_t port);

  /// Discover and connect to a GigE Vision device at device_ip via GVCP
  bool Connect(const std::string& device_ip);

  /// Configure stream channel and send AcquisitionStart
  bool Open();
  void Close();

  /// Receive one frame. Returns false on timeout (timeout_ms).
  bool Receive(gvsp::GvspFrameData* frame, int timeout_ms);
};

struct mediax::gige::gvsp::GvspFrameData {
  uint32_t width;
  uint32_t height;
  GvspPixelFormat pixel_format;
  std::vector<uint8_t> pixels;  ///< Raw pixel data
};

GvspPixelFormat enum

#include "gige/gige_types.h"

enum class mediax::gige::GvspPixelFormat : uint32_t {
  kMono8      = 0x01080001,  ///< 8-bit monochrome
  kMono16     = 0x01100007,  ///< 16-bit monochrome (big-endian)
  kRgb8       = 0x02180014,  ///< 24-bit RGB
  kBayerGr8   = 0x01080008,  ///< 8-bit Bayer, GR phase
  kBayerRg8   = 0x01080009,  ///< 8-bit Bayer, RG phase
  kBayerGb8   = 0x0108000A,  ///< 8-bit Bayer, GB phase
  kBayerBg8   = 0x0108000B,  ///< 8-bit Bayer, BG phase
  kYcbcr422_8 = 0x0210003B,  ///< YCbCr 4:2:2, 8-bit YUYV
};

Colourspace Conversion API

BayerPattern enum

#include "utils/colourspace.h"

enum class mediax::video::BayerPattern : uint8_t {
  kRggb = 0,  ///< R G / G B  (top-left pixel is Red)
  kGrbg = 1,  ///< G R / B G
  kGbrg = 2,  ///< G B / R G
  kBggr = 3,  ///< B G / G R  (top-left pixel is Blue)
};

ColourSpaceCpu

CPU scalar with optional AVX2 SIMD (auto-detected at runtime on x86_64).

#include "utils/colourspace_cpu.h"

class mediax::video::ColourSpaceCpu {
public:
  /// Bayer raw → RGB24 bilinear demosaic.
  /// Returns number of output bytes written, or 0 on error.
  int BayerToRgb(uint32_t height, uint32_t width,
                 const uint8_t* bayer, uint8_t* rgb,
                 BayerPattern pattern) const;

  /// RGB24 → Bayer raw (CFA channel selection — no averaging).
  /// Returns number of output bytes written, or 0 on error.
  int RgbToBayer(uint32_t height, uint32_t width,
                 const uint8_t* rgb, uint8_t* bayer,
                 BayerPattern pattern) const;

  // Other conversions:
  int RgbToYuv(uint32_t height, uint32_t width,
               const uint8_t* rgb, uint8_t* yuv) const;
  int YuvToRgb(uint32_t height, uint32_t width,
               const uint8_t* yuv, uint8_t* rgb) const;
  int RgbToMono(uint32_t height, uint32_t width,
                const uint8_t* rgb, uint8_t* mono) const;
  int ScaleToSizeRgb(uint32_t src_h, uint32_t src_w, const uint8_t* src,
                     uint32_t dst_h, uint32_t dst_w, uint8_t* dst) const;
};

ColourSpaceCuda

GPU-accelerated version with the same interface, plus CUDA kernels for Bayer demosaicing. Requires -DBUILD_CUDA=ON.

#include "utils/colourspace_cuda.h"

class mediax::video::ColourSpaceCuda {
public:
  int BayerToRgb(uint32_t height, uint32_t width,
                 const uint8_t* bayer, uint8_t* rgb,
                 BayerPattern pattern) const;
  int RgbToBayer(uint32_t height, uint32_t width,
                 const uint8_t* rgb, uint8_t* bayer,
                 BayerPattern pattern) const;
  // ... same interface as ColourSpaceCpu for all other methods
};

Support