Table of Contents

Interface IVideoFrameSink

Namespace
SharpConsoleUI.Video
Assembly
SharpConsoleUI.dll

Strategy for delivering decoded video frames to the terminal. Implementations provide different rendering backends — character-cell approximations (half-block, ASCII, braille) or the Kitty graphics protocol for pixel-accurate playback on supporting terminals.

public interface IVideoFrameSink : IDisposable
Inherited Members
Extension Methods

Remarks

Lifecycle:

IngestFrame(byte[], int, int, int, int, Color) is called on the playback background thread whenever FFmpeg produces a new frame. It may do heavy work (cell conversion, terminal transmission). Implementations must be thread-safe against concurrent Paint(CharacterBuffer, LayoutRect, LayoutRect, Color, Color) calls from the render thread.

Paint(CharacterBuffer, LayoutRect, LayoutRect, Color, Color) is called on the render thread from inside PaintDOM. It should be lightweight — blit cells, write placeholder cells.

OnStopped() is called when playback stops so the sink can release any terminal-side state (delete transmitted Kitty images).

Methods

ForceRefresh()

Requests that the sink rebuild any terminal-side state on the next ingested frame. No-op for cell-mode sinks; for the Kitty sink this triggers a full image+placement recreation, which is the same reset that happens on window resize and is the one reliable way to recover from the (rare) stuck-black state where the terminal stops redrawing after in-place frame updates. Exposed so a user-facing keybind can force recovery without having to resize the window.

void ForceRefresh()

GetPreferredPixelSize(int, int)

Returns the preferred pixel dimensions for FFmpeg to decode into, given the target cell area. Cell-mode sinks typically want (cellCols, cellRows * N) where N is the vertical pixel density of the mode; Kitty mode wants much higher resolution.

(int Width, int Height) GetPreferredPixelSize(int cellCols, int cellRows)

Parameters

cellCols int
cellRows int

Returns

(int absoluteLeft, int absoluteTop)

IngestFrame(byte[], int, int, int, int, Color)

Ingests a freshly decoded RGB24 frame. The caller must guarantee the byte array holds pixelWidth * pixelHeight * 3 bytes, row-major. Implementations must not retain the byte array beyond this call — copy out or consume synchronously, because the playback loop reuses the same buffer across frames.

void IngestFrame(byte[] rgb24, int pixelWidth, int pixelHeight, int targetCols, int targetRows, Color windowBackground)

Parameters

rgb24 byte[]
pixelWidth int
pixelHeight int
targetCols int

Terminal columns the playback loop intends the frame to occupy.

targetRows int

Terminal rows the playback loop intends the frame to occupy.

windowBackground Color

OnStopped()

Called when playback stops or the sink is being replaced. Releases any terminal-side resources (e.g. deletes transmitted Kitty images). Safe to call multiple times.

void OnStopped()

Paint(CharacterBuffer, LayoutRect, LayoutRect, Color, Color)

Paints the most recently ingested frame into the character buffer, centered within contentRect, respecting clipRect. Also fills any letterbox/pillarbox gaps with the window background so stale cells underneath don't bleed through. Safe to call even if no frame has been ingested yet (fills with background in that case).

void Paint(CharacterBuffer buffer, LayoutRect contentRect, LayoutRect clipRect, Color windowForeground, Color windowBackground)

Parameters

buffer CharacterBuffer
contentRect LayoutRect
clipRect LayoutRect
windowForeground Color
windowBackground Color