write alpha component for PGMYUV
[nihav.git] / src / frame.rs
... / ...
CommitLineData
1use std::cmp::max;
2use std::collections::HashMap;
3use std::fmt;
4use std::rc::Rc;
5use std::cell::*;
6use formats::*;
7
8#[allow(dead_code)]
9#[derive(Clone,Copy,PartialEq)]
10pub struct NAAudioInfo {
11 sample_rate: u32,
12 channels: u8,
13 format: NASoniton,
14 block_len: usize,
15}
16
17impl NAAudioInfo {
18 pub fn new(sr: u32, ch: u8, fmt: NASoniton, bl: usize) -> Self {
19 NAAudioInfo { sample_rate: sr, channels: ch, format: fmt, block_len: bl }
20 }
21 pub fn get_sample_rate(&self) -> u32 { self.sample_rate }
22 pub fn get_channels(&self) -> u8 { self.channels }
23 pub fn get_format(&self) -> NASoniton { self.format }
24 pub fn get_block_len(&self) -> usize { self.block_len }
25}
26
27impl fmt::Display for NAAudioInfo {
28 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29 write!(f, "{} Hz, {} ch", self.sample_rate, self.channels)
30 }
31}
32
33#[allow(dead_code)]
34#[derive(Clone,Copy,PartialEq)]
35pub struct NAVideoInfo {
36 width: usize,
37 height: usize,
38 flipped: bool,
39 format: NAPixelFormaton,
40}
41
42impl NAVideoInfo {
43 pub fn new(w: usize, h: usize, flip: bool, fmt: NAPixelFormaton) -> Self {
44 NAVideoInfo { width: w, height: h, flipped: flip, format: fmt }
45 }
46 pub fn get_width(&self) -> usize { self.width as usize }
47 pub fn get_height(&self) -> usize { self.height as usize }
48 pub fn is_flipped(&self) -> bool { self.flipped }
49 pub fn get_format(&self) -> NAPixelFormaton { self.format }
50}
51
52impl fmt::Display for NAVideoInfo {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 write!(f, "{}x{}", self.width, self.height)
55 }
56}
57
58#[derive(Clone,Copy,PartialEq)]
59pub enum NACodecTypeInfo {
60 None,
61 Audio(NAAudioInfo),
62 Video(NAVideoInfo),
63}
64
65impl NACodecTypeInfo {
66 pub fn get_video_info(&self) -> Option<NAVideoInfo> {
67 match *self {
68 NACodecTypeInfo::Video(vinfo) => Some(vinfo),
69 _ => None,
70 }
71 }
72 pub fn get_audio_info(&self) -> Option<NAAudioInfo> {
73 match *self {
74 NACodecTypeInfo::Audio(ainfo) => Some(ainfo),
75 _ => None,
76 }
77 }
78 pub fn is_video(&self) -> bool {
79 match *self {
80 NACodecTypeInfo::Video(_) => true,
81 _ => false,
82 }
83 }
84 pub fn is_audio(&self) -> bool {
85 match *self {
86 NACodecTypeInfo::Audio(_) => true,
87 _ => false,
88 }
89 }
90}
91
92impl fmt::Display for NACodecTypeInfo {
93 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94 let ret = match *self {
95 NACodecTypeInfo::None => format!(""),
96 NACodecTypeInfo::Audio(fmt) => format!("{}", fmt),
97 NACodecTypeInfo::Video(fmt) => format!("{}", fmt),
98 };
99 write!(f, "{}", ret)
100 }
101}
102
103pub type NABufferRefT<T> = Rc<RefCell<Vec<T>>>;
104
105#[derive(Clone)]
106pub struct NAVideoBuffer<T> {
107 info: NAVideoInfo,
108 data: NABufferRefT<T>,
109 offs: Vec<usize>,
110 strides: Vec<usize>,
111}
112
113impl<T: Clone> NAVideoBuffer<T> {
114 pub fn get_offset(&self, idx: usize) -> usize {
115 if idx >= self.offs.len() { 0 }
116 else { self.offs[idx] }
117 }
118 pub fn get_info(&self) -> NAVideoInfo { self.info }
119 pub fn get_data(&self) -> Ref<Vec<T>> { self.data.borrow() }
120 pub fn get_data_mut(&mut self) -> RefMut<Vec<T>> { self.data.borrow_mut() }
121 pub fn copy_buffer(&mut self) -> Self {
122 let mut data: Vec<T> = Vec::with_capacity(self.data.borrow().len());
123 data.clone_from(self.data.borrow().as_ref());
124 let mut offs: Vec<usize> = Vec::with_capacity(self.offs.len());
125 offs.clone_from(&self.offs);
126 let mut strides: Vec<usize> = Vec::with_capacity(self.strides.len());
127 strides.clone_from(&self.strides);
128 NAVideoBuffer { info: self.info, data: Rc::new(RefCell::new(data)), offs: offs, strides: strides }
129 }
130 pub fn get_stride(&self, idx: usize) -> usize {
131 if idx >= self.strides.len() { return 0; }
132 self.strides[idx]
133 }
134 pub fn get_dimensions(&self, idx: usize) -> (usize, usize) {
135 get_plane_size(&self.info, idx)
136 }
137}
138
139#[derive(Clone)]
140pub struct NAAudioBuffer<T> {
141 info: NAAudioInfo,
142 data: NABufferRefT<T>,
143 offs: Vec<usize>,
144 chmap: NAChannelMap,
145 len: usize,
146}
147
148impl<T: Clone> NAAudioBuffer<T> {
149 pub fn get_offset(&self, idx: usize) -> usize {
150 if idx >= self.offs.len() { 0 }
151 else { self.offs[idx] }
152 }
153 pub fn get_info(&self) -> NAAudioInfo { self.info }
154 pub fn get_chmap(&self) -> NAChannelMap { self.chmap.clone() }
155 pub fn get_data(&self) -> Ref<Vec<T>> { self.data.borrow() }
156 pub fn get_data_mut(&mut self) -> RefMut<Vec<T>> { self.data.borrow_mut() }
157 pub fn copy_buffer(&mut self) -> Self {
158 let mut data: Vec<T> = Vec::with_capacity(self.data.borrow().len());
159 data.clone_from(self.data.borrow().as_ref());
160 let mut offs: Vec<usize> = Vec::with_capacity(self.offs.len());
161 offs.clone_from(&self.offs);
162 NAAudioBuffer { info: self.info, data: Rc::new(RefCell::new(data)), offs: offs, chmap: self.get_chmap(), len: self.len }
163 }
164 pub fn get_length(&self) -> usize { self.len }
165}
166
167impl NAAudioBuffer<u8> {
168 pub fn new_from_buf(info: NAAudioInfo, data: NABufferRefT<u8>, chmap: NAChannelMap) -> Self {
169 let len = data.borrow().len();
170 NAAudioBuffer { info: info, data: data, chmap: chmap, offs: Vec::new(), len: len }
171 }
172}
173
174#[derive(Clone)]
175pub enum NABufferType {
176 Video (NAVideoBuffer<u8>),
177 Video16 (NAVideoBuffer<u16>),
178 VideoPacked(NAVideoBuffer<u8>),
179 AudioU8 (NAAudioBuffer<u8>),
180 AudioI16 (NAAudioBuffer<i16>),
181 AudioI32 (NAAudioBuffer<i32>),
182 AudioF32 (NAAudioBuffer<f32>),
183 AudioPacked(NAAudioBuffer<u8>),
184 Data (NABufferRefT<u8>),
185 None,
186}
187
188impl NABufferType {
189 pub fn get_offset(&self, idx: usize) -> usize {
190 match *self {
191 NABufferType::Video(ref vb) => vb.get_offset(idx),
192 NABufferType::Video16(ref vb) => vb.get_offset(idx),
193 NABufferType::VideoPacked(ref vb) => vb.get_offset(idx),
194 NABufferType::AudioU8(ref ab) => ab.get_offset(idx),
195 NABufferType::AudioI16(ref ab) => ab.get_offset(idx),
196 NABufferType::AudioF32(ref ab) => ab.get_offset(idx),
197 NABufferType::AudioPacked(ref ab) => ab.get_offset(idx),
198 _ => 0,
199 }
200 }
201 pub fn get_vbuf(&mut self) -> Option<NAVideoBuffer<u8>> {
202 match *self {
203 NABufferType::Video(ref vb) => Some(vb.clone()),
204 NABufferType::VideoPacked(ref vb) => Some(vb.clone()),
205 _ => None,
206 }
207 }
208 pub fn get_vbuf16(&mut self) -> Option<NAVideoBuffer<u16>> {
209 match *self {
210 NABufferType::Video16(ref vb) => Some(vb.clone()),
211 _ => None,
212 }
213 }
214 pub fn get_abuf_u8(&mut self) -> Option<NAAudioBuffer<u8>> {
215 match *self {
216 NABufferType::AudioU8(ref ab) => Some(ab.clone()),
217 NABufferType::AudioPacked(ref ab) => Some(ab.clone()),
218 _ => None,
219 }
220 }
221 pub fn get_abuf_i16(&mut self) -> Option<NAAudioBuffer<i16>> {
222 match *self {
223 NABufferType::AudioI16(ref ab) => Some(ab.clone()),
224 _ => None,
225 }
226 }
227 pub fn get_abuf_i32(&mut self) -> Option<NAAudioBuffer<i32>> {
228 match *self {
229 NABufferType::AudioI32(ref ab) => Some(ab.clone()),
230 _ => None,
231 }
232 }
233 pub fn get_abuf_f32(&mut self) -> Option<NAAudioBuffer<f32>> {
234 match *self {
235 NABufferType::AudioF32(ref ab) => Some(ab.clone()),
236 _ => None,
237 }
238 }
239}
240
241#[derive(Debug,Clone,Copy,PartialEq)]
242pub enum AllocatorError {
243 TooLargeDimensions,
244 FormatError,
245}
246
247pub fn alloc_video_buffer(vinfo: NAVideoInfo, align: u8) -> Result<NABufferType, AllocatorError> {
248 let fmt = &vinfo.format;
249 let mut new_size: usize = 0;
250 let mut offs: Vec<usize> = Vec::new();
251 let mut strides: Vec<usize> = Vec::new();
252
253 for i in 0..fmt.get_num_comp() {
254 if fmt.get_chromaton(i) == None { return Err(AllocatorError::FormatError); }
255 }
256
257 let align_mod = ((1 << align) as usize) - 1;
258 let width = ((vinfo.width as usize) + align_mod) & !align_mod;
259 let height = ((vinfo.height as usize) + align_mod) & !align_mod;
260 let mut max_depth = 0;
261 let mut all_packed = true;
262 for i in 0..fmt.get_num_comp() {
263 let ochr = fmt.get_chromaton(i);
264 if let None = ochr { continue; }
265 let chr = ochr.unwrap();
266 if !chr.is_packed() {
267 all_packed = false;
268 break;
269 }
270 max_depth = max(max_depth, chr.get_depth());
271 }
272
273//todo semi-packed like NV12
274 if fmt.is_paletted() {
275//todo various-sized palettes?
276 let stride = vinfo.get_format().get_chromaton(0).unwrap().get_linesize(width);
277 let pic_sz = stride.checked_mul(height);
278 if pic_sz == None { return Err(AllocatorError::TooLargeDimensions); }
279 let pal_size = 256 * (fmt.get_elem_size() as usize);
280 let new_size = pic_sz.unwrap().checked_add(pal_size);
281 if new_size == None { return Err(AllocatorError::TooLargeDimensions); }
282 offs.push(0);
283 offs.push(stride * height);
284 strides.push(stride);
285 let mut data: Vec<u8> = Vec::with_capacity(new_size.unwrap());
286 data.resize(new_size.unwrap(), 0);
287 let buf: NAVideoBuffer<u8> = NAVideoBuffer { data: Rc::new(RefCell::new(data)), info: vinfo, offs: offs, strides: strides };
288 Ok(NABufferType::Video(buf))
289 } else if !all_packed {
290 for i in 0..fmt.get_num_comp() {
291 let ochr = fmt.get_chromaton(i);
292 if let None = ochr { continue; }
293 let chr = ochr.unwrap();
294 if !vinfo.is_flipped() {
295 offs.push(new_size as usize);
296 }
297 let stride = chr.get_linesize(width);
298 let cur_h = chr.get_height(height);
299 let cur_sz = stride.checked_mul(cur_h);
300 if cur_sz == None { return Err(AllocatorError::TooLargeDimensions); }
301 let new_sz = new_size.checked_add(cur_sz.unwrap());
302 if new_sz == None { return Err(AllocatorError::TooLargeDimensions); }
303 new_size = new_sz.unwrap();
304 if vinfo.is_flipped() {
305 offs.push(new_size as usize);
306 }
307 strides.push(stride);
308 }
309 if max_depth <= 8 {
310 let mut data: Vec<u8> = Vec::with_capacity(new_size);
311 data.resize(new_size, 0);
312 let buf: NAVideoBuffer<u8> = NAVideoBuffer { data: Rc::new(RefCell::new(data)), info: vinfo, offs: offs, strides: strides };
313 Ok(NABufferType::Video(buf))
314 } else {
315 let mut data: Vec<u16> = Vec::with_capacity(new_size);
316 data.resize(new_size, 0);
317 let buf: NAVideoBuffer<u16> = NAVideoBuffer { data: Rc::new(RefCell::new(data)), info: vinfo, offs: offs, strides: strides };
318 Ok(NABufferType::Video16(buf))
319 }
320 } else {
321 let elem_sz = fmt.get_elem_size();
322 let line_sz = width.checked_mul(elem_sz as usize);
323 if line_sz == None { return Err(AllocatorError::TooLargeDimensions); }
324 let new_sz = line_sz.unwrap().checked_mul(height);
325 if new_sz == None { return Err(AllocatorError::TooLargeDimensions); }
326 new_size = new_sz.unwrap();
327 let mut data: Vec<u8> = Vec::with_capacity(new_size);
328 data.resize(new_size, 0);
329 strides.push(line_sz.unwrap());
330 let buf: NAVideoBuffer<u8> = NAVideoBuffer { data: Rc::new(RefCell::new(data)), info: vinfo, offs: offs, strides: strides };
331 Ok(NABufferType::VideoPacked(buf))
332 }
333}
334
335pub fn alloc_audio_buffer(ainfo: NAAudioInfo, nsamples: usize, chmap: NAChannelMap) -> Result<NABufferType, AllocatorError> {
336 let mut offs: Vec<usize> = Vec::new();
337 if ainfo.format.is_planar() {
338 let len = nsamples.checked_mul(ainfo.channels as usize);
339 if len == None { return Err(AllocatorError::TooLargeDimensions); }
340 let length = len.unwrap();
341 for i in 0..ainfo.channels {
342 offs.push((i as usize) * nsamples);
343 }
344 if ainfo.format.is_float() {
345 if ainfo.format.get_bits() == 32 {
346 let mut data: Vec<f32> = Vec::with_capacity(length);
347 data.resize(length, 0.0);
348 let buf: NAAudioBuffer<f32> = NAAudioBuffer { data: Rc::new(RefCell::new(data)), info: ainfo, offs: offs, chmap: chmap, len: nsamples };
349 Ok(NABufferType::AudioF32(buf))
350 } else {
351 Err(AllocatorError::TooLargeDimensions)
352 }
353 } else {
354 if ainfo.format.get_bits() == 8 && !ainfo.format.is_signed() {
355 let mut data: Vec<u8> = Vec::with_capacity(length);
356 data.resize(length, 0);
357 let buf: NAAudioBuffer<u8> = NAAudioBuffer { data: Rc::new(RefCell::new(data)), info: ainfo, offs: offs, chmap: chmap, len: nsamples };
358 Ok(NABufferType::AudioU8(buf))
359 } else if ainfo.format.get_bits() == 16 && ainfo.format.is_signed() {
360 let mut data: Vec<i16> = Vec::with_capacity(length);
361 data.resize(length, 0);
362 let buf: NAAudioBuffer<i16> = NAAudioBuffer { data: Rc::new(RefCell::new(data)), info: ainfo, offs: offs, chmap: chmap, len: nsamples };
363 Ok(NABufferType::AudioI16(buf))
364 } else {
365 Err(AllocatorError::TooLargeDimensions)
366 }
367 }
368 } else {
369 let len = nsamples.checked_mul(ainfo.channels as usize);
370 if len == None { return Err(AllocatorError::TooLargeDimensions); }
371 let length = ainfo.format.get_audio_size(len.unwrap() as u64);
372 let mut data: Vec<u8> = Vec::with_capacity(length);
373 data.resize(length, 0);
374 let buf: NAAudioBuffer<u8> = NAAudioBuffer { data: Rc::new(RefCell::new(data)), info: ainfo, offs: offs, chmap: chmap, len: nsamples };
375 Ok(NABufferType::AudioPacked(buf))
376 }
377}
378
379pub fn alloc_data_buffer(size: usize) -> Result<NABufferType, AllocatorError> {
380 let mut data: Vec<u8> = Vec::with_capacity(size);
381 data.resize(size, 0);
382 let buf: NABufferRefT<u8> = Rc::new(RefCell::new(data));
383 Ok(NABufferType::Data(buf))
384}
385
386pub fn copy_buffer(buf: NABufferType) -> NABufferType {
387 buf.clone()
388}
389
390#[allow(dead_code)]
391#[derive(Clone)]
392pub struct NACodecInfo {
393 name: &'static str,
394 properties: NACodecTypeInfo,
395 extradata: Option<Rc<Vec<u8>>>,
396}
397
398impl NACodecInfo {
399 pub fn new(name: &'static str, p: NACodecTypeInfo, edata: Option<Vec<u8>>) -> Self {
400 let extradata = match edata {
401 None => None,
402 Some(vec) => Some(Rc::new(vec)),
403 };
404 NACodecInfo { name: name, properties: p, extradata: extradata }
405 }
406 pub fn new_ref(name: &'static str, p: NACodecTypeInfo, edata: Option<Rc<Vec<u8>>>) -> Self {
407 NACodecInfo { name: name, properties: p, extradata: edata }
408 }
409 pub fn get_properties(&self) -> NACodecTypeInfo { self.properties }
410 pub fn get_extradata(&self) -> Option<Rc<Vec<u8>>> {
411 if let Some(ref vec) = self.extradata { return Some(vec.clone()); }
412 None
413 }
414 pub fn get_name(&self) -> &'static str { self.name }
415 pub fn is_video(&self) -> bool {
416 if let NACodecTypeInfo::Video(_) = self.properties { return true; }
417 false
418 }
419 pub fn is_audio(&self) -> bool {
420 if let NACodecTypeInfo::Audio(_) = self.properties { return true; }
421 false
422 }
423 pub fn new_dummy() -> Rc<Self> {
424 Rc::new(DUMMY_CODEC_INFO)
425 }
426 pub fn replace_info(&self, p: NACodecTypeInfo) -> Rc<Self> {
427 Rc::new(NACodecInfo { name: self.name, properties: p, extradata: self.extradata.clone() })
428 }
429}
430
431impl fmt::Display for NACodecInfo {
432 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
433 let edata = match self.extradata.clone() {
434 None => format!("no extradata"),
435 Some(v) => format!("{} byte(s) of extradata", v.len()),
436 };
437 write!(f, "{}: {} {}", self.name, self.properties, edata)
438 }
439}
440
441pub const DUMMY_CODEC_INFO: NACodecInfo = NACodecInfo {
442 name: "none",
443 properties: NACodecTypeInfo::None,
444 extradata: None };
445
446#[derive(Debug,Clone)]
447pub enum NAValue {
448 None,
449 Int(i32),
450 Long(i64),
451 String(String),
452 Data(Rc<Vec<u8>>),
453}
454
455#[derive(Debug,Clone,Copy,PartialEq)]
456#[allow(dead_code)]
457pub enum FrameType {
458 I,
459 P,
460 B,
461 Skip,
462 Other,
463}
464
465impl fmt::Display for FrameType {
466 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
467 match *self {
468 FrameType::I => write!(f, "I"),
469 FrameType::P => write!(f, "P"),
470 FrameType::B => write!(f, "B"),
471 FrameType::Skip => write!(f, "skip"),
472 FrameType::Other => write!(f, "x"),
473 }
474 }
475}
476
477#[derive(Debug,Clone,Copy)]
478pub struct NATimeInfo {
479 pts: Option<u64>,
480 dts: Option<u64>,
481 duration: Option<u64>,
482 tb_num: u32,
483 tb_den: u32,
484}
485
486impl NATimeInfo {
487 pub fn new(pts: Option<u64>, dts: Option<u64>, duration: Option<u64>, tb_num: u32, tb_den: u32) -> Self {
488 NATimeInfo { pts: pts, dts: dts, duration: duration, tb_num: tb_num, tb_den: tb_den }
489 }
490 pub fn get_pts(&self) -> Option<u64> { self.pts }
491 pub fn get_dts(&self) -> Option<u64> { self.dts }
492 pub fn get_duration(&self) -> Option<u64> { self.duration }
493 pub fn set_pts(&mut self, pts: Option<u64>) { self.pts = pts; }
494 pub fn set_dts(&mut self, dts: Option<u64>) { self.dts = dts; }
495 pub fn set_duration(&mut self, dur: Option<u64>) { self.duration = dur; }
496}
497
498#[allow(dead_code)]
499#[derive(Clone)]
500pub struct NAFrame {
501 ts: NATimeInfo,
502 buffer: NABufferType,
503 info: Rc<NACodecInfo>,
504 ftype: FrameType,
505 key: bool,
506 options: HashMap<String, NAValue>,
507}
508
509pub type NAFrameRef = Rc<RefCell<NAFrame>>;
510
511fn get_plane_size(info: &NAVideoInfo, idx: usize) -> (usize, usize) {
512 let chromaton = info.get_format().get_chromaton(idx);
513 if let None = chromaton { return (0, 0); }
514 let (hs, vs) = chromaton.unwrap().get_subsampling();
515 let w = (info.get_width() + ((1 << hs) - 1)) >> hs;
516 let h = (info.get_height() + ((1 << vs) - 1)) >> vs;
517 (w, h)
518}
519
520impl NAFrame {
521 pub fn new(ts: NATimeInfo,
522 ftype: FrameType,
523 keyframe: bool,
524 info: Rc<NACodecInfo>,
525 options: HashMap<String, NAValue>,
526 buffer: NABufferType) -> Self {
527 NAFrame { ts: ts, buffer: buffer, info: info, ftype: ftype, key: keyframe, options: options }
528 }
529 pub fn get_info(&self) -> Rc<NACodecInfo> { self.info.clone() }
530 pub fn get_frame_type(&self) -> FrameType { self.ftype }
531 pub fn is_keyframe(&self) -> bool { self.key }
532 pub fn set_frame_type(&mut self, ftype: FrameType) { self.ftype = ftype; }
533 pub fn set_keyframe(&mut self, key: bool) { self.key = key; }
534 pub fn get_time_information(&self) -> NATimeInfo { self.ts }
535 pub fn get_pts(&self) -> Option<u64> { self.ts.get_pts() }
536 pub fn get_dts(&self) -> Option<u64> { self.ts.get_dts() }
537 pub fn get_duration(&self) -> Option<u64> { self.ts.get_duration() }
538 pub fn set_pts(&mut self, pts: Option<u64>) { self.ts.set_pts(pts); }
539 pub fn set_dts(&mut self, dts: Option<u64>) { self.ts.set_dts(dts); }
540 pub fn set_duration(&mut self, dur: Option<u64>) { self.ts.set_duration(dur); }
541
542 pub fn get_buffer(&self) -> NABufferType { self.buffer.clone() }
543}
544
545impl fmt::Display for NAFrame {
546 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
547 let mut foo = format!("frame type {}", self.ftype);
548 if let Some(pts) = self.ts.pts { foo = format!("{} pts {}", foo, pts); }
549 if let Some(dts) = self.ts.dts { foo = format!("{} dts {}", foo, dts); }
550 if let Some(dur) = self.ts.duration { foo = format!("{} duration {}", foo, dur); }
551 if self.key { foo = format!("{} kf", foo); }
552 write!(f, "[{}]", foo)
553 }
554}
555
556/// Possible stream types.
557#[derive(Debug,Clone,Copy)]
558#[allow(dead_code)]
559pub enum StreamType {
560 /// video stream
561 Video,
562 /// audio stream
563 Audio,
564 /// subtitles
565 Subtitles,
566 /// any data stream (or might be an unrecognized audio/video stream)
567 Data,
568 /// nonexistent stream
569 None,
570}
571
572impl fmt::Display for StreamType {
573 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
574 match *self {
575 StreamType::Video => write!(f, "Video"),
576 StreamType::Audio => write!(f, "Audio"),
577 StreamType::Subtitles => write!(f, "Subtitles"),
578 StreamType::Data => write!(f, "Data"),
579 StreamType::None => write!(f, "-"),
580 }
581 }
582}
583
584#[allow(dead_code)]
585#[derive(Clone)]
586pub struct NAStream {
587 media_type: StreamType,
588 id: u32,
589 num: usize,
590 info: Rc<NACodecInfo>,
591 tb_num: u32,
592 tb_den: u32,
593}
594
595pub fn reduce_timebase(tb_num: u32, tb_den: u32) -> (u32, u32) {
596 if tb_num == 0 { return (tb_num, tb_den); }
597 if (tb_den % tb_num) == 0 { return (1, tb_den / tb_num); }
598
599 let mut a = tb_num;
600 let mut b = tb_den;
601
602 while a != b {
603 if a > b { a -= b; }
604 else if b > a { b -= a; }
605 }
606
607 (tb_num / a, tb_den / a)
608}
609
610impl NAStream {
611 pub fn new(mt: StreamType, id: u32, info: NACodecInfo, tb_num: u32, tb_den: u32) -> Self {
612 let (n, d) = reduce_timebase(tb_num, tb_den);
613 NAStream { media_type: mt, id: id, num: 0, info: Rc::new(info), tb_num: n, tb_den: d }
614 }
615 pub fn get_id(&self) -> u32 { self.id }
616 pub fn get_num(&self) -> usize { self.num }
617 pub fn set_num(&mut self, num: usize) { self.num = num; }
618 pub fn get_info(&self) -> Rc<NACodecInfo> { self.info.clone() }
619 pub fn get_timebase(&self) -> (u32, u32) { (self.tb_num, self.tb_den) }
620 pub fn set_timebase(&mut self, tb_num: u32, tb_den: u32) {
621 let (n, d) = reduce_timebase(tb_num, tb_den);
622 self.tb_num = n;
623 self.tb_den = d;
624 }
625}
626
627impl fmt::Display for NAStream {
628 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
629 write!(f, "({}#{} @ {}/{} - {})", self.media_type, self.id, self.tb_num, self.tb_den, self.info.get_properties())
630 }
631}
632
633#[allow(dead_code)]
634pub struct NAPacket {
635 stream: Rc<NAStream>,
636 ts: NATimeInfo,
637 buffer: Rc<Vec<u8>>,
638 keyframe: bool,
639// options: HashMap<String, NAValue<'a>>,
640}
641
642impl NAPacket {
643 pub fn new(str: Rc<NAStream>, ts: NATimeInfo, kf: bool, vec: Vec<u8>) -> Self {
644// let mut vec: Vec<u8> = Vec::new();
645// vec.resize(size, 0);
646 NAPacket { stream: str, ts: ts, keyframe: kf, buffer: Rc::new(vec) }
647 }
648 pub fn get_stream(&self) -> Rc<NAStream> { self.stream.clone() }
649 pub fn get_time_information(&self) -> NATimeInfo { self.ts }
650 pub fn get_pts(&self) -> Option<u64> { self.ts.get_pts() }
651 pub fn get_dts(&self) -> Option<u64> { self.ts.get_dts() }
652 pub fn get_duration(&self) -> Option<u64> { self.ts.get_duration() }
653 pub fn is_keyframe(&self) -> bool { self.keyframe }
654 pub fn get_buffer(&self) -> Rc<Vec<u8>> { self.buffer.clone() }
655}
656
657impl Drop for NAPacket {
658 fn drop(&mut self) {}
659}
660
661impl fmt::Display for NAPacket {
662 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
663 let mut foo = format!("[pkt for {} size {}", self.stream, self.buffer.len());
664 if let Some(pts) = self.ts.pts { foo = format!("{} pts {}", foo, pts); }
665 if let Some(dts) = self.ts.dts { foo = format!("{} dts {}", foo, dts); }
666 if let Some(dur) = self.ts.duration { foo = format!("{} duration {}", foo, dur); }
667 if self.keyframe { foo = format!("{} kf", foo); }
668 foo = foo + "]";
669 write!(f, "{}", foo)
670 }
671}
672
673pub trait FrameFromPacket {
674 fn new_from_pkt(pkt: &NAPacket, info: Rc<NACodecInfo>, buf: NABufferType) -> NAFrame;
675 fn fill_timestamps(&mut self, pkt: &NAPacket);
676}
677
678impl FrameFromPacket for NAFrame {
679 fn new_from_pkt(pkt: &NAPacket, info: Rc<NACodecInfo>, buf: NABufferType) -> NAFrame {
680 NAFrame::new(pkt.ts, FrameType::Other, pkt.keyframe, info, HashMap::new(), buf)
681 }
682 fn fill_timestamps(&mut self, pkt: &NAPacket) {
683 self.ts = pkt.get_time_information();
684 }
685}
686