Flashback’s video capture pipeline is built entirely on Windows-native APIs: Windows Graphics Capture (WGC) acquires frames as GPU textures, Direct3D 11 manages the texture lifetime, a Video Processor MFT converts and scales the frames, and a hardware or software H.264 encoder MFT produces the final H.264 bitstream thatDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/CaramelHQ/Flashback/llms.txt
Use this file to discover all available pages before exploring further.
IMFSinkWriter muxes into an MP4 container. All GPU-to-GPU copies mean the frame data rarely touches system memory.
The capture pipeline is Windows-only. The Rust modules compile stubs for other targets, but all real capture logic lives inside
#[cfg(target_os = "windows")] blocks in capture.rs.Frame Acquisition with Windows Graphics Capture
WGC is Microsoft’s sanctioned screen-capture API, available from Windows 10 1903 onwards. Flashback creates aDirect3D11CaptureFramePool in free-threaded mode (so the FrameArrived callback fires on a system thread pool thread rather than a UI thread) and starts a GraphicsCaptureSession against either a monitor handle or an application window handle.
IDirect3D11Texture2D surfaces in BGRA format. Each FrameArrived callback retrieves the surface, extracts the underlying ID3D11Texture2D via IDirect3DDxgiInterfaceAccess, copies it to a slot in a private ring of textures owned by Flashback, and then releases the WGC frame immediately — WGC reuses its own textures as soon as the frame is closed.
Frame-Rate Limiting
WGC delivers frames whenever the display surface changes — it is inherently variable-rate. Flashback applies a per-frame timestamp check (keep_frame) before copying the texture, discarding frames that arrive faster than the configured FPS target. This avoids over-encoding and keeps the encoder load bounded at high refresh rates.
Constant-Frame-Rate Pacing
Clips are recorded at a strict CFR. TheFrameArrived handler only ever updates the “latest texture” slot; a separate CFR pacing loop (running on the capture thread) wakes up once per frame-slot and emits whichever texture was most recently received, duplicating it if no new frame arrived since the last slot. Duplicated frames encode as near-zero-cost P-frames (“skip frames”) in Baseline H.264.
Even-Dimension Enforcement
NV12 and H.264 require that both width and height be even. Game windows can have odd dimensions, which would causeMF_E_INVALIDMEDIATYPE. Flashback rounds both dimensions down to the nearest even value before creating the frame pool:
D3D11 Texture Pipeline
Flashback creates a singleID3D11Device with both D3D11_CREATE_DEVICE_BGRA_SUPPORT (required for WGC interop) and D3D11_CREATE_DEVICE_VIDEO_SUPPORT (required for sharing the device with Media Foundation hardware encoders). The same device object is wrapped as an IDirect3DDevice (WinRT) for the frame pool and as an IMFDXGIDeviceManager for Media Foundation.
Multi-thread protection is enabled on the device context so that the FrameArrived callback thread and the CFR pacing thread can access it safely:
D3D11_USAGE_DEFAULT BGRA textures. The FrameArrived handler copies the WGC surface into the next ring slot (GPU→GPU, no CPU involvement) and marks that slot as “latest”. The CFR loop wraps the latest texture into a MFCreateDXGISurfaceBuffer and hands it to the IMFSinkWriter. The SinkWriter’s built-in Video Processor MFT performs BGRA→NV12 conversion and optional scaling entirely on the GPU.
Instant Replay uses a separate BGRA ring and a channel to decouple the FrameArrived callback from the encoding pump thread. The pump runs a Video Processor MFT (BGRA→NV12 + optional scale) and then feeds the H.264 encoder MFT directly, bypassing IMFSinkWriter so encoded packets can be intercepted and pushed into the ring buffer.
Hardware Encoder Selection
At startup Flashback enumerates available H.264 encoders viaMFTEnumEx and selects one according to a configurable preference (encoder_pref). The selection order is:
- NVENC — NVIDIA’s hardware H.264 encoder (keyword match: “nvenc” / “nvidia”)
- AMF — AMD’s Advanced Media Framework encoder (keyword match: “amf” / “amd”)
- Quick Sync — Intel’s Quick Sync Video encoder (keyword match: “quick sync” / “intel”)
- First available hardware encoder — fallback if the preferred vendor is not present
- Software (MS H.264) —
MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_TRANSCODE_ONLY
pts_fifo) to assign timestamps to encoder output packets: the N-th output packet gets the N-th input timestamp. B-frames would break this ordering guarantee.
Periodic IDR frames are requested via ICodecAPI:
Media Foundation SinkWriter (Manual Recording)
For manual recording,IMFSinkWriter manages the full encode-and-mux pipeline. Flashback declares a video output type (H.264) and a BGRA/ARGB32 input type; the SinkWriter automatically inserts a Video Processor MFT to convert and scale between the two. Audio tracks (AAC, one for system audio and optionally one for microphone) are added as additional streams with PCM input and AAC output types.
MF_SINK_WRITER_DISABLE_THROTTLING so it never blocks the capture thread waiting for the encoder to drain, and with MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS to allow the hardware encoder MFT to be inserted automatically.
Instant Replay Ring Buffer
The Instant Replay mode buffers a configurable duration of pre-encoded H.264 and AAC packets in memory so they can be flushed to disk on demand without re-encoding. This is fundamentally different from manual recording, where the SinkWriter owns the encoder.Buffer Trimming
The ring buffer trims old packets on every push. To ensure the saved clip always starts at an IDR frame, trimming finds the latest keyframe older than the window cutoff and discards everything before it:Saving a Replay
save_replay locks the buffer, clones the packets starting from the first IDR frame, releases the lock, and then muxes the clone into a new MP4 file on a dedicated MTA thread — all without pausing the live encoding pump:
IMFSinkWriter, declares the video stream in passthrough mode (H.264 in → H.264 out, no re-encode), writes every buffered packet with its original timestamp, and calls Finalize().
If no keyframe has arrived yet when
save_replay is called, the save fails gracefully. In practice this occurs only within the first ~0.5 s of starting the replay, before the first periodic IDR.Encoder Pump (Async vs. Sync)
Hardware encoders exposeIMFMediaEventGenerator and operate asynchronously: the pump must wait for ME_TRANSFORM_NEED_INPUT events before feeding frames and drain ME_TRANSFORM_HAVE_OUTPUT events to retrieve encoded packets. Software encoders are synchronous MFTs: the pump calls ProcessInput and immediately drains ProcessOutput in the same call.
Both paths maintain the same CFR pacing logic; the only difference is how they interact with the encoder MFT:
MMCSS Thread Priority
Both the capture thread (manual recording) and the replay pump thread register with the Multimedia Class Scheduler Service under the"Capture" task. This elevates their scheduling priority above normal user threads, ensuring the capture pipeline is not starved by a CPU-intensive game running in the foreground.
timeBeginPeriod(1) for the duration of capture, which makes the CFR pacing sleep (std::thread::sleep) precise enough for accurate frame timing.
Out-of-Focus Card
When a game window is minimized during an Instant Replay session, WGC stops delivering new frames. Rather than filling the gap with frozen duplicates, Flashback composites a single out-of-focus card — the last real frame, Gaussian-blurred and darkened, with the Flashback logo and the text “The game is out of focus” — and encodes it at a low cadence (~2 fps) for the duration of the minimized period. The card is rendered byoverlay::OutOfFocusCard using Direct2D and DirectWrite on the same ID3D11Device as the capture pipeline (zero additional device overhead):
Related Pages
Architecture
How the Rust backend and SvelteKit frontend fit together, including the command model and window setup.
Audio Pipeline
WASAPI loopback, per-track threads, PCM conversion, downmix, and AAC encoding with IMFTransform.
Instant Replay
User-facing guide to configuring and triggering Instant Replay.
Encoder Configuration
How to select NVENC, AMF, Quick Sync, or software encoding in the settings UI.