Recording Video

MediaX provides built-in recording capabilities to save video streams to Matroska (MKV) files.

Overview

Recording can be enabled on both payloaders (transmitters) and depayloaders (receivers), allowing you to:

  • Record locally generated video to file
  • Capture incoming RTP streams to disk
  • Stream and record simultaneously
  • Record with different codecs (raw, H.264)

Output Modes

MediaX supports three output modes:

Mode Description
kStreamOnly Stream only, no recording (default)
kRecordOnly Record only, no network streaming
kStreamAndRecord Both stream and record simultaneously

Recording with Payloaders

Uncompressed (Raw) Recording

#include "uncompressed/rtp_uncompressed_payloader.h"

mediax::rtp::uncompressed::RtpUncompressedPayloader payloader;

// Configure stream info
mediax::rtp::StreamInformation stream_info;
stream_info.session_name = "RawRecording";
stream_info.hostname = "127.0.0.1";  // Can be dummy for record-only mode
stream_info.port = 5004;
stream_info.width = 640;
stream_info.height = 480;
stream_info.framerate = 25;
stream_info.encoding = mediax::rtp::ColourspaceType::kColourspaceRgb24;

payloader.SetStreamInfo(stream_info);

// Configure recording
payloader.SetOutputMode(mediax::rtp::OutputMode::kRecordOnly);
payloader.SetRecordingFilename("output_raw.mkv");

payloader.Open();

// Send frames - they will be written to file
std::vector<uint8_t> rgb_buffer(640 * 480 * 3);
// Fill buffer with video frame...
payloader.Transmit(rgb_buffer.data(), true);

payloader.Close();  // Finalizes the recording

H.264 Recording with OpenH264

#include "h264/openh264/rtp_h264_openh264_payloader.h"

mediax::rtp::h264::openh264::RtpH264OpenH264Payloader payloader;

// Configure encoder
mediax::rtp::h264::openh264::EncoderConfig config;
config.width = 1920;
config.height = 1080;
config.framerate = 30;
config.bitrate = 4000000;         // 4 Mbps
config.keyframe_interval = 30;    // IDR every second
payloader.SetEncoderConfig(config);

// Configure stream info
mediax::rtp::StreamInformation stream_info;
stream_info.session_name = "H264Recording";
stream_info.hostname = "127.0.0.1";
stream_info.port = 5004;
stream_info.width = 1920;
stream_info.height = 1080;
stream_info.framerate = 30;
stream_info.encoding = mediax::rtp::ColourspaceType::kColourspaceRgb24;

payloader.SetStreamInfo(stream_info);

// Record only (no network streaming)
payloader.SetOutputMode(mediax::rtp::OutputMode::kRecordOnly);
payloader.SetRecordingFilename("output_h264.mkv");

payloader.Open();

// Transmit RGB frames - encoder compresses and writes to file
std::vector<uint8_t> rgb_buffer(1920 * 1080 * 3);
// Fill buffer with video frame...
payloader.Transmit(rgb_buffer.data(), true);

payloader.Close();

H.264 Recording with VAAPI (Hardware Accelerated)

#include "h264/vaapi/rtp_h264_vaapi_payloader.h"

// Check if VAAPI is available
if (!mediax::rtp::h264::vaapi::RtpH264VaapiPayloader::IsVaapiAvailable()) {
  std::cerr << "VAAPI not available on this system\n";
  return 1;
}

mediax::rtp::h264::vaapi::RtpH264VaapiPayloader payloader;

// Configure VAAPI encoder
mediax::rtp::h264::vaapi::VaapiEncoderConfig config;
config.width = 1920;
config.height = 1080;
config.framerate = 30;
config.bitrate = 4000000;         // 4 Mbps
config.keyframe_interval = 30;    // IDR every second
payloader.SetEncoderConfig(config);

// Configure stream info
mediax::rtp::StreamInformation stream_info;
stream_info.session_name = "VaapiRecording";
stream_info.hostname = "127.0.0.1";
stream_info.port = 5004;
stream_info.width = 1920;
stream_info.height = 1080;
stream_info.framerate = 30;
stream_info.encoding = mediax::rtp::ColourspaceType::kColourspaceRgb24;

payloader.SetStreamInfo(stream_info);

// Stream and record simultaneously
payloader.SetOutputMode(mediax::rtp::OutputMode::kStreamAndRecord);
payloader.SetRecordingFilename("output_vaapi.mkv");

payloader.Open();

// Transmit frames
std::vector<uint8_t> rgb_buffer(1920 * 1080 * 3);
payloader.Transmit(rgb_buffer.data(), true);

payloader.Close();

Recording with Depayloaders

You can also record incoming RTP streams directly:

Recording Incoming H.264 Stream

#include "h264/openh264/rtp_h264_openh264_depayloader.h"

mediax::rtp::h264::openh264::RtpH264OpenH264Depayloader depayloader;

mediax::rtp::StreamInformation stream_info;
stream_info.hostname = "239.192.1.1";
stream_info.port = 5004;
stream_info.width = 1920;
stream_info.height = 1080;
stream_info.encoding = mediax::rtp::ColourspaceType::kColourspaceH264Part10;

depayloader.SetStreamInfo(stream_info);

// Enable recording while receiving
depayloader.SetOutputMode(mediax::rtp::OutputMode::kStreamAndRecord);
depayloader.SetRecordingFilename("captured_stream.mkv");

depayloader.Open();
depayloader.Start();

// Receive and display frames while also recording
std::vector<uint8_t> rgb_buffer(1920 * 1080 * 3);
while (running) {
  depayloader.Receive(rgb_buffer.data(), 1000);
  // Display or process the frame...
}

depayloader.Stop();
depayloader.Close();

Recording Incoming Raw Stream

#include "uncompressed/rtp_uncompressed_depayloader.h"

mediax::rtp::uncompressed::RtpUncompressedDepayloader depayloader;

mediax::rtp::StreamInformation stream_info;
stream_info.hostname = "239.192.1.1";
stream_info.port = 5004;
stream_info.width = 640;
stream_info.height = 480;
stream_info.encoding = mediax::rtp::ColourspaceType::kColourspaceRgb24;

depayloader.SetStreamInfo(stream_info);

// Record only mode - capture to file without processing
depayloader.SetOutputMode(mediax::rtp::OutputMode::kRecordOnly);
depayloader.SetRecordingFilename("captured_raw.mkv");

depayloader.Open();
depayloader.Start();

// Recording happens automatically during Receive()
std::vector<uint8_t> buffer(640 * 480 * 3);
while (running) {
  depayloader.Receive(buffer.data(), 1000);
}

depayloader.Stop();
depayloader.Close();

API Reference

OutputMode Enum

enum class OutputMode {
  kStreamOnly,      // Stream only, no recording (default)
  kRecordOnly,      // Record only, no streaming
  kStreamAndRecord  // Both stream and record
};

Recording Methods

Both RtpPayloader and RtpDepayloader provide:

Method Description
SetOutputMode(mode) Set the output mode
GetOutputMode() Get the current output mode
SetRecordingFilename(filename) Set the output MKV filename
GetRecordingFilename() Get the recording filename
IsStreamingEnabled() Check if streaming is enabled
IsRecordingEnabled() Check if recording is enabled

File Format

Recordings are saved in Matroska (MKV) format:

Codec MKV Codec ID Description
Raw V_MS/VFW/FOURCC Uncompressed RGB24 video
H.264 V_MPEG4/ISO/AVC MPEG-4 AVC with AVCC format

MKV files can be played with:

  • VLC media player
  • ffplay (ffplay recording.mkv)
  • mpv
  • Most modern video players

Recording Example

A complete recording example is included in the examples:

# Build the recording example
cd build
make recording-example

# Record 10 seconds of uncompressed video
./bin/recording-example --duration=10 --encoder=0 --output=my_video

# Record with OpenH264
./bin/recording-example --duration=10 --encoder=1 --output=my_video

# Record with VAAPI (if available)
./bin/recording-example --duration=10 --encoder=2 --output=my_video

Example Options

Option Description Default
--width Video width 640
--height Video height 480
--framerate Frame rate 25
--duration Recording duration (seconds) 10
--output Output filename base rotating_cube
--encoder 0=Raw, 1=OpenH264, 2=VAAPI 0

Best Practices

  1. Always call Close(): This finalizes the MKV file structure
  2. Use H.264 for large recordings: Raw video uses significant disk space
  3. Hardware encoding: Use VAAPI when available for better performance
  4. Check VAAPI availability: Call IsVaapiAvailable() before using VAAPI encoder
  5. Set keyframe interval: For H.264, set a reasonable keyframe interval for seeking

Troubleshooting

Recording not playing

  • Ensure Close() was called to finalize the file
  • Check that frames were actually transmitted/received
  • Verify the output file size is reasonable

Large file sizes

  • Use H.264 encoding instead of raw
  • Reduce resolution or framerate
  • Adjust H.264 bitrate

VAAPI not available

  • Install VAAPI drivers (vainfo to check)
  • Ensure your GPU supports VAAPI
  • Try OpenH264 as an alternative