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.ps1Every 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.
$ 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.
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.
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.
$ 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.
$ 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.
$ 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]
-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' }$ 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.
$ 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",
| 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]
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.
- 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.
nomeans "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 -Softwareshows them, clearly labelled.
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.
| 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.ps1A 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.
- 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.
- 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
MIT - see LICENSE.