#![forbid(unsafe_code)]
use mediaway_common::{AudioFrame, CodecKind, Packet, SampleFormat, StreamInfo};
use mediaway_sw::opus::config::{OpusApplication, OpusEncoderConfig};
use mediaway_sw::opus::error::OpusError;
use crate::AudioEncoder;
use crate::error::EncodeError;
#[derive(Debug)]
pub struct SwOpusAudioEncoder {
inner: mediaway_sw::opus::encoder::OpusEncoder,
}
impl SwOpusAudioEncoder {
pub fn open(config: &crate::audio::AudioEncoderConfig) -> Result<Self, EncodeError> {
if config.codec != CodecKind::Opus {
return Err(EncodeError::Unsupported);
}
if config.sample_format != SampleFormat::F32 {
return Err(EncodeError::Unsupported);
}
let sw_config = OpusEncoderConfig {
sample_rate: config.sample_rate,
channels: config.channels,
application: OpusApplication::Audio,
time_base: config.time_base,
bitrate_bps: (config.bitrate_bps > 0).then_some(config.bitrate_bps),
inband_fec: false,
packet_loss_percent: 0,
};
match mediaway_sw::opus::encoder::OpusEncoder::open(&sw_config) {
Ok(inner) => Ok(Self { inner }),
Err(e) => Err(Self::map_err(&e)),
}
}
const fn map_err(e: &OpusError) -> EncodeError {
match e {
OpusError::UnsupportedSampleFormat
| OpusError::ConfigMismatch
| OpusError::FrameSizeMismatch { .. }
| OpusError::InvalidFrameDuration { .. } => EncodeError::InvalidInput,
OpusError::Closed => EncodeError::Closed,
_ => EncodeError::Backend, }
}
}
impl AudioEncoder for SwOpusAudioEncoder {
fn stream_info(&self) -> &StreamInfo {
self.inner.stream_info()
}
fn push_frame(&mut self, frame: &AudioFrame) -> Result<(), EncodeError> {
self.inner.push_frame(frame).map_err(|e| Self::map_err(&e))
}
fn poll_packet(&mut self) -> Result<Option<Packet>, EncodeError> {
self.inner.poll_packet().map_err(|e| Self::map_err(&e))
}
fn flush(&mut self) -> Result<(), EncodeError> {
self.inner.flush().map_err(|e| Self::map_err(&e))
}
}