fix(wzp-video): cfg-gate dav1d + svt-av1 off Android target

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) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-05-12 19:58:37 +04:00
parent f28f39d814
commit f3e3ee5ed0
3 changed files with 46 additions and 13 deletions

View File

@@ -7,11 +7,15 @@ rust-version.workspace = true
[dependencies] [dependencies]
bytes = { workspace = true } bytes = { workspace = true }
shiguredo_dav1d = "2026.1.0"
shiguredo_svt_av1 = "2026.1.0"
tracing = { workspace = true } tracing = { workspace = true }
wzp-proto = { path = "../wzp-proto" } 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] [target.'cfg(target_os = "macos")'.dependencies]
shiguredo_video_toolbox = "2026.1" shiguredo_video_toolbox = "2026.1"

View File

@@ -68,12 +68,21 @@ pub fn create_video_encoder(
} }
} }
CodecId::Av1Main => { CodecId::Av1Main => {
// SVT-AV1 is the universal SW fallback. // SVT-AV1 is the universal SW fallback for non-Android targets.
// macOS VideoToolbox has no AV1 encode. Android MediaCodec AV1 // On Android, MediaCodec AV1 (`video/av01`) is the only available
// encode requires API 29+ and may not be available on all devices. // path — shiguredo_svt_av1 does not build for aarch64-linux-android.
let _ = bitrate_bps; // SvtAv1Encoder currently hard-codes bitrate let _ = bitrate_bps; // SvtAv1Encoder currently hard-codes bitrate
#[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)?)) Ok(Box::new(crate::svt_av1::SvtAv1Encoder::new(width, height)?))
} }
}
_ => Err(VideoError::InvalidInput("not a video codec".into())), _ => Err(VideoError::InvalidInput("not a video codec".into())),
} }
} }
@@ -131,7 +140,9 @@ pub fn create_video_decoder(
} }
} }
CodecId::Av1Main => { 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")] #[cfg(target_os = "macos")]
{ {
if let Ok(dec) = crate::videotoolbox::VideoToolboxAv1Decoder::new(width, height) { if let Ok(dec) = crate::videotoolbox::VideoToolboxAv1Decoder::new(width, height) {
@@ -140,12 +151,14 @@ pub fn create_video_decoder(
} }
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
{ {
if let Ok(dec) = crate::mediacodec::MediaCodecAv1Decoder::new(width, height) { return crate::mediacodec::MediaCodecAv1Decoder::new(width, height)
return Ok(Box::new(dec)); .map(|d| Box::new(d) as Box<dyn VideoDecoder>);
}
} }
#[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())), _ => Err(VideoError::InvalidInput("not a video codec".into())),
} }
} }
@@ -157,18 +170,30 @@ mod tests {
#[test] #[test]
fn av1_encoder_factory_creates_svt_av1() { fn av1_encoder_factory_creates_svt_av1() {
let enc = create_video_encoder(CodecId::Av1Main, 640, 480, 2_000_000); 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!( assert!(
enc.is_ok(), enc.is_ok(),
"AV1 encoder factory should succeed on all platforms" "AV1 encoder factory should succeed on non-Android platforms"
); );
} }
#[test] #[test]
fn av1_decoder_factory_creates_decoder() { fn av1_decoder_factory_creates_decoder() {
let dec = create_video_decoder(CodecId::Av1Main, 640, 480); 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!( assert!(
dec.is_ok(), dec.is_ok(),
"AV1 decoder factory should succeed on all platforms" "AV1 decoder factory should succeed on non-Android (dav1d SW fallback)"
); );
} }

View File

@@ -6,6 +6,7 @@
pub mod av1_obu; pub mod av1_obu;
pub mod controller; pub mod controller;
#[cfg(not(target_os = "android"))]
pub mod dav1d; pub mod dav1d;
pub mod decoder; pub mod decoder;
pub mod depacketizer; pub mod depacketizer;
@@ -16,11 +17,13 @@ pub mod framer;
pub mod mediacodec; pub mod mediacodec;
pub mod nack; pub mod nack;
pub mod simulcast; pub mod simulcast;
#[cfg(not(target_os = "android"))]
pub mod svt_av1; pub mod svt_av1;
pub mod videotoolbox; pub mod videotoolbox;
pub use av1_obu::{Av1Depacketizer, Av1ObuFramer, is_keyframe_obu}; pub use av1_obu::{Av1Depacketizer, Av1ObuFramer, is_keyframe_obu};
pub use controller::{VideoQualityController, VideoTarget}; pub use controller::{VideoQualityController, VideoTarget};
#[cfg(not(target_os = "android"))]
pub use dav1d::Dav1dDecoder; pub use dav1d::Dav1dDecoder;
pub use decoder::VideoDecoder; pub use decoder::VideoDecoder;
pub use depacketizer::H264Depacketizer; pub use depacketizer::H264Depacketizer;
@@ -34,6 +37,7 @@ pub use mediacodec::{
}; };
pub use nack::{CachedPacket, NackAction, NackReceiver, NackSender}; pub use nack::{CachedPacket, NackAction, NackReceiver, NackSender};
pub use simulcast::{LayerPacket, LayerTarget, SimulcastEncoder, SimulcastLayer}; pub use simulcast::{LayerPacket, LayerTarget, SimulcastEncoder, SimulcastLayer};
#[cfg(not(target_os = "android"))]
pub use svt_av1::SvtAv1Encoder; pub use svt_av1::SvtAv1Encoder;
pub use videotoolbox::{ pub use videotoolbox::{
VideoToolboxAv1Decoder, VideoToolboxDecoder, VideoToolboxEncoder, VideoToolboxHevcDecoder, VideoToolboxAv1Decoder, VideoToolboxDecoder, VideoToolboxEncoder, VideoToolboxHevcDecoder,