Skip to main content

ffmpeg_pipeline/
types.rs

1use std::{
2    collections::HashMap,
3    fmt::{Display, Formatter, Result as fmtResult},
4    time::Duration,
5};
6
7use ffmpeg_next::format::Pixel;
8use log::warn;
9use serde::{Deserialize, Serialize};
10
11pub use ffmpeg_next::{
12    codec::Id as CodecId,
13    decoder::{Audio as AudioDecoder, Video as VideoDecoder},
14    encoder::{Audio as AudioEncoder, Video as VideoEncoder},
15    format::{
16        context::{Input, Output},
17        sample::Type as SampleType,
18        Pixel as VideoPixel, Sample,
19    },
20    media::Type as MediaType,
21    util::frame::{audio::Audio as AudioFrame, video::Video as VideoFrame},
22    ChannelLayout, Rational, Stream,
23};
24
25#[derive(Default, Clone, Copy)]
26pub enum FrameCalculation {
27    #[default]
28    Skip,
29    Fast,
30    Full,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub enum StreamFormat {
35    AV1,
36    H264,
37    HEVC,
38    Other(String),
39}
40
41impl Default for StreamFormat {
42    fn default() -> Self {
43        Self::Other("Unknown".into())
44    }
45}
46
47impl Display for StreamFormat {
48    fn fmt(&self, f: &mut Formatter<'_>) -> fmtResult {
49        let format = match self {
50            Self::AV1 => "ivf",
51            Self::H264 => "h264",
52            Self::HEVC => "hevc",
53            Self::Other(fmt) => {
54                warn!("unknown stream format: {}, get rawvideo", fmt);
55                "rawvideo"
56            }
57        };
58        f.write_str(format)
59    }
60}
61
62pub enum StreamDecoder {
63    Audio(AudioDecoder),
64    Video(VideoDecoder),
65}
66
67pub enum StreamEncoder {
68    Audio(AudioEncoder),
69    Video(VideoEncoder),
70}
71
72pub enum StreamFrame {
73    Audio(AudioFrame),
74    Video(VideoFrame),
75    Eof,
76}
77
78impl Display for StreamFrame {
79    fn fmt(&self, f: &mut Formatter<'_>) -> fmtResult {
80        f.write_str(match self {
81            StreamFrame::Audio(_) => "Audio",
82            StreamFrame::Video(_) => "Video",
83            StreamFrame::Eof => "Eof",
84        })
85    }
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct FrameSize {
90    pub width: isize,
91    pub height: isize,
92}
93
94impl FrameSize {
95    pub fn new() -> Self {
96        FrameSize {
97            width: 0,
98            height: 0,
99        }
100    }
101    pub fn is_empty(&self) -> bool {
102        self.width == 0 || self.height == 0
103    }
104    pub fn width<I: Into<isize>>(mut self, width: I) -> Self {
105        self.width = width.into();
106        self
107    }
108    pub fn height<I: Into<isize>>(mut self, height: I) -> Self {
109        self.height = height.into();
110        self
111    }
112}
113
114impl Default for FrameSize {
115    fn default() -> Self {
116        FrameSize::new()
117    }
118}
119
120impl Display for FrameSize {
121    fn fmt(&self, f: &mut Formatter<'_>) -> fmtResult {
122        write!(f, "{}x{}", self.width, self.height)
123    }
124}
125
126fn default_pixel() -> Pixel {
127    Pixel::None
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct VideoInfo {
132    pub format: StreamFormat,
133    #[serde(skip)]
134    pub stream: u16,
135    pub stream_type: String,
136    #[serde(skip, default = "default_pixel")]
137    pub pixel: Pixel,
138    pub size: FrameSize,
139    pub fps: Option<f64>,
140    pub frames: Option<u64>,
141    pub cost: Duration,
142    metadata: HashMap<String, String>,
143}
144
145impl Default for VideoInfo {
146    fn default() -> Self {
147        Self {
148            format: StreamFormat::default(),
149            stream: 0,
150            stream_type: "".into(),
151            pixel: Pixel::None,
152            size: FrameSize::default(),
153            fps: None,
154            frames: None,
155            cost: Duration::from_secs(0),
156            metadata: HashMap::new(),
157        }
158    }
159}
160
161impl VideoInfo {
162    pub fn stream(mut self, stream: u16) -> Self {
163        self.stream = stream;
164        self
165    }
166    pub fn stream_type(mut self, stream_type: String) -> Self {
167        self.stream_type = stream_type;
168        self
169    }
170    pub fn insert(mut self, key: String, val: String) -> Self {
171        self.metadata.insert(key, val);
172        self
173    }
174    pub fn size<I: Into<isize>>(mut self, w: I, h: I) -> Self {
175        self.size = self.size.width(w).height(h);
176        self
177    }
178    fn get_unnamed_title(&self) -> String {
179        format!("!unnamed_stream_{}", self.stream)
180    }
181    fn get_filename(&self) -> String {
182        self.metadata
183            .get("filename")
184            .unwrap_or(&self.get_unnamed_title())
185            .to_string()
186    }
187    pub fn get_handler_name(&self) -> String {
188        self.metadata
189            .get("handler_name")
190            .unwrap_or(&self.get_filename())
191            .to_string()
192    }
193    pub fn get_title(&self) -> String {
194        self.metadata
195            .get("title")
196            .unwrap_or(&self.get_handler_name())
197            .to_string()
198    }
199    pub fn get_mimetype(&self) -> String {
200        self.metadata
201            .get("mimetype")
202            .unwrap_or(&"binary".into())
203            .into()
204    }
205}
206
207pub type VideoGroups = HashMap<String, VideoInfo>;