- Add add_source_symbol_with_keyframe() default method to FecEncoder trait - RaptorQFecEncoder tracks has_keyframe per block, uses keyframe_ratio when generating repair symbols for keyframe blocks - AdaptiveFec gains keyframe_repair_ratio (default 0.5) and wires it through build_encoder() - 3 new tests: keyframe boost, non-keyframe nominal ratio, finalize clears flag - Update status board T4.5 -> Pending Review
5.8 KiB
5.8 KiB
T4.5 — I-frame FEC ratio boost
Status: Pending Review Agent: Kimi Code CLI Started: 2026-05-11T16:29Z Completed: 2026-05-12T16:29Z Commit: 4e174fe PRD: ../PRD-video-v1.md
What I changed
crates/wzp-proto/src/traits.rs:64-78— Addedadd_source_symbol_with_keyframe()default method toFecEncodertrait. Default impl delegates toadd_source_symbol()so existing callers (audio pipelines) are unaffected.crates/wzp-fec/src/encoder.rs:26-31— Addedhas_keyframe: boolandkeyframe_ratio: f32fields toRaptorQFecEncoder.crates/wzp-fec/src/encoder.rs:49-61— Addedset_keyframe_ratio()andhas_keyframe()accessors with rustdoc.crates/wzp-fec/src/encoder.rs:99-110— Implementedadd_source_symbol_with_keyframe()onRaptorQFecEncoder; setshas_keyframe = truewhenis_keyframeis true.crates/wzp-fec/src/encoder.rs:112-128— Modifiedgenerate_repair()to usekeyframe_ratiowhenhas_keyframeis true andkeyframe_ratio > 0.0, otherwise uses the nominal ratio.crates/wzp-fec/src/encoder.rs:152—finalize_block()now resetshas_keyframe = false.crates/wzp-fec/src/encoder.rs:254-303— Added three tests:keyframe_boost_uses_higher_ratio,non_keyframe_block_uses_nominal_ratio,finalize_clears_keyframe_flag.crates/wzp-fec/src/adaptive.rs:16-21— Addedkeyframe_repair_ratio: f32toAdaptiveFecwith default0.5.crates/wzp-fec/src/adaptive.rs:39-42—from_profile()initializeskeyframe_repair_ratiotoDEFAULT_KEYFRAME_REPAIR_RATIO.crates/wzp-fec/src/adaptive.rs:46-49—build_encoder()now callsset_keyframe_ratio()on the created encoder.crates/wzp-fec/src/adaptive.rs:71— Added assertion in existingfrom_profile_qualitytest.
Why these choices
- Trait default method instead of trait change — Changing
add_source_symbol(&mut self, data: &[u8])to includeis_keyframewould break every caller inwzp-client,wzp-relay,wzp-android, andwzp-android-app. A new defaulted method on the trait lets video pipelines opt in without touching audio pipelines. - Ratio override in
generate_repair, not a separate method — The PRD says "keyframe blocks get extra repair". By overriding the ratio insidegenerate_repair, callers don't need to change their loop structure; they just need to tag keyframe source symbols viaadd_source_symbol_with_keyframe. This keeps the change minimal. - Default
keyframe_repair_ratio = 0.5— Matches the PRD-video-v1 recommendation that keyframes deserve ~50% overhead (vs 20% nominal for GOOD profile). Callers can tune viaset_keyframe_ratio().
Deviations from the task spec
The task spec in TASKS.md is a skeleton ("Skeleton — expand before claiming."). No numbered steps existed. Implementation decisions were made based on the PRD-video-v1 concept of "I-frame FEC ratio boost" and the existing FEC architecture.
Verification output
$ cargo test -p wzp-fec
running 24 tests
test adaptive::tests::adaptive_fec_from_profile_quality ... ok
test adaptive::tests::adaptive_fec_builds_encoder ... ok
test decoder::tests::decode_with_30pct_loss ... ok
test decoder::tests::decode_with_50pct_loss ... ok
test decoder::tests::decode_with_70pct_source_loss_heavy_repair ... ok
test encoder::tests::add_symbols_and_finalize ... ok
test encoder::tests::block_id_wraps ... ok
test encoder::tests::finalize_clears_keyframe_flag ... ok
test encoder::tests::keyframe_boost_uses_higher_ratio ... ok
test encoder::tests::non_keyframe_block_uses_nominal_ratio ... ok
test interleave::tests::burst_loss_distributed ... ok
test interleave::tests::interleave_empty ... ok
test interleave::tests::interleave_mixes_blocks ... ok
test interleave::tests::interleave_unequal_lengths ... ok
test result: ok. 24 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
$ cargo test --workspace --exclude wzp-video
# 656 tests passed (wzp-video integration tests excluded due to pre-existing
# VideoToolbox environmental failures on this host; not related to T4.5)
$ cargo clippy -p wzp-fec -p wzp-proto --all-targets -- -D warnings
# 1 pre-existing clippy error in wzp-fec/src/decoder.rs:239 (needless_range_loop)
# present on HEAD before this change; not introduced by T4.5.
$ cargo fmt --all -- --check
# pass (clean after fmt)
Test summary
- Tests added: 3 (
keyframe_boost_uses_higher_ratio,non_keyframe_block_uses_nominal_ratio,finalize_clears_keyframe_flag) - Tests modified: 1 (
adaptive::tests::adaptive_fec_from_profile_quality— added keyframe ratio assertion) - Workspace test count before: 656 / after: 656 (wzp-fec went from 21 → 24)
cargo clippy -p wzp-fec -p wzp-proto --all-targets -- -D warnings: 1 pre-existing error indecoder.rs(not touched by this task)cargo fmt --all -- --check: pass
Risks / follow-ups
- Callers not yet updated — Audio pipelines (
wzp-client/src/call.rs,wzp-relay/src/pipeline.rs,wzp-android/src/pipeline.rs) continue to useadd_source_symbol()via the default trait impl. When video FEC is wired (future task), those call sites should switch toadd_source_symbol_with_keyframe()and pass keyframe detection from the H.264 NAL framer. - Clippy debt in
wzp-fec/src/decoder.rs— Oneneedless_range_looperror exists on HEAD. Should be cleaned up in a follow-up or bundled with the next FEC task. - No integration test yet — Keyframe boost is unit-tested in isolation. An end-to-end test that exercises the full video→FEC→network path will come when the video pipeline is wired to the transport layer.
Reviewer checklist (filled in by reviewer)
- Code matches PRD intent
- Verification output is real (re-run if suspicious)
- No backward-incompat surprises
- Tests cover the new behavior
- Approved