
VCodecV4L2 C++ library
v2.2.5
Table of contents
- Overview
- Versions
- Library files
- VCodecV4L2 class description
- Build and connect to your project
- Simple example
- Test application
Overview
The VCodecV4L2 C++ library provides hardware video encoding for H264 and JPEG codecs based on the V4L2 API on Linux only. The VCodecV4L2 class inherits its interface and data structures from the open-source VCodec library (source code included, Apache 2.0 license) and also includes the Logger open-source library, which provides functions for printing logs (source code included, Apache 2.0 license). VCodecV4L2 uses the V4L2 API and was tested on Raspberry PI4 and Raspberry Zero W2, but it is possible to use the library on other platforms by setting the appropriate encoder device name. The library provides a simple interface to be implemented in different C++ projects. The library is written using the C++17 standard and is supplied as source code only. The library is a CMake project. Encoding time on Raspberry PI 4B (msec):
| codec / resolution | 1920x1080 | 1280x720 | 640x512 |
|---|---|---|---|
| H264 | 12 msec | 5.4 msec | 2.5 msec |
| JPEG | 25 msec | 13 msec | 5.5 msec |
Encoding time on Raspberry Zero W2, msec:
| codec / resolution | 1920x1080 | 1280x720 | 640x512 |
|---|---|---|---|
| H264 | 19.5 msec | 8.7 msec | 2.8 msec |
| JPEG | 33.4 msec | 15.7 msec | 5.1 msec |
Versions
Table 1 - Library versions.
| Version | Release date | What’s new |
|---|---|---|
| 1.0.0 | 29.06.2023 | First version. |
| 2.0.0 | 02.08.2023 | - Interface changes to VCodec. - Added JPEG encoding support. - Test application updated. |
| 2.0.1 | 21.08.2023 | - Bug fixed in transcode on copy constructor of dst frame. |
| 2.1.0 | 28.08.2023 | - YUYV input pixel format changed to NV12 for H264 and JPEG codecs. - Added example application. |
| 2.1.1 | 20.11.2023 | - BGR565 conversion is fixed for JPEG encoding. |
| 2.1.2 | 10.01.2024 | - Submodules updated. - Documentation updated. - Test application updated. |
| 2.1.3 | 15.01.2024 | - Bug fixes. |
| 2.2.0 | 25.04.2024 | - Added new method to set hardware encoder device name. - Documentation updated. |
| 2.2.1 | 17.05.2024 | - Submodules updated. - Documentation updated. |
| 2.2.2 | 06.08.2024 | - Submodules updated. |
| 2.2.3 | 04.11.2024 | - Update VCodec interface with variable bitrate params. |
| 2.2.4 | 03.04.2025 | - Logger submodule update. |
| 2.2.5 | 02.11.2025 | - VCodec submodule update. - Documentation update. |
Library files
The library is supplied as source code only. The user is provided with a set of files in the form of a CMake project (repository). The repository structure is shown below:
CMakeLists.txt -------------- Main CMake file of the library.
3rdparty -------------------- Folder with third-party libraries.
CMakeLists.txt ---------- CMake file to include third-party libraries.
Logger ------------------ Folder with Logger library source code.
VCodec ------------------ Folder with VCodec interface library source code.
example --------------------- Folder with simple example of VCodecV4L2 usage.
CMakeLists.txt ---------- CMake file for example application.
main.cpp ---------------- Source code file of example application.
test ------------------------ Folder with codec test application.
CMakeLists.txt ---------- CMake file for codec test application.
main.cpp ---------------- Source code file of codec test application.
src ------------------------- Folder with source code of the library.
CMakeLists.txt ---------- CMake file of the library.
VCodecV4L2.cpp ---------- C++ implementation file.
VCodecV4L2.h ------------ Header file which includes VCodecV4L2 class declaration.
VCodecV4L2Version.h ----- Header file which includes version of the library.
VCodecV4L2Version.h.in -- CMake service file to generate version file.
VCodecV4L2 class description
VCodecV4L2 class declaration
The VCodecV4L2 class is declared in the VCodecV4L2.h file. Class declaration:
class VCodecV4L2 : public VCodec
{
public:
/// Get library version.
static std::string getVersion();
/// Class constructor.
VCodecV4L2();
/// Class destructor.
~VCodecV4L2();
/// Encode video frame.
bool transcode(Frame& src, Frame& dst);
/// Set parameter value.
bool setParam(VCodecParam id, float value);
/// Get parameter value.
float getParam(VCodecParam id);
/// Execute command.
bool executeCommand(VCodecCommand id);
/// Set device name.
void setDevice(std::string device);
};
getVersion method
The getVersion() method returns a string of the current version of the VCodecV4L2 class. Method declaration:
static std::string getVersion();
The method can be used without a VCodecV4L2 class instance:
cout << "VCodecV4L2 class version: " << VCodecV4L2::getVersion() << endl;
Console output:
VCodecV4L2 class version: 2.2.5
transcode method
The transcode(…) method is intended to encode and decode video frames (Frame class). The VCodecV4L2 library supports encoding only. The video codec encodes/decodes video frames frame-by-frame. Method declaration:
bool transcode(Frame& src, Frame& dst);
| Parameter | Value |
|---|---|
| src | Source video frame (see Frame class description). To encode video, the src frame must have the raw pixel format NV12. |
| dst | Result video frame (see Frame class description). To encode video data, the dst frame must have a compressed pixel format (field fourcc of Frame class): JPEG or H264. |
Returns: TRUE if the frame was encoded or FALSE if not.
setParam method
The setParam(…) method is designed to set new video codec parameter values. Method declaration:
setParam(VCodecParam id, float value);
| Parameter | Description |
|---|---|
| id | Video codec parameter ID according to VCodecParam enum. |
| value | Video codec parameter value. |
Returns: TRUE if the parameter was set or FALSE if not.
The VCodec.h file of the VCodec library defines IDs for parameters (VCodecParam enum) and IDs for commands (VCodecCommand enum). VCodecParam declaration:
namespace cr
{
namespace video
{
enum class VCodecParam
{
/// [read/write] Log level: 0-Disable, 1-Console, 2-File, 3-Console and file.
LOG_LEVEL = 1,
/// [read/write] Bitrate, kbps. For H264 and H265 codecs.
BITRATE_KBPS,
/// [read/write] Minimum bitrate, kbps. For variable bitrate mode.
MIN_BITRATE_KBPS,
/// [read/write] Maximum bitrate, kbps. For variable bitrate mode.
MAX_BITRATE_KBPS,
/// [read/write] Bitrate mode: 0 - constant bitrate, 1 - variable bitrate.
BITRATE_MODE,
/// [read/write] Quality 0-100%. For JPEG codecs.
QUALITY,
/// [read/write] FPS. For H264 and H265 codecs.
FPS,
/// [read/write] GOP size. For H264 and H265 codecs.
GOP,
/// [read/write] H264 profile: 0 - Baseline, 1 - Main, 2 - High.
H264_PROFILE,
/// [read/write] Codec type. Depends on implementation.
TYPE,
/// Custom 1. Depends on implementation.
CUSTOM_1,
/// Custom 2. Depends on implementation.
CUSTOM_2,
/// Custom 3. Depends on implementation.
CUSTOM_3
};
}
}
Table 2 - Video codec parameter descriptions. Some parameters are not supported by the particular VCodecV4L2 library.
| Parameter | Access | Description |
|---|---|---|
| LOG_LEVEL | read / write | Logging mode. Values: 0 - Disable. 1 - Only file. 2 - Only terminal (console). 3 - File and terminal. |
| BITRATE_KBPS | read / write | Bitrate in kbps. Range: 0 - 1,000,000 kbps. Default: 2000 kbps. For H264 encoding only. Sets special settings for noisy video if bitrate is 0. |
| QUALITY | read / write | JPEG quality. Range: 1 - 100 (1 = low quality, 100 = maximum quality). Default: 80. For JPEG hardware encoding only. |
| FPS | read / write | Frame rate. Range: 1 - 1000 fps. Default: 30 fps. For H264 encoding only. |
| GOP | read / write | GOP size (period of key frames). Range: 1 - 10,000. Default: 30. For H264 encoding only. Value 1 means each output frame is a key frame, 20 means every 20th frame is a key frame, etc. |
| H264_PROFILE | read / write | H264 profile for H264 encoding: 0 - Baseline. 1 - Main. 2 - High. For hardware encoding only. |
| MIN_BITRATE_KBPS | read / write | Not supported by VCodecV4L2 library. |
| MAX_BITRATE_KBPS | read / write | Not supported by VCodecV4L2 library. |
| BITRATE_MODE | read / write | Not supported by VCodecV4L2 library. |
| TYPE | read / write | Not supported by VCodecV4L2 library. |
| CUSTOM_1 | read / write | Not supported by VCodecV4L2 library. |
| CUSTOM_2 | read / write | Not supported by VCodecV4L2 library. |
| CUSTOM_3 | read / write | Not supported by VCodecV4L2 library. |
getParam method
The getParam(…) method is designed to obtain video codec parameter values. Method declaration:
float getParam(VCodecParam id);
| Parameter | Description |
|---|---|
| id | Video codec parameter ID according to VCodecParam enum (see Table 2). |
Returns: parameter value or -1 if the parameter is not supported.
executeCommand method
The executeCommand(…) method is designed to execute video codec commands. The current version supports the MAKE_KEY_FRAME command. Method declaration:
bool executeCommand(VCodecCommand id);
| Parameter | Description |
|---|---|
| id | Video codec command ID according to VCodecCommand enum. |
Returns: TRUE if the command was accepted or FALSE if not.
The VCodec.h file of the VCodec library defines IDs for parameters (VCodecParam enum) and IDs for commands (VCodecCommand enum). VCodecCommand declaration:
enum class VCodecCommand
{
/// Reset.
RESET = 1,
/// Generate key frame. For H264 and H265 codecs.
MAKE_KEY_FRAME
};
Table 3 - Video codec command descriptions. Some commands may be unsupported by particular video codec classes.
| Command | Description |
|---|---|
| RESET | Not supported by VCodecV4L2. |
| MAKE_KEY_FRAME | Generate the next key frame (for H264 encoder). Some hardware may not support this function. |
setDevice method
The setDevice(…) method changes the default name of the hardware encoder device. By default, the library supports Raspberry PI4 and Raspberry Zero W2 platforms, which have devices: /dev/video31 (for JPEG encoding) and /dev/video11 (for H264 encoding). If the user has a different platform, the device name can be changed. Method declaration:
void setDevice(std::string device);
| Parameter | Value |
|---|---|
| device | Device name, for example: “/dev/video31”. |
Build and connect to your project
Install additional software:
sudo apt-get -y install build-essential cmake git
Typical commands to build VCodecV4L2 library:
cd VCodecV4L2
git submodule update --init --recursive
mkdir build
cd build
cmake ..
make
If you want to connect the VCodecV4L2 library to your CMake project as source code, you can follow these steps. For example, if your repository has the following structure:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
Create a folder 3rdparty in your repository. Copy the repository folder VCodecV4L2 to the 3rdparty folder. The new structure of your repository:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
VCodecV4L2
Create a CMakeLists.txt file in the 3rdparty folder. The CMakeLists.txt should contain:
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)
################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
add_subdirectory(VCodecV4L2)
The file 3rdparty/CMakeLists.txt adds the folder VCodecV4L2 to your project and will exclude test applications from compiling. Your repository’s new structure will be:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
CMakeLists.txt
VCodecV4L2
Next, you need to include the folder 3rdparty in the main CMakeLists.txt file of your repository. Add this string at the end of your main CMakeLists.txt:
add_subdirectory(3rdparty)
Next, you have to include the VCodecV4L2 library in your src/CMakeLists.txt file:
target_link_libraries(${PROJECT_NAME} VCodecV4L2)
Done!
Simple example
The example application generates an image color pattern with a moving rectangle and writes compressed data to a binary file “out.h264”. The example shows how to create codec objects and how to encode video frames:
#include <iostream>
#include "VCodecV4L2.h"
int main(void)
{
// Create codec and set params.
cr::video::VCodec* videoCodec = new cr::video::VCodecV4L2();
videoCodec->setParam(cr::video::VCodecParam::BITRATE_KBPS, 2500);
videoCodec->setParam(cr::video::VCodecParam::GOP, 30);
videoCodec->setParam(cr::video::VCodecParam::FPS, 30);
videoCodec->setParam(cr::video::VCodecParam::H264_PROFILE, 0);
// Create NV12 frame and fill color plane by random values.
const int width = 1280;
const int height = 720;
cr::video::Frame frameNv12(width, height, cr::video::Fourcc::NV12);
for (uint32_t i = 0; i < frameNv12.size; ++i)
frameNv12.data[i] = (uint8_t)i;
// Create output H264 frame.
cr::video::Frame frameH264(width, height, cr::video::Fourcc::H264);
// Create output file.
FILE *outputFile = fopen("out.h264", "w+b");
// Params for moving object.
int objectWidth = 128;
int objectHeight = 128;
int directionX = 1;
int directionY = 1;
int objectX = width / 4;
int objectY = height / 2;
// Encode and record 200 frames.
for (uint8_t n = 0; n < 200; ++n)
{
// Draw moving object.
memset(frameNv12.data, 128, width * height);
for (int y = objectY; y < objectY + objectHeight; ++y)
for (int x = objectX; x < objectX + objectHeight; ++x)
frameNv12.data[y * width + x] = 255;
objectX += directionX;
objectY += directionY;
if (objectX >= width - objectWidth - 5 || objectX <= objectWidth + 5)
directionX = -directionX;
if (objectY >= height - objectHeight - 5 || objectY <= objectHeight + 5)
directionY = -directionY;
// Encode.
if (!videoCodec->transcode(frameNv12, frameH264))
{
std::cout << "Can't encode frame" << std::endl;
continue;
}
// Write to file.
fwrite(frameH264.data, frameH264.size, 1, outputFile);
}
// Close file.
fclose(outputFile);
return 1;
}
Test application
The test application (VCodecV4L2/test/main.cpp) for the VCodecV4L2 C++ library shows how the library works on the Raspberry PI platform. The test application generates artificial video, compresses it according to the user’s parameters (codec type, bitrate or JPEG quality, GOP size, and H264 profile), and writes the results to a binary file “out.h264” or “out.jpeg”. To run the application, perform the following commands:
cd <application folder>
sudo chmod +x VCodecV4L2Test
./VCodecV4L2Test
After starting, you will see the following output:
===========================================
VCodecV4L2 v2.2.5 test
===========================================
Enter Encoder type (0 - JPEG, 1 - H264) : 1
Choose the codec type (0 - JPEG, 1 - H264). If the H264 codec is chosen, you will see the following message:
===========================================
VCodecV4L2 v2.2.5 test
===========================================
Enter Encoder type (0 - JPEG, 1 - H264) : 1
Default params:
Bitrate, kbps 3000
FPS: 30
GOP size: 30
H264 profile: Baseline
Video width 1920
Video height 1080
Use default params (0 - no, 1 - yes) : 0
Set video width : 1280
Set video height : 720
Set bitrate, kbps : 2000
Set GOP size : 30
Set FPS : 30
Set profile 0-BASELINE, 1-MAIN, 2-HIGH : 0
Encoding on Raspberry PI4 ? (y/n): y
When the parameters are chosen, the test application will create an out.h264 file and record 1000 encoded frames. The user can set custom parameters (video resolution, bitrate, GOP size, and H264 profile). If the JPEG codec is chosen, you will see the following message:
Output file: out.jpeg
Data size 33457/3110400 time 88.127 msec
Data size 416690/3110400 time 41.159 msec
Data size 420353/3110400 time 34.041 msec
Data size 420908/3110400 time 33.631 msec
Data size 420895/3110400 time 33.205 msec