From f3e3ee5ed0efd02b6d32eb957b27ec622d60ac2c Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Tue, 12 May 2026 19:58:37 +0400 Subject: [PATCH] fix(wzp-video): cfg-gate dav1d + svt-av1 off Android target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit shiguredo_dav1d and shiguredo_svt_av1 build scripts panic with 'unsupported target: os=android, arch=aarch64'. The AV1 SW fallback is only needed on macOS / Linux desktop — Android uses MediaCodec for AV1 anyway. - Cargo.toml: AV1 SW deps moved under cfg(not(target_os = "android")) - lib.rs: cfg-gate the dav1d and svt_av1 modules and re-exports - factory.rs: on Android, Av1Main paths return NotInitialized when HW MediaCodec is also unavailable (only path on Android) - factory tests: assert NotInitialized on Android, Ok elsewhere Unblocks T4.3.1.1 (Android target-compile of wzp-video / mediacodec). Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/wzp-video/Cargo.toml | 8 ++++-- crates/wzp-video/src/factory.rs | 47 +++++++++++++++++++++++++-------- crates/wzp-video/src/lib.rs | 4 +++ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/crates/wzp-video/Cargo.toml b/crates/wzp-video/Cargo.toml index d2993ae..6f4b6fd 100644 --- a/crates/wzp-video/Cargo.toml +++ b/crates/wzp-video/Cargo.toml @@ -7,11 +7,15 @@ rust-version.workspace = true [dependencies] bytes = { workspace = true } -shiguredo_dav1d = "2026.1.0" -shiguredo_svt_av1 = "2026.1.0" tracing = { workspace = true } wzp-proto = { path = "../wzp-proto" } +# AV1 SW codecs do not support Android target (build.rs panics on +# aarch64-linux-android). Android uses MediaCodec for AV1 instead. +[target.'cfg(not(target_os = "android"))'.dependencies] +shiguredo_dav1d = "2026.1.0" +shiguredo_svt_av1 = "2026.1.0" + [target.'cfg(target_os = "macos")'.dependencies] shiguredo_video_toolbox = "2026.1" diff --git a/crates/wzp-video/src/factory.rs b/crates/wzp-video/src/factory.rs index 3b44cb7..0c762ab 100644 --- a/crates/wzp-video/src/factory.rs +++ b/crates/wzp-video/src/factory.rs @@ -68,11 +68,20 @@ pub fn create_video_encoder( } } CodecId::Av1Main => { - // SVT-AV1 is the universal SW fallback. - // macOS VideoToolbox has no AV1 encode. Android MediaCodec AV1 - // encode requires API 29+ and may not be available on all devices. + // SVT-AV1 is the universal SW fallback for non-Android targets. + // On Android, MediaCodec AV1 (`video/av01`) is the only available + // path — shiguredo_svt_av1 does not build for aarch64-linux-android. let _ = bitrate_bps; // SvtAv1Encoder currently hard-codes bitrate - Ok(Box::new(crate::svt_av1::SvtAv1Encoder::new(width, height)?)) + #[cfg(target_os = "android")] + { + let _ = (width, height); + #[allow(clippy::needless_return)] + return Err(VideoError::NotInitialized); + } + #[cfg(not(target_os = "android"))] + { + Ok(Box::new(crate::svt_av1::SvtAv1Encoder::new(width, height)?)) + } } _ => Err(VideoError::InvalidInput("not a video codec".into())), } @@ -131,7 +140,9 @@ pub fn create_video_decoder( } } CodecId::Av1Main => { - // Try platform HW decoders first, then fall back to dav1d. + // Try platform HW decoders first, then fall back to dav1d on + // non-Android targets. On Android, MediaCodec is the only path — + // shiguredo_dav1d does not build for aarch64-linux-android. #[cfg(target_os = "macos")] { if let Ok(dec) = crate::videotoolbox::VideoToolboxAv1Decoder::new(width, height) { @@ -140,11 +151,13 @@ pub fn create_video_decoder( } #[cfg(target_os = "android")] { - if let Ok(dec) = crate::mediacodec::MediaCodecAv1Decoder::new(width, height) { - return Ok(Box::new(dec)); - } + return crate::mediacodec::MediaCodecAv1Decoder::new(width, height) + .map(|d| Box::new(d) as Box); + } + #[cfg(not(target_os = "android"))] + { + Ok(Box::new(crate::dav1d::Dav1dDecoder::new()?)) } - Ok(Box::new(crate::dav1d::Dav1dDecoder::new()?)) } _ => Err(VideoError::InvalidInput("not a video codec".into())), } @@ -157,18 +170,30 @@ mod tests { #[test] fn av1_encoder_factory_creates_svt_av1() { let enc = create_video_encoder(CodecId::Av1Main, 640, 480, 2_000_000); + #[cfg(target_os = "android")] + assert!( + matches!(enc, Err(VideoError::NotInitialized)), + "AV1 SW encoder is unavailable on Android (no shiguredo_svt_av1)" + ); + #[cfg(not(target_os = "android"))] assert!( enc.is_ok(), - "AV1 encoder factory should succeed on all platforms" + "AV1 encoder factory should succeed on non-Android platforms" ); } #[test] fn av1_decoder_factory_creates_decoder() { let dec = create_video_decoder(CodecId::Av1Main, 640, 480); + #[cfg(target_os = "android")] + assert!( + matches!(dec, Err(VideoError::NotInitialized)), + "AV1 decoder requires MediaCodec on Android; non-Android device returns NotInitialized" + ); + #[cfg(not(target_os = "android"))] assert!( dec.is_ok(), - "AV1 decoder factory should succeed on all platforms" + "AV1 decoder factory should succeed on non-Android (dav1d SW fallback)" ); } diff --git a/crates/wzp-video/src/lib.rs b/crates/wzp-video/src/lib.rs index 1c7dc84..5dec541 100644 --- a/crates/wzp-video/src/lib.rs +++ b/crates/wzp-video/src/lib.rs @@ -6,6 +6,7 @@ pub mod av1_obu; pub mod controller; +#[cfg(not(target_os = "android"))] pub mod dav1d; pub mod decoder; pub mod depacketizer; @@ -16,11 +17,13 @@ pub mod framer; pub mod mediacodec; pub mod nack; pub mod simulcast; +#[cfg(not(target_os = "android"))] pub mod svt_av1; pub mod videotoolbox; pub use av1_obu::{Av1Depacketizer, Av1ObuFramer, is_keyframe_obu}; pub use controller::{VideoQualityController, VideoTarget}; +#[cfg(not(target_os = "android"))] pub use dav1d::Dav1dDecoder; pub use decoder::VideoDecoder; pub use depacketizer::H264Depacketizer; @@ -34,6 +37,7 @@ pub use mediacodec::{ }; pub use nack::{CachedPacket, NackAction, NackReceiver, NackSender}; pub use simulcast::{LayerPacket, LayerTarget, SimulcastEncoder, SimulcastLayer}; +#[cfg(not(target_os = "android"))] pub use svt_av1::SvtAv1Encoder; pub use videotoolbox::{ VideoToolboxAv1Decoder, VideoToolboxDecoder, VideoToolboxEncoder, VideoToolboxHevcDecoder,