rustpbx 0.3.18

A SIP PBX implementation in Rust
Documentation
use audio_codec::{CodecType, Decoder, Encoder, Resampler, create_decoder, create_encoder};
use rand::RngExt;
use rustrtc::media::AudioFrame;

pub struct Transcoder {
    decoder: Box<dyn Decoder>,
    encoder: Box<dyn Encoder>,
    source: CodecType,
    target: CodecType,
    resampler: Option<Resampler>,
    first_input_timestamp: Option<u32>,
    first_input_sequence: Option<u16>,
    first_output_timestamp: u32,
    first_output_sequence: u16,
}

impl Transcoder {
    pub fn new(source: CodecType, target: CodecType) -> Self {
        let decoder = create_decoder(source);
        let encoder = create_encoder(target);

        let source_sample_rate = decoder.sample_rate();
        let target_sample_rate = encoder.sample_rate();
        let resampler = if source_sample_rate != target_sample_rate {
            Some(Resampler::new(
                source_sample_rate as usize,
                target_sample_rate as usize,
            ))
        } else {
            None
        };

        let mut rng = rand::rng();
        let first_output_timestamp: u32 = rng.random();
        let first_output_sequence: u16 = rng.random();

        Self {
            decoder,
            encoder,
            source,
            target,
            resampler,
            first_input_timestamp: None,
            first_input_sequence: None,
            first_output_timestamp,
            first_output_sequence,
        }
    }

    pub fn transcode(&mut self, frame: &AudioFrame) -> AudioFrame {
        let mut pcmbuf = self.decoder.decode(&frame.data);
        if let Some(resampler) = &mut self.resampler {
            pcmbuf = resampler.resample(&pcmbuf);
        }

        let encoded_data = self.encoder.encode(&pcmbuf);

        let (rtp_timestamp, output_sequence) = self.new_timestamp(frame);

        AudioFrame {
            rtp_timestamp,
            clock_rate: self.target.clock_rate(),
            data: encoded_data.into(),
            sequence_number: Some(output_sequence),
            payload_type: Some(self.target.payload_type()),
            marker: frame.marker,
            raw_packet: None,
            source_addr: frame.source_addr,
        }
    }

    pub fn update_dtmf_timestamp(&mut self, frame: &mut AudioFrame) {
        let (rtp_timestamp, output_sequence) = self.new_timestamp(frame);
        frame.rtp_timestamp = rtp_timestamp;
        frame.sequence_number = Some(output_sequence);
    }

    fn new_timestamp(&mut self, frame: &AudioFrame) -> (u32, u16) {
        if self.first_input_timestamp.is_none() {
            self.first_input_timestamp = Some(frame.rtp_timestamp);
            self.first_input_sequence = frame.sequence_number;
        }

        let source_clock_rate = self.source.clock_rate();
        let target_clock_rate = self.target.clock_rate();

        let first_input_ts = self.first_input_timestamp.unwrap_or_default();
        let input_ts_delta = frame.rtp_timestamp.wrapping_sub(first_input_ts);
        let output_ts_delta =
            (input_ts_delta as u64 * target_clock_rate as u64 / source_clock_rate as u64) as u32;
        let output_timestamp = self.first_output_timestamp.wrapping_add(output_ts_delta);

        let first_input_seq = self.first_input_sequence.unwrap_or_default();
        let input_seq = frame.sequence_number.unwrap_or_default();
        let seq_delta = input_seq.wrapping_sub(first_input_seq);
        let output_sequence = self.first_output_sequence.wrapping_add(seq_delta);

        (output_timestamp, output_sequence)
    }
}