spike(rust/decode): FFmpeg vs gstreamer-rs binding decision (#108) - #109
Conversation
…fixtures Issue #108 needs a real .mp4 to test seek/decode accuracy for the ffmpeg-the-third vs gstreamer-rs binding decision. testsrc2 content is reproducible per-frame-index, so the reference PPMs stay valid ground truth even if the clip is regenerated later. Follows the spike/<name>/ convention from #93-99 rather than the issue's original spikes/ (plural) text, which has been corrected in the issue body. AC: issue #108 spike scope (fixture prerequisite for all other criteria)
… software + VideoToolbox Answers criteria #1 and #2 from issue #108 for this candidate. Software path is a straight port of the standard ffmpeg-next seek-then-decode- forward pattern; the --hw path required hand-written unsafe FFI through ffmpeg_the_third::ffi (av_hwdevice_ctx_create + a get_format callback on the *unopened* AVCodecContext + av_hwframe_transfer_data) because the crate has no high-level hwaccel wrapper at all. Verified on this M3 Mac: both paths are pixel-exact against the ffmpeg-CLI reference frames, and the hardware path is confirmed to actually engage VideoToolbox rather than silently falling back to software. AC: issue #108 criteria #1 (hardware codec access), #2 (seek/decode accuracy) for the ffmpeg-the-third candidate
…software + VideoToolbox Answers criteria #1 and #2 from issue #108 for the gstreamer-rs candidate. Hardware selection is just naming a different pipeline element (vtdec_hw vs avdec_h264) instead of ffmpeg-the-third's raw FFI hwaccel setup - a real build-complexity difference between the two candidates worth weighing on its own. Verified on this M3 Mac: the software path (avdec_h264) is a close but not pixel-exact match to the ffmpeg-CLI reference (mean diff 1.4, within tolerance). vtdec_hw negotiates and prerolls successfully (hardware path genuinely active, confirmed by diffing the decoded frame against its timestamp neighbors to rule out an off-by-one-frame seek bug instead), but its output pixel-mismatches the reference well outside tolerance (mean diff 3.9, max 168/255) - most likely a colorimetry/GL-readback difference given a plain `vtdec_hw ! videoconvert` pipeline outputs GLMemory-backed buffers. Also surfaced a `GStreamer-GL-WARNING` that vtdec_hw's GL path expects an NSApplication run loop on macOS, which a render-engine binary won't have by default. Left as an honest FAIL rather than a loosened tolerance or a deeper GL-pipeline fix - this friction is exactly what the spike exists to surface for criterion #1. AC: issue #108 criteria #1 (hardware codec access), #2 (seek/decode accuracy) for the gstreamer-rs candidate
Records the actual evidence gathered on this M3 Mac against all five evaluation criteria in issue #108, including two findings beyond what either candidate's happy-path docs would suggest: gstreamer-rs's vtdec_hw negotiates hardware decode but produces pixel output outside tolerance (root-cause not yet fixed, ruled out an off-by-one-frame seek bug specifically so this isn't mistaken for one), and the GPL-vs-LGPL FFmpeg build question applies equally to both candidates, not just gstreamer-rs as the issue originally scoped it. Recommends ffmpeg-the-third, contingent on the still-open Windows/NVIDIA row. README gives the exact per-platform setup and run commands for the Mac M2 and Windows/NVIDIA contributors to fill in the remaining rows. AC: issue #108 all five evaluation criteria; FINDINGS.md deliverable
Future agents touching RFC 0001 or issue #108 need to know spike/ holds throwaway crates separate from the numbered refactor phases, and where the decode-binding spike's findings live.
Ready-to-paste Claude Code prompts for the remaining hardware rowsCopy the block matching your machine into a Claude Code session in this repo. Each one is Mac M2Windows + NVIDIA |
Apple M2 (MacBook Air Mac14,2, macOS 14.5, Rust 1.97.1) results match M3 exactly across all eight test cases: - ffmpeg-the-third software: pixel-exact (mean=0, max=0) both timestamps - ffmpeg-the-third --hw (VideoToolbox): pixel-exact, HARDWARE PATH active - gstreamer-rs software: mean≈1.39, max=6, PASS (matches M3) - gstreamer-rs --hw (vtdec_hw): mean≈3.86, max≈175, FAIL (matches M3) - cargo test: 3/3 ffmpeg-candidate, 2/2 gstreamer-candidate One notable difference from M3: GStreamer-GL-WARNING about NSApplication did not appear on macOS 14.5 (Darwin 23.5.0). vtdec_hw pixel failure is identical in magnitude regardless, confirming the colorimetry issue is not GL-warning-correlated. Criterion #5 licensing confirmed matching M3: applemedia/vtdec_hw is LGPL + Apple system frameworks only (clean); libgstlibav links this machine's Homebrew ffmpeg 8.1.2 (--enable-gpl, same risk as M3). Recommendation unchanged: ffmpeg-the-third. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Mac M2 verification completeHardware: Apple M2 (MacBook Air, Mac14,2), macOS 14.5, Rust 1.97.1 All results match M3 exactly across all 8 test cases:
One notable difference from M3: The Criterion #5 licensing (M2): matches M3 findings exactly — Build notes: Rust not preinstalled ( Recommendation unchanged: FINDINGS.md updated and pushed to this branch. |
Summary
Implements the issue #108 spike: a minimal Rust harness at
spike/rust-decode-spike/comparingffmpeg-the-thirdvsgstreamer-rsas the decode/encode binding for the RFC 0001 native render engine.Mac M3 results are real and verified in this branch (not just scaffolded) — see
FINDINGS.mdfor the full evidence per criterion. Headlines:ffmpeg-the-third: pixel-exact frame-accurate seek+decode on both software and VideoToolbox hardware paths. No high-level hwaccel API exists in the crate — required ~40 lines of hand-written unsafe FFI (documented as a working reference for Epic 1).gstreamer-rs: hardware selection is just namingvtdec_hwinstead ofavdec_h264(zero unsafe code), and it does negotiate/preroll successfully — but its pixel output is outside tolerance (confirmed not an off-by-one-frame bug by diffing against neighboring frames), likely a GL-readback colorimetry issue, plus aGStreamer-GL-WARNINGabout needing anNSApplicationrun loop that a render-engine binary won't have.--enable-gpl, sogstreamer-rs's software fallback (avdec_h264, viagst-libav) is GPL-contaminated, whilevtdec_hw(Apple system frameworks only) is clean. Flagged as its own prerequisite issue for Epic 1 regardless of binding choice.Recommendation:
ffmpeg-the-third, contingent on the Windows/NVIDIA row below. Full rationale inFINDINGS.md.Also corrected issue #108's
spikes/(plural) path tospike/(singular) to match the established convention from the audio-sync spike (#93–#99) — standaloneCargo.tomlper spike, no root-level workspace.What's left for reviewers
Mac M2 and Windows+NVIDIA rows in
FINDINGS.mdare open — @Saloni @victoria, whichever of you has that hardware, please run the commands inspike/rust-decode-spike/README.mdand paste your output intoFINDINGS.md(or a comment here). The Windows candidates also need anvh264dec/NVDEC code path added — TODOs are left in bothmain.rsfiles marking exactly where.Test plan
npm test— 20/20 suites pass (this change doesn't touch JS/TS)docs/implementation-guides/issue-108-rust-decode-spike.md)cargo testpasses for both candidate crates (PPM/pixel-compare unit tests)🤖 Generated with Claude Code