Overview
The 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. 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). Encoder and decoder have zero frame latency. Encoding/decoding time on 11th Gen Intel(R) Core(TM) i5-1145G7E @ 2.60GHz, Ubuntu 22.10: 1920x1080 - 32 / 13 msec, 1280x720 - 17 / 7 msec, 640x512 - 6 / 3 msec..
Documentation
Documentation: GO TO DOCUMENTATION
Simple interface
class VCodecOpenH264 : public VCodec
{
public:
/// 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);
};
Simple example
#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;
}
}