Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

codecmap

Which video codecs this PC can encode and decode in hardware. codecmap asks Media Foundation what your GPU can record and asks Direct3D 11 what it can play, then prints both halves side by side with the adapter that owns each one.

Zero dependencies. One PowerShell file. Read-only - it never instantiates a codec, never opens a device for capture and never changes a setting.

powershell -NoProfile -ExecutionPolicy Bypass -File codecmap.ps1

The gap this fills

Every streaming guide tells you to "use hardware encoding". None of them tell you how to find out what your machine actually has.

Where you'd look What it tells you
dxdiag Adapter name, driver, memory. Not one word about codecs.
Device Manager That a display adapter exists. Nothing else.
OBS encoder dropdown The encode half only, already filtered by what OBS supports, with no reason given when something is missing.
A GPU spec page What the silicon can do - not what this driver, on this Windows build, actually registered.
Nothing at all The decode half. No shipping UI on Windows lists your DXVA decoder profiles.

So "why is NVENC missing from OBS", "will this machine scrub 10-bit HEVC smoothly", and "can it play back the VP9 I just downloaded without melting the CPU" are all questions Windows can answer and simply never does.

Real output

$ codecmap.ps1 -NoColor
codecmap 1.0.0  -  PC
3 adapter(s), 2 with a video engine

GRAPHICS ADAPTERS
  [0] Intel(R) Iris(R) Plus Graphics
      Intel  128 MB  video engine  pci 0x8086/0x8a52
  [1] NVIDIA GeForce GTX 1660 Ti with Max-Q Design
      NVIDIA  5.8 GB  video engine  pci 0x10de/0x2191
  [2] Microsoft Basic Render Driver
      Microsoft  0 MB  NO video engine  pci 0x1414/0x008c

HARDWARE ENCODE   (what a capture app can pick)
  H.264      yes   NVIDIA, Intel
  HEVC       yes   NVIDIA, Intel   10-bit ready
  AV1        no
  VP9        yes   Intel
  VP8        no
  MJPEG      no

HARDWARE DECODE   (Direct3D 11 accelerated playback)
  H.264      yes   Intel, NVIDIA   VLD NoFGT, VLD Stereo Progressive, VLD Stereo, VLD Multiview
  HEVC       yes   Intel, NVIDIA   Main, Main10
  AV1        no
  VP9        yes   Intel, NVIDIA   Profile 0, 10-bit Profile 2
  VP8        yes   Intel   VLD
  MPEG-2     yes   Intel, NVIDIA   IDCT, VLD, VLD (with MPEG-1)
  MPEG-4 p2  yes   NVIDIA   Simple, Advanced Simple NoGMC
  VC-1       yes   Intel, NVIDIA   IDCT, VLD, D2010
  WMV9       yes   Intel   IDCT
  MJPEG      yes   NVIDIA, Intel   via decoder transform, no DXVA profile

NOTES
  - Play-only: VP8, MPEG-2, MPEG-4 p2, VC-1, WMV9, MJPEG. These decode in
    hardware but this PC has no hardware encoder for them, so recording them
    uses the CPU.
  - 3 encoder transform(s) are registered up to 2 times: 'Intel(R) Quick
    Sync Video H.264 Encoder MFT', 'Intel(R) Hardware H265 Encoder MFT',
    'Intel(R) Hardware VP9 Encoder MFT'. That is one physical engine listed
    once per adapter, not several encoders.
  - Adapter [2] Microsoft Basic Render Driver exposes no Direct3D video
    engine. It is a software renderer and will never accelerate anything.
[exit 0]

That is a 2019 laptop. It can record H.264, HEVC and VP9 on silicon, cannot touch AV1 in either direction, and can hardware-play five formats it can never hardware-record. No single Windows dialog shows any of that.

Encode and decode are two different questions

This is the part a transform-only tool gets wrong, and it is why codecmap queries two subsystems instead of one.

Encode comes from Media Foundation. MFTEnumEx is asked, once per codec, for hardware transforms that produce that subtype. That is literally the list a capture app builds its encoder dropdown from, so if a codec is missing here it will be missing in the app too.

Decode comes from Direct3D 11. Every DXGI adapter is asked for its DXVA decoder profile GUIDs. A GPU accelerates decoding through DXVA whether or not it registers a decoder transform - and for H.264, HEVC and VP9 it usually registers none at all. A tool that counted transforms would report "no hardware H.264 decode" on the machine above, which plainly does have it.

MJPEG proves neither half is sufficient on its own. There is no DXVA profile GUID for M-JPEG anywhere in the Windows headers, yet both vendors on this machine ship a hardware M-JPEG decoder MFT. So codecmap reports the route it found rather than pretending there is only one:

  MJPEG      yes   NVIDIA, Intel   via decoder transform, no DXVA profile

Ask a single subsystem and you get the wrong answer for at least one codec, in one direction, on most machines.

Two adapters, one physical encoder

MFTEnumEx returns a hardware encoder once per adapter it is bound to. Count the rows and this laptop appears to have six Intel encoders. It has three. The note above says so in plain words, and -Detail shows the registration count next to the CLSID:

    encode: Intel(R) Quick Sync Video H.264 Encoder MFT  (registered 2 times)
            clsid  4be8d3c0-0515-4a37-ad55-e4bae19af471
            vendor Intel [VEN_8086]
            accepts {3231564e-3961-42ae-ba67-ff47ccc13eed} NV12 {00000015-0000-0010-8000-00aa00389b71}

Formats codecmap cannot name are printed as their raw GUID. It never invents a label it has not verified - the same rule applies to the 55 DXVA profiles on this machine that have no published name.

Usage

$ codecmap.ps1 -Help -NoColor
codecmap 1.0.0  -  which video codecs this PC can encode and decode in hardware

USAGE
  codecmap.ps1 [options]

OPTIONS
  -Codec <name>       Only report one codec. One of:
                      h264, hevc, av1, vp9, vp8, mpeg2, mpeg4, vc1, wmv9, mjpeg
  -Encoders           Only the encode half.
  -Decoders           Only the decode half.
  -Detail             Every transform, CLSID, pixel format and profile GUID.
  -Software           With -Detail, also list software encoder fallbacks.
  -Adapters           Only the adapter list.
  -Json               Emit the whole model as JSON.
  -Save <file>        Write the JSON model to a file.
  -FromJson <file>    Render a previously saved model instead of querying.
  -FailIfMissing <c>  Exit 3 if codec <c> has no hardware encoder.
  -Info               Print what codecmap is running on.
  -Quiet              Print nothing, just set the exit code.
  -Version            Print the version and exit.
  -Help               This text.

One codec at a time

$ codecmap.ps1 -Codec hevc -NoColor
codecmap 1.0.0  -  PC
3 adapter(s), 2 with a video engine

GRAPHICS ADAPTERS
  [0] Intel(R) Iris(R) Plus Graphics
      Intel  128 MB  video engine  pci 0x8086/0x8a52
  [1] NVIDIA GeForce GTX 1660 Ti with Max-Q Design
      NVIDIA  5.8 GB  video engine  pci 0x10de/0x2191
  [2] Microsoft Basic Render Driver
      Microsoft  0 MB  NO video engine  pci 0x1414/0x008c

HARDWARE ENCODE   (what a capture app can pick)
  HEVC       yes   NVIDIA, Intel   10-bit ready

HARDWARE DECODE   (Direct3D 11 accelerated playback)
  HEVC       yes   Intel, NVIDIA   Main, Main10

NOTES
  - 1 encoder transform(s) are registered up to 2 times: 'Intel(R) Hardware
    H265 Encoder MFT'. That is one physical engine listed once per adapter,
    not several encoders.
  - Adapter [2] Microsoft Basic Render Driver exposes no Direct3D video
    engine. It is a software renderer and will never accelerate anything.
[exit 0]

10-bit ready means an encoder on this machine accepts a 10-bit input format (P010 or Y410), so HDR and 10-bit capture will not silently fall back to the CPU.

Just the adapters

$ codecmap.ps1 -Adapters -NoColor
GRAPHICS ADAPTERS
  [0] Intel(R) Iris(R) Plus Graphics
      Intel  128 MB  video engine  pci 0x8086/0x8a52
  [1] NVIDIA GeForce GTX 1660 Ti with Max-Q Design
      NVIDIA  5.8 GB  video engine  pci 0x10de/0x2191
  [2] Microsoft Basic Render Driver
      Microsoft  0 MB  NO video engine  pci 0x1414/0x008c
[exit 0]

Use it in a script

-FailIfMissing turns the question into an exit code, so a capture script can refuse to start rather than quietly recording with the CPU:

$ codecmap.ps1 -FailIfMissing h264 -Quiet -NoColor

[exit 0]

$ codecmap.ps1 -FailIfMissing av1 -Quiet -NoColor

[exit 3]
powershell -NoProfile -File codecmap.ps1 -FailIfMissing hevc -Quiet
if ($LASTEXITCODE -ne 0) { throw 'this machine cannot record HEVC on the GPU' }

Save it and read it back

$ codecmap.ps1 -Save "...\codecs.json" -Quiet -NoColor

[exit 0]

$ codecmap.ps1 -FromJson "...\codecs.json" -NoColor
codecmap 1.0.0  -  PC
3 adapter(s), 2 with a video engine
...

-FromJson re-renders a saved model without touching the hardware, so you can collect one file from a machine you do not have in front of you and read it anywhere. The replayed output is byte-for-byte identical to the live run that produced it - which is checked on every test run, not just asserted here.

The whole model as JSON

$ codecmap.ps1 -Json
{
    "Tool":  "codecmap",
    "Captured":  "2026-09-14 10:36:06",
    "Codecs":  [
                   {
                       "HwDecoders":  [

                                      ],
                       "EncodeQueried":  true,
                       "Fourcc":  "H264",
                       "SwEncoders":  [
                                          {
                                              "VendorId":  "",
                                              "Name":  "H264 Encoder MFT",
                                              "Clsid":  "6ca50344-051a-4ded-9779-a43305165e35",
                                              "Registrations":  1,
                                              "Vendor":  "",
                                              "Formats":  [
                                                              "IYUV",

Exit codes

Code Meaning
0 The query ran.
2 The command line could not be understood.
3 -FailIfMissing was given and that codec has no hardware encoder.
4 Neither Direct3D nor Media Foundation could be queried.
$ codecmap.ps1 -Codec nonsense -NoColor
codecmap: unknown codec 'nonsense'. Known: h264, hevc, av1, vp9, vp8, mpeg2, mpeg4, vc1, wmv9, mjpeg
[exit 2]

How it reads the hardware

codecmap compiles a small C# helper at run time and calls the same APIs a media app would.

Adapters. CreateDXGIFactory1, then EnumAdapters1 until it runs out. GetDesc1 gives the description, vendor and device IDs and dedicated video memory. Each adapter is then used to create a D3D11 device, and the device is queried for ID3D11VideoDevice. An adapter that will not produce one has no video engine - that is how the Microsoft Basic Render Driver is identified without matching on its name.

Decode. GetVideoDecoderProfileCount and GetVideoDecoderProfile list every DXVA profile GUID the adapter advertises. codecmap maps the GUIDs it knows to human names and prints the rest as GUIDs under UNRECOGNISED DECODER PROFILES. Profiles are attributed to the specific adapters that reported them, so a profile only one GPU supports is not credited to both.

Encode. MFStartup, then MFTEnumEx per codec with the hardware flag set, asking for transforms that output that subtype. The friendly name, CLSID and vendor come from each transform's IMFAttributes, and the accepted input formats from its registered type info. A second pass with the software flag feeds -Software.

Decoder transforms. The same enumeration in the other direction catches codecs like M-JPEG that are accelerated by a transform rather than by DXVA.

Nothing is instantiated. Enumerating a transform reads its registration; it does not load the codec or touch the GPU's encode engine, so running codecmap while you are recording will not disturb the recording.

Things it is deliberately honest about

  • Store-packaged media extensions have no CLSID. The HEVC and AV1 Video Extensions register with an all-zero GUID. codecmap prints none (packaged media extension) instead of a made-up identifier.
  • Unnamed profiles stay as GUIDs. 55 of the profiles on the test machine have no published name. Guessing would be worse than showing the GUID.
  • no means "not registered right now", not "impossible". A driver update can add AV1 encode to hardware that always had it.
  • Software fallbacks are hidden by default. Every machine has them and listing them next to the hardware rows is how people end up believing they have hardware AV1. -Detail -Software shows them, clearly labelled.

Cross-check it yourself

Nothing here has to be taken on trust.

The adapter list matches Device Manager, and the PCI IDs match the hardware IDs on each adapter's Details tab.

The encoder transforms are real registered COM servers. Take a CLSID from -Detail and look it up:

Get-ItemProperty "HKLM:\SOFTWARE\Classes\CLSID\{4be8d3c0-0515-4a37-ad55-e4bae19af471}"

The decode profiles can be listed by any DXVA checker - the GUIDs codecmap prints are the raw values the driver returned, unmodified.

The encode half matches what a capture app offers. Open OBS, look at the encoder list in Output settings, and compare it with the HARDWARE ENCODE table. They agree, because they are built from the same enumeration.

realcheck.ps1 does all of this automatically, on your machine, against three independent oracles: WMI Win32_VideoController for the adapters, the registry for every CLSID, and a separately compiled copy of the native queries that shares no code with the tool. That last one does not merely confirm what codecmap reported - it enumerates each codec itself and demands an exact match, so a codec codecmap failed to find is a failure too.

Testing

Suite What it does Result
selftest.ps1 Hermetic. Builds synthetic models and drives every renderer, parser, exit code and CLI path in a temp directory. Touches no hardware. 548 assertions
realcheck.ps1 Runs against this machine and cross-checks every number against three independent oracles. 286 assertions
mutate.ps1 Breaks codecmap 111 different ways, one at a time, and requires the suites to catch each one. 111 mutations, 0 survivors
powershell -NoProfile -ExecutionPolicy Bypass -File selftest.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File realcheck.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File mutate.ps1

A green test suite proves nothing on its own, so mutate.ps1 checks the tests instead of the tool. It rewrites one line of codecmap - flips a GUID, drops a flag, removes a bounds check, changes a vtable slot - and fails if the suites still pass. Every one of the 111 mutations is caught. The gate for shipping is three consecutive clean runs of all three suites.

One mutation is a deliberate tripwire that must survive: removing a defensive dictionary branch that PowerShell's foreach makes unreachable anyway. If the harness ever reports that one as killed, the harness is lying and the run fails.

Requirements

  • Windows 10 or 11
  • Windows PowerShell 5.1 (ships with Windows) or PowerShell 7
  • No admin rights, no installs, no downloads

Tested on Windows 11 26200 with PowerShell 5.1.26100.9444.

See also

  • obs-4k60-recorder - OBS settings for 4K60 capture that does not drop frames
  • gpucheck - is the GPU actually being used
  • framecheck - frame pacing and stutter
  • truehz - the refresh rate you are really getting
  • fragmap - where a file actually lives on disk

License

MIT - see LICENSE.

About

Shows which video codecs your PC can actually hardware-encode and decode. Enumerates every Media Foundation hardware transform per GPU, maps vendor IDs to real names, flags decode-only codecs and duplicate registrations, and explains why NVENC or Quick Sync is missing from your OBS encoder list. Zero dependencies, read-only.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages