fix(video): force h264 and trace frame pipeline
Some checks failed
Build Release Binaries / build-amd64 (push) Failing after 3m32s
Mirror to GitHub / mirror (push) Failing after 28s

This commit is contained in:
Siavash Sameni
2026-05-25 20:03:11 +04:00
parent 7eca79846f
commit d57ebe3d2c
9 changed files with 761 additions and 43 deletions

View File

@@ -538,7 +538,7 @@ async fn run_call(
alias: alias.map(|s| s.to_string()),
protocol_version: 2,
supported_versions: vec![2],
video_codecs: vec![],
video_codecs: vec![CodecId::H264Baseline],
};
transport.send_signal(&offer).await?;
info!("CallOffer sent, waiting for CallAnswer...");

View File

@@ -8,6 +8,8 @@ use wzp_proto::{
CodecId, HangupReason, MediaTransport, QualityProfile, SignalMessage, default_signal_version,
};
const SUPPORTED_VIDEO_CODECS: &[CodecId] = &[CodecId::H264Baseline];
/// Result of a successful client-side handshake.
pub struct HandshakeResult {
pub session: Box<dyn CryptoSession>,
@@ -102,7 +104,7 @@ pub async fn perform_handshake(
alias: alias.map(|s| s.to_string()),
protocol_version: 2,
supported_versions: vec![2],
video_codecs: vec![CodecId::Av1Main, CodecId::H264Baseline, CodecId::H265Main],
video_codecs: SUPPORTED_VIDEO_CODECS.to_vec(),
};
transport
.send_signal(&offer)
@@ -189,16 +191,17 @@ mod tests {
let mut kx2 = WarzoneKeyExchange::from_identity_seed(&[0x66; 32]);
kx2.generate_ephemeral();
let session2 = kx2.derive_session(&[0u8; 32]).unwrap();
let hs2 = HandshakeResult { session: session2, video_codec: Some(CodecId::Av1Main) };
assert_eq!(hs2.video_codec, Some(CodecId::Av1Main));
let hs2 = HandshakeResult {
session: session2,
video_codec: Some(CodecId::H264Baseline),
};
assert_eq!(hs2.video_codec, Some(CodecId::H264Baseline));
}
#[test]
fn offer_contains_three_video_codecs() {
// The offer sent in perform_handshake always includes the three codecs
// declared in order: AV1 > H264 > H265. Verify via the const list.
let offered = vec![CodecId::Av1Main, CodecId::H264Baseline, CodecId::H265Main];
assert_eq!(offered.len(), 3);
assert_eq!(offered[0], CodecId::Av1Main, "AV1 must be preferred");
fn offer_contains_h264_only() {
// Keep room video on the common denominator until Android AV1/HEVC
// send paths are proven in-device.
assert_eq!(SUPPORTED_VIDEO_CODECS, &[CodecId::H264Baseline]);
}
}

View File

@@ -177,9 +177,9 @@ mod tests {
#[test]
fn video_codec_picks_first_offered() {
let codecs = vec![CodecId::Av1Main, CodecId::H264Baseline, CodecId::H265Main];
let codecs = vec![CodecId::H264Baseline];
let chosen: Option<CodecId> = codecs.into_iter().next();
assert_eq!(chosen, Some(CodecId::Av1Main));
assert_eq!(chosen, Some(CodecId::H264Baseline));
}
#[test]

View File

@@ -160,8 +160,11 @@ impl VideoEncoder for MediaCodecEncoder {
if packet.is_empty() {
return false;
}
let nal_type = packet[0] & 0x1F;
nal_type == 5
let nals = split_annex_b(packet);
if nals.is_empty() {
return (packet[0] & 0x1F) == 5;
}
nals.iter().any(|nal| !nal.is_empty() && (nal[0] & 0x1F) == 5)
}
}
@@ -1135,6 +1138,11 @@ mod tests {
};
assert!(enc.is_keyframe(&[0x65, 0x01]));
assert!(!enc.is_keyframe(&[0x41, 0x01]));
assert!(enc.is_keyframe(&[
0x00, 0x00, 0x00, 0x01, 0x67, 0x01, // SPS
0x00, 0x00, 0x00, 0x01, 0x68, 0x02, // PPS
0x00, 0x00, 0x00, 0x01, 0x65, 0x03, // IDR
]));
}
#[test]

View File

@@ -160,9 +160,11 @@ impl VideoEncoder for VideoToolboxEncoder {
if packet.is_empty() {
return false;
}
let nal_type = packet[0] & 0x1F;
// NAL type 5 = IDR slice (keyframe).
nal_type == 5
let nals = split_annex_b(packet);
if nals.is_empty() {
return (packet[0] & 0x1F) == 5;
}
nals.iter().any(|nal| !nal.is_empty() && (nal[0] & 0x1F) == 5)
}
}
@@ -791,6 +793,11 @@ mod tests {
let enc = VideoToolboxEncoder::new(1280, 720, 2_000_000).unwrap();
assert!(enc.is_keyframe(&[0x65, 0x01, 0x02]));
assert!(!enc.is_keyframe(&[0x41, 0x01, 0x02]));
assert!(enc.is_keyframe(&[
0x00, 0x00, 0x00, 0x01, 0x67, 0x01, // SPS
0x00, 0x00, 0x00, 0x01, 0x68, 0x02, // PPS
0x00, 0x00, 0x00, 0x01, 0x65, 0x03, // IDR
]));
}
#[test]

View File

@@ -177,9 +177,9 @@ fn missing_fragment_blocks_reassembly() {
#[test]
fn video_codec_selection_semantics() {
// The relay's selection rule is: first codec offered by the caller.
let offered = vec![CodecId::Av1Main, CodecId::H264Baseline, CodecId::H265Main];
let offered = vec![CodecId::H264Baseline];
let chosen = offered.into_iter().next();
assert_eq!(chosen, Some(CodecId::Av1Main));
assert_eq!(chosen, Some(CodecId::H264Baseline));
// When no codecs are offered, video is audio-only.
let empty: Vec<CodecId> = vec![];