VCodecOpenH264 C++ library
v1.0.5
Table of contents
- Overview
- Versions
- Library files
- VCodecOpenH264 class description
- Build and connect to your project
- Simple example
- Test application
Overview
VCodecOpenH264 C++ library provides video encoding and decoding functions for H264 codec for Linux based on Openh264. The library supports only software H264 encoding / decoding. VCodecOpenH264 video codec class inherits interface and data structures form VCodec interface library (provides interface for video codecs, source code included, Apache 2.0 license) and also depends on open source Logger (provides logging functions, source code included, source code included, Apache 2.0 license). 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 | - Update VCodec interface with variable bitrate params. |
Library files
The library supplied by source code only. The user would be given 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 for 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
VCodecOpenH264 class declared in 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 string of current version of VCodecOpenH264 class. Method declaration:
static std::string getVersion();
Method can be used without VCodecOpenH264 class instance:
std::cout << "VCodecOpenH264 class version: " << VCodecOpenH264::getVersion();
Console output:
VCodecOpenH264 class version: 1.0.4
transcode method
The transcode(…) method intended to encode and decode video frame (Frame class). 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 src frame must have NV12 pixel format. To decode video data src frame must have compressed pixel format (field fourcc of Frame class): H264. |
dst | Result video frame (see Frame class description). To decode video data src frame must have compressed pixel format (field fourcc of Frame class): H264. User must specify output pixel format in advance. In case decoding video codec will set NV12 pixel format automatically. |
Returns: TRUE if frame was encoded/decoded or FALSE if not.
setParam method
The setParam(…) method designed to set new video codec parameters value. Method declaration:
bool setParam(VCodecParam id, float value);
Parameter | Description |
---|---|
id | Video codec parameter ID according to VCodecParam enum. |
value | Video codec parameter value. Valid values depends on parameter ID. |
Returns: TRUE is the parameter is set or FALSE if not.
VCodec.h file of 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 params description. Some params not supported by particular VCodecLibav 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. Default 5000 kbps. For H264 and H265(HEVC) encoding. According to this value, FPS and GOP size video codec calculate parameter for H264 or H265(HEVC) encoding. - Sets special settings for noisy video if bitrate is 0 for hardware encoding. - For software JPEG encoding bitrate incising gives higher quality. |
MIN_BITRATE_KBPS | read / write | Minimum bitrate, kbps. Only for H264 and H265(HEVC) codecs. Default 2000 kbps. For variable bitrate mode. For H264 and H265(HEVC) encoding. |
MAX_BITRATE_KBPS | read / write | Maximum bitrate, kbps. Only for H264 and H265(HEVC) codecs. Default 8000 kbps. For variable bitrate mode. For H264 and H265(HEVC) encoding. |
BITRATE_MODE | read / write | Only for H264 and H265(HEVC) codecs. Bitrate mode: 0 - constant bitrate (default), 1 - variable bitrate. In variable bitrate mode for software encoder |
QUALITY | read / write | Quality 0(low quality)-100%(maximum quality). Only for hardware JPEG encoding. Not supported by JPEG SW encoding. |
FPS | read / write | FPS. For H264 and H265(HEVC) encoding only. According to this value, FPS and GOP size video codec calculate parameter for H264 and H265(HEVC) encoding. |
GOP | read / write | GOP size (Period of key frames) for H264 and H265(HEVC) encoding. Value: 1 - each output frame is key frame, 20 - each 20th frame is key frame etc. |
H264_PROFILE | read / write | H264 profile for H264 encoding: 0 - Baseline. 1 - Main. 2 - High. For hardware encoding only. |
TYPE | read / write | Type of encoder/decoder: 0 - hardware (default). 1 - software. |
CUSTOM_1 | read / write | Number of thread for software encoder/decoder. Thread’s count for software encoder\decoder H264 / HEVC(H265) (not for JPEG): 1 - 32, default value 1. Note: in case one thread software encoder produces only one slice per frame. In case multiple threads frame can have multiple slices which can effect on RTSP servers. |
CUSTOM_2 | read / write | Not supported by VCodecLibav library. |
CUSTOM_3 | read / write | Not supported by VCodecLibav library. |
getParam method
The getParam(…) method designed to obtain video codec parameter value. 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 of the parameters doesn’t exist in particular video codec class.
executeCommand method
The executeCommand(…) method designed to execute video codec command. The library doesn’t support commands. Method will return FALSE. Method declaration:
bool executeCommand(VCodecCommand id);
Parameter | Description |
---|---|
id | Video codec command ID according to VCodecCommand enum. |
Returns: method returns FALSE in any case.
VCodec.h file of 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 maybe unsupported by particular video codec class.
Command | Description |
---|---|
RESET | Not supported by VCodecOpenH264. |
MAKE_KEY_FRAME | Not supported by VCodecOpenH264. |
Build and connect to your project
Before compiling you have to 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 example you have to install OpenCV by command:
sudo apt-get -y install libopencv-dev
Typical commands to build VCodecOpenH264 library:
cd VCodecOpenH264
mkdir build
cd build
cmake ..
make
If you want connect VCodecOpenH264 library to your CMake project as source code you can make follow. For example, if your repository has structure:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
Create folder 3rdparty in your repository and copy VCodecOpenH264 repository folder to 3rdparty folder. New structure of your repository:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
VCodecOpenH264
Create CMakeLists.txt file in 3rdparty folder. 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()
File 3rdparty/CMakeLists.txt adds folder VCodecOpenH264 to your project and excludes test application and example from compiling (by default test application is excluded from compiling if FlirBosonCamera is included as sub-repository). The new structure of your repository:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
CMakeLists.txt
VCodecOpenH264
Next you need include folder 3rdparty in main CMakeLists.txt file of your repository. Add string at the end of your main CMakeLists.txt:
add_subdirectory(3rdparty)
Next you have to include VCodecOpenH264 library in your src/CMakeLists.txt file:
target_link_libraries(${PROJECT_NAME} VCodecOpenH264)
Done!
Simple example
Simple example opens video file with OpenCV, captures video from file, convert frame to NV12 pixel format (required for codec) and encodes. 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 (replacing pixels). You can use something else.
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
Test application (VCodecOpenH264/test/main.cpp) for VCodecOpenH264 C++ library shows how library works. The test application generates an 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 it set. To run application perform commands:
cd <application folder>
sudo chmod +x VCodecOpenH264Test
sudo ./VCodecOpenH264Test
After start you will see output:
====================================
VCodecOpenH264 v1.0.5 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 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