Skip to content

feat: configurable decoded-frame cache + multithreaded decode by default#2

Merged
jens-duttke merged 1 commit into
mainfrom
feat/cache-mt-seeking
Jul 16, 2026
Merged

feat: configurable decoded-frame cache + multithreaded decode by default#2
jens-duttke merged 1 commit into
mainfrom
feat/cache-mt-seeking

Conversation

@jens-duttke

Copy link
Copy Markdown
Owner

feat: configurable decoded-frame cache + multithreaded decode by default

Backward / repeat / Reverse() access is the pathological case for a source
filter: with only IDRs as random-access points, some 3D Blu-rays run 600+ frames
between IDRs, so a backward pass re-decodes a whole GOP once per cache-window.
Two changes make that usable without giving up the fast (parse-only) open or
bit-exactness:

  • cachesize: the decoded-frame cache is now a caller-set ceiling (MiB), default
    512 (was a fixed ~128 MB), and the ring can hold far more than the previous
    64-slot cap so the byte budget is the real limit. A larger cache spans more of
    a long GOP, so a backward pass triggers one cold re-decode per window instead
    of one per frame. Buffers are still allocated lazily, so the budget is a
    ceiling, not an up-front reservation.
  • threads now defaults to -1 (auto-detect cores) in both plugins. getFrame is
    serialised for the node (VapourSynth fmUnordered / AviSynth MVC_MT_SERIALIZED),
    so edge264's internal decode threads are safe and bit-exact, and they make the
    forward re-decode a seek performs several times faster. Pass threads=0 for the
    old single-thread behaviour.

Measured on a real multi-thousand-frame 3D Blu-ray, a backward pass near the end
sped up roughly 20x at the new defaults over the previous single-thread /
small-cache behaviour, and more with a GOP-spanning cachesize - all bit-exact to
a sequential decode. Seeking remains anchored to IDRs, so every returned frame is
still bit-exact; only the amount cached and the decode parallelism changed.

seektest now also runs its reverse seek==sequential check with a minimum cache to
guard the cachesize plumbing and ring sizing. Validated bit-exact (seek ==
sequential over reverse-tail + strides + jumps) on five real 3D Blu-ray MVC
streams, single- and multi-threaded, plus make check.

Backward / repeat / Reverse() access is the pathological case for a source
filter: with only IDRs as random-access points, some 3D Blu-rays run 600+ frames
between IDRs, so a backward pass re-decodes a whole GOP once per cache-window.
Two changes make that usable without giving up the fast (parse-only) open or
bit-exactness:

- cachesize: the decoded-frame cache is now a caller-set ceiling (MiB), default
  512 (was a fixed ~128 MB), and the ring can hold far more than the previous
  64-slot cap so the byte budget is the real limit. A larger cache spans more of
  a long GOP, so a backward pass triggers one cold re-decode per window instead
  of one per frame. Buffers are still allocated lazily, so the budget is a
  ceiling, not an up-front reservation.
- threads now defaults to -1 (auto-detect cores) in both plugins. getFrame is
  serialised for the node (VapourSynth fmUnordered / AviSynth MVC_MT_SERIALIZED),
  so edge264's internal decode threads are safe and bit-exact, and they make the
  forward re-decode a seek performs several times faster. Pass threads=0 for the
  old single-thread behaviour.

Measured on a real multi-thousand-frame 3D Blu-ray, a backward pass near the end
sped up roughly 20x at the new defaults over the previous single-thread /
small-cache behaviour, and more with a GOP-spanning cachesize - all bit-exact to
a sequential decode. Seeking remains anchored to IDRs, so every returned frame is
still bit-exact; only the amount cached and the decode parallelism changed.

seektest now also runs its reverse seek==sequential check with a minimum cache to
guard the cachesize plumbing and ring sizing. Validated bit-exact (seek ==
sequential over reverse-tail + strides + jumps) on five real 3D Blu-ray MVC
streams, single- and multi-threaded, plus make check.
@jens-duttke
jens-duttke merged commit 8c207d4 into main Jul 16, 2026
8 checks passed
@jens-duttke
jens-duttke deleted the feat/cache-mt-seeking branch July 16, 2026 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant