Overview
VCodecV4L2 C++ library provides hardware video encoding for H264 and JPEG codecs based on V4L2 API on Linux only. VCodecV4L2 class inherits interface and data structures from open source VCodec library (source code included, Apache 2.0 license) and also includes Logger open source library which provides function for print logs (source code included, Apache 2.0 license). VCodecV4L2 uses V4L2 API and was tested on Raspberry PI4 and Raspberry Zero W2 but it is possible to use the library on any other platforms with setting appropriate encoder device name. The library provides simple interface to be implemented in different C++ projects. The library is written with C++17 standard. It is supplied as source code only. The library is a CMake project. Encoding time, msec:
RPI 4, H264 codec, 1920x1080 - 12 msec, 1280x720 - 5.4 msec, 640x512 - 2.5 msec.
RPI 4, JPEG codec, 1920x1080 - 25 msec, 1280x720 - 13 msec, 640x512 - 5.5 msec.
Zero W2, H264 codec, 1920x1080 - 19.5 msec, 1280x720 - 8.7 msec, 640x512 - 2.8 msec.
Zero W2, JPEG codec, 1920x1080 - 33.4 msec, 1280x720 - 15.7 msec, 640x512 - 5.1 msec.
Documentation
Documentation: GO TO DOCUMENTATION
Simple interface
class VCodecV4L2 : public VCodec
{
public:
/// Get library version.
static std::string getVersion();
/// 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);
};
Simple example
#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;
}