Releases: NuclearMeltdown/CapView
Release list
CapView 3.0
The virtual camera was rebuilt on DirectShow, and it now hands on the source exactly as it arrives — its resolution, its frame rate, no ceiling anywhere.
Upgrading from 2.x: the camera has to be installed again.
The old camera and the new one are different COM classes, so installing 3.0 cannot convert the old registration. Open Settings → Recording and install the camera once. The 2.x registration is deleted for you at the same time; left alone it would keep appearing in device lists pointing at a DLL that is no longer there.
The source, 1:1
2.x offered three fixed sizes — 1920×1080, 1280×720, 640×480 — all at 30 fps, whatever the card was actually doing. A 50 Hz PAL console went out at 30. A 59.94 Hz source went out at 30.
3.0 offers what the card is giving, first in the list, in its own size at its own rate, and puts the familiar sizes behind it for consumers that cannot take it.
| Consumer | What it takes |
|---|---|
| OBS | the native entry — 1920×1080 @ 59.94 |
| Discord | 1280×720 @ 60, its own ceiling |
| Browsers | whichever list entry the page asks for |
Each entry describes exactly one size, and nothing above the source is ever offered — a camera that advertises what it has not got pins a consumer to a size the console cannot fill. A consumer that wants something in between can still ask for it outright: the offer is narrow, the acceptance is not. Measured against a live 1080p59.94 source:
| asked for | arrived | picture |
|---|---|---|
| native | 300 samples in 5.005 s — 59.94 fps | luma 17..234 |
| 1280×720 @ 30 | 150 samples in 5.000 s — 30 fps | luma 17..233 |
| 640×480 @ 15 | 61 samples in 4.067 s — 15 fps | luma 16..233, pillarboxed |
Three consumers at once, at three different sizes and rates, each got its own exactly.
Shrinking now averages the whole area a destination pixel covers instead of reading two source pixels and skipping what lies between them. At a six-to-five shrink the two-tap sampling phase repeats 0.1, 0.3, 0.5, 0.7, 0.9 — every fifth pixel nearly a copy, the next a half-and-half blend — and that regular alternation is what showed as grain. Enlarging still uses two taps, and a consumer taking the source untouched still goes through no scaler at all.
It says when it is idle
The camera is registered machine-wide, so it is in every device list from the
moment it is installed — running or not, the same as OBS's virtual camera. A
camera that is always listed and shows black when idle is indistinguishable from
a broken one, so it now shows the mark and CapView is not running instead,
at whatever size the program asked for.
Black is kept for the case it belongs to: a picture that is expected and a frame
or two late.
One thing worth knowing about changing console
A program settles its format when it opens the camera and keeps it for as long
as it holds it open. That is DirectShow's rule — the buffers are committed at
that size and cannot grow underneath a running graph.
So swapping a 1080p console for a 576i one changes what CapView publishes
straight away, and changes nothing for a program already reading: it goes on
asking for the size it negotiated and gets the new picture fitted into it. The
fix is to reopen the camera there.
Whatever program reads the camera, leave its resolution on automatic — hands
off any custom resolution. In OBS that is Resolution/FPS Type: Device
Default. Then a console change is a matter of disabling the device and
enabling it again, and OBS picks up the new size. Discord needs no more than
its camera off and back on.
No ceilings
There is no maximum resolution and no maximum frame rate in the code any more. An 8K120 source is offered as 7680 × 4320 at up to 120 fps, and delivers: 8K30 measured 98 fresh frames of 110, 4K120 measured 286 of 324.
No hardware here can do that. The limits were arbitrary, so they are gone.
Why DirectShow, having chosen Media Foundation in 1.9
The Media Foundation camera was a frame server: it ran in a process of Windows' choosing, which is why it needed objects in the Global namespace, which is why it needed SeCreateGlobalPrivilege, which is why it needed a service.
A DirectShow source filter runs inside the application that opened the camera. That single fact removes the whole chain. Local names are enough, CapView creates the shared objects itself, and the format negotiation is an ordinary interface call instead of a fixed list.
The trade is at the other end: Local names are invisible inside an app container, so packaged Store apps cannot see the camera. That is the deliberate price of not needing administrator rights to use it.
Fixed: large formats went black and stayed black
The consumer reads frames out of shared memory through a seqlock. If it caught a slot mid-write it gave up — and at 8K120 catching a slot mid-write is ordinary rather than rare, so the picture went black and never recovered: 94 frames delivered, 0 of them fresh.
The reader now retries up to three times. Same source, after: 239 fresh of 269. Nothing measurable changed at 1080p, where the collision almost never happened in the first place.
Also
- The filter lives inside
CapView.exeand is written out next to it when the camera is installed, so the two can never be from different builds. Its filename carries an FNV-1a hash of its own contents, because Windows identifies a loaded module by name and a file in use cannot be replaced. - The camera reports who is using it. Settings → Recording lists each consumer by process name with the format it negotiated and how many frames it has taken.
- HDR passes through as P010, offered ahead of NV12. A P010 consumer sees the full 64..940 10-bit video range; an NV12 consumer against the same HDR source gets a converted picture rather than nothing.
- Shift+F5 reinitialises the capture card without restarting CapView. It looks the video standard, resolution and frame rate up again — a different console may be in front of it now — but keeps the pixel format you chose. A card that could do RGB32 a moment ago can still do it, and picking it back out of the list every time was work for nothing.
- The frame rate list works like OBS's — highest available, rather than a fixed set.
Still one file, about 2 MB, nothing installed unless you ask for the camera.
CapView 2.0
The settings now show what the source can actually use, and the first run says hello instead of opening ten tabs of options.
The settings adapt to what is plugged in
Nothing but the device picker until a device is picked. Everything else — standard, input, audio, format, and the nine other tabs — describes a card, and there is not one yet. A no device entry in the dropdown makes that state reachable without editing the configuration by hand.
Once a card is running, controls that cannot apply are absent rather than greyed out. A disabled control still has to be read and dismissed.
And absent means inactive. Move from a SNES to an HD console and the dot crawl filters and the pixel grid stop acting on the picture — otherwise you would be looking at something you did not ask for with no control anywhere to change it, the control having gone precisely because it does not fit. The values stay in the profile, because a profile describes a console and that console will be back. They are not restored on the way out and back: the next analogue source may be a different console, so restoring would be a guess.
Measured with a native width of 256 against a 1080p source: with the signal type forced to Analogue the grid applies and a row shows 55 column transitions; on Automatic, where 1080 lines cannot have come from an analogue decoder, the same row shows 240.
| Shown when | |
|---|---|
| Native pixel grid, composite filter | the source is analogue |
| Scanlines and CRT mask | the source is 576 lines or fewer |
| Deinterlacing | the source has fields |
| HDR source curve, source peak | the source is not analogue |
Two of those deliberately do not key on analogue versus digital, because the obvious rule is wrong in both directions. Scanlines go by line count: a RetroTINK or a MiSTer hangs off HDMI at 480p and its owner is precisely who wants them. Deinterlacing goes by whether there are fields: 1080i and 480i exist over HDMI too.
The HDR tab is split rather than hidden. The source half — which transfer curve arrives, how bright the source peaks — is meaningless for an analogue decoder and goes away. The display half stays, because it is not about the source: with the desktop in HDR mode an SDR picture still has to be written into the HDR container at a chosen white level, or it comes out too dim or too bright. That is as true of a SNES as of anything else.
Automatic now looks at the picture, not just at the card. Having an analogue decoder is not the same as using it. On a hybrid card both inputs sit on one board, the decoder is reported either way, and a console at 1080p60 over the digital input was being treated as an analogue source. No analogue standard produces more than 576 lines, so anything taller did not come from one.
One profile per console, and an easier way to make one
A profile holds everything — device, card input, video standard, capture format, and every picture and audio setting — and Ctrl+1 to Ctrl+9 switch between them. Almost nothing carries over between consoles: a SNES over composite wants the four-frame average, the demodulator, a native width of 256 and PAL at 50 Hz; a Switch over HDMI wants none of that. Set both up once and swapping a cable is one keystroke.
Save current as … replaces Duplicate. Connecting a second console almost never means starting over — you change what is different and want to keep the result, while an empty profile forces you to set up everything that was already right. It asks for a name with the cursor already in the field, and Enter confirms.
A welcome screen on the first run
Ten tabs of options are the worst possible first thing to see. The first run opens on a welcome screen instead — the same screen as "no signal", but the line underneath says which key opens the settings rather than reporting that something is missing. Nothing is missing the first time.
From the second run onward the old shortcut returns and a missing device opens the settings directly, because by then it is a problem rather than a greeting.
A separate settings window by default
It has a Direct3D device of its own and is therefore fully decoupled from the preview: nothing it does can affect the preview's pacing, and the preview's size and position do not constrain it. It can go on a second monitor.
The embedded panel stays, and not only for taste — a window capture in OBS cannot see a second window.
Screenshots can keep the interface
A screenshot has always been the picture itself: source resolution, after crop and deinterlacing, taken between the first draw pass and the interface, so no toolbar, statistics overlay or toast could reach the file. There was no way to capture the window as it stands.
Include the interface, in the Recording tab, moves the grab to the far side of that line — after the interface is drawn and before the frame is presented, which is the only moment the back buffer holds the finished window. Two consequences worth knowing before turning it on: the result is the size of the window rather than of the source, and it is always SDR. With HDR output the back buffer is scRGB in half floats, and rather than convert that by untested colour maths the grab is refused, the picture alone is saved, and the message says so.
Measured on a Switch at 1920x1080: off, the file is 1920x1080; on, it is 1280x1176 — the window — with the statistics overlay in it.
Fixed
The embedded panel ran at 4.7 frames a second with no capture device. It is drawn by the same loop that draws the video, and that loop's idle floor of 200 ms is right for a picture that is not changing and wrong for an interface that has to respond. The floor now asks what is on screen: an embedded panel, the crop overlay, a toast or the volume display each want 16 ms. Measured, no device: 4.7 fps before, 58.6 after, and 4.6 again once the panel is closed, so a genuinely idle screen still costs nothing.
Since 1.9
Reinitialise card, and two other places where a video standard was travelling to an input it says nothing about — a card that seemed stuck between decoder profiles after moving between analogue and digital. Confirmed on a StarTech PEXHDCAP60L: switch from composite to DVI, press it, and 1920x1080 at 60 is found on its own.
The crop overlay's dimming no longer paints over its own Apply and Cancel buttons.
Full detail in the wiki.
CapView 1.9.1
A video standard no longer travels to an input it says nothing about.
Reinitialise card
A video standard belongs to the analogue decoder, not to the card. Move between the analogue and the digital input and PAL D was left standing in the profile, where it means nothing over HDMI and pins the card to 720x576 at 50 Hz. What that looks like is a card stuck between decoder profiles after re-plugging.
There were three ways in, so there are three changes:
Changing the device forgets it. On a card whose analogue and digital inputs enumerate as separate devices, re-plugging is a device change. That path already cleared the format and the crossbar input — "format belongs to the old card" — and the standard belongs to the old card for the same reason. It was simply missing.
A source declared Digital never gets one. A card that does both still reports its analogue standards over a digital input, and that report says nothing about what is on the socket. Start now checks the signal type before applying anything.
And a button, for everything else. Reinitialise card, next to Configure card on the Source tab: releases the card, re-enumerates the device list — a re-plugged card can appear under a different path — puts the standard and the format back to automatic, and starts over.
The device and the crossbar input stay as they are. Those are decisions somebody made; the standard and the format are things CapView measured or guessed, and measurements are what a reinitialise is entitled to discard.
Confirmed on a StarTech PEXHDCAP60L: switch the card from composite to DVI, press it, and 1920x1080 at 60 is found on its own.
The crop overlay's buttons
Folded into 1.9 after it went out, and repeated here for anyone who took the first binary: dragging a crop edge over the overlay's own Apply and Cancel controls no longer turns them too dark to read. The dimming was on ImGui's foreground draw list, which is composited after every window rather than before.
Not changed, and why
The settings window can still hitch slightly while it is being dragged. That was measured this time rather than guessed at, across three drags on live hardware:
| Mouse messages during a drag | ~790 a second |
| CapView's share of the drag | 2.6 – 3.0 % |
| Time lost to gaps over 8 ms | 10.9 – 13.1 % |
| Gaps attributable to CapView | 1 of 181 |
Every one of the ten largest gaps in every drag had 0.00 ms of CapView's work immediately before it. Dragging the window clear of the preview made it slightly worse rather than better, which also rules out the composition of two overlapping windows — the explanation that had been assumed until it was measured.
There is no lever left inside CapView, so nothing was changed on a guess.
CapView 1.9
Retro scaling, a settings window that stays out of the preview's way, and an autocrop that knows when not to.
Native pixel grid
Every output pixel resolves to the console's own pixel rather than to a fraction of one. A card samples the line at a fixed rate — usually 720 — while a SNES draws 256 across it, so each console pixel lands on about 2.8 samples and the boundaries end up wherever the arithmetic puts them. Told the real count, the grid comes back: measured, 245 to 252 clean column transitions out of a theoretical 255.
The dropdown names the console next to each width, because "256" is a number and "SNES, Mega Drive" is an answer.
This recovers the grid, not the detail the grid used to carry. An OSSC samples the waveform at the console's dot clock and can do the second; nothing downstream of a capture card can.
Scanlines and a shadow mask
Off by default, display only, and both compensate their own brightness so the controls change structure rather than exposure — measured mean exactly 1.000 across every scale. Scanlines switch off below twice the source height, where there is nowhere to put a gap and the result would be moire.
Both are capped at 0.5. Past that the compensation cannot hold the colour: the lift needed to restore the brightness starts clipping channels apart from one another, and what arrives is a colour cast rather than a stronger effect. The gain is additionally limited by the pixel's brightest channel, so a bright area gets darker than ideal instead of changing hue.
Avoid ghosting
The four-frame average can only average, and averaging across movement is smearing. The new checkbox moves where that trade happens rather than pretending to remove it: held on late, slow low-contrast movement drags a trail; released early, moving edges stay clean and slow areas keep some crawl for the demodulator to pick up.
The gate keeps five levels out of 255 of slack either way. That is not a sensitivity — it is the card's noise floor, and removing it makes the filter switch on and off on a still picture.
No-signal detection and an idle screen
Snow, a flat line and a real picture are told apart from the luma itself, with the thresholds set against live content rather than guessed. Losing the signal brings up CapView's own idle screen instead of leaving whatever the card last produced on screen.
Autocrop refuses to crop to a logo
The border measurement finds the edges of what is not black, and cannot tell a border from a part of the picture that simply is not lit right now. A console on its home screen is exactly that case.
Detect now asks how much would survive, and the statistic is area — a real border eats one direction, a logo on black eats both. Measured on a GameCube home screen at 720x480: 48 % wide, 77 % tall, 37 % of the area, against 57 % for the widest border that is still a border. It refuses, and names the number it refused on.
The settings window
The preview no longer cares what the window does. Two wrong fixes came before this one, and both were a number: a fixed 30 ms ceiling, then the source's own frame rate — which was worse, because PAL delivers 25 frames while the preview shows 50 deinterlaced fields, and GetTickCount rounds any threshold up to its next 15.6 ms step. 40 ms becomes 46.8, which is 21 frames a second. There is no ceiling now; the drag loop applies the same three conditions the main loop always has.
Switching between embedded and separate hands the position over instead of each form reappearing wherever it last was. Matched outer edge to outer edge, because the embedded panel counts its own title bar and a real window does not — that difference was the few pixels of drift on every switch. A separate window dragged outside the main window centres itself when embedded, rather than opening somewhere unreachable.
The black flicker on interlaced sources is gone. With the settings open the message queue never goes quiet, and the field schedule was conditional on it being quiet — so every second field was dropped for as long as the dialog was open.
Smaller things
- The crop overlay's dimming no longer paints over its own Apply and Cancel buttons. Dragging an edge across them used to make them too dark to read, exactly when you were reaching for them — the four dimmed rectangles were on ImGui's foreground draw list, which is composited after every window rather than before.
- The demodulator slider snaps to the steps that actually change the window width, nine of them on PAL. The positions in between computed the same filter.
- Sharpening works. It was scaling its sample offsets by the destination size instead of the source, so at any real scale factor it sampled inside a single source pixel and returned the pixel unchanged.
- Colour shimmer weights each neighbour by how close its colour is to the centre's. An unweighted average across a colour edge turns complementary colours grey — measured saturation loss 0.42 down to 0.09.
Full detail in the wiki.
CapView 1.8
Two picture bugs that had been there a while, a new empty state, and a landing page.
The viewer says when nothing is coming in
A capture card with nothing on its analogue input keeps delivering frames — it just delivers whatever an open wire decodes to. Asking "are frames arriving" therefore answers nothing on composite, so CapView now asks the pixels instead.
No signal has two appearances and they look nothing like each other. An unterminated input is snow, which is full of contrast; a muted card or an unlocked decoder is a flat field with none. Snow is decidable — that much contrast with that little correlation between frames cannot be a picture. Flat is not, because a black loading screen measures identically, so it is only reported after it has held for a while.
When there is nothing to show, the picture is replaced by the CapView icon and one line saying why, instead of the old text card.
The thresholds were set against real captures rather than guessed, and the first attempt was wrong in both directions: fast motion on a live 1080p60 source reaches a frame-to-frame change of 52 where a synthetic estimate had predicted 17, so the snow threshold moved from 48 to 65 and now has real margin. Snow also has to persist for two seconds, because a hard cut between two busy scenes can clear the thresholds for a single measurement and a viewer that blinks mid-game is worse than one that takes a moment to notice a pulled cable.
Sharpening actually does something now
The offset was measured in destination pixels while sampling the source texture, so every step was srcSize / dstSize source texels — less than one whenever the picture was enlarged. Both halves then collapsed together: the neighbours were sampled between texels so the unsharp sum shrank, and the clamp is built from those same samples so its headroom shrank with it.
Measured against a bandwidth-limited edge on a 720×576 source, the mean change per pixel at full strength:
| Window | 1:1 | 2× | 4× | 4K |
|---|---|---|---|---|
| before | 0.71 | 0.38 | 0.12 | 0.06 |
| after | 0.71 | 1.52 | 1.77 | 1.90 |
At 1:1 the two agree, which is why it was not obviously broken. Beyond that it faded out in proportion to how large you made the window — which is exactly the regime a 240p or 576i picture is normally watched in. Shrinking the picture had the opposite fault, stepping across more than one texel and over-sharpening.
If you had the sharpening slider turned up, it will now do considerably more than it used to. That is the fix working, but it is worth a look.
Colour survives colour edges
Turning up colour shimmer used to put a grey fringe around anything gold on a blue background. The tempting diagnosis — that keeping the original luma was done wrongly — is provably not it: adding Luma(rgb) − Luma(soft) to all three channels is algebraically identical to averaging Cb and Cr and recombining, to the last decimal.
The actual cause is that gold and blue are close to complementary, so the mean of their chroma genuinely is grey. No unweighted average across that edge can return anything else. Each neighbour is now weighted by how close its colour is to the centre's, which drops the saturation lost at such an edge from 0.42 to 0.09 while leaving smoothing inside flat areas completely unchanged — inside a flat area there is no colour distance to discount, so the weighting is free on the half of the job that matters.
Every second field is no longer dropped while the settings are open
On an interlaced source, the second field was scheduled behind lastWait_ == WAIT_TIMEOUT, which is only true when nothing else woke the message loop. Open the settings window and there is a steady stream of messages, so that branch never ran and the next arriving picture reset the field index before the second field had been drawn.
It now asks the clock instead of asking how the wait ended. Same shape of mistake as the timer that could not compete with the drag loop's message flood: a schedule must not be conditional on the queue being quiet.
Documentation
- A landing page at https://nuclearmeltdown.github.io/CapView/
- The README is a third of its former length; the detail moved into a wiki of 22 pages, one per feature, covering what the code does and what was measured to arrive at it
- Before-and-after images for the composite filter and the deinterlacer, with the crop chosen by measuring where the filter actually acts rather than by eye
Still open
The preview occasionally flickers black in places when the settings have their own window, on an interlaced source. Not reproduced here across two attempts — screen capture at twenty frames a second is the wrong instrument against a sixty frame preview. Stale scissor rectangles, undefined back-buffer content and repeated frame-latency calls have each been ruled out by inspection. The dropped-field bug above was found on the same trail and is fixed, but claiming it as the cause without a reproduction would be guessing twice.
CapView 1.7
The settings, rearranged by what they affect.
Ten tabs instead of nine. The old arrangement had a real symptom rather than an aesthetic one: the three switches deciding whether a recording, a screenshot or the virtual camera keeps its full range sat under Display — three tabs away from every one of the things they govern.
- HDR gets a tab of its own. It is not a display setting: its source curve belongs to the card, its tone mapping to the screen, and those three switches to three other tabs.
- Encoder splits off from Recording, and ffmpeg goes with it. Where the file goes and how big is a decision about the recording; which chip encodes it and how hard it works is a decision about the machine — one set once, the other every session.
- Tools is gone. Rewrapping to MP4 and the virtual camera both leave CapView, so they sit under Recording with the rest of them.
The ffmpeg block stops moving, but not by being pinned. It used to jump to the top when ffmpeg was missing so the download would be found — deliberate, and 1.6.1 broke that by fixing the symptom. On a tab that is about the encoder it is the first thing either way.
The settings window stays where it is put. It is destroyed and rebuilt whenever the mode is switched, so it came up wherever Windows felt like — the jumping that was reported. The saved rectangle is the restored one, so a window read while minimised is not remembered at the wrong size, and it is checked against the virtual screen so a position on a monitor that is gone does not put it out of reach.
CapView 1.6.2
Bugfix release. The settings-as-a-window stutter, measured rather than reasoned about.
Three separate causes, in the order the measurements found them. The dialog's present cost 12–17 ms and up to 41, about thirty-five times a second — better than half of every second with the thread that owns both windows parked and not pumping messages, which is why the desktop's cursor stuttered. A flip-model swapchain with sync interval zero and no tearing flag still waits, whatever the comment in the code claimed. Then SetMaximumFrameLatency(1) — what makes the preview's latency as short as it is — applies to the device, so two swapchains sharing one frame of queue each waited for the other. And the preview redrew on every wake-up of the message loop: the whole pipeline ran 235 times a second for a source delivering 25.
Dragging the window froze the preview for up to 1.24 seconds. Windows' modal move loop does not return until the mouse is released. There was a timer meant to cover that; measuring showed it firing 7 times a second instead of 125, because WM_TIMER is the lowest-priority message there is and a drag never leaves the queue empty. It hangs off WM_MOVING now, and the preview runs at better than 30/s through a drag at 0.6 ms a frame.
What is left is not CapView's: dragging the dialog across the preview still hitches, because two overlapping windows must be composed together and one is repainting thirty times a second. Off the preview it is smooth.
Also: the open tab survives moving the settings between the preview and their own window; "What is new" opens the release page; and checking for updates by hand no longer raises the startup popup.
CapView 1.6.1
Bugfix release, mostly the settings-as-a-window mode.
Stuttering — including the desktop's own mouse cursor. The settings window's frame was drawn and presented from inside the preview's frame, and presenting a second swapchain part-way through another window's frame flushes everything already queued for it, sixty times a second. It runs after the preview's present now. The preview loop also free-ran at up to 125 Hz whenever the settings were open, redrawing the same captured field through the whole pipeline; that is 16 ms now.
No taskbar button, and minimising put it in a corner of the screen. One cause: an owned window without WS_EX_APPWINDOW is deliberately kept off the taskbar, and a window with no taskbar button has nowhere to go when minimised. Fixing that exposed a second fault — reopening the settings after minimising them did nothing, because SW_SHOW displays a minimised window still minimised.
Switching back to settings-in-the-picture broke the whole interface until restart. Two ImGui contexts share one font atlas, and the DX11 backend keeps the atlas's texture id in the atlas — so closing the second window released the texture the first was still drawing with.
Dot crawl is two controls now. They were always two bargains: averaging costs nothing and only helps a standing picture, demodulation is the only thing that helps a moving one and costs sharpness. One slider hid that the first step did most of the work. The averaging locks on whenever demodulation is asked for, and the slider now says what it costs.
Also: a help marker was on the wrong checkbox, showing the toolbar had no setting at all, the ffmpeg block moved around depending on whether ffmpeg was found, two sections were both called "Window", the settings window had no icon, and its present ignored occlusion.
CapView 1.6
The virtual camera actually works now, and the encoder has settings.
Virtual camera fixed. It delivered black frames, and the reason was not where the last three attempts looked: the media source answered every request the instant it was asked, so it was asked again the instant it answered — better than two thousand samples a second, measured. Consumers' buffers overflowed, the frame server tore the stream down and rebuilt it underneath, and in the churn the announcement of what format was wanted got zeroed while another instance was still streaming. Samples are now paced to the declared rate, and what the consumer wants is restated with every sample rather than announced once. Registering also stops the frame server on its way through, because a service does not reread a DLL it already has open.
Encoder settings. Rate control (CBR, VBR, constant quality), preset, tuning, look-ahead, adaptive quantisation and multipass — under one set of names, translated into whatever NVENC, AMF, Quick Sync or the software encoder actually calls them. What an encoder has no opinion about is greyed out rather than hidden. Keyframe interval and B-frames stay automatic.
HDR screenshots can be AVIF as well as JPEG XR. JPEG XR needs nothing; AVIF is read by every browser but goes through ffmpeg.
CapView 1.5
Virtual camera and high dynamic range.
Virtual camera — offers the picture to other programs as a webcam. Built on Media Foundation, so it also appears where DirectShow cameras are invisible: the Windows Camera app, the camera list in Settings, packaged apps, Teams. Installed once with a UAC prompt, used afterwards without any rights at all. Windows 11 only, which is where MFCreateVirtualCamera first appeared.
High dynamic range — P010 and P016 input, PQ and HLG, BT.2020. What happens next follows the screen rather than the source: an ordinary monitor gets BT.2390 tone mapping, an HDR one gets scRGB. Recording, screenshots and the virtual camera each have their own switch for keeping the range instead of the tone mapped picture.
A release is one file: the camera's media source travels inside the executable.