VideoFrameIndex.kt
src/jvmMain/kotlin/afield/graphics/texture/video/VideoFrameIndex.kt · 30 lines
Frame-number arithmetic for constant-frame-rate video, shared by the code that asks for a frame and the code that reports which frame a decoder produced.
A timeline position belongs to the frame whose interval contains it, so VideoFrameIndex.requested
floors seconds * fps. A decoded presentation timestamp marks a frame's own start, which may
carry rounding error in either direction, so VideoFrameIndex.decoded rounds to the nearest frame.
package afield.graphics.texture.video
import kotlin.math.floor
import kotlin.math.roundToLong
object VideoFrameIndex
CFR frame identity: timeline positions floor; decoded presentation timestamps identify centres.
object VideoFrameIndex {
fun requested(seconds: Double, fps: Double): Long
The frame shown at timeline position seconds: floor of seconds * fps (tolerating 1e-9 of floating-point noise at a boundary), with negative times clamped to frame 0.
fun requested(seconds: Double, fps: Double): Long {
require(seconds.isFinite() && fps.isFinite() && fps > 0)
// Tolerate only floating-point noise at an exact frame boundary, not half a source frame.
return floor(seconds.coerceAtLeast(0.0) * fps + 1e-9).toLong()
}
fun decoded(seconds: Double, fps: Double): Long
The frame a decoder's presentation timestamp seconds identifies: seconds * fps rounded to the nearest frame.
fun decoded(seconds: Double, fps: Double): Long {
require(seconds.isFinite() && fps.isFinite() && fps > 0)
return (seconds * fps).roundToLong()
}
}