Repository navigation
Conversation
|
@Addin is attempting to deploy a commit to the Cap Software Inc Team on Vercel. A member of the Team first needs to authorize it. |
2affb95 to
0bd3685
Compare
|
@greptileai review |
1 similar comment
|
@greptileai review |
|
Thanks for splitting this out. Before we can review it for merge, a few things need to change:
Once these are in, we'll run the Greptile review, and it needs a 5/5 plus green CI to merge. |
|
Follow-up, one by one:
Validation: |
|
Hi @richiemcilroy can I have a review on this, or should this be closed? |
|
Thanks! Can you get Greptile to 5/5 on the latest commit? Then we'll take a look. |
|
@greptileai review |
| ) | ||
| .unwrap() | ||
| }; | ||
| assert_eq!(new.as_slice(), old.as_slice()); |
There was a problem hiding this comment.
Padding can fail pixel comparisons
If an adapter reports RowPitch greater than WIDTH, software_decoded_1080p_frame_matches_blocking_readback compares unwritten padding from two separately allocated staging textures. The width-limited copy writes the visible pixels, but those padding bytes need not match. This can fail the test even when every pixel is correct.
Compare only the visible bytes in each luma and chroma row.
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/video-decode/src/media_foundation.rs
Line: 1962
Comment:
**Padding can fail pixel comparisons**
If an adapter reports `RowPitch` greater than `WIDTH`, `software_decoded_1080p_frame_matches_blocking_readback` compares unwritten padding from two separately allocated staging textures. The width-limited copy writes the visible pixels, but those padding bytes need not match. This can fail the test even when every pixel is correct.
Compare only the visible bytes in each luma and chroma row.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.|
@greptileai review. |
|
@richiemcilroy Review is 5/5, this is ready. |
|
Thanks, the 4K readback win is real. It conflicts with #3279 and #3249, which take the same copy out with less risk, and keeping textures mapped across threads for the whole frame cache shows p95 +3.77 ms end to end. We're taking #3279 and #3249 first; if you still see a win on top of them, a rebase with a soak on real GPUs would be the way. |
Summary
Media Foundation readback blocked on
Map, copied the NV12 staging texture into a freshVec<u8>, and unmapped it for every frame. This keeps the staging texture mapped, hands the mapped NV12 bytes to the renderer, and pools the staging textures. Readback still reserves the process-wide idle staging budget and bounds the per-decoder frame cache.Review follow-up
sync-testsnow runscargo test -p cap-video-decode --libon Windows and triggers oncrates/video-decode/**andcrates/d3d-adapter/**. The functional tests no longer use#[ignore]. The hosted runner has no video-capable D3D11 adapter, so CI forces plain WARP and exercises the same Media Foundation decoder with a software device (CAP_FORCE_WARP_TESTS=1); the required flags turn a missing device or decoder into a failure. The job logs include:MediaFoundation readback parity: 21 frames, 1920x1080, 1088-row decoder surfaceMediaFoundation 1088-row copy: only visible 1080 luma and chroma rowsMediaFoundation software-decode parity: 1 frame, 1920x1080, 1088-row sourcepipelined_readback_returns_every_sample_in_ordernow uses a committed 1920x1080 H.264 fixture whose decoder surface is 1088 rows. Its expected side uses the previous blockingMap, a copy into aVec<u8>, andUnmap, with the same source box as the new path, then compares every frame byte for byte withread_nv12().staging_cache_budget()and the per-live-decoder division from this PR.FrameRequestskeeps the existing 128 MB per-decoder cache and its eviction behavior is unchanged. The idle staging pool caps remain.mpscchannel. The decoder thread unmaps and recycles it before its nextMap, so the render thread never callsUnmapin steady state. The inline fallback only runs after the decoder has shut down. A regression test asserts the pool is untouched until the decoder drains the reclaim queue.Microsoft Basic Render Driver.perf/ffmpeg-borrowed-planes; it keeps both the borrowed-AVFrame backing and the staging epoch, and adds a test covering both (storage_identity_combines_ffmpeg_backing_and_staging_epochs).Changes
cap-video-decode:MappedNV12owns the mapped staging texture and exposes its bytes;StagingTexturePoolrecycles textures;D3D11_MAP_FLAG_DO_NOT_WAITis tried first with a blockingMapfallback; the copy uses an explicitD3D11_BOXlimited to the visible frame so a 1088-row decoder surface only copies 1080 rows.MappedNV12::dropreturns the texture to the decoder's reclaim channel;MediaFoundationDecoderdrains it before the next map and when seeking.MFInitGuardis reference-counted by mapped frames, soMFShutdowncannot run while a frame is still mapped.NV12ReadbackStats: frames, bytes, map waits, immediate/blocked maps, pool hits/misses.cap-rendering: Media Foundation frames store the mapped NV12 and a readback epoch; the epoch is the storage identity, because staging textures are recycled.Map+ fresh-Vecpath.Test machine
x86_64-pc-windows-msvcPerformance
4K NV12 readback (Windows, 60 frames, release)
Map+ freshVecMapping dominates the remaining 3.77 ms (
Mapwait 3.4–3.6 ms); the removed 2.2 ms is allocation and the memcpy into a freshVec. The staging pool hit 59 of 60 frames.Playback and export
The macOS after runs are within the baseline range and do not show a regression. The Windows laptop throttles across a run (back-to-back p95 swings from 27 ms to 199 ms), so the paired deltas are the meaningful local pipeline numbers; the controlled Windows measurement is the 4K readback table above.
Validation
cargo fmt --all -- --check: pass.cargo clippy -p cap-video-decode --all-targets -- -D warnings(Windows MSVC): pass.cargo test -p cap-video-decode --lib: 21 passed, 2 ignored (performance probes), both with the hardware decoder and withCAP_FORCE_WARP_TESTS=1.cap-rendering: combined FFmpeg-backing + staging-epoch identity tests pass on the companion branch.sync-testsWindows job: https://github.com/Addin/Cap/actions/runs/40215806884 (logs:MediaFoundation readback parity: 21 frames, 1920x1080, 1088-row decoder surface).performance-regressionsmacOS after: https://github.com/Addin/Cap/actions/runs/40213064453, https://github.com/Addin/Cap/actions/runs/40213069883, https://github.com/Addin/Cap/actions/runs/40213074991.performance-regressionsmacOS baseline (08242c3): https://github.com/Addin/Cap/actions/runs/40213654764, https://github.com/Addin/Cap/actions/runs/40213659266, https://github.com/Addin/Cap/actions/runs/40213663832.Scope


Confidence Score: 5/5
The PR appears safe to merge; no new actionable issues were found.Summary
This PR keeps Media Foundation staging textures mapped and passes their bytes to the renderer without a fresh frame copy.
Review checks were source-only; Windows tests were not run locally.
Reviews (5) · Last reviewed commit: "test(decoding): compare only visible NV1..." · Reviewed by Greptile