Animated AVIF Timing and the Browser Render Loop
Animated AVIF files rely on the ISO Base Media File Format (ISOBMFF) container to store AV1-encoded video sequences as image animations. To render these animations smoothly, modern web browsers coordinate multi-threaded decoding engines with the browser render loop, synchronizing individual frame presentation timestamps (PTS) against display refresh intervals (vsync). This article breaks down how browsers parse AVIF timing metadata, manage asynchronous frame decoding pipelines, and handle frame scheduling to avoid drift and visual stutter.
Parsing Temporal Metadata from ISOBMFF
Animated AVIF files encapsulate AV1 video frames within ISOBMFF tracks. Unlike animated GIFs, which define inter-frame delays directly in graphic control extensions, AVIF derives its timing logic from standard media container boxes:
- Media Header (
mdhd): Establishes thetimescale, defining the number of time units that pass per second. - Time-to-Sample (
stts) and Composition Time to Sample (ctts): Detail the decoding and presentation durations for each sample (frame). - Edit Lists (
elst): Define start offsets, playback rates, and looping behaviors.
When the browser's media or image decoder encounters an animated AVIF, it reads these tables to construct a timeline of target Presentation Timestamps (PTS) for each frame relative to the animation’s start time (\(T_0\)).
Decoupled Decoding via Media Threads
Browsers avoid decoding AV1 video frames on the main thread or the
primary compositor thread. Instead, decoding is delegated to dedicated
worker threads or system-level media decoders (such as
dav1d in Chromium and Firefox, or hardware-accelerated
video decoders via the GPU process).
- Asynchronous Prefetching: The demuxer reads chunks ahead of the current playback position and sends compressed bitstreams to the decoder.
- Decoded Frame Buffer: The decoder outputs raw planar frames (typically YUV420, YUV422, or YUV444) into a bounded ring buffer.
- Color Conversion: Frames are converted to the target rendering color space (sRGB or Display P3) and uploaded as GPU textures, ready for consumption by the compositor.
Because AV1 uses complex inter-frame compression techniques (including forward and backward reference frames), frames may be decoded out of presentation order. The decoder relies on the Decoding Timestamp (DTS) for processing and reorders frames according to their PTS before placing them in the presentation queue.
Synchronizing with the Browser Render Loop
The browser's render loop operates rhythmically, aligned with the monitor’s hardware refresh rate (vsync), typically at 60Hz, 120Hz, or variable refresh rates.
When a frame is scheduled for rendering:
- Clock Evaluation: The compositor queries the animation clock. This internal high-resolution timer measures elapsed time since the animation began: \[\Delta t = T_{\text{current}} - T_{\text{start}}\]
- Frame Selection: The compositor inspects the decoded frame buffer to find the frame whose \([PTS_n, PTS_{n+1})\) interval encompasses \(\Delta t\).
- Invalidation: If the active frame has changed since the previous render tick, the element’s visual layer is marked dirty. The compositor pulls the corresponding texture into the scene graph during the composite phase, avoiding layout and paint recalculations on the main thread.
Handling Frame Rate Discrepancies and Jitter
AVIF animations frequently have frame durations that do not divide evenly into the monitor's display refresh interval (e.g., an animation authored at 24 fps on a 60 Hz display). The render loop resolves this via temporal quantization:
- Frame Extension (Hold): If \(\Delta t\) has not yet reached the PTS of the subsequent frame, the compositor continues to draw the current frame texture across multiple vsync pulses (e.g., a 3:2 pull-down pattern for 24 fps on a 60 Hz display).
- Frame Dropping (Late Frames): If heavy system load or decoding latency delays a frame such that \(\Delta t > PTS_{n+1}\), the compositor skips \(Frame_n\) entirely to catch up with the timeline. The decoder drops rendering steps for expired non-reference frames to preserve synchronization without breaking the temporal prediction chain of upcoming inter-frames.
- Cumulative Drift Compensation: Rather than incrementing durations incrementally, the browser calculates the absolute target display time against the global master clock. This prevents rounding errors from accumulating over thousands of loop cycles.
Resource Throttling and Off-Screen Execution
To preserve CPU, GPU, and battery resources, the browser synchronizes AVIF animation updates with visibility tracking via the Intersection Observer infrastructure.
When an animated AVIF scrolls out of the viewport, the render loop suspends frame invalidation and freezes decoder requests for that element. Upon re-entering the viewport, the browser either resumes playback from the suspended timestamp or fast-forwards the timeline to match the continuous global wall-clock time, depending on whether the animation loop is configured as synchronized across instances or independent per element.