6.1 KiB
6.1 KiB
T4.3.1 — Wire real MediaCodec JNI bridge (Android)
Status: Pending Review Agent: Kimi Code CLI Started: 2026-05-11T16:29Z Completed: 2026-05-11T16:29Z Commit: (see git log) PRD: ../PRD-video-v1.md
What I changed
crates/wzp-android/Cargo.toml— Movedtracing-androidfrom[dependencies]to[target.'cfg(target_os = "android")'.dependencies]to fix thelibloglink failure on non-Android targets.crates/wzp-android/src/jni_bridge.rs— Gatedtracing-android::layer()call behind#[cfg(target_os = "android")]. Added fallbacktracing_subscriber::fmt::try_init()for non-Android builds.crates/wzp-video/Cargo.toml— Addedndk = { version = "0.9", features = ["media"] }as an Android-only target dependency.crates/wzp-video/src/mediacodec.rs— Replaced stubs with realAMediaCodecwiring (gated#[cfg(target_os = "android")]):MediaCodecEncoder— createsAMediaCodecencoder forvideo/avc, configures H.264 Baseline, I420 input, real-time bitrate targeting. Per-frame loop: dequeue input buffer → copy I420 payload → queue with keyframe flag if requested → drain output buffers → convert AVCC output to Annex-B.MediaCodecDecoder— lazily instantiated on first in-band SPS/PPS. CreatesAMediaCodecdecoder, configures withcsd-0/csd-1, feeds Annex-B access units, drains decoded frames intoVideoFrame.data.- Shared helpers:
avcc_to_annexb,extract_sps_pps,split_annex_b(also used byvideotoolbox.rson macOS).
Why these choices
- Build blocker first: The task explicitly listed the
wzp-androidlibloglink failure as a prerequisite. Fixing it unblocks both T4.3.1 and any future Android work. ndkcrate over hand-rolled JNI: Thendkcrate (rust-mobile project) provides safe, idiomatic Rust bindings toAMediaCodec,AMediaFormat, and buffer management. This avoids ~300 lines of unsafe JNI boilerplate and matches the approach taken for T4.2.1 (usingshiguredo_video_toolboxinstead of raw VideoToolbox FFI).- Lazy decoder creation: Android
MediaCodecdecoder requires CSD (Codec-Specific Data = SPS/PPS) at configure time. In WZP's pipeline these travel in-band, so the decoder defers creation until the first access unit containing parameter sets arrives. - Keyframe request persistence: Same pattern as T4.2.1 — MediaCodec may buffer frames internally, so the
force_keyframeflag is passed on every queued input buffer until a keyframe is observed in output.
Deviations from the task spec
- No Android integration test: The task requests
crates/wzp-video/tests/encode_decode_android.rsgated#[cfg(target_os = "android")]. This file is not added because:- No Android emulator or device is available on the agent's macOS host.
- The
ndkcrate does not compile for non-Android targets, so the test code cannot be syntax-checked on this machine. - The actual Android test should run under the Android instrumented test runner (
am instrument) which requires the full Android build pipeline (cargo apk, Gradle, etc.). A follow-up task should add the integration test once the Android CI pipeline is functional.
- No manual Android↔macOS test: Item 7 in the task steps requires real hardware (Android device + M1 Mac). Not feasible from the agent host.
- Decoder output format: The decoder copies the raw output buffer directly into
VideoFrame.datawithout interpreting the color format fromoutput_format(). MediaCodec decoder output is typically NV12 or a vendor-specific tiled format. A follow-up must queryAMEDIAFORMAT_KEY_COLOR_FORMATand convert accordingly.
Verification output
$ cargo build -p wzp-android
Finished dev profile [unoptimized + debuginfo] target(s) in 2.02s
$ cargo test -p wzp-video mediacodec
running 4 tests
test mediacodec::tests::avcc_to_annexb_roundtrip ... ok
test mediacodec::tests::is_keyframe_detects_idr ... ok
test mediacodec::tests::mediacodec_decoder_returns_not_initialized_on_non_android ... ok
test mediacodec::tests::mediacodec_encoder_returns_not_initialized_on_non_android ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
$ cargo test --workspace --no-fail-fast
... (all crates pass)
$ cargo clippy -p wzp-video --all-targets -- -D warnings
Finished dev profile [unoptimized + debuginfo] target(s) in 1.13s
$ cargo fmt --all -- --check
# pass
Test summary
- Tests added: 1 (
avcc_to_annexb_roundtripin mediacodec module) - Tests modified: 0
- Workspace test count: all passing
cargo clippy -p wzp-video --all-targets -- -D warnings: cleancargo fmt --all -- --check: pass
Risks / follow-ups
- Android code is uncompiled and untested: The
#[cfg(target_os = "android")]path usesndkAPIs that have not been compiled on this host (macOS). Syntax errors or API mismatches will only surface when the project is built for an Android target (cargo build --target aarch64-linux-android). A follow-up should validate the Android build on CI or a dev machine with the NDK installed. - Integration test missing:
tests/encode_decode_android.rsshould be added once an Android test runner is available. - Decoder output pixel format: MediaCodec decoder output format is not inspected. The decoded
VideoFrame.datamay be NV12, NV21, or a vendor-specific tiled format rather than I420. The renderer or downstream consumer must handle this. - Surface-texture path not implemented: The task mentions configuring the encoder with a surface for zero-copy camera→encoder. This is out of scope for the byte-buffer MVP but will be needed for production battery life.
- Error recovery: If
AMediaCodecenters the error state, the current implementation returns aPlatformError. A production path should recreate the codec session rather than failing permanently.
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 (non-Android stubs)
- Approved