vcodecwmf_web_logo

VCodecWmf C++ library

v1.0.0

Table of contents

Overview

The VCodecWmf C++ library provides hardware-accelerated and software video encoding and decoding for H264, HEVC (H.265), and JPEG formats based on Microsoft Media Foundation (WMF) and Windows Imaging Component (WIC) for Windows (Windows 11 and later). The VCodecWmf class implements the open-source VCodec interface (source code included, Apache 2.0 license) and adheres to the RapidPixel Coding Standards.

The library automatically enumerates and prioritizes the best available backend at runtime:

  1. Hardware acceleration priority: Dedicated GPU (NVIDIA NVENC/NVDEC) -> Integrated GPU (Intel Quick Sync / AMD AMF) -> Software fallback (Microsoft MFT / WIC).
  2. Low-latency real-time streaming: Disables B-frames (CODECAPI_AVEncMPVDefaultBPictureCount = 0), enables low-latency pipeline (CODECAPI_AVEncCommonLowLatency = TRUE), supports dynamic GOP and CBR/VBR rate control.
  3. JPEG processing: Uses Windows Imaging Component (WIC) with native SIMD acceleration on CPU/GPU, providing sub-millisecond JPEG encoding and decoding without external dependencies.
  4. C++ standard: Strictly written in C++17, compiling cleanly under warning level /W4.

Encoding time of VCodecWmf on Windows 11 (Intel Core i7-13700H, NVIDIA GeForce RTX 4050 Laptop GPU, NV12 input, 30 fps, 3000 kbps, CBR):

codec / resolution 1920x1080 1280x720 640x480
H264 ~4.17 msec ~1.99 msec ~1.07 msec
HEVC ~4.71 msec ~2.35 msec ~1.22 msec
JPEG ~6.30 msec ~3.02 msec ~0.96 msec

Decoding time of VCodecWmf on Windows 11 (Intel Core i7-13700H, NVIDIA GeForce RTX 4050 Laptop GPU, NV12 output):

codec / resolution 1920x1080 1280x720 640x480
H264 ~8.53 msec ~8.12 msec ~7.56 msec
HEVC ~8.53 msec ~7.41 msec ~7.37 msec
JPEG ~5.43 msec ~2.40 msec ~0.84 msec

Performance comparison: VCodecWmf vs FFmpeg

The following table compares the performance (average frame latency and throughput) of VCodecWmf directly against FFmpeg 6.0 (hardware accelerated with NVENC/CUVID) on the same machine and identical test datasets (100 frames):

Codec Resolution VCodecWmf Encode FFmpeg NVENC Encode VCodecWmf Decode FFmpeg CUVID Decode
H264 1920x1080 4.17 ms (~240 fps) 20.37 ms (~49 fps) 8.53 ms (~117 fps) 2.82 ms (~354 fps)
H264 1280x720 1.99 ms (~502 fps) 3.00 ms (~333 fps) 8.12 ms (~123 fps) 2.08 ms (~480 fps)
H264 640x480 1.07 ms (~935 fps) 2.06 ms (~484 fps) 7.56 ms (~132 fps) 1.47 ms (~682 fps)
HEVC 1920x1080 4.71 ms (~212 fps) 4.83 ms (~207 fps) 8.53 ms (~117 fps) 2.44 ms (~410 fps)
HEVC 1280x720 2.35 ms (~425 fps) 3.00 ms (~333 fps) 7.41 ms (~135 fps) 1.90 ms (~525 fps)
HEVC 640x480 1.22 ms (~820 fps) 2.00 ms (~501 fps) 7.37 ms (~136 fps) 1.51 ms (~664 fps)
JPEG 1920x1080 6.30 ms (~159 fps) 3.60 ms (~278 fps) 5.43 ms (~184 fps) 0.69 ms (~1445 fps)
JPEG 1280x720 3.02 ms (~331 fps) 1.84 ms (~542 fps) 2.40 ms (~417 fps) 0.67 ms (~1498 fps)
JPEG 640x480 0.96 ms (~1042 fps) 1.01 ms (~987 fps) 0.84 ms (~1190 fps) 0.51 ms (~1954 fps)

Versions

Table 1 - Library versions.

Version Release date What’s new
1.0.0 28.09.2026 - Initial release of Microsoft Media Foundation (WMF) and Windows Imaging Component (WIC) codec library for Windows 11 and later.

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 (enforces Windows platform).
3rdparty -------------------- Folder with third-party libraries.
    CMakeLists.txt ---------- CMake file to include third-party libraries.
    VCodec ------------------ Folder with VCodec interface library source code.
example --------------------- Folder with simple example of VCodecWmf usage.
    CMakeLists.txt ---------- CMake file for example application.
    main.cpp ---------------- Source code file of example application.
static ---------------------- Folder with static project resources.
    vcodecwmf_web_logo.png -- Web logo used in README.
test ------------------------ Folder with codec test application.
    CMakeLists.txt ---------- CMake file for codec test application.
    main.cpp ---------------- Source code file of codec test application.
    data -------------------- Pre-generated bitstreams for decoder auto tests.
        test_*.h264 --------- H264 test streams for different resolutions.
        test_*.hevc --------- HEVC test streams for different resolutions.
        test_*.jpeg --------- JPEG test streams for different resolutions.
src ------------------------- Folder with source code of the library.
    CMakeLists.txt ---------- CMake file of the library.
    VCodecWmf.cpp ----------- C++ implementation file with public API exports.
    VCodecWmf.h ------------- Header file which includes VCodecWmf class declaration.
    VCodecWmfVersion.h ------ Header file which includes version of the library.
    VCodecWmfVersion.h.in --- CMake service file to generate version file.
    impl -------------------- Internal WMF and WIC implementation details.
        WmfContext.cpp ------ Direct3D 11 device and DXGI GPU adapter management.
        WmfContext.h -------- Direct3D 11 device manager declaration.
        WmfEncoder.cpp ------ Hardware-accelerated and software MFT video encoder.
        WmfEncoder.h -------- MFT video encoder declaration.
        WmfDecoder.cpp ------ Hardware-accelerated and software MFT video decoder.
        WmfDecoder.h -------- MFT video decoder declaration.
        WicJpegCodec.cpp ---- WIC JPEG encoder and decoder with NV12 conversion.
        WicJpegCodec.h ------ WIC JPEG codec declaration.
        VCodecWmfImpl.cpp --- Internal backend implementation and routing.
        VCodecWmfImpl.h ----- Internal backend declaration.

VCodecWmf class description

VCodecWmf class declaration

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

class VCodecWmf : public VCodec
{
public:

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

    /// Class constructor.
    VCodecWmf();

    /// Class destructor.
    ~VCodecWmf() override;

    /// Transcode (encode or decode) video frame.
    bool transcode(Frame& src, Frame& dst) override;

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

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

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

getVersion method

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

static std::string getVersion();

The method can be used without a VCodecWmf class instance:

std::cout << "VCodecWmf class version: " << cr::video::VCodecWmf::getVersion() << std::endl;

Console output:

VCodecWmf class version: 1.0.0

transcode method

The transcode(…) method is intended to encode and decode video frames (Frame class). The direction (encode or decode) is determined by the fourcc fields of the src and dst frames: if src is NV12 and dst is a compressed format (H264, HEVC, JPEG), the library encodes; if src is compressed and dst is NV12, the library decodes. The video codec processes frames one at a time. Method declaration:

bool transcode(Frame& src, Frame& dst);
Parameter Value
src Source video frame (see Frame class description). For encoding: must have raw pixel format NV12. For decoding: must have compressed format H264, HEVC, or JPEG (set size to the actual bitstream length).
dst Result video frame (see Frame class description). For encoding: must have compressed format H264, HEVC, or JPEG. For decoding: must have raw pixel format NV12.

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

setParam method

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

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

Returns: TRUE if the parameter was set 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 parameter descriptions for VCodecWmf.

Parameter Access Description
LOG_LEVEL read / write Logging mode: 0 - Disable, 1 - File, 2 - Console, 3 - File & console.
BITRATE_KBPS read / write Target bitrate in kbps. Range: 100 - 100,000 kbps. Default: 3000 kbps. For H264/HEVC encoding. Applied on-the-fly via ICodecAPI.
MIN_BITRATE_KBPS read / write Minimum bitrate in kbps. Always 0 (WMF hardware/software encoders do not impose a minimum bitrate floor; getParam always returns 0.0f).
MAX_BITRATE_KBPS read / write Maximum peak bitrate in kbps for variable bitrate mode (BITRATE_MODE = 1). Default: 5000 kbps. Dynamically applied via CODECAPI_AVEncCommonMaxBitRate.
BITRATE_MODE read / write Bitrate mode: 0 - Constant Bitrate (CBR), 1 - Variable Bitrate (Peak-constrained VBR). Dynamically applied via CODECAPI_AVEncCommonRateControlMode.
QUALITY read / write JPEG encoding quality. Range: 1 - 100 (1 = lowest, 100 = highest). Default: 80.
FPS read / write Frame rate. Range: 1 - 240 fps. Default: 30 fps. Used for rate control and timestamp calculation.
GOP read / write GOP size (keyframe interval in frames). Range: 1 - 1000. Default: 30.
H264_PROFILE read / write H264 profile for H264 encoding: 0 - Baseline, 1 - Main, 2 - High.
TYPE read / write Not used. The value is only stored: setParam accepts any value, getParam returns the last value set (default 0). It does not select the backend and does not report the backend in use: the encoder, decoder and GPU adapter are always selected automatically (see Overview).
CUSTOM_1 read / write Custom parameter 1.
CUSTOM_2 read / write Custom parameter 2.
CUSTOM_3 read / write Custom parameter 3.

getParam method

The getParam(…) method is designed to obtain video codec parameter values. 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 if the parameter is not supported.

executeCommand method

The executeCommand(…) method is designed to execute video codec commands. Method declaration:

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

Returns: TRUE if the command was accepted or FALSE if not.

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 command descriptions for VCodecWmf.

Command Description
RESET Resets encoder and decoder state.
MAKE_KEY_FRAME Forces the next encoded frame to be an IDR keyframe via CODECAPI_AVEncVideoForceKeyFrame.

Build and connect to your project

Prerequisites and System Requirements

The library is designed for Windows 11 and later (x64 architecture).

  1. Operating System: Windows 11 (64-bit).
  2. Build Tools:
    • Microsoft Visual Studio 2022 (version 17.0 or higher) with the “Desktop development with C++” workload installed.
    • CMake version 3.16 or higher.
    • Windows 11 SDK (included with Visual Studio 2022). All required system libraries are part of the standard Windows SDK:
      • Media Foundation (mfplat.lib, mfuuid.lib)
      • Direct3D 11 & DXGI (d3d11.lib, dxgi.lib)
      • Windows Imaging Component (windowscodecs.lib)
      • Shell & COM (shlwapi.lib, ole32.lib, oleaut32.lib)
  3. GPU Drivers:
    • For NVIDIA GPU hardware encoding/decoding: latest NVIDIA Game Ready or Studio drivers supporting NVENC/NVDEC.
    • For Intel integrated GPUs: latest Intel Graphics drivers with Quick Sync Video support.
    • For AMD GPUs: latest AMD Radeon Software drivers with AMF support.
  4. HEVC Codec Note:
    • Windows 11 includes native hardware HEVC MFT transforms when compatible GPU drivers are installed.
    • If software HEVC decoding is required on systems without hardware HEVC blocks, install the “HEVC Video Extensions” package from the Microsoft Store.

Typical commands to build VCodecWmf library

Run the following commands in PowerShell or Visual Studio Developer Command Prompt:

git clone --recurse-submodules https://github.com/ConstantRobotics-Ltd/VCodecWmf.git
cd VCodecWmf
cmake -B build -S .
cmake --build build --config Release

The compiled library will be located in build/src/Release/VCodecWmf.lib, and the example and test executables in build/bin/Release/.

Connect to your CMake project

If you want to connect the VCodecWmf 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
    CMakeLists.txt
    yourLib.h
    yourLib.cpp

Create a folder 3rdparty in your repository. Copy the repository folder VCodecWmf to the 3rdparty folder. The new structure of your repository:

CMakeLists.txt
src
    CMakeLists.txt
    yourLib.h
    yourLib.cpp
3rdparty
    VCodecWmf

Create a CMakeLists.txt file in the 3rdparty folder. The CMakeLists.txt should contain:

cmake_minimum_required(VERSION 3.16)

################################################################################
## 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)

################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
add_subdirectory(VCodecWmf)

The file 3rdparty/CMakeLists.txt adds the folder VCodecWmf to your project and will exclude test applications from compiling. Your repository’s new structure will be:

CMakeLists.txt
src
    CMakeLists.txt
    yourLib.h
    yourLib.cpp
3rdparty
    CMakeLists.txt
    VCodecWmf

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

add_subdirectory(3rdparty)

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

target_link_libraries(${PROJECT_NAME} VCodecWmf)

Done!

Simple example

The example application generates an image color pattern with a moving rectangle, encodes it to HEVC using VCodecWmf, and writes compressed data to a binary file “out.hevc”:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include "VCodecWmf.h"

int main(void)
{
    // Create codec and set params.
    cr::video::VCodecWmf codec;
    codec.setParam(cr::video::VCodecParam::BITRATE_KBPS, 7500);
    codec.setParam(cr::video::VCodecParam::GOP, 30);
    codec.setParam(cr::video::VCodecParam::FPS, 30);

    // Create NV12 frame.
    const int width = 1280;
    const int height = 720;
    cr::video::Frame frameNv12(width, height, cr::video::Fourcc::NV12);

    // Fill NV12 frame with pattern.
    for (int i = 0; i < frameNv12.size; ++i)
        frameNv12.data[i] = static_cast<uint8_t>(i);

    // Create output HEVC frame.
    cr::video::Frame frameHEVC(width, height, cr::video::Fourcc::HEVC);

    // Create output file.
    FILE* outputFile = fopen("out.hevc", "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 (int n = 0; n < 200; ++n)
    {
        // Draw moving object.
        memset(frameNv12.data, 128, width * height);
        for (int y = objectY; y < objectY + objectHeight && y < height; ++y)
            for (int x = objectX; x < objectX + objectWidth && x < width; ++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 (!codec.transcode(frameNv12, frameHEVC))
        {
            std::cout << "Cannot encode frame" << std::endl;
            continue;
        }

        // Write to file.
        if (frameHEVC.size > 0)
            fwrite(frameHEVC.data, frameHEVC.size, 1, outputFile);
    }

    // Close file.
    fclose(outputFile);

    return 0;
}

Test application

The test application (test/main.cpp) for the VCodecWmf C++ library has two modes: Manual encoder test and Auto test. All parameters are entered via an interactive terminal dialog (no command-line arguments). To run the application:

cd build\bin\Release
.\VCodecWmfTest.exe

After starting, you will see the mode selection menu:

========================================
  VCodecWmf v1.0.0 test
========================================

========================================
              SET MODE
========================================
  1 - Manual encoder
  2 - Auto test
  0 - Exit
>

Manual encoder mode

Allows to select a codec (H264, HEVC, or JPEG), use default parameters or enter custom ones (resolution, frame count, bitrate/GOP/FPS/profile for H264/HEVC, or quality for JPEG), and encode a test video pattern. The test pattern consists of 8 colored vertical bars with a scrolling brightness wave and a white square bouncing diagonally. Encoded output is saved to out.h264, out.hevc, or out.jpeg. For JPEG, only the last encoded frame is kept in the file.

=== MANUAL ENCODER TEST ===
Codec (0-H264, 1-HEVC, 2-JPEG): 0

Defaults:
  Resolution: 1920x1080
  Frames: 100
  Bitrate: 3000 kbps
  FPS: 30
  GOP: 30
  Profile: Baseline

Use defaults? (1-yes, 0-no): 1

Output: out.h264
  Frame 100/100  size=5765  time=4.15 ms

========================================
           SUMMARY
========================================
Encoded: 100/100
Avg: 4.17 ms/frame
File: out.h264

Auto test mode

Runs encoding and decoding tests for all 3 codecs (H264, HEVC, JPEG) across 3 resolutions (1920x1080, 1280x720, 640x480) with 100 frames each. Decoding uses pre-generated test data files from test/data/. After all tests complete, a summary table is displayed:

========================================
           AUTO TEST
========================================

=== ENCODING ===
  H264 1920x1080 ... 4.17 ms (100/100)
  H264 1280x720 ... 1.99 ms (100/100)
  H264 640x480 ... 1.07 ms (100/100)
  HEVC 1920x1080 ... 4.71 ms (100/100)
  HEVC 1280x720 ... 2.35 ms (100/100)
  HEVC 640x480 ... 1.22 ms (100/100)
  JPEG 1920x1080 ... 6.30 ms (100/100)
  JPEG 1280x720 ... 3.02 ms (100/100)
  JPEG 640x480 ... 0.96 ms (100/100)

=== DECODING ===
  H264 1920x1080 ... 8.53 ms (100/100)
  H264 1280x720 ... 8.12 ms (100/100)
  H264 640x480 ... 7.56 ms (100/100)
  HEVC 1920x1080 ... 8.53 ms (100/100)
  HEVC 1280x720 ... 7.41 ms (100/100)
  HEVC 640x480 ... 7.37 ms (100/100)
  JPEG 1920x1080 ... 5.43 ms (100/100)
  JPEG 1280x720 ... 2.40 ms (100/100)
  JPEG 640x480 ... 0.84 ms (100/100)

========================================
           SUMMARY
========================================

  Codec Res        | Encode             | Decode            
  ----- ---------- | ------------------ | ------------------
  H264  1920x1080  |   4.17 ms 100/100  |   8.53 ms 100/100 
  H264  1280x720   |   1.99 ms 100/100  |   8.12 ms 100/100 
  H264  640x480    |   1.07 ms 100/100  |   7.56 ms 100/100 
  ----- -----------+--------------------+-------------------
  HEVC  1920x1080  |   4.71 ms 100/100  |   8.53 ms 100/100 
  HEVC  1280x720   |   2.35 ms 100/100  |   7.41 ms 100/100 
  HEVC  640x480    |   1.22 ms 100/100  |   7.37 ms 100/100 
  ----- -----------+--------------------+-------------------
  JPEG  1920x1080  |   6.30 ms 100/100  |   5.43 ms 100/100 
  JPEG  1280x720   |   3.02 ms 100/100  |   2.40 ms 100/100 
  JPEG  640x480    |   0.96 ms 100/100  |   0.84 ms 100/100 

Table of contents