vcodecopenh264_web_logo

VCodecOpenH264 C++ library

v1.0.8

Table of contents

Overview

The VCodecOpenH264 C++ library provides video encoding and decoding functions for the H264 codec on Linux based on OpenH264. The library supports only software H264 encoding/decoding. The VCodecOpenH264 video codec class inherits interface and data structures from the VCodec interface library (provides interface for video codecs, source code included, Apache 2.0 license) and also depends on the open-source Logger (provides logging functions, source code included, Apache 2.0 license). The encoder and decoder have zero frame latency. Encoding/decoding time on 11th Gen Intel(R) Core(TM) i5-1145G7E @ 2.60GHz, Ubuntu 22.10:

Software codec (1 thread) / resolution 1920x1080 1280x720 640x512
H264 32 msec / 13 msec 17 msec / 7 msec 6 msec / 3 msec

Versions

Table 1 - Library versions.

Version Release date What’s new
1.0.0 19.03.2024 First version.
1.0.1 26.04.2024 - Documentation updated.
- Test application updated.
1.0.2 17.05.2024 - Documentation updated.
- Submodules updated.
1.0.3 06.08.2024 - Submodules updated.
1.0.4 07.08.2024 - CMake structure updated.
1.0.5 04.11.2024 - Updated VCodec interface with variable bitrate params.
1.0.6 03.04.2025 - Logger submodule update.
1.0.7 17.08.2025 - CMake update.
1.0.8 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.
    VCodec ---------------------- Folder with VCodec interface library source code.
    Logger ---------------------- Folder with Logger library source code.
src ----------------------------- Folder with library source code.
    wels ------------------------ Folder with header files for openh264 library.
    CMakeLists.txt -------------- CMake file of the library.
    VCodecOpenH264.h ------------ Main library header file.
    VCodecOpenH264Version.h ----- Header file with library version.
    VCodecOpenH264Version.h.in -- Service CMake file to generate version header.
    VCodecOpenH264.cpp ---------- C++ implementation file.
test ---------------------------- Folder for test application files.
    CMakeLists.txt -------------- CMake file for test application.
    main.cpp -------------------- Source C++ file of test application.
example ------------------------- Folder for simple example.
    CMakeLists.txt -------------- CMake file of example.
    main.cpp -------------------- Source C++ file of example.

VCodecOpenH264 class description

VCodecOpenH264 class declaration

The VCodecOpenH264 class is declared in the VCodecOpenH264.h file. Class declaration:

class VCodecOpenH264 : public VCodec
{
public:

    /// Class constructor.
    VCodecOpenH264();

    /// Class destructor.
    ~VCodecOpenH264();

    /// Get string of current library version.
    static std::string getVersion();

    /// Encode or decode frame.
    bool transcode(Frame& src, Frame& dst);

    /// Set codec parameter.
    bool setParam(VCodecParam id, float value);

    /// Get parameter value.
    float getParam(VCodecParam id);

    /// Execute command.
    bool executeCommand(VCodecCommand id);
};

getVersion method

The getVersion() method returns a string of the current version of the VCodecOpenH264 class. Method declaration:

static std::string getVersion();

This method can be used without a VCodecOpenH264 class instance:

std::cout << "VCodecOpenH264 class version: " << VCodecOpenH264::getVersion();

Console output:

VCodecOpenH264 class version: 1.0.8

transcode method

The transcode(…) method is intended to encode and decode video frames (Frame class). 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 data, the src frame must have NV12 pixel format. To decode video data, the src frame must have a compressed pixel format (field fourcc of Frame class): H264.
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): H264. The user must specify the output pixel format in advance. When decoding, the video codec will set the NV12 pixel format automatically.

Returns: TRUE if the frame was encoded/decoded successfully or FALSE if not.

setParam method

The setParam(…) method is designed to set a new video codec parameter value. Method declaration:

bool setParam(VCodecParam id, float value);
Parameter Description
id Video codec parameter ID according to the VCodecParam enum.
value Video codec parameter value. Valid values depend on the parameter ID.

Returns: TRUE if the parameter was set successfully 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 parameters description. Some parameters are not supported by the VCodecOpenH264 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, kbps. Range: 0-10,000,000 kbps. Default: 5000 kbps. For H264 encoding.
MIN_BITRATE_KBPS read / write Not supported by the VCodecOpenH264 library.
MAX_BITRATE_KBPS read / write Not supported by the VCodecOpenH264 library.
BITRATE_MODE read / write Not supported by the VCodecOpenH264 library.
QUALITY read / write Not supported by the VCodecOpenH264 library.
FPS read / write Frames per second. Range: 1-1000. Default: 30. For H264 encoding only.
GOP read / write GOP size (period of key frames). Range: 1-10,000. Default: 30. For H264 encoding. Value: 1 - each output frame is a key frame, 20 - each 20th frame is a key frame, etc.
H264_PROFILE read / write H264 profile for H264 encoding. Range: 0-2. Default: 0. Values:
0 - Baseline.
1 - Main.
2 - High.
TYPE read / write Not supported by the VCodecOpenH264 library (only software encoding is available).
CUSTOM_1 read / write Number of threads for software encoder/decoder. Range: 1-32. Default: 1. Thread count for software encoder/decoder H264. Note: When using one thread, the software encoder produces only one slice per frame. When using multiple threads, the frame can have multiple slices, which can affect RTSP servers.
CUSTOM_2 read / write Not supported by the VCodecOpenH264 library.
CUSTOM_3 read / write Not supported by the VCodecOpenH264 library.

getParam method

The getParam(…) method is designed to obtain a video codec parameter value. Method declaration:

float getParam(VCodecParam id);
Parameter Description
id Video codec parameter ID according to the VCodecParam enum (see Table 2).

Returns: Parameter value or -1 if the parameter doesn’t exist in the particular video codec class.

executeCommand method

The executeCommand(…) method is designed to execute video codec commands. The library doesn’t support commands. The method will return FALSE. Method declaration:

bool executeCommand(VCodecCommand id);
Parameter Description
id Video codec command ID according to the VCodecCommand enum.

Returns: The method returns FALSE in any case.

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 commands description. Some commands may be unsupported by particular video codec classes.

Command Description
RESET Not supported by the VCodecOpenH264 library.
MAKE_KEY_FRAME Not supported by the VCodecOpenH264 library.

Build and connect to your project

Before compiling, you must install nasm packages, openh264 libraries, and additional applications for your system.

sudo apt-get -y install nasm
git clone https://github.com/cisco/openh264.git
cd openh264
make OS=linux ARCH=x86_64
sudo make install
sudo ln -s /usr/local/lib/libopenh264.so.7 /usr/lib/libopenh264.so.7

To compile the example, you must install OpenCV with the following command:

sudo apt-get -y install libopencv-dev

Typical commands to build the VCodecOpenH264 library:

cd VCodecOpenH264
mkdir build
cd build
cmake ..
make

If you want to connect the VCodecOpenH264 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 3rdparty folder in your repository and copy the VCodecOpenH264 repository folder to the 3rdparty folder. The new structure of your repository:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp
3rdparty
    VCodecOpenH264

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)

################################################################################
## CONFIGURATION
## 3rd-party submodules configuration
################################################################################
SET(${PARENT}_SUBMODULE_VCODEC_OPENH264                 ON  CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_VCODEC_OPENH264)
    SET(${PARENT}_VCODEC_OPENH264                       ON  CACHE BOOL "" FORCE)
    SET(${PARENT}_VCODEC_OPENH264_TEST                  OFF CACHE BOOL "" FORCE)
    SET(${PARENT}_VCODEC_OPENH264_EXAMPLE               OFF CACHE BOOL "" FORCE)
endif()

################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
if (${PARENT}_SUBMODULE_VCODEC_OPENH264)
    add_subdirectory(VCodecOpenH264)
endif()

The 3rdparty/CMakeLists.txt file adds the VCodecOpenH264 folder to your project and excludes the test application and example from compilation (by default, the test application is excluded from compilation if VCodecOpenH264 is included as a sub-repository). The new structure of your repository:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp
3rdparty
    CMakeLists.txt
    VCodecOpenH264

Next, you need to include the 3rdparty folder in the main CMakeLists.txt file of your repository. Add the following line at the end of your main CMakeLists.txt:

add_subdirectory(3rdparty)

Next, you need to include the VCodecOpenH264 library in your src/CMakeLists.txt file:

target_link_libraries(${PROJECT_NAME} VCodecOpenH264)

Done!

Simple example

This simple example opens a video file with OpenCV, captures video from the file, converts frames to NV12 pixel format (required for the codec), and encodes them. Source code:

#include <iostream>
#include <opencv2/opencv.hpp>
#include "VCodecOpenH264.h"

int main(void)
{
    // Create codec object and set params.
    cr::video::VCodec* encoder = new cr::video::VCodecOpenH264();
    encoder->setParam(cr::video::VCodecParam::BITRATE_KBPS, 10000);
    encoder->setParam(cr::video::VCodecParam::FPS, 20);
    encoder->setParam(cr::video::VCodecParam::GOP, 30);
    encoder->setParam(cr::video::VCodecParam::H264_PROFILE, 0);

    // Open video file with OpenCV.
    cv::VideoCapture videoSource;
    if (!videoSource.open("test.mp4"))
        return -1;

    // Get frame size from video source.
    int width = (int)videoSource.get(cv::CAP_PROP_FRAME_WIDTH);
    int height = (int)videoSource.get(cv::CAP_PROP_FRAME_HEIGHT);

    // Init frames.
    cv::Mat inputFrameBgr(height, width, CV_8UC3);
    cv::Mat inputFrameYuv(height, width, CV_8UC3);
    cr::video::Frame nv12Frame(width, height, cr::video::Fourcc::NV12);
    cr::video::Frame h264Frame(width, height, cr::video::Fourcc::H264);

    // Main loop.
    while (true)
    {
        // Capture next video frame.
        videoSource >> inputFrameBgr;
        if (inputFrameBgr.empty())
        {
            // Set first video frame position.
            videoSource.set(cv::CAP_PROP_POS_FRAMES, 1);
            continue;
        }

        // Convert BGR to YUV.
        cvtColor(inputFrameBgr, inputFrameYuv, cv::COLOR_BGR2YUV);

        // Convert YUV to NV12 (pixel format conversion). You can use alternative methods.
        size_t p = height;
        nv12Frame.frameId++; // Just to show unique info.
        for (size_t i = 0; i < (size_t)height; i = i + 2)
        {
            for (size_t j = 0; j < (size_t)width; j = j + 2)
            {
                nv12Frame.data[i * (size_t)width + j] =
                inputFrameYuv.data[i * (size_t)width * 3 + j * 3];
                nv12Frame.data[i * (size_t)width + j + 1] =
                inputFrameYuv.data[i * (size_t)width * 3 + j * 3 + 3];
                nv12Frame.data[(i + 1) * (size_t)width + j] =
                inputFrameYuv.data[(i + 1) * (size_t)width * 3 + j * 3];
                nv12Frame.data[(i + 1) * (size_t)width + j + 1] =
                inputFrameYuv.data[(i + 1) * (size_t)width * 3 + j * 3 + 3];
                nv12Frame.data[p * width + j] =
                inputFrameYuv.data[i * (size_t)width * 3 + j * 3 + 1];
                nv12Frame.data[p * width + j + 1] =
                inputFrameYuv.data[i * (size_t)width * 3 + j * 3 + 2];
            }
            ++p;
        }

        // Encode data.
        if (!encoder->transcode(nv12Frame, h264Frame))
        {
            std::cout << "Can't encode frame" << std::endl;
            continue;
        }

        // Show info.
        std::cout << "[" << h264Frame.frameId << "] Size " <<
        h264Frame.size << " Compression ratio : %" <<
        (int)(100.0f * ((float)h264Frame.size / (float)nv12Frame.size)) <<
        std::endl;
    }
}

Test application

The test application (VCodecOpenH264/test/main.cpp) for the VCodecOpenH264 C++ library demonstrates how the library works. The test application generates artificial video, compresses it based on user-defined parameters such as bitrate, GOP size, and H264 profile, and writes the results to a binary file named “out.h264”. The compressed frame is then decoded, and the generated frame and the frame after encoding and decoding are displayed if configured. To run the application, perform the following commands:

cd <application folder>
sudo chmod +x VCodecOpenH264Test
sudo ./VCodecOpenH264Test

After starting, you will see the following output:

====================================
VCodecOpenH264 v1.0.8 test
====================================

Default params:
Bitrate, kbps 6000
FPS: 30
GOP size: 30
Video width 1920
Video height 1080
H264 Profile: 0
Use default params (0 - no, 1 - yes) : 1
Set number frames: 100

During encoding and decoding, the application shows the encoded data size and encoding/decoding time:

Data size 3110400 / 11816   encoding time  34452 us / decoding time 13707 us
Data size 3110400 / 583   encoding time  8051 us / decoding time 2434 us
Data size 3110400 / 3781   encoding time  7237 us / decoding time 3302 us
Data size 3110400 / 9366   encoding time  12972 us / decoding time 4712 us
Data size 3110400 / 4920   encoding time  10599 us / decoding time 4317 us
Data size 3110400 / 373   encoding time  5673 us / decoding time 3520 us
Data size 3110400 / 435   encoding time  6857 us / decoding time 4760 us
Data size 3110400 / 331   encoding time  5709 us / decoding time 3130 us
Data size 3110400 / 164   encoding time  6148 us / decoding time 3071 us
Data size 3110400 / 178   encoding time  5260 us / decoding time 3001 us

Table of contents