Skip to content

About

Windows .NET 10 test-card generator with 1080p/4K NDI and UDP outputs, synchronized motion and a 1 kHz test tone.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

TestCard

A native Windows x64 test-signal generator built with WPF and .NET 10. A live source preview and two independent switches control NDI High Bandwidth and H.264/AAC MPEG-TS over UDP.

Download for Windows · Installation guide · MIT License

TestCard interface

Run

Download and extract the Windows ZIP, then open TestCard.exe. Keep the other files and the .runtime folder beside the executable. This portable build includes a private .NET 10 runtime; the machine running it does not need .NET installed separately. Install FFmpeg and the NDI runtime separately as described in INSTALL.md.

For local builds, the app is published to artifacts/TestCard-win-x64/TestCard.exe.

For development, run scripts/run.ps1 in PowerShell. It uses the project-local .NET 10 SDK when available, otherwise the installed SDK.

  1. Choose 1080p (1920 × 1080) or UHD 4K (3840 × 2160), the frame rate, and a label.
  2. Switch NDI on, then select testcard in NDI Studio Monitor or another NDI receiver. The source name is fixed and NDI uses unicast.
  3. For UDP, set the destination IPv4 address, port and transport mode, then switch it on. Open udp://@:5000 in VLC for the default port, or use ffplay -fflags nobuffer udp://127.0.0.1:5000 on the destination machine.
  4. Switch either output off independently. Closing the app stops both workers and FFmpeg. Outputs always start off, even when settings were saved during transmission.

Dependencies + network lets you select FFmpeg, the NDI x64 runtime DLL, a local IPv4 network interface, and UDP multicast TTL. Paths are auto-detected. Saved settings and rolling diagnostics live in %LOCALAPPDATA%\TestCardGen.

Signal

  • Progressive 23.976, 24, 25, 29.97, 30, 50, 59.94 or 60 fps. Fractional rates use exact 24000/1001, 30000/1001 and 60000/1001 ratios.
  • 75% RGB bars, 11-step grayscale, centre crosshair, native-pixel resolution gratings, 90%/80% safe-area guides, source label, format label, elapsed time and absolute frame counter.
  • A moving marker sweeps once per second. A white sync indicator illuminates with the tone; fractional-rate flashes include the video frame containing the audio onset.
  • Fixed 1 kHz stereo at 48 kHz: 100 ms on / 900 ms off, −18 dBFS peak. A 1 ms amplitude ramp reduces clicks. The app always uses these settings, including when loading older preferences.
  • Exactly one white source pixel on all four outer edges, drawn after all other elements at the selected output resolution. The reduced preview is scaled; verification checks the exact native-resolution source pixels.
  • Source is full-range BGRA. UDP is explicitly converted to limited-range BT.709 YUV 4:2:0, with BT.709 metadata. NDI performs its own conversion/compression. Lossy encoding and display scaling can change the received border's sample values; the source PNG is exact.

The preview and both outputs use the same session timeline, based on Windows' monotonic performance counter. Activating or restarting an output joins the current elapsed time and frame number instead of starting at zero. UDP's tone is offset to that same starting video frame, preserving its beep/flash phase; both workers pace video against the shared clock. The session origin is sent to workers but never saved in user preferences. Restarting the app starts a new session.

The preview shows the generator, not decoded network output. Encoder, network and receiver buffering can make the received picture appear later than the preview; a shared software timeline does not provide hardware genlock or remove that latency. A UDP encoder that cannot sustain the selected format will fall behind and report a low frame rate.

Network behaviour

NDI uses unicast only. It advertises a named source and receivers initiate connections, rather than the app pushing to an entered IP/port. The worker explicitly disables NDI multicast sending. Removed multicast preferences from older settings files are ignored and cannot re-enable it.

NDI runs in a separate process with an app-specific NDI_CONFIG_DIR set before runtime initialization. It does not edit the machine-wide Access Manager configuration. Explicit adapter selection is shared by both outputs; automatic mode lets the runtime/system choose routing.

UDP unicast sends to a destination IPv4 address and port. UDP multicast sends to the entered multicast group and port. Datagrams contain 1316 bytes (seven 188-byte MPEG-TS packets). TTL defaults to 1. UDP has no receiver handshake, so “Sending” indicates encoder output, not confirmed reception.

For another computer to receive NDI, allow the app/worker through Windows Firewall when Windows prompts. For multicast, the receiving interface, IGMP configuration and switch/router support must be correct. Same-machine tests cannot validate a physical switch, routed multicast, or a remote firewall.

Encoding and performance

UDP defaults to software libx264, ultrafast/zero-latency, 20 Mb/s at 1080p or 60 Mb/s when selecting 4K. The encoding expander offers NVIDIA NVENC, Intel QSV and AMD AMF H.264 encoders. Hardware choices require a matching GPU/driver and support in the chosen FFmpeg build. Encoder failures are shown in the UI with details in the log; there is no silent fallback.

4K at high frame rates can require substantial CPU, memory bandwidth and network capacity, especially with both outputs enabled. Each output reports its observed frame rate. NDI skips stale timeline frames after a stall; UDP reports an encoder that falls behind. The generated pattern is diagnostic, not a certified SMPTE/EBU calibration card.

Build and verify

Prerequisites: Windows x64, .NET 10 SDK, an FFmpeg Windows build with libx264, and NDI Runtime. The NDI SDK is not required to build; the app dynamically loads the installed runtime.

./scripts/build.ps1 -Test
./scripts/build.ps1 -Integration
./scripts/build.ps1 -Lifecycle
./scripts/build.ps1 -Publish
./scripts/package.ps1
./scripts/run.ps1

The dependency-free verification executable checks full-resolution borders, deterministic motion, tone frequency/amplitude/cadence, fractional-rate sample accounting, address validation and NDI ABI layouts. It also verifies that legacy settings cannot re-enable NDI multicast and that the shared session origin survives worker serialization.

Integration checks capture both UDP unicast and multicast on loopback at 1080p25, UHD 4K25 and 1080p29.97. They inspect MPEG-TS packets and ffprobe metadata, decode H.264 frames to confirm moving video, and decode AAC to verify the 1 kHz tone and one-second cadence. An additional FFmpeg PCM check compares its delayed-start tone sample-for-sample with the NDI tone generator. NDI discovery/receive checks cover 1080p and UHD 4K unicast. All workers join a session that is already running, verifying that their clock does not restart at zero. UDP captures and source PNGs are saved under artifacts/verification; physical-network multicast routing still needs testing on the intended network.

App icon

The executable, title bar and app header use a test-card icon with colour bars, a white screen border and a mint pulse trace. Editable artwork is in src/TestCard.App/Assets/TestCard.svg; the Windows .ico includes 16, 20, 24, 32, 40, 48, 64, 96, 128 and 256 px sizes. Run scripts/create-icon.ps1 to regenerate the ICO and PNG from the matching drawing geometry.

Projects:

  • TestCard.Core: shared settings, validation, raster renderer, audio timing, FFmpeg arguments and NDI interop.
  • TestCard.Worker: isolated output workers, lifecycle, pacing and telemetry.
  • TestCard.App: WPF interface, local preferences, preview and process control.
  • TestCard.Tests: executable numerical, pixel and network integration checks.

The publish script creates a portable x64 folder, copies the matching .NET 10 and Windows Desktop runtimes from the build SDK into .runtime, and configures both apphosts to locate that private runtime using AppHostRelativeDotNet. This avoids requiring a machine-wide .NET install or an additional runtime-pack download. It optionally copies a project-local FFmpeg build into tools and uses the already installed NDI runtime. Keep the complete output folder together. See THIRD-PARTY-NOTICES.md before redistributing third-party binaries.

scripts/package.ps1 builds and tests a fresh public package under artifacts/releases, including the MIT license, installation guide, private .NET runtime and SHA-256 checksum. Public packages exclude FFmpeg, NDI binaries and local debug symbols. GitHub Actions builds and packages pushes and pull requests; pushing a matching vX.Y.Z tag publishes a GitHub Release after checks pass.

License

Copyright (c) 2026 John Lightfoot. TestCard's original source and artwork are licensed under the MIT License, allowing free use, modification and distribution, including commercial use. Keep the copyright and license notice with copies. Third-party components retain their own licenses; see THIRD-PARTY-NOTICES.md.

Implementation references

About

Windows .NET 10 test-card generator with 1080p/4K NDI and UDP outputs, synchronized motion and a 1 kHz test tone.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages