use crate::proxy::proxy_call::media_peer::MediaPeer;
use audio_codec::{CodecType, Decoder};
use std::sync::Arc;
pub struct MixerInput {
pub id: String,
peer: Arc<dyn MediaPeer>,
codec: CodecType,
decoder: Option<Box<dyn Decoder + Send>>,
track_id: Option<String>,
}
impl MixerInput {
pub fn new(id: String, peer: Arc<dyn MediaPeer>, codec: CodecType) -> Self {
Self {
id,
peer,
codec,
decoder: None,
track_id: None,
}
}
pub fn codec(&self) -> CodecType {
self.codec
}
pub fn with_track(mut self, track_id: String) -> Self {
self.track_id = Some(track_id);
self
}
fn ensure_decoder(&mut self) {
if self.decoder.is_none() {
self.decoder = Some(audio_codec::create_decoder(self.codec));
}
}
pub async fn read_frame(&mut self) -> Option<DecodedFrame> {
self.ensure_decoder();
let tracks = self.peer.get_tracks().await;
if tracks.is_empty() {
return None;
}
let track = if let Some(ref track_id) = self.track_id {
tracks
.iter()
.find(|t| {
let guard = t.blocking_lock();
guard.id() == track_id
})
.cloned()
} else {
tracks.first().cloned()
}?;
let _track_guard = track.lock().await;
None
}
pub fn decode(&mut self, encoded_data: &[u8]) -> Option<Vec<i16>> {
self.ensure_decoder();
self.decoder
.as_mut()
.map(|decoder| decoder.decode(encoded_data))
}
pub fn sample_rate(&self) -> u32 {
self.decoder
.as_ref()
.map(|d| d.sample_rate())
.unwrap_or(8000)
}
pub fn create_decoder(codec: CodecType) -> Box<dyn Decoder + Send> {
audio_codec::create_decoder(codec)
}
}
#[derive(Debug, Clone)]
pub struct DecodedFrame {
pub input_id: String,
pub samples: Vec<i16>,
pub sample_rate: u32,
pub timestamp: u64,
pub sequence: Option<u16>,
}
impl DecodedFrame {
pub fn new(input_id: String, samples: Vec<i16>, sample_rate: u32, timestamp: u64) -> Self {
Self {
input_id,
samples,
sample_rate,
timestamp,
sequence: None,
}
}
pub fn with_sequence(mut self, seq: u16) -> Self {
self.sequence = Some(seq);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::proxy::proxy_call::test_util::tests::MockMediaPeer;
#[test]
fn test_mixer_input_creation() {
let peer = Arc::new(MockMediaPeer::new());
let input = MixerInput::new("input-1".to_string(), peer, CodecType::PCMU);
assert_eq!(input.id, "input-1");
assert_eq!(input.codec(), CodecType::PCMU);
}
#[test]
fn test_mixer_input_with_track() {
let peer = Arc::new(MockMediaPeer::new());
let input = MixerInput::new("input-1".to_string(), peer, CodecType::PCMU)
.with_track("audio-0".to_string());
assert_eq!(input.track_id, Some("audio-0".to_string()));
}
#[test]
fn test_mixer_input_ensure_decoder() {
let peer = Arc::new(MockMediaPeer::new());
let mut input = MixerInput::new("input-1".to_string(), peer, CodecType::PCMU);
assert!(input.decoder.is_none());
input.ensure_decoder();
assert!(input.decoder.is_some());
}
#[test]
fn test_mixer_input_ensure_decoder_opus() {
let peer = Arc::new(MockMediaPeer::new());
let mut input = MixerInput::new("input-1".to_string(), peer, CodecType::Opus);
input.ensure_decoder();
assert!(input.decoder.is_some());
}
#[test]
fn test_mixer_input_sample_rate() {
let peer = Arc::new(MockMediaPeer::new());
let mut input = MixerInput::new("input-1".to_string(), peer, CodecType::PCMU);
assert_eq!(input.sample_rate(), 8000);
input.ensure_decoder();
assert_eq!(input.sample_rate(), 8000);
}
#[test]
fn test_decoded_frame() {
let frame = DecodedFrame::new("test-input".to_string(), vec![0i16; 160], 8000, 0);
assert_eq!(frame.input_id, "test-input");
assert_eq!(frame.samples.len(), 160);
assert_eq!(frame.sample_rate, 8000);
}
#[test]
fn test_decoded_frame_with_sequence() {
let frame = DecodedFrame::new("test-input".to_string(), vec![1i16, 2i16, 3i16], 8000, 100)
.with_sequence(42);
assert_eq!(frame.sequence, Some(42));
assert_eq!(frame.timestamp, 100);
}
}