use mediaway_common::CodecKind;
use mediaway_decoder::capability::{DecodeSupport, DecodeUnavailable};
use mediaway_decoder::{DecodeError, VideoDecoder, VideoDecoderConfig};
use mediaway_device::audio::{AudioCapture, AudioCaptureConfig};
use mediaway_device::desktop::{DesktopVideoCapture, DesktopVideoCaptureConfig};
use mediaway_device::{CaptureError, DeviceKind, PermissionState, Support};
use mediaway_encoder::auto::AutoVideoEncodeConfig;
use mediaway_encoder::capability::EncoderCapability;
use mediaway_encoder::{EncodeError, VideoEncoder};
pub struct AutoEncoder;
impl AutoEncoder {
pub fn open(config: &AutoVideoEncodeConfig) -> Result<Box<dyn VideoEncoder>, EncodeError> {
#[cfg(windows)]
{
use mediaway_encoder::windows::auto::AutoVideoEncoder;
let enc = AutoVideoEncoder::open(config)?;
Ok(Box::new(enc))
}
#[cfg(target_os = "linux")]
{
use mediaway_encoder::VideoInputPreference;
use mediaway_encoder::linux::LinuxVideoEncoder;
let low_level =
config.to_low_level(VideoInputPreference::CpuUploadOk, config.gpu_device);
let enc = LinuxVideoEncoder::open(&low_level)?;
Ok(Box::new(enc))
}
#[cfg(not(any(windows, target_os = "linux")))]
{
let _ = config;
Err(EncodeError::NoBackend)
}
}
}
#[must_use]
#[allow(
clippy::missing_const_for_fn,
reason = "the Windows branch calls a non-const backend probe; only the other-platforms \
branch (compiled alone on non-Windows) is trivially const-eligible"
)]
pub fn encoder_support(codec: CodecKind) -> Vec<EncoderCapability> {
#[cfg(windows)]
{
if codec == CodecKind::Opus {
use mediaway_common::{Rational, SampleFormat};
use mediaway_encoder::auto::{Backend, EncodePathClass};
use mediaway_encoder::capability::{EncodeSupport, EncodeUnavailable};
use mediaway_encoder::{AudioEncoderConfig, EncodeError, SwOpusAudioEncoder};
let cfg = AudioEncoderConfig {
codec,
sample_rate: 48_000,
channels: 2,
sample_format: SampleFormat::F32,
time_base: Rational::new(1, 50),
bitrate_bps: 0,
};
let support = match SwOpusAudioEncoder::open(&cfg) {
Ok(_) => EncodeSupport::Supported(EncodePathClass::Software),
Err(EncodeError::Backend) => {
EncodeSupport::Unavailable(EncodeUnavailable::NoDevice)
}
Err(_) => EncodeSupport::Unavailable(EncodeUnavailable::NotImplemented),
};
return vec![EncoderCapability::new(Backend::Software, support)];
}
mediaway_encoder::windows::auto::support(codec)
}
#[cfg(not(windows))]
{
let _ = codec;
Vec::new()
}
}
pub struct AutoDecoder;
impl AutoDecoder {
pub fn open(config: &VideoDecoderConfig) -> Result<Box<dyn VideoDecoder>, DecodeError> {
#[cfg(windows)]
{
use mediaway_decoder::windows::WindowsVideoDecoder;
let dec = WindowsVideoDecoder::open(config)?;
Ok(Box::new(dec))
}
#[cfg(target_os = "linux")]
{
use mediaway_decoder::linux::LinuxVideoDecoder;
let dec = LinuxVideoDecoder::open(config)?;
Ok(Box::new(dec))
}
#[cfg(not(any(windows, target_os = "linux")))]
{
let _ = config;
Err(DecodeError::NoBackend)
}
}
}
#[must_use]
pub fn decoder_support(codec: CodecKind) -> DecodeSupport {
#[cfg(windows)]
{
use mediaway_decoder::windows::{OpusDecoderConfig, WindowsVideoDecoder, WmfOpusDecoder};
if codec == CodecKind::Opus {
return match WmfOpusDecoder::open(&OpusDecoderConfig::new(48_000, 2)) {
Ok(_) => DecodeSupport::Supported,
Err(_) => DecodeSupport::Unavailable(DecodeUnavailable::NoDevice),
};
}
let cfg = VideoDecoderConfig {
codec,
output: mediaway_decoder::VideoOutputPreference::CpuFramesOk,
..VideoDecoderConfig::h264(64, 64, mediaway_common::Rational::new(1, 30))
};
match WindowsVideoDecoder::open(&cfg) {
Ok(_) => DecodeSupport::Supported,
Err(DecodeError::Unsupported) => {
DecodeSupport::Unavailable(DecodeUnavailable::NotImplemented)
}
Err(_) => DecodeSupport::Unavailable(DecodeUnavailable::NoDevice),
}
}
#[cfg(target_os = "linux")]
{
use mediaway_decoder::linux::LinuxVideoDecoder;
let cfg = VideoDecoderConfig {
codec,
output: mediaway_decoder::VideoOutputPreference::CpuFramesOk,
..VideoDecoderConfig::h264(64, 64, mediaway_common::Rational::new(1, 30))
};
match LinuxVideoDecoder::open(&cfg) {
Ok(_) => DecodeSupport::Supported,
Err(DecodeError::Unsupported) => {
DecodeSupport::Unavailable(DecodeUnavailable::NotImplemented)
}
Err(_) => DecodeSupport::Unavailable(DecodeUnavailable::NoDevice),
}
}
#[cfg(not(any(windows, target_os = "linux")))]
{
let _ = codec;
DecodeSupport::Unavailable(DecodeUnavailable::NotImplemented)
}
}
pub struct ScreenCapture;
impl ScreenCapture {
pub fn open(
config: &DesktopVideoCaptureConfig,
) -> Result<Box<dyn DesktopVideoCapture>, CaptureError> {
#[cfg(windows)]
{
use mediaway_device::windows_desktop::WindowsScreenCapture;
let cap = WindowsScreenCapture::open(config)?;
Ok(Box::new(cap))
}
#[cfg(target_os = "linux")]
{
use mediaway_device::linux::LinuxScreenCapture;
let cap = LinuxScreenCapture::open(config)?;
Ok(Box::new(cap))
}
#[cfg(not(any(windows, target_os = "linux")))]
{
let _ = config;
Err(CaptureError::NoBackend)
}
}
}
pub struct Microphone;
impl Microphone {
pub fn open(config: &AudioCaptureConfig) -> Result<Box<dyn AudioCapture>, CaptureError> {
#[cfg(windows)]
{
use mediaway_device::windows_audio::WindowsWasapiCapture;
let cap = WindowsWasapiCapture::open_microphone(config)?;
Ok(Box::new(cap))
}
#[cfg(not(windows))]
{
let _ = config;
Err(CaptureError::NoBackend)
}
}
}
#[must_use]
pub fn device_support(kind: DeviceKind) -> Support {
#[cfg(windows)]
{
mediaway_device::windows::support(kind)
}
#[cfg(target_os = "linux")]
{
mediaway_device::linux::support(kind)
}
#[cfg(not(any(windows, target_os = "linux")))]
{
let _ = kind;
Support::Unavailable(mediaway_device::Unavailable::NotImplemented)
}
}
pub fn request_device_permission(kind: DeviceKind) -> Result<PermissionState, CaptureError> {
#[cfg(windows)]
{
mediaway_device::windows::request_permission(kind)
}
#[cfg(target_os = "linux")]
{
mediaway_device::linux::request_permission(kind)
}
#[cfg(not(any(windows, target_os = "linux")))]
{
let _ = kind;
Ok(PermissionState::NotSupported)
}
}