use std::fmt;
use std::time::Duration;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time(Duration);
impl Time {
pub const fn zero() -> Self {
Self(Duration::from_secs(0))
}
pub fn from_seconds(seconds: u64) -> Self {
Self(Duration::from_secs(seconds))
}
pub fn from_seconds_f64(seconds: f64) -> Self {
let nanos = (seconds * 1_000_000_000.0).round();
let secs = (nanos / 1_000_000_000.0).trunc() as u64;
let sub_nanos = (nanos % 1_000_000_000.0) as u32;
Self(Duration::new(secs, sub_nanos))
}
pub const fn from_duration(duration: Duration) -> Self {
Self(duration)
}
pub const fn as_duration(self) -> Duration {
self.0
}
pub fn to_ffmpeg_timestamp(self) -> String {
let total_secs = self.0.as_secs();
let hours = total_secs / 3600;
let minutes = (total_secs % 3600) / 60;
let seconds = total_secs % 60;
let millis = self.0.subsec_millis();
format!("{hours:02}:{minutes:02}:{seconds:02}.{millis:03}")
}
}
impl From<Duration> for Time {
fn from(duration: Duration) -> Self {
Self(duration)
}
}
impl From<Time> for Duration {
fn from(value: Time) -> Self {
value.0
}
}
impl fmt::Display for Time {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_ffmpeg_timestamp())
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum CodecType {
H264,
Hevc,
Vp9,
Av1,
Aac,
Mp3,
Opus,
PcmS16Le,
Copy,
Other(String),
}
impl CodecType {
pub fn from_name(name: &str) -> Self {
match name.to_lowercase().as_str() {
"h264" | "libx264" => CodecType::H264,
"hevc" | "h265" | "libx265" => CodecType::Hevc,
"vp9" => CodecType::Vp9,
"av1" => CodecType::Av1,
"aac" => CodecType::Aac,
"mp3" => CodecType::Mp3,
"opus" => CodecType::Opus,
"pcm_s16le" => CodecType::PcmS16Le,
"copy" => CodecType::Copy,
other => CodecType::Other(other.to_string()),
}
}
pub fn as_str(&self) -> &str {
match self {
CodecType::H264 => "libx264",
CodecType::Hevc => "libx265",
CodecType::Vp9 => "libvpx-vp9",
CodecType::Av1 => "libaom-av1",
CodecType::Aac => "aac",
CodecType::Mp3 => "libmp3lame",
CodecType::Opus => "libopus",
CodecType::PcmS16Le => "pcm_s16le",
CodecType::Copy => "copy",
CodecType::Other(name) => name,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum StreamType {
Video,
Audio,
Subtitle,
Data,
}
#[derive(Clone, Debug)]
pub struct FormatInfo {
pub format_name: Option<String>,
pub format_long_name: Option<String>,
pub duration: Option<Duration>,
pub bit_rate: Option<u64>,
pub size: Option<u64>,
}
impl FormatInfo {
pub fn new(
format_name: Option<String>,
format_long_name: Option<String>,
duration: Option<Duration>,
bit_rate: Option<u64>,
size: Option<u64>,
) -> Self {
Self {
format_name,
format_long_name,
duration,
bit_rate,
size,
}
}
}
#[derive(Clone, Debug)]
pub enum StreamInfo {
Video(VideoStreamInfo),
Audio(AudioStreamInfo),
Subtitle(SubtitleStreamInfo),
Data(DataStreamInfo),
}
#[derive(Clone, Debug)]
pub struct VideoStreamInfo {
pub codec: CodecType,
pub width: Option<u32>,
pub height: Option<u32>,
pub bit_rate: Option<u64>,
pub frame_rate: Option<f64>,
}
#[derive(Clone, Debug)]
pub struct AudioStreamInfo {
pub codec: CodecType,
pub channels: Option<u32>,
pub sample_rate: Option<u32>,
pub bit_rate: Option<u64>,
}
#[derive(Clone, Debug)]
pub struct SubtitleStreamInfo {
pub codec: CodecType,
pub language: Option<String>,
}
#[derive(Clone, Debug)]
pub struct DataStreamInfo {
pub codec: CodecType,
pub description: Option<String>,
}
#[derive(Clone, Debug)]
pub struct ProbeResult {
format: FormatInfo,
streams: Vec<StreamInfo>,
}
impl ProbeResult {
pub fn new(format: FormatInfo, streams: Vec<StreamInfo>) -> Self {
Self { format, streams }
}
pub fn format(&self) -> &FormatInfo {
&self.format
}
pub fn streams(&self) -> &[StreamInfo] {
&self.streams
}
pub fn first_video(&self) -> Option<&VideoStreamInfo> {
self.streams.iter().find_map(|stream| match stream {
StreamInfo::Video(info) => Some(info),
_ => None,
})
}
pub fn first_audio(&self) -> Option<&AudioStreamInfo> {
self.streams.iter().find_map(|stream| match stream {
StreamInfo::Audio(info) => Some(info),
_ => None,
})
}
pub fn duration(&self) -> Option<Duration> {
self.format.duration
}
}