Every real decoded frame of a range, in presentation order, exactly once.
Nothing here is synthesized: the walk reads the source's own frames and counts
them. Timestamps built from a frame rate and resolved through at-or-before
extraction cannot promise that. One falling a float's width short of a sample
lands on the frame before it, so the caller gets that frame twice and never
sees the one it was aiming at.
Every sample the walk decodes and does not yield is closed here: the frames
before the range, the ones stride skips, and the first one past the end.
Breaking out of the walk returns the underlying stream, which releases the
decoder's read of the source; the sample in the caller's hand at that moment
is still the caller's to close.
Every real decoded frame of a range, in presentation order, exactly once.
Nothing here is synthesized: the walk reads the source's own frames and counts them. Timestamps built from a frame rate and resolved through at-or-before extraction cannot promise that. One falling a float's width short of a sample lands on the frame before it, so the caller gets that frame twice and never sees the one it was aiming at.
Every sample the walk decodes and does not yield is closed here: the frames before the range, the ones stride skips, and the first one past the end. Breaking out of the walk returns the underlying stream, which releases the decoder's read of the source; the sample in the caller's hand at that moment is still the caller's to close.