Skip to content

Quicktime fixes - #4463

Open
Darlokt wants to merge 4 commits into
ome:developfrom
Darlokt:quicktime-fixes
Open

Quicktime fixes#4463
Darlokt wants to merge 4 commits into
ome:developfrom
Darlokt:quicktime-fixes

Conversation

@Darlokt

@Darlokt Darlokt commented Aug 1, 2026

Copy link
Copy Markdown

Hej,
while investigating weird memoization behaviors, I came upon the old issue #4091. It was on the way, and only partially related to the memoization problems.

These commits now fix QuickTime parsing for variable-sized samples and random access to QTRLE delta frames after memoization, by which it fixes #4091

Changes

  • Correct QuickTime sample-size and chunk-offset table parsing.
  • Handle leading atoms and final sample boundaries correctly.
  • Rebuild preceding QTRLE reference frames when accessing delta frames non-sequentially.
  • Add regression tests covering variable sample sizes and memoized random access.

Darlokt added 2 commits August 1, 2026 04:54
QTReader treated the stsz sample-count field as the first sample size and the stco entry-count field as the first chunk offset. It then advanced a one-chunk movie by the following sample's size instead of the preceding sample's size. Together these errors shifted variable-size sample boundaries and could make valid compressed frames unreadable.

Read both tables from the first actual entry and derive each subsequent offset from the size of the sample immediately before it. Also keep the mdat end as an absolute file offset and apply the first-sample scale to the final sample boundary, so leading ftyp/wide atoms and the last frame are handled consistently.

Add a six-frame QTRLE fixture with a non-zero mdat offset, one stco entry, and variable stsz entries. The regression test verifies that all six samples decode to the expected image.
QuickTime RLE delta frames depend on the pixels decoded for the preceding frame. A newly initialized or deserialized QTReader has sample-table metadata but no previous pixel buffer, so opening a later plane directly can return null or incorrect pixels. Memoizer makes that state especially visible because each fresh reader can load initialized metadata and immediately request an arbitrary plane.

Track the absence of a decoded plane with -1 and, before decoding a non-sequential QTRLE request, replay the preceding frames to reconstruct the required reference image. Sequential reads and repeated reads retain the existing fast path; codecs without QTRLE frame dependencies are unchanged.

Extend the QTRLE regression fixture to seed a memo, create a fresh Memoizer for every plane, assert each reader loaded from the memo, and compare every randomly requested plane with sequential direct-reader output.

Fixes ome#4091.
Comment thread components/formats-bsd/src/loci/formats/in/QTReader.java Outdated
Comment thread components/formats-bsd/src/loci/formats/in/QTReader.java Outdated
Comment thread components/formats-bsd/test/loci/formats/utests/QTReaderTest.java Outdated
Comment thread components/formats-bsd/test/loci/formats/utests/QTReaderTest.java Outdated
Keep pixelBytes as a payload length while deriving the final sample boundary
from its absolute end. Index variable sample sizes directly when constructing
frame offsets, and close test Memoizers on every path with try-with-resources.
@Darlokt

Darlokt commented Aug 3, 2026

Copy link
Copy Markdown
Author

This should address it all, I saw that I also forgot the closeable in #4464 so i will clean it up.

@Darlokt Darlokt mentioned this pull request Aug 3, 2026
@Darlokt
Darlokt requested a review from melissalinkert August 3, 2026 21:56
Replace deferred deleteOnExit cleanup with immediate recursive deletion in
always-run teardown. Ensure temporary fixtures created before setup failures are
tracked and cleanup errors are reported.
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.

QuickTime: images may not be readable when using Memoizer

2 participants