MXWrite - simple static library for writing RGBA video
FFmpeg-Based Video Writer
This repository provides a C++ class (Writer) that uses the FFmpeg libraries to write raw RGBA frames to an MP4 (or TS) file in H.264 format. It supports both a straightforward, frame-by-frame workflow (open(), write(), and close()) and a timestamp-based workflow (open_ts(), write_ts(), and close()).
Overview
Writer is a C++ class that simplifies encoding and writing video frames to a container file. You can:
- Open an output file (MP4 or TS container).
- Write raw RGBA data (passed in as a pointer) to the file, converting it to YUV420P under the hood.
- Optionally use hardware acceleration (CUDA) if available.
- Close and finalize the file properly.
It can handle both:
- Frame-by-frame mode: For applications where you generate or capture frames at a known rate.
- Timestamp-based mode: For applications that require precise PTS (presentation timestamp) control, typically when your source frames arrive at irregular intervals.
Dependencies
Required Libraries
- FFmpeg – The code specifically uses the following components:
- libavcodec
- libavformat
- libavutil
- libswscale
- Threads (C++11 and above) – Uses <thread> and <mutex> from the standard library.
- A C++17 (or higher) compatible compiler.
To install FFmpeg development libraries on your platform:
- Ubuntu / Debian:
sudo apt-get update
sudo apt-get install ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev
- Windows:
- Install via vcpkg, MSYS2, or download and build FFmpeg from source.
- macOS:
Building
Configure and build:
mkdir -p build
cd build
cmake ..
cmake --build .
Usage
You can include the mxwrite.hpp header in your own C++ files and link against the library. Below is a quick example:
#include <vector>
bool ok = writer.
open(
"output.mp4", 1280, 720, 30.0f,
"24");
if (!ok) {
return 1;
}
std::vector<uint8_t> dummyRGBA(1280 * 720 * 4, 255);
for (int i = 0; i < 60; ++i) {
writer.
write(dummyRGBA.data());
}
return 0;
}
FFmpeg-backed RGBA video writer.
bool open(const std::string &filename, int width, int height, float fps, const char *crf)
Open an output file using the legacy CRF string interface.
void write(void *rgba_buffer)
Queue a host RGBA frame for immediate-mode encoding.
void close()
Close the writer and flush pending packets.
int main(int argc, char **argv)
FFmpeg-based video writer used by MXWrite.
For explicit HEVC NVENC configuration, use EncodeOptions. Extra parameters use FFmpeg command-line spelling and override the built-in preset/tune defaults:
options.
codec =
"hevc_nvenc";
"-preset p6 -tune lossless -profile:v rext -pix_fmt yuv444p";
if (!writer.
open(
"output_hardware_lossless.mkv", 1920, 1080, 60.0f, options)) {
return 1;
}
User-configurable video encoder quality options.
std::string codec
Encoder selection policy or exact FFmpeg encoder name.
std::string ffmpeg_options
Additional FFmpeg-style video encoder options.
MXWrite uses the FFmpeg libraries directly, so the parameter string contains video encoder/muxer options only; input and output filenames are supplied to Writer::open().
EncodeOptions::codec also accepts any exact video encoder name registered by the linked FFmpeg libraries. For example, libx264 and libx265 remain separate selections, and codecs such as libsvtav1, libvpx-vp9, prores_ks, ffv1, h264_qsv, hevc_vaapi, and h264_videotoolbox can be selected when present. MXWrite automatically chooses a compatible system-memory pixel format; hardware-frame-only encoders use FFmpeg's device and frame-pool APIs.
Applications can populate encoder controls without maintaining a hard-coded list:
std::cout << encoder.name << " (" << encoder.codec_name << ")\n";
}
std::cout << "-" << option.name << ": " << option.help << "\n";
}
std::vector< EncoderInfo > available_video_encoders()
std::vector< EncoderOptionInfo > video_encoder_options(std::string_view encoder_name)
Return the options exposed by one registered video encoder.
A video encoder reported by the linked FFmpeg installation.
One configurable AVOption exposed by a video encoder.
An encoder being registered does not guarantee that its hardware is usable. Device-backed encoders return a clear open error when the required GPU, driver, or operating-system device is unavailable.