
VideoRecorderMp4 C++ library
v3.1.1
Table of contents
- Overview
- Versions
- Library files
- VideoRecorderMp4 class description
- Limits and guarantees
- Security and hardening
- Portability
- Build and connect to your project
- Example application
- Third-party components
Overview
The VideoRecorderMp4 C++ library records video into standard .mp4 files. It records compressed video (H264, HEVC/H265 and JPEG) as it is and compresses uncompressed video frames (NV12, NV21, YU12, YV12, YUYV, UYVY, BGR24, RGB24, YUV24, GRAY) before recording.
VideoRecorderMp4 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.
Key capabilities of the library:
- Asynchronous recording:
write()copies the frame into an internal buffer and returns. Pixel format conversion, compression and file writing take place on a background worker thread. The calling thread waits only if the worker is still busy with the previous frame. - Direct recording of compressed video: frames already compressed in H264, HEVC or JPEG are packed into the MP4 container as they are. H264 / HEVC parameter sets are stored in the file header, all slices of a picture form one MP4 sample.
- Built-in compression of uncompressed video: when no custom codec is set, uncompressed frames are converted to NV12 (if they are not NV12 already) with the FormatConverter library (2 threads) and encoded to JPEG with the VEncoderJPEG library (quality 80%, 2 threads).
- Custom codec support: an external encoder can be set with
setCodec()/addCodec()to compress uncompressed frames to H264, HEVC or JPEG. - Recording modes:
- Single file mode: one MP4 file is recorded until
stop()is called or theVideoRecorderMp4object is destroyed. - Segmented mode: a new file is started when the file reaches the file size limit, and the oldest recordings are deleted when the recordings in the folder exceed the folder size limit.
- Single file mode: one MP4 file is recorded until
The library is cross-platform, written in C++17 and works on Windows and Linux (x86-64, ARM).
Versions
Table 1 - Library versions.
| Version | Release date | What’s new |
|---|---|---|
| 1.0.0 | 31.03.2025 | - First version. |
| 1.0.1 | 14.08.2025 | - Fix compiler warnings. |
| 1.0.2 | 15.11.2025 | - VCodecLibav submodule updated for test application. |
| 1.0.3 | 17.04.2026 | - VCodecLibav submodule updated for test application. |
| 2.0.0 | 08.05.2026 | - Remove mp4v2 dependency. - Implement mp4 container packer. - Added HEVC and JPEG support. - Remove VCodecLibav from the test app. - Added VSourceFile to the test app. - Rewrite the test app. |
| 2.0.1 | 31.07.2026 | - Increase file and folder size limits. |
| 3.0.0 | 30.09.2026 | - Asynchronous background worker thread for non-blocking write().- Integrated internal format conversion and encoding using FormatConverter, VCodec, and VEncoderJPEG. - Automatic compression of uncompressed frames (NV12, BGR24, RGB24, YUYV, UYVY, GRAY, etc.) to JPEG (quality 80%, 2 threads) with NV12 conversion (2 threads). - Added setCodec() / addCodec() to support custom external encoders.- Added single-file continuous recording mode without file/folder rotation. - Overhauled example application with CLI arguments support and all pixel format choices. |
| 3.1.0 | 08.10.2026 | - Source code restructured (implementation in the src/impl folder). MP4 files written for valid input are bit-identical with version 3.0.0, except for the fixes below. - Fixed: all slices of a multi-slice H264 / HEVC picture are written as one MP4 sample (each slice was a separate sample). - Fixed: folder size control deleted any file of the folder and could delete the file being recorded; now only recordings are deleted and never the current file. - Fixed: a new file started within the same second as the previous one overwrote it; now “_1”, “_2”, … is added to the name. - Fixed: data races and a possible deadlock when methods were called from different threads; all methods are thread-safe now. - Fixed: chroma format and bit depth in the ‘avcC’ / ‘hvcC’ boxes are taken from the SPS (4:2:2, 4:4:4, 10-bit streams). - Uncompressed frames smaller than their width, height and format require are refused by write(); frames of another format than the open file are refused; pictures wider or higher than 65535 pixels are refused (they were truncated in the file header).- init() checks the parameters strictly (numbers, fps 1..90000, folder must exist or be creatable).- Compiler warnings and exploit mitigation options for all targets. - Example application rewritten, documentation updated. |
| 3.1.1 | 15.10.2026 | - The repository has no sub-repositories: Frame, FormatConverter, VCodec and VEncoderJPEG are expected in the folders next to the library or are added by the project that includes the library (see Build and connect to your project). The example application generates its video and does not use VSourceFile. - Fixed: the folder size control could delete a newer recording instead of the oldest one when files were written within the same clock tick; a new file that starts within the same second as other files gets the number after the highest number of those files. - Fixed: H264 / HEVC NAL units do not contain the zero bytes in front of the next start code (trailing_zero_8bits); empty NAL units and NAL units with forbidden_zero_bit set are skipped; a frame with more than 65536 NAL units is refused. - Fixed: HEVC BLA pictures are random access pictures (sync samples, start of a file). - Fixed: the ‘avcC’ box of H264 profiles 44, 83, 86, 118, 128, 134, 135, 138, 139 and 244 carries the chroma format and the bit depths (only profiles 100, 110, 122 and 144 had them). - JPEG frames that do not start with a JPEG signature are refused. - init() rejects a prefix with control characters, path separators or the characters : * ? " < > \|, paths with control characters and file paths without a file name (for example "dir/").- In segmented mode the frame that would start the next file is refused if the previous file could not be completed. - Fixed: the sample tables grow before the sample is written, so a failed memory allocation cannot leave the file and its tables inconsistent. - Example application: non-zero exit code if writing fails. - The options ${PARENT}_VIDEO_RECORDER_MP4 and ${PARENT}_VIDEO_RECORDER_MP4_EXAMPLE follow ${PARENT}_SUBMODULE_CACHE_OVERWRITE. |
Library files
The library is supplied as source code only. The repository structure is shown below (the libraries it depends on are described in Build stand alone):
CMakeLists.txt ------------------- Main CMake file of the library.
example -------------------------- Folder of the example application.
CMakeLists.txt --------------- CMake file of the example application.
main.cpp --------------------- Source code of the example application (test video generator and recorder).
src ------------------------------ Folder with library source code.
CMakeLists.txt --------------- CMake file of the library.
VideoRecorderMp4.cpp --------- VideoRecorderMp4 class implementation.
VideoRecorderMp4.h ----------- VideoRecorderMp4 class declaration.
VideoRecorderMp4Version.h ---- Header file with library version.
VideoRecorderMp4Version.h.in - CMake template of the version header.
impl ------------------------- Folder with internal implementation.
AnnexB.cpp --------------- H264 / HEVC NAL unit parsing.
AnnexB.h ----------------- H264 / HEVC NAL unit parsing declarations.
Mp4Boxes.cpp ------------- MP4 box serialization.
Mp4Boxes.h --------------- MP4 box serialization declarations.
Mp4FileWriter.cpp -------- MP4 file writer (one video track).
Mp4FileWriter.h ---------- MP4 file writer declaration.
RecorderSettings.cpp ----- Parsing and validation of init() parameters.
RecorderSettings.h ------- Recorder settings declaration.
RecordingStorage.cpp ----- File names, file size check, folder size control.
RecordingStorage.h ------- Recording storage declaration.
StreamRecorder.cpp ------- Compressed frames to MP4 samples, segments.
StreamRecorder.h --------- Stream recorder declaration.
VideoRecorderMp4Impl.cpp - Worker thread, compression of raw frames.
VideoRecorderMp4Impl.h --- Implementation class declaration.
static --------------------------- Documentation image and test videos (H264, HEVC, Motion JPEG).
VideoRecorderMp4 class description
VideoRecorderMp4 class declaration
The VideoRecorderMp4 class is declared in the src/VideoRecorderMp4.h header file:
namespace rapidpixel
{
class VideoRecorderMp4
{
public:
/// Class constructor.
VideoRecorderMp4();
/// Class destructor. Stops the recording and completes the file.
~VideoRecorderMp4();
/// Copy and move are deleted.
VideoRecorderMp4(const VideoRecorderMp4&) = delete;
VideoRecorderMp4(VideoRecorderMp4&&) = delete;
VideoRecorderMp4& operator=(const VideoRecorderMp4&) = delete;
VideoRecorderMp4& operator=(VideoRecorderMp4&&) = delete;
/// Get current class version string.
static std::string getVersion();
/// Init video recorder with a configuration string.
bool init(std::string initString);
/// Init video recorder for one file.
bool init(std::string filePath, int fps);
/// Init video recorder with a recording folder.
bool init(std::string folder, int maxFolderSizeMB, int maxFileSizeMB,
std::string prefix, int fps);
/// Write video frame.
bool write(Frame& frame);
/// Stop video recording and complete the file.
void stop();
/// Set custom video codec for encoding raw frames.
void setCodec(rapidpixel::VCodec* codec);
/// Set custom video codec (alias for setCodec).
void addCodec(rapidpixel::VCodec* codec);
};
}
getVersion method
The getVersion() method returns a string of the current VideoRecorderMp4 library version:
static std::string getVersion();
Example usage:
std::cout << "VideoRecorderMp4 v" << rapidpixel::VideoRecorderMp4::getVersion() << std::endl;
Console output:
VideoRecorderMp4 v3.1.1
init methods
Each init(…) method stops a running recording first and returns true if the new recording was started or false if the parameters are invalid or the folder cannot be created. File paths are UTF-8 strings without control characters; missing folders are created. The first file is created when the first frame that can start a file arrives, so true does not mean that the file can be created. On Windows a path longer than 259 characters is refused by init(…) unless it starts with the extended-length prefix \\?\ or the application is long path aware.
1. Initialization with a string
bool init(std::string initString);
The fields of the string are separated by ; (empty fields are ignored), so a path or a prefix cannot contain ;. Numbers are decimal integers. The rules of the third and the second init(…) method apply to the paths and to the prefix.
- Recording folder:
"<folder>;<maxFolderSizeMB>;<maxFileSizeMB>;<prefix>;<fps>", for example"recordings;2000;200;cam1;30". The fields have the meaning of the parameters of the third init(…) method. If both size limits are0(or less), one file with a generated name is recorded in the folder. - One file:
"<filePath>;<fps>"or"<filePath>"(30 fps), for example"output.mp4;25"or"D:/records/camera.mp4".
2. One file
bool init(std::string filePath, int fps);
| Parameter | Description |
|---|---|
| filePath | Output file path, for example "video.mp4" or "records/test.mp4". It must name a file (not "records/", "." or ".."). An existing file is overwritten. |
| fps | Frame rate, 1..90000. |
The file is recorded until stop() is called or the object is destroyed.
3. Recording folder
bool init(std::string folder, int maxFolderSizeMB, int maxFileSizeMB, std::string prefix, int fps);
| Parameter | Description |
|---|---|
| folder | Recording folder, must not be empty or contain control characters. |
| maxFolderSizeMB | Folder size limit in decimal megabytes (1 MB = 1 000 000 bytes). |
| maxFileSizeMB | File size limit in decimal megabytes. If both limits are 0 (or less), one file is recorded until stop() (single file mode). Otherwise both limits must be greater than 0 and maxFolderSizeMB must not be smaller than maxFileSizeMB (segmented mode). |
| prefix | File name prefix, must not be empty in segmented mode. It must not contain control characters, path separators or the characters : * ? " < > \| (they are not allowed in Windows file names). |
| fps | Frame rate, 1..90000. |
Files are named <prefix>_DD_MM_YYYY_HH_MM_SS.mp4 (local time). If files of that second exist (for example when several files start within one second), _<number> is added before .mp4: the number after the highest number of those files (_1 if only the name without a number exists). The file name is chosen by checking that it is free and the file is created afterwards, so the recording folder must not be writable by untrusted users.
In segmented mode:
- The file size is checked before each frame. When the file reached maxFileSizeMB, the next file starts with the next frame that carries parameter sets or a key picture (H264, HEVC) or with the next frame (JPEG). The current file can therefore be larger than the limit by the frames up to the next key frame.
- Before the first file and before each new file, the oldest recordings are deleted while all recordings in the folder together are larger than maxFolderSizeMB. Only files named like recordings (
<any prefix>_DD_MM_YYYY_HH_MM_SS.mp4or with a_Nsuffix) are counted and deleted; other files of the folder are never touched. The file being recorded is counted but never deleted, so the folder can exceed the limit by the size of the current file. The oldest recording is the one with the oldest modification time; for equal times the time and the number in the name decide.
setCodec and addCodec methods
By default uncompressed frames are compressed to JPEG with the built-in VEncoderJPEG library. To encode them with another codec (for example a hardware H264 / HEVC encoder or a JPEG encoder with other settings), pass a pointer to a VCodec instance:
void setCodec(rapidpixel::VCodec* codec);
void addCodec(rapidpixel::VCodec* codec);
| Parameter | Description |
|---|---|
| codec | Pointer to a VCodec instance whose transcode() method outputs H264, HEVC or JPEG frames, or nullptr to use the built-in JPEG encoder. |
The codec is used from the next frame on. The method waits until a frame that is being processed is done, so the previous codec is not used after the method returns. The codec object must stay valid until it is replaced or the recording is stopped. addCodec() is an alias of setCodec().
write method
bool write(Frame& frame);
The write(…) method passes a video frame for recording:
- Asynchronous execution: the frame is copied into an internal buffer and the method returns. Compression, format conversion and file writing run on the background worker thread. The method waits only if the processing of the previous frame has not finished yet.
- Compressed frames: H264 and HEVC frames are Annex B access units (NAL units with start codes, at most 65536 NAL units per frame), JPEG frames are complete JPEG images that start with the JPEG signature (
0xFF 0xD8 0xFF). They are written without re-encoding. The width and the height of the frame (1..65535) are written into the file header. Parameter sets (SPS, PPS and VPS) are taken from the stream and written into the file header. A file starts when the parameter sets are known and a key frame arrives. Frames are dropped until the parameter sets are known; after that the file starts with a key frame or, if none comes, after 60 dropped frames in total. - Uncompressed frames (NV12, NV21, YU12, YV12, YUYV, UYVY, BGR24, RGB24, YUV24, GRAY):
frame.sizemust be at least the size ofwidth x heightpixels of the format. The built-in converter and encoder need an even width and an even height of at most 65535; the encoder can refuse a frame of about 16x16 pixels or less that is full of noise. A frame that they refuse is accepted by write(…) but not recorded, and the failure is reported by the next call. Without a custom codec the frame is converted to NV12 (if needed) by FormatConverter with 2 threads and encoded to JPEG by VEncoderJPEG with quality 80% and 2 threads. With a custom codec the frame is encoded by that codec. - One format per file: all frames written into one file must have the same compressed format. Frames of another format are refused while the file is open.
The data pointer of the frame must be readable for frame.size bytes: the method cannot check it.
Returns: true if the frame was accepted for recording. false if the recorder is not initialized, the frame is invalid (no data, size or dimensions not positive, too small for its format) or recording of the previous frame failed. Errors of the worker thread are reported once by the next call of write(…), and the frame of that call is not recorded. If a segmented recording cannot complete a file (for example because the disk is full), the frame that would start the next file is not recorded and the failure is reported in the same way; the frame after it starts the next file.
stop method
void stop();
The stop() method completes recording:
- Waits until the frame being processed is written.
- Stops the background worker thread.
- Writes the MP4 index (
moovbox with sample tables and durations) and closes the output file.
Calling stop() is recommended when finishing a recording. If it is not called, the class destructor calls it. Calling stop() without a running recording does nothing. A failure to complete the last file (for example a full disk) is not reported by this method.
Limits and guarantees
Table 2 - Limits of the library.
| Item | Limit / behaviour |
|---|---|
| File size | The media data of one file must stay below 4 GiB (32-bit chunk offsets). In segmented mode a new file is started; in single file mode further frames are refused. |
| Samples per file | 300 000 000 (keeps the MP4 index below 4 GiB); afterwards frames are refused as above. |
| Picture size | 1..65535 pixels in width and height (MP4 sample entry). |
| NAL units per frame | At most 65536; a frame with more NAL units is refused. |
| Raw frames | Even width and height of at most 65535 pixels for the built-in converter and encoder. |
| Frame rate | 1..90000 fps. The time scale is 90 kHz, every sample lasts 90000 / fps ticks (integer division). |
| Start of a file | Parameter sets are needed: frames are dropped until they are known. Then the file starts with a key frame, or with the next frame after 60 dropped frames in total. |
| B-frames | Composition time offsets (ctts) are not written: samples are stored in decoding order with equal durations. |
| Parameter set changes | The parameter sets of the start of a file are stored in its header and removed from the samples. Streams that change SPS / PPS within one file (for example a resolution change) need a new file (init() or a new segment). |
| Memory | Two frame buffers of the size of the largest frame, the buffers of the encoders and up to 12 bytes of sample tables per recorded frame. |
| Thread safety | All methods can be called from different threads. write(…) blocks while the previous frame is processed. The methods must not be called from inside the transcode() method of a codec set with setCodec(). |
Security and hardening
Untrusted input. Frames passed to write(), the init() parameters and the content of the recording folder are treated as untrusted:
- H264 / HEVC frames are split into NAL units without reading outside the frame; the number of NAL units is limited. Parameter sets larger than 65535 bytes are rejected, the SPS fields are parsed from at most 256 bytes with bounds checks. NAL units shorter than their header are not written.
- JPEG frames must start with the JPEG signature.
- File name prefixes cannot contain path separators, so a file is always created inside the recording folder.
- Uncompressed frames are checked against the size their width, height and format require before any converter or encoder reads them.
- Numbers of the initialization string must be complete decimal integers in range; invalid parameters make
init()fail. - Folder size control only deletes files named like recordings and never the file being recorded.
Memory and CPU use are bounded by the frame size and by the limits in Table 2. The worker thread processes one frame at a time; there is no frame queue.
What the library does not do: it does not open network connections, run other programs, load plugins, read environment variables or print messages. It writes only the recording files and, in segmented mode, deletes only old recordings in the recording folder.
Build hardening. The library and the example are compiled with all warnings and with exploit mitigation options:
- GCC / Clang:
-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion -Wold-style-cast -Wcast-qual -Wformat=2 -Wnon-virtual-dtor -Woverloaded-virtual -Wdouble-promotion -Wimplicit-fallthrough -Wmissing-declarations -Wundef -Wextra-semi -Wzero-as-null-pointer-constant(-Wdocumentationfor Clang),-fstack-protector-strong,-D_FORTIFY_SOURCE=2(optimized builds),-fstack-clash-protection,-fcf-protection=full(x86) or-mbranch-protection=standard(ARM) if supported, linker options-z relro -z now -z noexecstack. - MSVC:
/W4 /permissive- /sdl /GS /guard:cf, linker options/DYNAMICBASE /NXCOMPAT /guard:cf.
Portability
The library is written in C++17 without compiler extensions. It does not depend on the byte order of the host: every multi-byte field of the MP4 files is written big-endian byte by byte. File and folder paths are UTF-8 strings (Windows and Linux). The library has no SIMD code of its own: the pixel format converter (AVX2, SSE4.1, NEON or plain C++) and the JPEG encoder (AVX2, SSSE3 or plain C++) it uses select their instruction set when they run, so one build runs on every CPU of its architecture.
The library and the example application are built without compiler warnings and run with MSVC 2022 (Windows, x86-64), GCC 12 and 13 and Clang 15 and 18 (Linux, x86-64) and GCC 13 (Linux, AArch64, run under emulation), in Release and Debug configurations. MP4 files recorded from the same compressed or uncompressed frames are identical on all of them (the creation time in the file header is not compared).
Build and connect to your project
Build stand alone
The repository does not contain sub-repositories. The libraries VideoRecorderMp4 depends on (Frame, FormatConverter, VCodec and VEncoderJPEG) must be cloned into the same folder as VideoRecorderMp4. The library uses CMake (3.13 or newer) and C++17. The folder structure must be:
<work folder>
VideoRecorderMp4
Frame
FormatConverter
VCodec
VEncoderJPEG
Typical commands to build the library and the example application (use the URLs of the repositories provided to you):
git clone <VideoRecorderMp4 repository URL>
git clone <Frame repository URL>
git clone <FormatConverter repository URL>
git clone <VCodec repository URL>
git clone <VEncoderJPEG repository URL>
cd VideoRecorderMp4
mkdir build
cd build
cmake ..
make
On Windows use cmake --build . --config Release instead of make. The executable VideoRecorderMp4Example is placed in the bin folder of the build folder. If VideoRecorderMp4 is the top-level CMake project, the main CMakeLists.txt file adds the folders ../Frame, ../FormatConverter, ../VCodec and ../VEncoderJPEG (in this order) before the library itself. If a folder does not exist CMake stops with an error.
CMake options
Table 3 - CMake options of the repository. In the options below ${PARENT} is the prefix defined by the top-level project (empty if VideoRecorderMp4 is the top-level project).
| Option | Default | Description |
|---|---|---|
| ${PARENT}_VIDEO_RECORDER_MP4 | ON | Build the library. |
| ${PARENT}_VIDEO_RECORDER_MP4_EXAMPLE | ON (stand alone), OFF (included in other project) | Build the example application. |
| ${PARENT}_SUBMODULE_CACHE_OVERWRITE | ON | Forced rewriting of the options above in the CMake cache. The top-level project sets it to OFF when it includes VideoRecorderMp4 as a sub-repository and chooses the options itself. |
| CMAKE_BUILD_TYPE | Release (if not specified) | Build type. |
Connect to your project
Add the repositories of VideoRecorderMp4 and of the libraries it depends on to your project (for example as sub-repositories inside a 3rdparty folder), add them to CMake in the order of their dependencies (Frame, FormatConverter, VCodec, VEncoderJPEG, VideoRecorderMp4) and link the library to your target. When VideoRecorderMp4 is included in another project it does not add its dependencies: the project must add them, otherwise the build fails because the header files of the dependencies are not found (for example Frame.h: No such file or directory).
The 3rdparty/CMakeLists.txt file of your project:
cmake_minimum_required(VERSION 3.13)
################################################################################
## 3RD-PARTY
## dependencies for the project
################################################################################
project(3rdparty LANGUAGES CXX)
################################################################################
## SETTINGS
## basic 3rd-party settings before use
################################################################################
# To inherit the top-level architecture when the project is used as a submodule.
SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
# Disable self-overwriting of parameters inside included subdirectories.
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)
################################################################################
## CONFIGURATION
## 3rd-party submodules configuration
################################################################################
SET(${PARENT}_SUBMODULE_FRAME ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_FRAME)
SET(${PARENT}_FRAME ON CACHE BOOL "" FORCE)
SET(${PARENT}_FRAME_TEST OFF CACHE BOOL "" FORCE)
endif()
SET(${PARENT}_SUBMODULE_FORMAT_CONVERTER ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_FORMAT_CONVERTER)
SET(${PARENT}_FORMAT_CONVERTER ON CACHE BOOL "" FORCE)
SET(${PARENT}_FORMAT_CONVERTER_BENCHMARK OFF CACHE BOOL "" FORCE)
endif()
SET(${PARENT}_SUBMODULE_VCODEC ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_VCODEC)
SET(${PARENT}_VCODEC ON CACHE BOOL "" FORCE)
endif()
SET(${PARENT}_SUBMODULE_VENCODERJPEG ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_VENCODERJPEG)
SET(${PARENT}_VENCODERJPEG ON CACHE BOOL "" FORCE)
SET(${PARENT}_VENCODERJPEG_TEST OFF CACHE BOOL "" FORCE)
SET(${PARENT}_VENCODERJPEG_EXAMPLE OFF CACHE BOOL "" FORCE)
SET(${PARENT}_VENCODERJPEG_BENCHMARK OFF CACHE BOOL "" FORCE)
endif()
SET(${PARENT}_SUBMODULE_VIDEO_RECORDER_MP4 ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_VIDEO_RECORDER_MP4)
SET(${PARENT}_VIDEO_RECORDER_MP4 ON CACHE BOOL "" FORCE)
SET(${PARENT}_VIDEO_RECORDER_MP4_EXAMPLE OFF CACHE BOOL "" FORCE)
endif()
################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
if (${PARENT}_SUBMODULE_FRAME)
add_subdirectory(Frame)
endif()
if (${PARENT}_SUBMODULE_FORMAT_CONVERTER)
add_subdirectory(FormatConverter)
endif()
if (${PARENT}_SUBMODULE_VCODEC)
add_subdirectory(VCodec)
endif()
if (${PARENT}_SUBMODULE_VENCODERJPEG)
add_subdirectory(VEncoderJPEG)
endif()
if (${PARENT}_SUBMODULE_VIDEO_RECORDER_MP4)
add_subdirectory(VideoRecorderMp4)
endif()
Add the folder to the main CMakeLists.txt file of your project and link the library to your target in the CMakeLists.txt file of the target:
add_subdirectory(3rdparty)
target_link_libraries(${PROJECT_NAME} VideoRecorderMp4)
The example application is not built when the library is included in another project.
The library starts a worker thread. The threads library (Threads::Threads, linked by VEncoderJPEG) and, if FormatConverter is built with OpenMP, the OpenMP runtime (for example libgomp with GCC) are needed by a program that links the library; CMake adds them to targets that link VideoRecorderMp4.
Example application
The repository includes an example application in example/ (the whole code is in the main() function of example/main.cpp). It does not read any files: it generates artificial video and records it with VideoRecorderMp4:
- Frames are 1280x720, YUV24, 30 Hz (the resolution and the frame rate are fixed). Each frame is a colour gradient that moves from frame to frame with pseudo-random noise added to every pixel.
- The frames are passed to
write()as they are. No custom codec is set, so the library converts them to NV12 and compresses them to JPEG with its built-in encoder. - The recording is segmented: files are written into the Records folder (created in the current directory), a new file is started when the file reaches the file size limit, the oldest files are deleted when the folder exceeds the folder size limit.
Running
VideoRecorderMp4Example [maxFolderSizeMB maxFileSizeMB]
Parameters:
maxFolderSizeMB: folder size limit in MB.maxFileSizeMB: file size limit in MB, must be greater than0and not larger than the folder size limit.
If the parameters are not given, the application asks for them. The recording runs until Ctrl+C is pressed: the application then stops the recorder, which completes the last file.
Examples
- Folder of 100 MB with files of 10 MB:
VideoRecorderMp4Example 100 10 - Interactive mode:
VideoRecorderMp4Example Enter max folder size, MB: 100 Enter max file size, MB: 10
A noisy frame is compressed to about 250-300 KB, so the data rate of the example is about 8 MB per second.
Third-party components
Table 4 - Components used by the library.
| Component | Version | Location | Used by |
|---|---|---|---|
| Frame | 5.1.1 (commit d1b3acd) | ../Frame | library |
| FormatConverter | 1.5.2 (commit 2df55dd) | ../FormatConverter | library |
| VCodec | 2.2.3 (commit 3a311ac) | ../VCodec | library |
| VEncoderJPEG | 1.0.2 (commit c3f2cf0) | ../VEncoderJPEG | library |