feat: codec2 support — adaptive encoder/decoder, per-packet codec switch
Some checks failed
Mirror to GitHub / mirror (push) Failing after 33s
Build Release Binaries / build-amd64 (push) Failing after 3m57s

Android engine:
- Use wzp_codec::create_encoder/create_decoder (factory) instead of
  hardcoded OpusEncoder/OpusDecoder
- Recv path: auto-switch decoder based on incoming packet's codec_id
- Supports mixed-codec rooms (one client Opus, another Codec2)

Desktop client already uses factory functions — no changes needed.

Codec selection via QualityProfile:
- GOOD: Opus 24kbps
- DEGRADED: Opus 6kbps
- CATASTROPHIC: Codec2 1200bps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-04-07 10:34:14 +04:00
parent 1e40dec468
commit 00fa109f07

View File

@@ -16,8 +16,6 @@ use std::time::Instant;
use bytes::Bytes;
use tracing::{error, info, warn};
use wzp_codec::agc::AutoGainControl;
use wzp_codec::opus_dec::OpusDecoder;
use wzp_codec::opus_enc::OpusEncoder;
use wzp_crypto::{KeyExchange, WarzoneKeyExchange};
use wzp_fec::{RaptorQFecDecoder, RaptorQFecEncoder};
use wzp_proto::{
@@ -333,11 +331,9 @@ async fn run_call(
stats.state = CallState::Active;
}
// Initialize Opus codec
let mut encoder =
OpusEncoder::new(profile).map_err(|e| anyhow::anyhow!("opus encoder init: {e}"))?;
let mut decoder =
OpusDecoder::new(profile).map_err(|e| anyhow::anyhow!("opus decoder init: {e}"))?;
// Initialize codec (Opus or Codec2 based on profile)
let mut encoder = wzp_codec::create_encoder(profile);
let mut decoder = wzp_codec::create_decoder(profile);
// Initialize FEC encoder/decoder
let mut fec_enc = wzp_fec::create_encoder(&profile);
@@ -598,6 +594,14 @@ async fn run_call(
// Source packets: decode directly
if !is_repair {
// Switch decoder to match incoming codec if different
if pkt.header.codec_id != decoder.codec_id() {
let switch_profile = QualityProfile {
codec: pkt.header.codec_id,
..profile
};
let _ = decoder.set_profile(switch_profile);
}
match decoder.decode(&pkt.payload, &mut decode_buf) {
Ok(samples) => {
playout_agc.process_frame(&mut decode_buf[..samples]);