Repository navigation
Releases
v0.19.0
Playlist failures end in Ended, and failures keep their category. Minor bump per 0.x SemVer
(breaking changes). docs/BREAKING-CHANGES.md has the entries and what to do.
- BREAKING (behaviour): a run of failed items ends in Ended, not Error, however long the
playlist and however its items fail (#810). A jump or replace recorded before the end is
taken (#809), and a reload that opens no item also ends in Ended (#857). - BREAKING (enum, behaviour): ErrorCategory gains Sink; a decoder that cannot open reports
Decode (#836, #837). - BREAKING (behaviour): a decoder opened on a lost lent device fails with
DeviceLostException, under Auto too (#843). - BREAKING (pixels): the H.264 encoder converts with BT.709 and tags the stream; older
recordings stay untagged (#850). - Fix: every fault of an item goes through the item runtime's core (#852), and the playlist
protocol decides what a preparation's outcome means (#853). - Fix: an end-of-stream from a run a seek has replaced is dropped (#851); a dispose leaves
the commands queued behind a seek to the loop (#844).
v0.18.0
One colour rule on every path, and a caller-chosen matrix. Minor bump per 0.x SemVer (breaking
changes). docs/BREAKING-CHANGES.md has the entry and what to do.
- BREAKING (pixels, no compile error): an untagged frame converts with BT.601 below 720 rows and
BT.709 at 720 rows or more, on CPU conversion, hardware readback and both presenters (#841). - BREAKING (binary): PlaybackController.Create gains an optional colorMatrix parameter; code
compiled against 0.17.0 that calls it must be rebuilt. - The D3D11 and D3D12 presenters convert with the frame's matrix, so tagged BT.601 and BT.2020
frames now display correctly in the view. - New ColorMatrix option (Auto, Bt601, Bt709, Bt2020) on VideoDecoderOptions,
IPlayerBuilder.WithColorMatrix and IPassBuilder.WithColorMatrix.
v0.17.0
Correct colour, recoverable playlists, and multi-view playback that scales. Minor bump per 0.x
SemVer (breaking changes). docs/BREAKING-CHANGES.md lists the six entries with fixes.
- BREAKING (pixels, no compile error): decoded frames convert to BGRA with the stream's own matrix
and range, and hardware and software decodes give identical BGRA (#792, #796). - BREAKING (behaviour): a playlist whose every item fails to start ends instead of retrying, and
LoadAsync and ReplaceAsync can leave Error (#758). - BREAKING (behaviour): a media failure reports its own ErrorCategory with its FFmpeg code, and
decode and demux failures throw MediaException (#755, #757). - BREAKING (behaviour): ErrorCategory gains DeviceLost, and the shared GPU device raises one
DeviceLost event (#759, #530). - Playlist transitions and loop events name their timeline (#756, ADR-0084).
- Fill placement on both video views (#766); converter rings sized to the view on D3D11 and D3D12
(#767, #772, #774). - The interop view converts frames off the UI thread (#781, ADR-0087).
- Faster switches: a switch waits only for the old item to release what it shares (#780), the
pacer stop no longer waits a timer tick (#785), and the preroll skips non-reference frames (#784). - Software video decode uses several threads, with a WithDecoderThreads option (#788).
- Test fixes: #765, #776, #778.
v0.16.0
Timelines, one lifecycle for views, and work held until it ends. Minor bump
per 0.x SemVer (breaking changes). docs/BREAKING-CHANGES.md has the v0.16.0
section, 31 entries; several change behaviour without a compile error.
- BREAKING: frames, buffers and captions carry the timeline they belong to,
and captions, PresentedResults and SyncJoinNode follow it across a seek
(ADR-0084). - BREAKING: one player or pass per in-box video sink, claimed at build. The
views keep their sink for their life, and a disposed sink disposes the
frames it is given (ADR-0085). FanOutVideoSink and DelegatingVideoSink are
in FrameFlow.Media. - BREAKING: work in flight is held until it ends (ADR-0086). Disposing a
pass, a player or a view cancels its work and waits for it, and a second
dispose waits for the first and ends as it did. The item runtime runs on a
pure core: seeks, plays and pauses follow one order, superseding seeks
coalesce, and a cancellation reaches a demuxer call waiting on a stalled
source. - BREAKING: a pass deactivates its audio sink and the end of playback waits
for the audio to play out (WaitForEndAsync). IMediaTransport gained
RepeatMode. IMediaPlayer and IPlayerBuilder gained media clips, which open
at a start position and can end at one. - Player: prepare a playlist item ahead, automatically or by name; one
hardware device per backend across items. - Decoding: AV1 on hardware through FFmpeg's native decoder; ExcludedCodecs
keeps a codec on software; FromStill opens a GIF; Auto does not bind CUDA
for MJPEG; swscale converts into whole rows. - Fixes: a throwing video sink is reported and one that keeps throwing fails
the item; CompositionInteropVideoView presents again after it rejoins the
visual tree; a seek that holds an item that has played pauses its clocks;
Whisper starts a new window when its audio jumps. - SDL: SdlCommandQueue runs asynchronous commands beside SdlEventLoop.
- Inference: Windows ML sessions take ONNX Runtime session config entries;
a CUDA provider that cannot load its libraries is ruled out.
v0.15.1
Decoding: under HardwareDecodeMode.Auto, a hardware decoder that binds and
then rejects a stream's first packet (CUDA MJPEG on a progressive JPEG) now
reopens the stream in software and resends the packet, with a warning. A
later fault, and Required, still fault (#572, #573, #578).
Presenter: AvaloniaVideoSink measures a PRESENT GAP from the end of the
previous frame's display, so a still from MediaSource.FromStill held for its
dwell no longer warns, and a real stall still does (#576, #577).
v0.15.0
Presenter and graph fixes, and an in-place converter resize. Minor bump per
0.x SemVer (breaking changes). docs/BREAKING-CHANGES.md has the v0.15.0
section.
- BREAKING: FrameMemoryDomains names each GPU API, and Gpu is their union
(#566). A binary change, and HasFlag(FrameMemoryDomains.Gpu) now asks for
every GPU API at once. Rebuild, and test with (domains & Gpu) != 0. - BREAKING, not a compile error: frameflow.presenter.device_resolution_rebuilds
counts only the size changes that still rebuild; resizes are counted by the
new resolution_resizes (#571). - Perf: CompositionInteropVideoView resizes its D3D11 converter in place on a
resolution change, keeping its device and shader pipeline, instead of
rebuilding it (#571). - Fix: the D3D11 converter presents 10-bit frames (#559).
- Fix: a player or pass downloads frames from a backend its path cannot read
(#566). - Refactor: the video processor drain is gone; the lease stands for the
driver's limit (#565).
v0.14.0
Driver video super resolution in the Windows presenter, anamorphic and rotated
video at their display geometry, and a player that reports a stalled source.
Minor bump per 0.x SemVer: the minor position is the breaking one below 1.0.
BREAKING (presenters): both Avalonia presenters show anamorphic video at its
display shape and rotated video upright, so a host that corrected either
itself now corrects twice. CpuVideoFrame.Create gained two optional
parameters, a binary break (#542).
BREAKING (playback): a source that stops delivering video enters Rebuffering,
which nothing reached before, and returns to Playing when frames flow again
(#547).
BREAKING (API): IPlayerBuilder and IPassBuilder gained WithPreferredBackends.
PlaybackController.Create gained an optional parameter, a binary break
(#532).
- CompositionInteropVideoView.DriverSuperResolution: opt-in NVIDIA RTX Video
Super Resolution for D3D11VA NV12 frames while the view is larger than the
frame. DriverSuperResolutionStatus says why it is off (#560, ADR-0082). - Frames, VideoStreamInfo and VideoFormatInfo carry the sample aspect ratio
and the display rotation, with the display size (#542). - A video sink or a caller sets the order hardware decode backends are tried
in (#532). - The pixel and tensor conversion kernels compile optimized on their first
call, so the first calls are no longer several times slower (#546).
Every break, with what to write instead: docs/BREAKING-CHANGES.md.
v0.13.0
fp16 model I/O, ONNX Runtime's OpenVINO provider, and a graph that names the
node that failed. Minor bump per 0.x SemVer: the minor position is the
breaking one below 1.0.
BREAKING (face): BlazeFace letterboxes its input and merges overlapping
detections by weighted average, so boxes and keypoints move on non-square
ROIs. Preprocess returns the transform to decode through (#473, #477).
BREAKING (API): Yolov8Detector.Create and CreateAsync take YoloThresholds, a
binary break (#23). A bare null or default second argument to
DmlInferenceSession or WinMLInferenceSession is ambiguous (#472, #481).
IPassBuilder gained WithDecodeDiscard and WithRange (#482, #483).
BREAKING (graph): an OperationCanceledException from a node body is a fault
unless the graph was cancelled (#509). Two nodes on one id refuse to run
(#512). A node's fault surfaces as GraphFaultException (#513). A detector
whose model returns NaN fails to load (#498).
- FrameFlow.Inference.OpenVino: ONNX Runtime's OpenVINO provider on Windows
x64, for Intel GPUs below Windows ML's 24H2 floor (#523, #522). - fp16 inputs and outputs. IElementTypedSession reports a session's declared
element types, and the YOLO and BlazeFace detectors take fp16 models (#520,
#10). ImageToTensor writes uint8 and fp16 tensors (#480). - Inference: a provider out of memory for one model no longer moves every
later model (#497). DirectML opens read the GPU's memory budget (#503), fix
a model's free dimensions (#472) and take a graph optimization level (#481).
Models whose output shape depends on the input run (#479). TensorToImage
turns a model's image output into a frame (#470). - Player: a pass can be bounded to a time range or decode keyframes only
(#482, #483). A seek lands on a keyframe on MPEG-TS (#495), and a seek past
the end steps back to the last keyframe (#519). - Graph: each node counts what it discards (#514).
Every break, with what to write instead: docs/BREAKING-CHANGES.md.
v0.12.0
One ownership contract for graph items, frame budgets for fixed pools, and
GPU-resident inference. Minor bump per 0.x SemVer: the minor position is the
breaking one below 1.0.
BREAKING (graph items): frames and audio buffers are the graph's items.
VideoFrameRef and PcmAudioBufferRef are gone, fan-out shares an item by
AddRef and has no edge cloner, CPU frames and PCM buffers are made through a
fill factory, and video sinks have no frame pool. (ADR-0080)
BREAKING (budgets and domains): nodes declare what they hold and which memory
domains they take. A graph that could exhaust a fixed pool, or hand a node a
frame it cannot read, is refused before it runs instead of failing mid-run.
The node constructors take new optional parameters, a binary break.
(ADR-0081, #451)
BREAKING (API): Branch returns a BranchChain whose first hop takes no edge
options (#460). The Avalonia chrome controls take Transport, not MediaPlayer
(#463). SyncJoinNode.ResetWindow() is gone (#469). Holding is FrameHolding (#412).
IVideoSurface.PrefersHardwareFrames is gone, and PlaybackController.Create
takes bool? yieldHardwareFrames (#455).
- GPU-resident inference. Hardware frames stay on the GPU when the video path
takes them (#455). D3D12VA frames present through the composition view
(#454). DirectML takes a D3D12 buffer (#444), and FrameFlow.Inference.WinML runs
sessions through Windows ML's vendor providers (#447). NVDEC frames expose their
CUDA device memory (#457), and ToGpu uploads CPU frames to a hardware
device (#458). - Fixed pools are sized from the graph's frame budget, and a hardware decoder
waits at its budget instead of exhausting its pool (#411, #403). - FrameCopyMetrics counts every frame copy and conversion by site (#456).
- Operators take a cleanup hook, and AudioOperators.Resample uses it to
release its native resampler once per run (#469). - Fix: the MotionClip release zip carried FFmpeg 7.1 for an FFmpeg 9 loader,
and would not start. The runtime package is pinned, and the release checks
the published app for every library the loader asks for (#468). - Fix: a sync join evicted every later secondary after a backward step in the
primary's time, such as a timestamp wrap (#461). - Fix: MediaInfo.ContainerName was always "unknown" (#467).
Full list of breaks with the fix for each: docs/BREAKING-CHANGES.md.
v0.11.0
FFmpeg 9.0 under the bindings, macOS natives built from source, and three
decode/playback fixes. Minor bump per 0.x SemVer: the minor position is the
breaking one below 1.0.
BREAKING (native runtime, not the API): FrameFlow targets FFmpeg 9.0, not 7.1.
Every shipped library file name changes, and not by the same amount (avutil
59->61, avcodec 61->63, avformat 61->63, avdevice 61->63, avfilter 10->12,
swscale 8->10, swresample 5->7). Consumers on the bundled package are
unaffected. A self-supplied 7.x install is now refused at bootstrap by name,
which is v0.10.1's ABI check doing its job rather than a second break. No
type, member or signature moves. (#351)
BREAKING (platform): Intel macOS is not supported. No osx-x64 RID was ever in
FrameFlow.Native.Runtime, so nothing leaves the package; what goes is the
develop-time path that pretended otherwise. (#352)
- macOS natives are built from source as the repo's own LGPL-2.1 build and
shipped as osx-arm64, so Apple silicon no longer needs a system FFmpeg.
(#345, #347) - Fix: four-plane pixel formats decoded nothing. The software conversion
passed sws_scale three source plane pointers and a hardcoded null for the
fourth, so every yuva420p, YUVA variant and GBRAP frame failed with "bad src
image pointers". Animated WebP is the case that surfaced it. A conversion
that failed for every frame also reported no error; it now counts. (#357) - Fix: a container whose timestamps do not start at zero played from the wrong
origin. MPEG-TS conventionally starts at 1.4s, so every .ts held frames
against a clock seated at zero, presented a fraction of them and ran its
position past its own duration. (#361) - Fix: playback could sit five seconds past its last frame before reaching
Ended. The end-of-content hold waited for the master clock to reach the last
frame's end, and an audio master can stop marginally short of it. (#362) - Tests: the FFmpeg library names are held to the bindings by a sweep, and
Auto hardware decode is asserted to actually select hardware where the codec
can use it. (#350, #354)
Full list of breaks with the fix for each: docs/BREAKING-CHANGES.md.