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:
- 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.
- 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.
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 swdecodediagnoses this itself, and its verdict already points at #407.Environment
AetherPlayerSurface)aetherctlon macOS 15.7, x86_64The headless reproduction uses no host code, so this is not an integration artifact on my side.
Reproduction
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:
Per-frame, over a 25-frame window mid-file:
interlaced_frame=0andrepeat_pict=0on every frame — the source is progressivebest_effort_timestamp_timeadvances evenly at 0.0417 s with no gaps or duplicatesI B P B P B B P …— B-frames throughoutSo 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:
deinterlaceMode(.auto/.software) anddeinterlaceFieldRate(.field/.frame) changed nothing, which is consistent with the deinterlacer never engaging — correctly so, since no frame carriesAV_FRAME_FLAG_INTERLACED.preferredDecodePath = .softwarechanged nothing.Suggested fix
Two options, either of which should resolve it:
mpeg4_unpack_bframesbitstream 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.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
AVFramerather 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.mddocuments AVI and MPEG-4 Part 2 as supported, which is what led me to expect these to play.Happy to run further
aetherctlcommands against the sample or test a patch.