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>;