VCodecLibav C++ lib. Fast HEVC, H264 and JPEG encoding/decoding based on Libav

€1,500.00

VCodecLibav C++ library provides video encoding and decoding functions for H264, HEVC(H265) and JPEG codecs for Linux OS based on FFmpeg.

LICENSE: We sell source code of this library as is, without future updates and technical support according to perpetual non-exclusive royalty-free license. You pay once and can use this library in your software and hardware products without limits. Please read the license agreement before purchasing: LICENSE.

VCodecLibav C++ library provides video encoding and decoding functions for H264, HEVC(H265) and JPEG codecs for Linux OS based on FFmpeg.

LICENSE: We sell source code of this library as is, without future updates and technical support according to perpetual non-exclusive royalty-free license. You pay once and can use this library in your software and hardware products without limits. Please read the license agreement before purchasing: LICENSE.

Overview

VCodecLibav C++ library provides video encoding and decoding functions for H264, HEVC(H265) and JPEG codecs for Linux and Windows OS based on FFmpeg. The library supports software encoders / decoders and Intel hardware encoders / decoders. The library compatible with any CPU (software encoder) which supports FFmpeg. VCodecLibav video codec class inherits interface and data structures form VCodec interface library. The library depends on open source VCodec library (provides codec interface, source code included, Apache 2.0 license), open source Libav library (part of FFmpeg, linked) and open source Logger (provides functions to print logs, source code included, Apache 2.0). the library uses C++17 standard. Used FFmpeg codecs:

  • H264: h264_vaapi hardware encoder, h264_qsv hardware decoder, libx264 software encoder and decoder.

  • HEVC(H265): hevc_vaapi hardware encoder, hevc_qsv hardware decoder, libx265 software encoder and decoder.

  • JPEG: mjpeg_vaapi hardware encoder, mjpeg_qsv hardware decoder, mjpeg software encoder and decoder.

Hardware encoding / decoding time (msec) for 11th Gen Intel(R) Core(TM) i5-1145G7E on Ubuntu 22.10:

  • H264 codec, 1920x1080 - 5 / 3 msec, 1280x720 - 2 / 1.6 msec, 640x512 - 0.6 / 0.5 msec.

  • HEVC codec, 1920x1080 - 5 / 3 msec, 1280x720 - 3 / 1.2 msec, 640x512 - 2 / 0.6 msec.

  • JPEG codec, 1920x1080 - 2 / 4 msec, 1280x720 - 1 / 1.5 msec, 640x512 - 0.3 / 0.6 msec.

Software encoding / decoding time (msec) for 11th Gen Intel(R) Core(TM) i5-1145G7E on Ubuntu 22.10:

  • H264 codec, 1920x1080 - 8 / 3 msec, 1280x720 - 3.5 / 1.5 msec, 640x512 - 1.8 / 0.9 msec.

  • HEVC codec, 1920x1080 - 35 / 10 msec, 1280x720 - 25 / 8 msec, 640x512 - 15 / 7 msec.

  • JPEG codec, 1920x1080 - 4 / 3 msec, 1280x720 - 1.8 / 1.4 msec, 640x512 - 0.9 / 0.7 msec.

The primary difference between software (SW) and hardware (HW) encoders and decoders is the latency they introduce. SW encoders and decoders have zero frame latency, but they take more time than HW encoders and decoders. On the other hand, HW encoders have 1 frame latency, and HW decoders have 3 frames latency for H264 codecs.

Documentation

Documentation: GO TO DOCUMENTATION

Simple interface

class VCodecLibav : 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 <opencv2/opencv.hpp>
#include "VCodecLibav.h"

int main(void)
{
    // Create codec object and set params.
    cr::video::VCodec* encoder = new cr::video::VCodecLibav();
    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;
    }
}