Skip to content

AVI with packed B-frames: presentation timestamps derived from decode order (mpeg4/XviD) #516

Description

@a1go3

Summary

For AVI files carrying MPEG-4 ASP (XviD/DivX) with packed B-frames, the engine pairs decoded pictures with timestamps derived from decode order. Playback shows the picture stepping backwards several times a second while audio runs clean.

aetherctl swdecode diagnoses this itself, and its verdict already points at #407.

Environment

  • AetherEngine 6.73.0 (SPM)
  • Observed on iPhone 13 Pro / iOS 26.5 (host app, AetherPlayerSurface)
  • Reproduced headless with aetherctl on macOS 15.7, x86_64

The headless reproduction uses no host code, so this is not an integration artifact on my side.

Reproduction

$ aetherctl swdecode --frames 120 file:///path/to/sample.avi

[SWDecoder] Opened: 720x304, codec=mpeg4, threads=8, 8-bit
[mpeg4 @ 0x…] Video uses a non-standard and wasteful way to store B-frames
('packed B-frames'). Consider using the mpeg4_unpack_bframes bitstream filter
without encoding but stream copy to fix it.

=== SW DECODER RESULT ===
Codec:                mpeg4 (id=12)
Source resolution:    720x304
Decoder open:         OK
Frames decoded:       38

=== FRAME TIMES (presentation order, first 38) ===
0.042  0.083  0.167  0.125  0.209  0.292  0.250  0.334  0.417  0.375  0.459  0.542
Steps backwards:      12 of 37
VERDICT: the pictures are paired with the wrong timestamps. The container withheld
         its PTS and something invented one from decode order (#407).

12 backwards steps out of 37 — roughly a third of frames. On screen this reads as the image jittering forward and back on any motion.

Source characteristics

A 2000s-era XviD AVI rip. Nothing unusual beyond the packed bitstream:

codec_name=mpeg4
profile=Advanced Simple Profile
codec_tag_string=XVID
width=720  height=304
field_order=unknown
r_frame_rate=2500000/104271   (≈23.975)

Per-frame, over a 25-frame window mid-file:

  • interlaced_frame=0 and repeat_pict=0 on every frame — the source is progressive
  • best_effort_timestamp_time advances evenly at 0.0417 s with no gaps or duplicates
  • frame types I B P B P B B P … — B-frames throughout

So the container's timing is not damaged and no telecine or interlacing is involved. The only unusual property is the packed bitstream.

What I ruled out first

In case it saves someone time:

  • Interlacing / field order. Toggling deinterlaceMode (.auto / .software) and deinterlaceFieldRate (.field / .frame) changed nothing, which is consistent with the deinterlacer never engaging — correctly so, since no frame carries AV_FRAME_FLAG_INTERLACED.
  • Decode path. Forcing preferredDecodePath = .software changed nothing.
  • Frame rate / cadence. Timestamps are evenly spaced; there are no duplicated or dropped frames in the source.

Suggested fix

Two options, either of which should resolve it:

  1. Apply the mpeg4_unpack_bframes bitstream filter when the AVI demuxer yields an MPEG-4 stream whose extradata/packets indicate a packed bitstream — this is what libavcodec's own warning recommends.
  2. Take presentation time from the decoded frame (best_effort_timestamp / AVFrame.pts) rather than deriving it from packet order, for containers that supply no PTS.

For what it's worth, another FFmpeg-based iOS player handles this class of file by taking the timestamp from the decoded AVFrame rather than from the packet, with a source comment noting that AVI packet PTS order is unreliable for exactly these files.

Why it matters

Packed B-frames were the norm for DivX/XviD AVI rips through roughly 2000–2008, so this affects a broad class of legacy files rather than one damaged sample. docs/formats.md documents AVI and MPEG-4 Part 2 as supported, which is what led me to expect these to play.

Happy to run further aetherctl commands against the sample or test a patch.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions