No description
  • C++ 59.2%
  • C 38.3%
  • Python 1.3%
  • CMake 1.2%
Find a file
2026-10-22 02:58:36 +02:00
src Docs 2026-10-22 02:58:36 +02:00
tools First commit 2026-10-22 02:57:01 +02:00
.gitignore First commit 2026-10-22 02:57:01 +02:00
CMakeLists.txt First commit 2026-10-22 02:57:01 +02:00
CMakePresets.json First commit 2026-10-22 02:57:01 +02:00
README.md Docs 2026-10-22 02:58:36 +02:00
vcpkg.json First commit 2026-10-22 02:57:01 +02:00

DeckLink test apps

Two Windows apps (MSVC x64, vcpkg, Dear ImGui on D3D11) for a Blackmagic DeckLink card, plus two console tools.

target what
decklink_rx Receiver: live video in a resizable, letterboxed window, audio monitoring, optional VU meter
decklink_tx Signal generator: pick resolution / frame rate / audio channels and one of six generators
decklink_list Console: lists devices and the input/output modes each supports
decklink_selftest Console loopback check (see below)

Build

set VCPKG_ROOT=C:\Users\Samuel\.vcpkg-clion\vcpkg
cmake --preset msvc-x64
cmake --build build --config Release

Binaries land in build\bin\<Config>. In CLion enable the vcpkg integration; vcpkg.json is the manifest (imgui with the win32 + dx11 bindings, and miniaudio). The triplet is x64-windows-static-md, so there are no DLLs to ship. Requires the Blackmagic Desktop Video driver.

No SDK download is needed. src/common/decklink_api.h is generated from the type library embedded in the installed driver (tools/gen_decklink_api.py, currently driver 14.5), so the interface layouts match the driver. To refresh it after a driver upgrade, compile a file containing #import "DeckLinkAPI64.dll" raw_interfaces_only no_namespace named_guids and run python tools/gen_decklink_api.py DeckLinkAPI64.tlh src/common/decklink_api.h. The official SDK headers can be used instead by swapping the include.

Command line: decklink_rx.exe [--device N] [--start] (N indexes the input devices in the list).

  • Device / Format: pick an input, and either a fixed format or Auto-detect input format (cards that support it). Detected changes of mode or colour space are followed automatically.
  • Video: UYVY (or BGRA for RGB sources) is uploaded to the GPU, converted to RGB (Rec.709 for height >= 720, else Rec.601) and drawn letterboxed. The window is freely resizable and keeps updating while you drag it. F11 toggles fullscreen, H hides the control panel. Keep last frame on signal loss holds the final picture instead of going black.
  • Audio: the card's embedded audio is captured (16 channels, falling back to 8 then 2) and one stereo pair is played on the default Windows output (Monitor selects the pair; volume / mute are provided).
  • VU meter: one bar per captured channel, -60..0 dBFS, with peak hold. Optional checkbox.

Command line: decklink_tx.exe [--mode N] (index into the Mode dropdown).

Resolution and frame rate come from the display modes the selected device reports; audio is 48 kHz / 16-bit with 2, 8 or 16 channels. Mode can be switched while outputting (video immediately, audio within ~0.2 s); the Audio level slider and the pattern options are live too. The window shows frames scheduled, late / dropped counts and buffer depth.

mode output
Test pattern Colour bars, grey ramp, sweeping line, bouncing square, timecode, frame counter, orange marker. Each second the picture flashes white while a 1 kHz blip starts on the same frame. Line / square / marker are individually switchable.
SDI check field (pathological) SMPTE RP 198 (HD) / RP 178 (SD) stress signal: equaliser words (Cb/Cr 300h, Y 198h) and PLL words (Cb/Cr 200h, Y 110h), with the polarity-alternating word on every other frame. 10-bit v210 if the card supports it. Double-handle sliders set the vertical extent of each signal; uncovered lines are black. No audio.
Colour bars + 1 kHz tone Static bars, continuous tone on all channels.
A/V sync flash + beep Black with one white frame per second and a beep starting on that frame.
Audio channel identify A 1 kHz beep on one channel at a time (0.5 s each) while the picture shows the channel number.
Black + silence

How A/V sync is kept

Video frame n is scheduled at n * frameDuration; audio is a continuous stream where sample s is a pure function of its index. A blip starts at the audio sample that coincides with the start of the flashing frame (k * blipFrames * frameDuration * 48000 / timeScale), so both come from one timeline. Playback starts when the first audio preroll callback fires.

Code map

src/common/decklink_api.h     generated COM interfaces (subset)
src/common/decklink_util.*    device/mode enumeration, FrameLock, callback IUnknown macro
src/common/d3d_app.*          Win32 window + D3D11 swap chain + ImGui shell
src/rx/capture.*              input capture, format-change handling, audio hand-off
src/rx/video_renderer.*       YUV->RGB shader path and letterboxed draw
src/rx/audio_monitor.*        miniaudio playback + peak levels
src/rx/main.cpp               receiver UI
src/tx/generator.*            scheduled playback, frame ring, audio timeline, generator modes
src/tx/pattern.*              UYVY / v210 renderers (test pattern, bars, flash, channel id, check field)
src/tx/main.cpp               generator UI
src/tools/                    decklink_list, decklink_selftest
tools/gen_decklink_api.py     regenerates decklink_api.h from the installed driver

Threading: DeckLink callbacks run on driver threads. Capture hands frames to the UI thread under a mutex; Generator renders inside its completion callbacks and keeps live settings in atomics (the check-field ranges use a small mutex).

Self test

decklink_selftest <tx-idx> <rx-idx> <secs> <mode> [capture|capture-fixed] [generator mode 0-5]

Plays a generator on one device while another device's input (cabled loopback) receives it. Without capture it prints late/dropped frames, received frame spacing and the measured offset between flash and beep; with capture it drives the receiver app's Capture class (including auto-detect) and prints received pixel words.