use std::sync::Arc;
use bytes::Bytes;
use tokio::sync::RwLock;
use crate::api::common::frame::MediaFrame;
use crate::api::common::error::MediaTransportError;
use crate::api::common::frame::MediaFrameType;
use crate::packet::RtpPacket;
pub async fn mix_audio_frames(
frames: Vec<MediaFrame>,
output_payload_type: u8,
output_timestamp: u32,
output_ssrc: u32,
) -> Result<MediaFrame, MediaTransportError> {
if frames.is_empty() {
return Err(MediaTransportError::InvalidInput("No frames to mix".to_string()));
}
let first_frame = &frames[0];
let mixed_frame = MediaFrame {
frame_type: MediaFrameType::Audio,
data: first_frame.data.clone(),
timestamp: output_timestamp,
sequence: first_frame.sequence, marker: first_frame.marker,
payload_type: output_payload_type,
ssrc: output_ssrc,
csrcs: frames.iter().map(|f| f.ssrc).collect(), };
Ok(mixed_frame)
}
pub async fn mix_active_speakers(
frames: Vec<(String, MediaFrame)>,
max_speakers: usize,
output_payload_type: u8,
output_timestamp: u32,
output_ssrc: u32,
) -> Result<MediaFrame, MediaTransportError> {
if frames.is_empty() {
return Err(MediaTransportError::InvalidInput("No frames to mix".to_string()));
}
let audio_frames = frames
.into_iter()
.filter(|(_, frame)| frame.frame_type == MediaFrameType::Audio)
.collect::<Vec<_>>();
if audio_frames.is_empty() {
return Err(MediaTransportError::InvalidInput("No audio frames to mix".to_string()));
}
let frames_to_mix = audio_frames
.into_iter()
.take(max_speakers)
.map(|(_, frame)| frame)
.collect::<Vec<_>>();
mix_audio_frames(frames_to_mix, output_payload_type, output_timestamp, output_ssrc).await
}
pub fn calculate_audio_level(frame: &MediaFrame) -> u8 {
if frame.data.is_empty() {
return 0;
}
let sum: u32 = frame.data.iter().map(|&b| b as u32).sum();
let avg = sum / frame.data.len() as u32;
let level = (avg * 127 / 255) as u8;
level
}
pub fn detect_voice_activity(frame: &MediaFrame, threshold: u8) -> (bool, u8) {
let level = calculate_audio_level(frame);
let voice_active = level > threshold;
(voice_active, level)
}