T1.5: Migrate emit/parse sites to v2 wire format
This commit is contained in:
@@ -326,7 +326,10 @@ pub fn pin_to_big_core() {
|
||||
&set,
|
||||
);
|
||||
if ret != 0 {
|
||||
warn!("sched_setaffinity failed: {}", std::io::Error::last_os_error());
|
||||
warn!(
|
||||
"sched_setaffinity failed: {}",
|
||||
std::io::Error::last_os_error()
|
||||
);
|
||||
} else {
|
||||
info!(start, num_cpus, "pinned to big cores");
|
||||
}
|
||||
|
||||
@@ -77,7 +77,8 @@ impl AudioRing {
|
||||
}
|
||||
}
|
||||
|
||||
self.write_pos.store(w.wrapping_add(count), Ordering::Release);
|
||||
self.write_pos
|
||||
.store(w.wrapping_add(count), Ordering::Release);
|
||||
count
|
||||
}
|
||||
|
||||
@@ -112,7 +113,8 @@ impl AudioRing {
|
||||
out[i] = unsafe { *self.buf.as_ptr().add((r + i) & RING_MASK) };
|
||||
}
|
||||
|
||||
self.read_pos.store(r.wrapping_add(count), Ordering::Release);
|
||||
self.read_pos
|
||||
.store(r.wrapping_add(count), Ordering::Release);
|
||||
count
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,11 @@ const PROFILES: [QualityProfile; 6] = [
|
||||
];
|
||||
|
||||
fn profile_to_index(p: &QualityProfile) -> u8 {
|
||||
PROFILES.iter().position(|pp| pp.codec == p.codec).map(|i| i as u8).unwrap_or(3)
|
||||
PROFILES
|
||||
.iter()
|
||||
.position(|pp| pp.codec == p.codec)
|
||||
.map(|i| i as u8)
|
||||
.unwrap_or(3)
|
||||
}
|
||||
|
||||
fn index_to_profile(idx: u8) -> Option<QualityProfile> {
|
||||
@@ -149,9 +153,10 @@ impl WzpEngine {
|
||||
.enable_all()
|
||||
.build()?;
|
||||
|
||||
let relay_addr: SocketAddr = config.relay_addr.parse().map_err(|e| {
|
||||
anyhow::anyhow!("invalid relay address '{}': {e}", config.relay_addr)
|
||||
})?;
|
||||
let relay_addr: SocketAddr = config
|
||||
.relay_addr
|
||||
.parse()
|
||||
.map_err(|e| anyhow::anyhow!("invalid relay address '{}': {e}", config.relay_addr))?;
|
||||
|
||||
let room = config.room.clone();
|
||||
let identity_seed = config.identity_seed;
|
||||
@@ -165,7 +170,16 @@ impl WzpEngine {
|
||||
|
||||
let state_clone = state.clone();
|
||||
runtime.block_on(async move {
|
||||
if let Err(e) = run_call(relay_addr, &room, &identity_seed, profile, auto_profile, alias.as_deref(), state_clone).await
|
||||
if let Err(e) = run_call(
|
||||
relay_addr,
|
||||
&room,
|
||||
&identity_seed,
|
||||
profile,
|
||||
auto_profile,
|
||||
alias.as_deref(),
|
||||
state_clone,
|
||||
)
|
||||
.await
|
||||
{
|
||||
error!("call failed: {e}");
|
||||
}
|
||||
@@ -233,16 +247,21 @@ impl WzpEngine {
|
||||
let server_fp = conn
|
||||
.peer_identity()
|
||||
.and_then(|id| id.downcast::<Vec<rustls::pki_types::CertificateDer>>().ok())
|
||||
.and_then(|certs| certs.first().map(|c| {
|
||||
use std::hash::{Hash, Hasher};
|
||||
let mut h = std::collections::hash_map::DefaultHasher::new();
|
||||
c.as_ref().hash(&mut h);
|
||||
format!("{:016x}", h.finish())
|
||||
}))
|
||||
.and_then(|certs| {
|
||||
certs.first().map(|c| {
|
||||
use std::hash::{Hash, Hasher};
|
||||
let mut h = std::collections::hash_map::DefaultHasher::new();
|
||||
c.as_ref().hash(&mut h);
|
||||
format!("{:016x}", h.finish())
|
||||
})
|
||||
})
|
||||
.unwrap_or_default();
|
||||
conn.close(0u32.into(), b"ping");
|
||||
|
||||
Ok::<_, anyhow::Error>(format!(r#"{{"rtt_ms":{},"server_fingerprint":"{}"}}"#, rtt_ms, server_fp))
|
||||
Ok::<_, anyhow::Error>(format!(
|
||||
r#"{{"rtt_ms":{},"server_fingerprint":"{}"}}"#,
|
||||
rtt_ms, server_fp
|
||||
))
|
||||
});
|
||||
|
||||
// Shutdown runtime cleanly with timeout
|
||||
@@ -392,7 +411,11 @@ impl WzpEngine {
|
||||
}
|
||||
|
||||
/// Answer an incoming direct call.
|
||||
pub fn answer_call(&self, call_id: &str, mode: wzp_proto::CallAcceptMode) -> Result<(), anyhow::Error> {
|
||||
pub fn answer_call(
|
||||
&self,
|
||||
call_id: &str,
|
||||
mode: wzp_proto::CallAcceptMode,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let _ = self.state.command_tx.send(EngineCommand::AnswerCall {
|
||||
call_id: call_id.to_string(),
|
||||
accept_mode: mode,
|
||||
@@ -412,7 +435,9 @@ impl WzpEngine {
|
||||
/// Stores the type atomically; the recv task polls it on each packet.
|
||||
pub fn on_network_changed(&self, network_type: u8, bandwidth_kbps: u32) {
|
||||
info!(network_type, bandwidth_kbps, "on_network_changed");
|
||||
self.state.pending_network_type.store(network_type, Ordering::Release);
|
||||
self.state
|
||||
.pending_network_type
|
||||
.store(network_type, Ordering::Release);
|
||||
}
|
||||
|
||||
pub fn get_stats(&self) -> CallStats {
|
||||
@@ -518,12 +543,16 @@ async fn run_call(
|
||||
.ok_or_else(|| anyhow::anyhow!("connection closed before CallAnswer"))?;
|
||||
|
||||
let (relay_ephemeral_pub, chosen_profile) = match answer {
|
||||
SignalMessage::CallAnswer { ephemeral_pub, chosen_profile, .. } => (ephemeral_pub, chosen_profile),
|
||||
SignalMessage::CallAnswer {
|
||||
ephemeral_pub,
|
||||
chosen_profile,
|
||||
..
|
||||
} => (ephemeral_pub, chosen_profile),
|
||||
other => {
|
||||
return Err(anyhow::anyhow!(
|
||||
"expected CallAnswer, got {:?}",
|
||||
std::mem::discriminant(&other)
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -725,9 +754,7 @@ async fn run_call(
|
||||
if send_errors <= 3 || last_send_error_log.elapsed().as_secs() >= 1 {
|
||||
warn!(
|
||||
seq = s,
|
||||
send_errors,
|
||||
frames_dropped,
|
||||
"send_media error (dropping packet): {e}"
|
||||
send_errors, frames_dropped, "send_media error (dropping packet): {e}"
|
||||
);
|
||||
last_send_error_log = Instant::now();
|
||||
}
|
||||
@@ -820,7 +847,11 @@ async fn run_call(
|
||||
avg_total_us = avg(t_agc_us + t_opus_us + t_fec_us + t_send_us),
|
||||
"send stats"
|
||||
);
|
||||
t_agc_us = 0; t_opus_us = 0; t_fec_us = 0; t_send_us = 0; t_frames = 0;
|
||||
t_agc_us = 0;
|
||||
t_opus_us = 0;
|
||||
t_fec_us = 0;
|
||||
t_send_us = 0;
|
||||
t_frames = 0;
|
||||
last_stats_log = Instant::now();
|
||||
}
|
||||
}
|
||||
@@ -849,12 +880,9 @@ async fn run_call(
|
||||
// when a packet arrives with seq > expected_seq, the frames in
|
||||
// between are missing and we attempt to reconstruct them via
|
||||
// DRED before decoding the newly-arrived packet.
|
||||
let mut dred_decoder =
|
||||
DredDecoderHandle::new().expect("opus_dred_decoder_create failed");
|
||||
let mut dred_parse_scratch =
|
||||
DredState::new().expect("opus_dred_alloc failed (scratch)");
|
||||
let mut last_good_dred =
|
||||
DredState::new().expect("opus_dred_alloc failed (good state)");
|
||||
let mut dred_decoder = DredDecoderHandle::new().expect("opus_dred_decoder_create failed");
|
||||
let mut dred_parse_scratch = DredState::new().expect("opus_dred_alloc failed (scratch)");
|
||||
let mut last_good_dred = DredState::new().expect("opus_dred_alloc failed (good state)");
|
||||
let mut last_good_dred_seq: Option<u16> = None;
|
||||
let mut expected_seq: Option<u16> = None;
|
||||
let mut dred_reconstructions: u64 = 0;
|
||||
@@ -884,7 +912,9 @@ async fn run_call(
|
||||
|
||||
// Check for network transport change from ConnectivityManager
|
||||
{
|
||||
let net = state.pending_network_type.swap(PROFILE_NO_CHANGE, Ordering::Acquire);
|
||||
let net = state
|
||||
.pending_network_type
|
||||
.swap(PROFILE_NO_CHANGE, Ordering::Acquire);
|
||||
if net != PROFILE_NO_CHANGE {
|
||||
use wzp_proto::NetworkContext;
|
||||
let ctx = match net {
|
||||
@@ -927,12 +957,7 @@ async fn run_call(
|
||||
// would accumulate block_id=0 duplicates that never
|
||||
// decode. Codec2 packets still feed RaptorQ.
|
||||
if !pkt_is_opus {
|
||||
let _ = fec_dec.add_symbol(
|
||||
pkt_block,
|
||||
pkt_symbol,
|
||||
is_repair,
|
||||
&pkt.payload,
|
||||
);
|
||||
let _ = fec_dec.add_symbol(pkt_block, pkt_symbol, is_repair, &pkt.payload);
|
||||
}
|
||||
|
||||
// Source packets: decode directly
|
||||
@@ -952,7 +977,10 @@ async fn run_call(
|
||||
frame_duration_ms: 20,
|
||||
frames_per_block: 5,
|
||||
},
|
||||
other => QualityProfile { codec: other, ..QualityProfile::GOOD },
|
||||
other => QualityProfile {
|
||||
codec: other,
|
||||
..QualityProfile::GOOD
|
||||
},
|
||||
};
|
||||
info!(from = ?decoder.codec_id(), to = ?pkt.header.codec_id, "recv: switching decoder");
|
||||
let _ = decoder.set_profile(switch_profile);
|
||||
@@ -984,10 +1012,7 @@ async fn run_call(
|
||||
// Update DRED state from the current packet.
|
||||
match dred_decoder.parse_into(&mut dred_parse_scratch, &pkt.payload) {
|
||||
Ok(available) if available > 0 => {
|
||||
std::mem::swap(
|
||||
&mut dred_parse_scratch,
|
||||
&mut last_good_dred,
|
||||
);
|
||||
std::mem::swap(&mut dred_parse_scratch, &mut last_good_dred);
|
||||
last_good_dred_seq = Some(pkt.header.seq);
|
||||
}
|
||||
Ok(_) => {
|
||||
@@ -1006,8 +1031,7 @@ async fn run_call(
|
||||
let current_profile_frame_samples =
|
||||
(48_000 * profile.frame_duration_ms as i32) / 1000;
|
||||
let available = last_good_dred.samples_available();
|
||||
let pcm_slice_len =
|
||||
current_profile_frame_samples as usize;
|
||||
let pcm_slice_len = current_profile_frame_samples as usize;
|
||||
|
||||
for gap_idx in 0..gap {
|
||||
let missing_seq = expected.wrapping_add(gap_idx);
|
||||
@@ -1026,28 +1050,24 @@ async fn run_call(
|
||||
None => -1,
|
||||
};
|
||||
|
||||
let reconstructed = if offset_samples > 0
|
||||
&& offset_samples <= available
|
||||
{
|
||||
decoder
|
||||
.reconstruct_from_dred(
|
||||
&last_good_dred,
|
||||
offset_samples,
|
||||
&mut decode_buf[..pcm_slice_len],
|
||||
)
|
||||
.ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let reconstructed =
|
||||
if offset_samples > 0 && offset_samples <= available {
|
||||
decoder
|
||||
.reconstruct_from_dred(
|
||||
&last_good_dred,
|
||||
offset_samples,
|
||||
&mut decode_buf[..pcm_slice_len],
|
||||
)
|
||||
.ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
match reconstructed {
|
||||
Some(samples) => {
|
||||
playout_agc.process_frame(
|
||||
&mut decode_buf[..samples],
|
||||
);
|
||||
state
|
||||
.playout_ring
|
||||
.write(&decode_buf[..samples]);
|
||||
playout_agc
|
||||
.process_frame(&mut decode_buf[..samples]);
|
||||
state.playout_ring.write(&decode_buf[..samples]);
|
||||
dred_reconstructions += 1;
|
||||
frames_decoded += 1;
|
||||
}
|
||||
@@ -1144,7 +1164,10 @@ async fn run_call(
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
info!(frames_decoded, fec_recovered, "relay disconnected (stream ended)");
|
||||
info!(
|
||||
frames_decoded,
|
||||
fec_recovered, "relay disconnected (stream ended)"
|
||||
);
|
||||
break;
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -1162,7 +1185,10 @@ async fn run_call(
|
||||
}
|
||||
}
|
||||
}
|
||||
info!(frames_decoded, fec_recovered, recv_errors, "recv task ended");
|
||||
info!(
|
||||
frames_decoded,
|
||||
fec_recovered, recv_errors, "recv task ended"
|
||||
);
|
||||
};
|
||||
|
||||
// Stats task — polls path quality + quinn RTT every 500ms
|
||||
@@ -1195,7 +1221,10 @@ async fn run_call(
|
||||
let signal_task = async {
|
||||
loop {
|
||||
match transport_signal.recv_signal().await {
|
||||
Ok(Some(SignalMessage::RoomUpdate { count, participants })) => {
|
||||
Ok(Some(SignalMessage::RoomUpdate {
|
||||
count,
|
||||
participants,
|
||||
})) => {
|
||||
info!(count, "RoomUpdate received");
|
||||
let members: Vec<crate::stats::RoomMember> = participants
|
||||
.iter()
|
||||
@@ -1209,7 +1238,10 @@ async fn run_call(
|
||||
stats.room_participant_count = count;
|
||||
stats.room_participants = members;
|
||||
}
|
||||
Ok(Some(SignalMessage::QualityDirective { recommended_profile, reason })) => {
|
||||
Ok(Some(SignalMessage::QualityDirective {
|
||||
recommended_profile,
|
||||
reason,
|
||||
})) => {
|
||||
let idx = profile_to_index(&recommended_profile);
|
||||
info!(
|
||||
codec = ?recommended_profile.codec,
|
||||
@@ -1247,7 +1279,9 @@ async fn run_call(
|
||||
match tokio::time::timeout(
|
||||
std::time::Duration::from_millis(500),
|
||||
transport.connection().closed(),
|
||||
).await {
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => info!("QUIC connection closed cleanly"),
|
||||
Err(_) => info!("QUIC close timed out (relay may not have ack'd)"),
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
use std::panic;
|
||||
use std::sync::Once;
|
||||
|
||||
use jni::JNIEnv;
|
||||
use jni::objects::{JClass, JObject, JString};
|
||||
use jni::sys::{jboolean, jint, jlong, jstring};
|
||||
use jni::JNIEnv;
|
||||
use tracing::{error, info};
|
||||
use wzp_proto::QualityProfile;
|
||||
|
||||
@@ -26,19 +26,20 @@ const PROFILE_AUTO: jint = 7;
|
||||
|
||||
fn profile_from_int(value: jint) -> QualityProfile {
|
||||
match value {
|
||||
0 => QualityProfile::GOOD, // Opus 24k
|
||||
1 => QualityProfile::DEGRADED, // Opus 6k
|
||||
2 => QualityProfile::CATASTROPHIC, // Codec2 1.2k
|
||||
3 => QualityProfile { // Codec2 3.2k
|
||||
0 => QualityProfile::GOOD, // Opus 24k
|
||||
1 => QualityProfile::DEGRADED, // Opus 6k
|
||||
2 => QualityProfile::CATASTROPHIC, // Codec2 1.2k
|
||||
3 => QualityProfile {
|
||||
// Codec2 3.2k
|
||||
codec: wzp_proto::CodecId::Codec2_3200,
|
||||
fec_ratio: 0.5,
|
||||
frame_duration_ms: 20,
|
||||
frames_per_block: 5,
|
||||
},
|
||||
4 => QualityProfile::STUDIO_32K, // Opus 32k
|
||||
5 => QualityProfile::STUDIO_48K, // Opus 48k
|
||||
6 => QualityProfile::STUDIO_64K, // Opus 64k
|
||||
_ => QualityProfile::GOOD, // auto falls back to GOOD
|
||||
4 => QualityProfile::STUDIO_32K, // Opus 32k
|
||||
5 => QualityProfile::STUDIO_48K, // Opus 48k
|
||||
6 => QualityProfile::STUDIO_64K, // Opus 64k
|
||||
_ => QualityProfile::GOOD, // auto falls back to GOOD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,11 +102,26 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativeStartCall(
|
||||
profile_j: jint,
|
||||
) -> jint {
|
||||
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let relay_addr: String = env.get_string(&relay_addr_j).map(|s| s.into()).unwrap_or_default();
|
||||
let room: String = env.get_string(&room_j).map(|s| s.into()).unwrap_or_default();
|
||||
let seed_hex: String = env.get_string(&seed_hex_j).map(|s| s.into()).unwrap_or_default();
|
||||
let token: String = env.get_string(&token_j).map(|s| s.into()).unwrap_or_default();
|
||||
let alias: String = env.get_string(&alias_j).map(|s| s.into()).unwrap_or_default();
|
||||
let relay_addr: String = env
|
||||
.get_string(&relay_addr_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
let room: String = env
|
||||
.get_string(&room_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
let seed_hex: String = env
|
||||
.get_string(&seed_hex_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
let token: String = env
|
||||
.get_string(&token_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
let alias: String = env
|
||||
.get_string(&alias_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
|
||||
let h = unsafe { handle_ref(handle) };
|
||||
|
||||
@@ -128,7 +144,11 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativeStartCall(
|
||||
auto_profile: profile_j == PROFILE_AUTO,
|
||||
relay_addr,
|
||||
room,
|
||||
auth_token: if token.is_empty() { Vec::new() } else { token.into_bytes() },
|
||||
auth_token: if token.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
token.into_bytes()
|
||||
},
|
||||
identity_seed,
|
||||
alias: if alias.is_empty() { None } else { Some(alias) },
|
||||
};
|
||||
@@ -241,7 +261,8 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativeOnNetworkChang
|
||||
) {
|
||||
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let h = unsafe { handle_ref(handle) };
|
||||
h.engine.on_network_changed(network_type as u8, bandwidth_kbps as u32);
|
||||
h.engine
|
||||
.on_network_changed(network_type as u8, bandwidth_kbps as u32);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -307,13 +328,14 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativeWriteAudioDire
|
||||
) -> jint {
|
||||
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let h = unsafe { handle_ref(handle) };
|
||||
let ptr = env.get_direct_buffer_address(&buffer).unwrap_or(std::ptr::null_mut());
|
||||
let ptr = env
|
||||
.get_direct_buffer_address(&buffer)
|
||||
.unwrap_or(std::ptr::null_mut());
|
||||
if ptr.is_null() || sample_count <= 0 {
|
||||
return 0;
|
||||
}
|
||||
let samples = unsafe {
|
||||
std::slice::from_raw_parts(ptr as *const i16, sample_count as usize)
|
||||
};
|
||||
let samples =
|
||||
unsafe { std::slice::from_raw_parts(ptr as *const i16, sample_count as usize) };
|
||||
h.engine.write_audio(samples) as jint
|
||||
}));
|
||||
result.unwrap_or(0)
|
||||
@@ -332,13 +354,14 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativeReadAudioDirec
|
||||
) -> jint {
|
||||
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let h = unsafe { handle_ref(handle) };
|
||||
let ptr = env.get_direct_buffer_address(&buffer).unwrap_or(std::ptr::null_mut());
|
||||
let ptr = env
|
||||
.get_direct_buffer_address(&buffer)
|
||||
.unwrap_or(std::ptr::null_mut());
|
||||
if ptr.is_null() || max_samples <= 0 {
|
||||
return 0;
|
||||
}
|
||||
let samples = unsafe {
|
||||
std::slice::from_raw_parts_mut(ptr as *mut i16, max_samples as usize)
|
||||
};
|
||||
let samples =
|
||||
unsafe { std::slice::from_raw_parts_mut(ptr as *mut i16, max_samples as usize) };
|
||||
h.engine.read_audio(samples) as jint
|
||||
}));
|
||||
result.unwrap_or(0)
|
||||
@@ -367,7 +390,10 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativePingRelay<'a>(
|
||||
) -> jstring {
|
||||
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let h = unsafe { handle_ref(handle) };
|
||||
let relay: String = env.get_string(&relay_j).map(|s| s.into()).unwrap_or_default();
|
||||
let relay: String = env
|
||||
.get_string(&relay_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
match h.engine.ping_relay(&relay) {
|
||||
Ok(json) => Some(json),
|
||||
Err(_) => None,
|
||||
@@ -399,10 +425,22 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativeStartSignaling
|
||||
) -> jint {
|
||||
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let h = unsafe { handle_ref(handle) };
|
||||
let relay_addr: String = env.get_string(&relay_addr_j).map(|s| s.into()).unwrap_or_default();
|
||||
let seed_hex: String = env.get_string(&seed_hex_j).map(|s| s.into()).unwrap_or_default();
|
||||
let token: String = env.get_string(&token_j).map(|s| s.into()).unwrap_or_default();
|
||||
let alias: String = env.get_string(&alias_j).map(|s| s.into()).unwrap_or_default();
|
||||
let relay_addr: String = env
|
||||
.get_string(&relay_addr_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
let seed_hex: String = env
|
||||
.get_string(&seed_hex_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
let token: String = env
|
||||
.get_string(&token_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
let alias: String = env
|
||||
.get_string(&alias_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
|
||||
h.engine.start_signaling(
|
||||
&relay_addr,
|
||||
@@ -414,8 +452,14 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativeStartSignaling
|
||||
|
||||
match result {
|
||||
Ok(Ok(())) => 0,
|
||||
Ok(Err(e)) => { error!("start_signaling failed: {e}"); -1 }
|
||||
Err(_) => { error!("start_signaling panicked"); -1 }
|
||||
Ok(Err(e)) => {
|
||||
error!("start_signaling failed: {e}");
|
||||
-1
|
||||
}
|
||||
Err(_) => {
|
||||
error!("start_signaling panicked");
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,14 +474,23 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativePlaceCall<'a>(
|
||||
) -> jint {
|
||||
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let h = unsafe { handle_ref(handle) };
|
||||
let target: String = env.get_string(&target_fp_j).map(|s| s.into()).unwrap_or_default();
|
||||
let target: String = env
|
||||
.get_string(&target_fp_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
h.engine.place_call(&target)
|
||||
}));
|
||||
|
||||
match result {
|
||||
Ok(Ok(())) => 0,
|
||||
Ok(Err(e)) => { error!("place_call failed: {e}"); -1 }
|
||||
Err(_) => { error!("place_call panicked"); -1 }
|
||||
Ok(Err(e)) => {
|
||||
error!("place_call failed: {e}");
|
||||
-1
|
||||
}
|
||||
Err(_) => {
|
||||
error!("place_call panicked");
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,7 +506,10 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativeAnswerCall<'a>
|
||||
) -> jint {
|
||||
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let h = unsafe { handle_ref(handle) };
|
||||
let call_id: String = env.get_string(&call_id_j).map(|s| s.into()).unwrap_or_default();
|
||||
let call_id: String = env
|
||||
.get_string(&call_id_j)
|
||||
.map(|s| s.into())
|
||||
.unwrap_or_default();
|
||||
let accept_mode = match mode {
|
||||
0 => wzp_proto::CallAcceptMode::Reject,
|
||||
1 => wzp_proto::CallAcceptMode::AcceptTrusted,
|
||||
@@ -464,7 +520,13 @@ pub unsafe extern "system" fn Java_com_wzp_engine_WzpEngine_nativeAnswerCall<'a>
|
||||
|
||||
match result {
|
||||
Ok(Ok(())) => 0,
|
||||
Ok(Err(e)) => { error!("answer_call failed: {e}"); -1 }
|
||||
Err(_) => { error!("answer_call panicked"); -1 }
|
||||
Ok(Err(e)) => {
|
||||
error!("answer_call failed: {e}");
|
||||
-1
|
||||
}
|
||||
Err(_) => {
|
||||
error!("answer_call panicked");
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,6 @@ pub mod audio_android;
|
||||
pub mod audio_ring;
|
||||
pub mod commands;
|
||||
pub mod engine;
|
||||
pub mod jni_bridge;
|
||||
pub mod pipeline;
|
||||
pub mod stats;
|
||||
pub mod jni_bridge;
|
||||
|
||||
@@ -9,8 +9,8 @@ use wzp_codec::{AdaptiveDecoder, AdaptiveEncoder, AutoGainControl, EchoCanceller
|
||||
use wzp_fec::{RaptorQFecDecoder, RaptorQFecEncoder};
|
||||
use wzp_proto::jitter::{JitterBuffer, PlayoutResult};
|
||||
use wzp_proto::quality::AdaptiveQualityController;
|
||||
use wzp_proto::traits::{AudioDecoder, AudioEncoder, FecDecoder, FecEncoder};
|
||||
use wzp_proto::traits::QualityController;
|
||||
use wzp_proto::traits::{AudioDecoder, AudioEncoder, FecDecoder, FecEncoder};
|
||||
use wzp_proto::{MediaPacket, QualityProfile};
|
||||
|
||||
use crate::audio_android::FRAME_SAMPLES;
|
||||
@@ -58,14 +58,12 @@ pub struct Pipeline {
|
||||
impl Pipeline {
|
||||
/// Create a new pipeline configured for the given quality profile.
|
||||
pub fn new(profile: QualityProfile) -> Result<Self, anyhow::Error> {
|
||||
let encoder = AdaptiveEncoder::new(profile)
|
||||
.map_err(|e| anyhow::anyhow!("encoder init: {e}"))?;
|
||||
let decoder = AdaptiveDecoder::new(profile)
|
||||
.map_err(|e| anyhow::anyhow!("decoder init: {e}"))?;
|
||||
let fec_encoder =
|
||||
RaptorQFecEncoder::with_defaults(profile.frames_per_block as usize);
|
||||
let fec_decoder =
|
||||
RaptorQFecDecoder::with_defaults(profile.frames_per_block as usize);
|
||||
let encoder =
|
||||
AdaptiveEncoder::new(profile).map_err(|e| anyhow::anyhow!("encoder init: {e}"))?;
|
||||
let decoder =
|
||||
AdaptiveDecoder::new(profile).map_err(|e| anyhow::anyhow!("decoder init: {e}"))?;
|
||||
let fec_encoder = RaptorQFecEncoder::with_defaults(profile.frames_per_block as usize);
|
||||
let fec_decoder = RaptorQFecDecoder::with_defaults(profile.frames_per_block as usize);
|
||||
let jitter_buffer = JitterBuffer::new(10, 250, 3);
|
||||
let quality_ctrl = AdaptiveQualityController::new();
|
||||
|
||||
@@ -211,10 +209,7 @@ impl Pipeline {
|
||||
///
|
||||
/// Returns a new profile if a tier transition occurred.
|
||||
#[allow(unused)]
|
||||
pub fn observe_quality(
|
||||
&mut self,
|
||||
report: &wzp_proto::QualityReport,
|
||||
) -> Option<QualityProfile> {
|
||||
pub fn observe_quality(&mut self, report: &wzp_proto::QualityReport) -> Option<QualityProfile> {
|
||||
let new_profile = self.quality_ctrl.observe(report);
|
||||
if let Some(ref profile) = new_profile {
|
||||
if let Err(e) = self.encoder.set_profile(*profile) {
|
||||
|
||||
Reference in New Issue
Block a user