#![forbid(unsafe_code)]
use crate::error::EncodeError;
use mediaway_common::{
CodecKind, GpuDeviceHandle, Packet, PixelFormat, Rational, StreamInfo, VideoFrame,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum VideoInputPreference {
#[default]
ZeroCopyGpu,
CpuUploadOk,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VideoEncoderConfig {
pub codec: CodecKind,
pub width: u32,
pub height: u32,
pub time_base: Rational,
pub bitrate_bps: u32,
pub pixel_format: PixelFormat,
pub input: VideoInputPreference,
pub gpu_device: Option<GpuDeviceHandle>,
}
impl VideoEncoderConfig {
#[must_use]
pub const fn h264(width: u32, height: u32, time_base: Rational) -> Self {
Self {
codec: CodecKind::H264,
width,
height,
time_base,
bitrate_bps: 0,
pixel_format: PixelFormat::Nv12,
input: VideoInputPreference::ZeroCopyGpu,
gpu_device: None,
}
}
#[must_use]
pub const fn hevc(width: u32, height: u32, time_base: Rational) -> Self {
Self {
codec: CodecKind::Hevc,
width,
height,
time_base,
bitrate_bps: 0,
pixel_format: PixelFormat::Nv12,
input: VideoInputPreference::ZeroCopyGpu,
gpu_device: None,
}
}
#[must_use]
pub const fn av1(width: u32, height: u32, time_base: Rational) -> Self {
Self {
codec: CodecKind::Av1,
width,
height,
time_base,
bitrate_bps: 0,
pixel_format: PixelFormat::Nv12,
input: VideoInputPreference::ZeroCopyGpu,
gpu_device: None,
}
}
#[must_use]
pub const fn vp9(width: u32, height: u32, time_base: Rational) -> Self {
Self {
codec: CodecKind::Vp9,
width,
height,
time_base,
bitrate_bps: 0,
pixel_format: PixelFormat::Nv12,
input: VideoInputPreference::ZeroCopyGpu,
gpu_device: None,
}
}
}
pub trait VideoEncoder {
fn stream_info(&self) -> &StreamInfo;
fn push_frame(&mut self, frame: &VideoFrame) -> Result<(), EncodeError>;
fn poll_packet(&mut self) -> Result<Option<Packet>, EncodeError>;
fn flush(&mut self) -> Result<(), EncodeError>;
}
impl<T: VideoEncoder + ?Sized> VideoEncoder for Box<T> {
fn stream_info(&self) -> &StreamInfo {
(**self).stream_info()
}
fn push_frame(&mut self, frame: &VideoFrame) -> Result<(), EncodeError> {
(**self).push_frame(frame)
}
fn poll_packet(&mut self) -> Result<Option<Packet>, EncodeError> {
(**self).poll_packet()
}
fn flush(&mut self) -> Result<(), EncodeError> {
(**self).flush()
}
}