]>
Commit | Line | Data |
---|---|---|
1 | use std::collections::HashMap; | |
2 | use std::fmt; | |
3 | use std::rc::Rc; | |
4 | use formats::*; | |
5 | ||
6 | #[allow(dead_code)] | |
7 | #[derive(Clone,Copy,PartialEq)] | |
8 | pub struct NAAudioInfo { | |
9 | sample_rate: u32, | |
10 | channels: u8, | |
11 | format: NASoniton, | |
12 | block_len: usize, | |
13 | } | |
14 | ||
15 | impl NAAudioInfo { | |
16 | pub fn new(sr: u32, ch: u8, fmt: NASoniton, bl: usize) -> Self { | |
17 | NAAudioInfo { sample_rate: sr, channels: ch, format: fmt, block_len: bl } | |
18 | } | |
19 | pub fn get_sample_rate(&self) -> u32 { self.sample_rate } | |
20 | pub fn get_channels(&self) -> u8 { self.channels } | |
21 | pub fn get_format(&self) -> NASoniton { self.format } | |
22 | pub fn get_block_len(&self) -> usize { self.block_len } | |
23 | } | |
24 | ||
25 | impl fmt::Display for NAAudioInfo { | |
26 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
27 | write!(f, "{} Hz, {} ch", self.sample_rate, self.channels) | |
28 | } | |
29 | } | |
30 | ||
31 | #[allow(dead_code)] | |
32 | #[derive(Clone,Copy,PartialEq)] | |
33 | pub struct NAVideoInfo { | |
34 | width: usize, | |
35 | height: usize, | |
36 | flipped: bool, | |
37 | format: NAPixelFormaton, | |
38 | } | |
39 | ||
40 | impl NAVideoInfo { | |
41 | pub fn new(w: usize, h: usize, flip: bool, fmt: NAPixelFormaton) -> Self { | |
42 | NAVideoInfo { width: w, height: h, flipped: flip, format: fmt } | |
43 | } | |
44 | pub fn get_width(&self) -> usize { self.width as usize } | |
45 | pub fn get_height(&self) -> usize { self.height as usize } | |
46 | pub fn is_flipped(&self) -> bool { self.flipped } | |
47 | pub fn get_format(&self) -> NAPixelFormaton { self.format } | |
48 | } | |
49 | ||
50 | impl fmt::Display for NAVideoInfo { | |
51 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
52 | write!(f, "{}x{}", self.width, self.height) | |
53 | } | |
54 | } | |
55 | ||
56 | #[derive(Clone,Copy,PartialEq)] | |
57 | pub enum NACodecTypeInfo { | |
58 | None, | |
59 | Audio(NAAudioInfo), | |
60 | Video(NAVideoInfo), | |
61 | } | |
62 | ||
63 | impl fmt::Display for NACodecTypeInfo { | |
64 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
65 | let ret = match *self { | |
66 | NACodecTypeInfo::None => format!(""), | |
67 | NACodecTypeInfo::Audio(fmt) => format!("{}", fmt), | |
68 | NACodecTypeInfo::Video(fmt) => format!("{}", fmt), | |
69 | }; | |
70 | write!(f, "{}", ret) | |
71 | } | |
72 | } | |
73 | ||
74 | ||
75 | #[allow(dead_code)] | |
76 | #[derive(Clone)] | |
77 | pub struct NABuffer { | |
78 | id: u64, | |
79 | data: Rc<Vec<u8>>, | |
80 | } | |
81 | ||
82 | impl Drop for NABuffer { | |
83 | fn drop(&mut self) { } | |
84 | } | |
85 | ||
86 | impl NABuffer { | |
87 | pub fn get_data(&self) -> Rc<Vec<u8>> { self.data.clone() } | |
88 | pub fn get_data_mut(&mut self) -> Option<&mut Vec<u8>> { Rc::get_mut(&mut self.data) } | |
89 | } | |
90 | ||
91 | #[allow(dead_code)] | |
92 | #[derive(Clone)] | |
93 | pub struct NACodecInfo { | |
94 | name: &'static str, | |
95 | properties: NACodecTypeInfo, | |
96 | extradata: Option<Rc<Vec<u8>>>, | |
97 | } | |
98 | ||
99 | impl NACodecInfo { | |
100 | pub fn new(name: &'static str, p: NACodecTypeInfo, edata: Option<Vec<u8>>) -> Self { | |
101 | let extradata = match edata { | |
102 | None => None, | |
103 | Some(vec) => Some(Rc::new(vec)), | |
104 | }; | |
105 | NACodecInfo { name: name, properties: p, extradata: extradata } | |
106 | } | |
107 | pub fn new_ref(name: &'static str, p: NACodecTypeInfo, edata: Option<Rc<Vec<u8>>>) -> Self { | |
108 | NACodecInfo { name: name, properties: p, extradata: edata } | |
109 | } | |
110 | pub fn get_properties(&self) -> NACodecTypeInfo { self.properties } | |
111 | pub fn get_extradata(&self) -> Option<Rc<Vec<u8>>> { | |
112 | if let Some(ref vec) = self.extradata { return Some(vec.clone()); } | |
113 | None | |
114 | } | |
115 | pub fn get_name(&self) -> &'static str { self.name } | |
116 | pub fn is_video(&self) -> bool { | |
117 | if let NACodecTypeInfo::Video(_) = self.properties { return true; } | |
118 | false | |
119 | } | |
120 | pub fn is_audio(&self) -> bool { | |
121 | if let NACodecTypeInfo::Audio(_) = self.properties { return true; } | |
122 | false | |
123 | } | |
124 | } | |
125 | ||
126 | impl fmt::Display for NACodecInfo { | |
127 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
128 | let edata = match self.extradata.clone() { | |
129 | None => format!("no extradata"), | |
130 | Some(v) => format!("{} byte(s) of extradata", v.len()), | |
131 | }; | |
132 | write!(f, "{}: {} {}", self.name, self.properties, edata) | |
133 | } | |
134 | } | |
135 | ||
136 | pub const DUMMY_CODEC_INFO: NACodecInfo = NACodecInfo { | |
137 | name: "none", | |
138 | properties: NACodecTypeInfo::None, | |
139 | extradata: None }; | |
140 | ||
141 | fn alloc_video_buf(vinfo: NAVideoInfo, data: &mut Vec<u8>, offs: &mut Vec<usize>) { | |
142 | //todo use overflow detection mul | |
143 | let width = vinfo.width as usize; | |
144 | let height = vinfo.height as usize; | |
145 | let fmt = &vinfo.format; | |
146 | let mut new_size = 0; | |
147 | for i in 0..fmt.get_num_comp() { | |
148 | let chr = fmt.get_chromaton(i).unwrap(); | |
149 | if !vinfo.is_flipped() { | |
150 | offs.push(new_size as usize); | |
151 | } | |
152 | new_size += chr.get_data_size(width, height); | |
153 | if vinfo.is_flipped() { | |
154 | offs.push(new_size as usize); | |
155 | } | |
156 | } | |
157 | data.resize(new_size, 0); | |
158 | } | |
159 | ||
160 | fn alloc_audio_buf(ainfo: NAAudioInfo, data: &mut Vec<u8>, offs: &mut Vec<usize>) { | |
161 | //todo better alloc | |
162 | let length = ((ainfo.sample_rate as usize) * (ainfo.format.get_bits() as usize)) >> 3; | |
163 | let new_size: usize = length * (ainfo.channels as usize); | |
164 | data.resize(new_size, 0); | |
165 | for i in 0..ainfo.channels { | |
166 | if ainfo.format.is_planar() { | |
167 | offs.push((i as usize) * length); | |
168 | } else { | |
169 | offs.push(((i * ainfo.format.get_bits()) >> 3) as usize); | |
170 | } | |
171 | } | |
172 | } | |
173 | ||
174 | pub fn alloc_buf(info: &NACodecInfo) -> (Rc<NABuffer>, Vec<usize>) { | |
175 | let mut data: Vec<u8> = Vec::new(); | |
176 | let mut offs: Vec<usize> = Vec::new(); | |
177 | match info.properties { | |
178 | NACodecTypeInfo::Audio(ainfo) => alloc_audio_buf(ainfo, &mut data, &mut offs), | |
179 | NACodecTypeInfo::Video(vinfo) => alloc_video_buf(vinfo, &mut data, &mut offs), | |
180 | _ => (), | |
181 | } | |
182 | (Rc::new(NABuffer { id: 0, data: Rc::new(data) }), offs) | |
183 | } | |
184 | ||
185 | pub fn copy_buf(buf: &NABuffer) -> Rc<NABuffer> { | |
186 | let mut data: Vec<u8> = Vec::new(); | |
187 | data.clone_from(buf.get_data().as_ref()); | |
188 | Rc::new(NABuffer { id: 0, data: Rc::new(data) }) | |
189 | } | |
190 | ||
191 | #[derive(Debug,Clone)] | |
192 | pub enum NAValue { | |
193 | None, | |
194 | Int(i32), | |
195 | Long(i64), | |
196 | String(String), | |
197 | Data(Rc<Vec<u8>>), | |
198 | } | |
199 | ||
200 | #[allow(dead_code)] | |
201 | #[derive(Clone)] | |
202 | pub struct NAFrame { | |
203 | pts: Option<u64>, | |
204 | dts: Option<u64>, | |
205 | duration: Option<u64>, | |
206 | buffer: Rc<NABuffer>, | |
207 | info: Rc<NACodecInfo>, | |
208 | offsets: Vec<usize>, | |
209 | options: HashMap<String, NAValue>, | |
210 | } | |
211 | ||
212 | fn get_plane_size(info: &NAVideoInfo, idx: usize) -> (usize, usize) { | |
213 | let chromaton = info.get_format().get_chromaton(idx); | |
214 | if let None = chromaton { return (0, 0); } | |
215 | let (hs, vs) = chromaton.unwrap().get_subsampling(); | |
216 | let w = (info.get_width() + ((1 << hs) - 1)) >> hs; | |
217 | let h = (info.get_height() + ((1 << vs) - 1)) >> vs; | |
218 | (w, h) | |
219 | } | |
220 | ||
221 | impl NAFrame { | |
222 | pub fn new(pts: Option<u64>, | |
223 | dts: Option<u64>, | |
224 | duration: Option<u64>, | |
225 | info: Rc<NACodecInfo>, | |
226 | options: HashMap<String, NAValue>) -> Self { | |
227 | let (buf, offs) = alloc_buf(&info); | |
228 | NAFrame { pts: pts, dts: dts, duration: duration, buffer: buf, offsets: offs, info: info, options: options } | |
229 | } | |
230 | pub fn from_copy(src: &NAFrame) -> Self { | |
231 | let buf = copy_buf(src.get_buffer().as_ref()); | |
232 | let mut offs: Vec<usize> = Vec::new(); | |
233 | offs.clone_from(&src.offsets); | |
234 | NAFrame { pts: None, dts: None, duration: None, buffer: buf, offsets: offs, info: src.info.clone(), options: src.options.clone() } | |
235 | } | |
236 | pub fn get_pts(&self) -> Option<u64> { self.pts } | |
237 | pub fn get_dts(&self) -> Option<u64> { self.dts } | |
238 | pub fn get_duration(&self) -> Option<u64> { self.duration } | |
239 | pub fn set_pts(&mut self, pts: Option<u64>) { self.pts = pts; } | |
240 | pub fn set_dts(&mut self, dts: Option<u64>) { self.dts = dts; } | |
241 | pub fn set_duration(&mut self, dur: Option<u64>) { self.duration = dur; } | |
242 | ||
243 | pub fn get_offset(&self, idx: usize) -> usize { self.offsets[idx] } | |
244 | pub fn get_buffer(&self) -> Rc<NABuffer> { self.buffer.clone() } | |
245 | pub fn get_buffer_mut(&mut self) -> Option<&mut NABuffer> { Rc::get_mut(&mut self.buffer) } | |
246 | pub fn get_stride(&self, idx: usize) -> usize { | |
247 | if let NACodecTypeInfo::Video(vinfo) = self.info.get_properties() { | |
248 | if idx >= vinfo.get_format().get_num_comp() { return 0; } | |
249 | vinfo.get_format().get_chromaton(idx).unwrap().get_linesize(vinfo.get_width()) | |
250 | } else { | |
251 | 0 | |
252 | } | |
253 | } | |
254 | pub fn get_dimensions(&self, idx: usize) -> (usize, usize) { | |
255 | match self.info.get_properties() { | |
256 | NACodecTypeInfo::Video(ref vinfo) => get_plane_size(vinfo, idx), | |
257 | _ => (0, 0), | |
258 | } | |
259 | } | |
260 | } | |
261 | ||
262 | /// Possible stream types. | |
263 | #[derive(Debug,Clone,Copy)] | |
264 | #[allow(dead_code)] | |
265 | pub enum StreamType { | |
266 | /// video stream | |
267 | Video, | |
268 | /// audio stream | |
269 | Audio, | |
270 | /// subtitles | |
271 | Subtitles, | |
272 | /// any data stream (or might be an unrecognized audio/video stream) | |
273 | Data, | |
274 | /// nonexistent stream | |
275 | None, | |
276 | } | |
277 | ||
278 | impl fmt::Display for StreamType { | |
279 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
280 | match *self { | |
281 | StreamType::Video => write!(f, "Video"), | |
282 | StreamType::Audio => write!(f, "Audio"), | |
283 | StreamType::Subtitles => write!(f, "Subtitles"), | |
284 | StreamType::Data => write!(f, "Data"), | |
285 | StreamType::None => write!(f, "-"), | |
286 | } | |
287 | } | |
288 | } | |
289 | ||
290 | #[allow(dead_code)] | |
291 | #[derive(Clone)] | |
292 | pub struct NAStream { | |
293 | media_type: StreamType, | |
294 | id: u32, | |
295 | num: usize, | |
296 | info: Rc<NACodecInfo>, | |
297 | } | |
298 | ||
299 | impl NAStream { | |
300 | pub fn new(mt: StreamType, id: u32, info: NACodecInfo) -> Self { | |
301 | NAStream { media_type: mt, id: id, num: 0, info: Rc::new(info) } | |
302 | } | |
303 | pub fn get_id(&self) -> u32 { self.id } | |
304 | pub fn get_num(&self) -> usize { self.num } | |
305 | pub fn set_num(&mut self, num: usize) { self.num = num; } | |
306 | pub fn get_info(&self) -> Rc<NACodecInfo> { self.info.clone() } | |
307 | } | |
308 | ||
309 | impl fmt::Display for NAStream { | |
310 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
311 | write!(f, "({}#{} - {})", self.media_type, self.id, self.info.get_properties()) | |
312 | } | |
313 | } | |
314 | ||
315 | #[allow(dead_code)] | |
316 | pub struct NAPacket { | |
317 | stream: Rc<NAStream>, | |
318 | pts: Option<u64>, | |
319 | dts: Option<u64>, | |
320 | duration: Option<u64>, | |
321 | buffer: Rc<Vec<u8>>, | |
322 | keyframe: bool, | |
323 | // options: HashMap<String, NAValue<'a>>, | |
324 | } | |
325 | ||
326 | impl NAPacket { | |
327 | pub fn new(str: Rc<NAStream>, pts: Option<u64>, dts: Option<u64>, dur: Option<u64>, kf: bool, vec: Vec<u8>) -> Self { | |
328 | // let mut vec: Vec<u8> = Vec::new(); | |
329 | // vec.resize(size, 0); | |
330 | NAPacket { stream: str, pts: pts, dts: dts, duration: dur, keyframe: kf, buffer: Rc::new(vec) } | |
331 | } | |
332 | pub fn get_stream(&self) -> Rc<NAStream> { self.stream.clone() } | |
333 | pub fn get_pts(&self) -> Option<u64> { self.pts } | |
334 | pub fn get_dts(&self) -> Option<u64> { self.dts } | |
335 | pub fn get_duration(&self) -> Option<u64> { self.duration } | |
336 | pub fn is_keyframe(&self) -> bool { self.keyframe } | |
337 | pub fn get_buffer(&self) -> Rc<Vec<u8>> { self.buffer.clone() } | |
338 | } | |
339 | ||
340 | impl Drop for NAPacket { | |
341 | fn drop(&mut self) {} | |
342 | } | |
343 | ||
344 | impl fmt::Display for NAPacket { | |
345 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
346 | let mut foo = format!("[pkt for {} size {}", self.stream, self.buffer.len()); | |
347 | if let Some(pts) = self.pts { foo = format!("{} pts {}", foo, pts); } | |
348 | if let Some(dts) = self.dts { foo = format!("{} dts {}", foo, dts); } | |
349 | if let Some(dur) = self.duration { foo = format!("{} duration {}", foo, dur); } | |
350 | if self.keyframe { foo = format!("{} kf", foo); } | |
351 | foo = foo + "]"; | |
352 | write!(f, "{}", foo) | |
353 | } | |
354 | } | |
355 | ||
356 | pub trait FrameFromPacket { | |
357 | fn new_from_pkt(pkt: &NAPacket, info: Rc<NACodecInfo>) -> NAFrame; | |
358 | fn fill_timestamps(&mut self, pkt: &NAPacket); | |
359 | } | |
360 | ||
361 | impl FrameFromPacket for NAFrame { | |
362 | fn new_from_pkt(pkt: &NAPacket, info: Rc<NACodecInfo>) -> NAFrame { | |
363 | NAFrame::new(pkt.pts, pkt.dts, pkt.duration, info, HashMap::new()) | |
364 | } | |
365 | fn fill_timestamps(&mut self, pkt: &NAPacket) { | |
366 | self.set_pts(pkt.pts); | |
367 | self.set_dts(pkt.dts); | |
368 | self.set_duration(pkt.duration); | |
369 | } | |
370 | } | |
371 |