write alpha component for PGMYUV
[nihav.git] / src / frame.rs
CommitLineData
22cb00db 1use std::cmp::max;
5869fd63 2use std::collections::HashMap;
83e603fa 3use std::fmt;
8869d452 4use std::rc::Rc;
88c03b61 5use std::cell::*;
fba6f8e4 6use formats::*;
94dbb551 7
5869fd63 8#[allow(dead_code)]
66116504 9#[derive(Clone,Copy,PartialEq)]
5869fd63
KS
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 }
66116504
KS
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 }
5869fd63
KS
25}
26
83e603fa
KS
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
5869fd63 33#[allow(dead_code)]
66116504 34#[derive(Clone,Copy,PartialEq)]
5869fd63 35pub struct NAVideoInfo {
66116504
KS
36 width: usize,
37 height: usize,
5869fd63
KS
38 flipped: bool,
39 format: NAPixelFormaton,
40}
41
42impl NAVideoInfo {
66116504 43 pub fn new(w: usize, h: usize, flip: bool, fmt: NAPixelFormaton) -> Self {
5869fd63
KS
44 NAVideoInfo { width: w, height: h, flipped: flip, format: fmt }
45 }
66116504
KS
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 }
5869fd63
KS
50}
51
83e603fa
KS
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
66116504 58#[derive(Clone,Copy,PartialEq)]
5869fd63
KS
59pub enum NACodecTypeInfo {
60 None,
61 Audio(NAAudioInfo),
62 Video(NAVideoInfo),
63}
64
22cb00db
KS
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 }
5076115b
KS
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 }
22cb00db
KS
90}
91
83e603fa
KS
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
22cb00db 103pub type NABufferRefT<T> = Rc<RefCell<Vec<T>>>;
88c03b61 104
22cb00db
KS
105#[derive(Clone)]
106pub struct NAVideoBuffer<T> {
6c8e5c40
KS
107 info: NAVideoInfo,
108 data: NABufferRefT<T>,
109 offs: Vec<usize>,
110 strides: Vec<usize>,
22cb00db
KS
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);
6c8e5c40
KS
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 }
22cb00db
KS
129 }
130 pub fn get_stride(&self, idx: usize) -> usize {
6c8e5c40
KS
131 if idx >= self.strides.len() { return 0; }
132 self.strides[idx]
22cb00db
KS
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,
5076115b 145 len: usize,
22cb00db
KS
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);
5076115b 162 NAAudioBuffer { info: self.info, data: Rc::new(RefCell::new(data)), offs: offs, chmap: self.get_chmap(), len: self.len }
22cb00db 163 }
5076115b 164 pub fn get_length(&self) -> usize { self.len }
22cb00db
KS
165}
166
87a1ebc3
KS
167impl NAAudioBuffer<u8> {
168 pub fn new_from_buf(info: NAAudioInfo, data: NABufferRefT<u8>, chmap: NAChannelMap) -> Self {
5076115b
KS
169 let len = data.borrow().len();
170 NAAudioBuffer { info: info, data: data, chmap: chmap, offs: Vec::new(), len: len }
87a1ebc3
KS
171 }
172}
173
22cb00db
KS
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>),
87a1ebc3 181 AudioI32 (NAAudioBuffer<i32>),
22cb00db
KS
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()),
87a1ebc3
KS
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()),
22cb00db
KS
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;
6c8e5c40
KS
250 let mut offs: Vec<usize> = Vec::new();
251 let mut strides: Vec<usize> = Vec::new();
22cb00db
KS
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() {
6c8e5c40
KS
263 let ochr = fmt.get_chromaton(i);
264 if let None = ochr { continue; }
265 let chr = ochr.unwrap();
22cb00db
KS
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
bc6aac3d
KS
274 if fmt.is_paletted() {
275//todo various-sized palettes?
6c8e5c40
KS
276 let stride = vinfo.get_format().get_chromaton(0).unwrap().get_linesize(width);
277 let pic_sz = stride.checked_mul(height);
bc6aac3d
KS
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);
6c8e5c40
KS
283 offs.push(stride * height);
284 strides.push(stride);
bc6aac3d
KS
285 let mut data: Vec<u8> = Vec::with_capacity(new_size.unwrap());
286 data.resize(new_size.unwrap(), 0);
6c8e5c40 287 let buf: NAVideoBuffer<u8> = NAVideoBuffer { data: Rc::new(RefCell::new(data)), info: vinfo, offs: offs, strides: strides };
bc6aac3d
KS
288 Ok(NABufferType::Video(buf))
289 } else if !all_packed {
22cb00db 290 for i in 0..fmt.get_num_comp() {
6c8e5c40
KS
291 let ochr = fmt.get_chromaton(i);
292 if let None = ochr { continue; }
293 let chr = ochr.unwrap();
22cb00db
KS
294 if !vinfo.is_flipped() {
295 offs.push(new_size as usize);
296 }
6c8e5c40 297 let stride = chr.get_linesize(width);
22cb00db 298 let cur_h = chr.get_height(height);
6c8e5c40 299 let cur_sz = stride.checked_mul(cur_h);
22cb00db
KS
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 }
6c8e5c40 307 strides.push(stride);
22cb00db
KS
308 }
309 if max_depth <= 8 {
310 let mut data: Vec<u8> = Vec::with_capacity(new_size);
311 data.resize(new_size, 0);
6c8e5c40 312 let buf: NAVideoBuffer<u8> = NAVideoBuffer { data: Rc::new(RefCell::new(data)), info: vinfo, offs: offs, strides: strides };
22cb00db
KS
313 Ok(NABufferType::Video(buf))
314 } else {
315 let mut data: Vec<u16> = Vec::with_capacity(new_size);
316 data.resize(new_size, 0);
6c8e5c40 317 let buf: NAVideoBuffer<u16> = NAVideoBuffer { data: Rc::new(RefCell::new(data)), info: vinfo, offs: offs, strides: strides };
22cb00db
KS
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);
6c8e5c40
KS
329 strides.push(line_sz.unwrap());
330 let buf: NAVideoBuffer<u8> = NAVideoBuffer { data: Rc::new(RefCell::new(data)), info: vinfo, offs: offs, strides: strides };
22cb00db
KS
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);
5076115b 348 let buf: NAAudioBuffer<f32> = NAAudioBuffer { data: Rc::new(RefCell::new(data)), info: ainfo, offs: offs, chmap: chmap, len: nsamples };
22cb00db
KS
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);
5076115b 357 let buf: NAAudioBuffer<u8> = NAAudioBuffer { data: Rc::new(RefCell::new(data)), info: ainfo, offs: offs, chmap: chmap, len: nsamples };
22cb00db
KS
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);
5076115b 362 let buf: NAAudioBuffer<i16> = NAAudioBuffer { data: Rc::new(RefCell::new(data)), info: ainfo, offs: offs, chmap: chmap, len: nsamples };
22cb00db
KS
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);
5076115b 374 let buf: NAAudioBuffer<u8> = NAAudioBuffer { data: Rc::new(RefCell::new(data)), info: ainfo, offs: offs, chmap: chmap, len: nsamples };
22cb00db
KS
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
5869fd63 390#[allow(dead_code)]
8869d452
KS
391#[derive(Clone)]
392pub struct NACodecInfo {
ccae5343 393 name: &'static str,
5869fd63 394 properties: NACodecTypeInfo,
8869d452 395 extradata: Option<Rc<Vec<u8>>>,
5869fd63
KS
396}
397
8869d452 398impl NACodecInfo {
ccae5343 399 pub fn new(name: &'static str, p: NACodecTypeInfo, edata: Option<Vec<u8>>) -> Self {
8869d452
KS
400 let extradata = match edata {
401 None => None,
402 Some(vec) => Some(Rc::new(vec)),
403 };
ccae5343 404 NACodecInfo { name: name, properties: p, extradata: extradata }
8869d452 405 }
66116504
KS
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 }
8869d452
KS
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
5869fd63 413 }
66116504
KS
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 }
5076115b
KS
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 }
66116504
KS
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
66116504
KS
446#[derive(Debug,Clone)]
447pub enum NAValue {
5869fd63
KS
448 None,
449 Int(i32),
450 Long(i64),
451 String(String),
66116504 452 Data(Rc<Vec<u8>>),
5869fd63
KS
453}
454
88c03b61
KS
455#[derive(Debug,Clone,Copy,PartialEq)]
456#[allow(dead_code)]
457pub enum FrameType {
458 I,
459 P,
460 B,
bc6aac3d 461 Skip,
88c03b61
KS
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"),
bc6aac3d 471 FrameType::Skip => write!(f, "skip"),
88c03b61
KS
472 FrameType::Other => write!(f, "x"),
473 }
474 }
475}
476
e189501e
KS
477#[derive(Debug,Clone,Copy)]
478pub struct NATimeInfo {
5869fd63
KS
479 pts: Option<u64>,
480 dts: Option<u64>,
481 duration: Option<u64>,
e189501e
KS
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,
22cb00db 502 buffer: NABufferType,
66116504 503 info: Rc<NACodecInfo>,
88c03b61
KS
504 ftype: FrameType,
505 key: bool,
66116504
KS
506 options: HashMap<String, NAValue>,
507}
508
ebd71c92
KS
509pub type NAFrameRef = Rc<RefCell<NAFrame>>;
510
66116504
KS
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 {
e189501e 521 pub fn new(ts: NATimeInfo,
88c03b61
KS
522 ftype: FrameType,
523 keyframe: bool,
66116504 524 info: Rc<NACodecInfo>,
22cb00db
KS
525 options: HashMap<String, NAValue>,
526 buffer: NABufferType) -> Self {
e189501e 527 NAFrame { ts: ts, buffer: buffer, info: info, ftype: ftype, key: keyframe, options: options }
ebd71c92 528 }
5076115b 529 pub fn get_info(&self) -> Rc<NACodecInfo> { self.info.clone() }
88c03b61
KS
530 pub fn get_frame_type(&self) -> FrameType { self.ftype }
531 pub fn is_keyframe(&self) -> bool { self.key }
88c03b61
KS
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; }
e189501e
KS
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); }
66116504 541
22cb00db 542 pub fn get_buffer(&self) -> NABufferType { self.buffer.clone() }
5869fd63
KS
543}
544
ebd71c92
KS
545impl fmt::Display for NAFrame {
546 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22cb00db 547 let mut foo = format!("frame type {}", self.ftype);
e189501e
KS
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); }
ebd71c92
KS
551 if self.key { foo = format!("{} kf", foo); }
552 write!(f, "[{}]", foo)
553 }
554}
88c03b61 555
48c88fde
KS
556/// Possible stream types.
557#[derive(Debug,Clone,Copy)]
5869fd63 558#[allow(dead_code)]
48c88fde
KS
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>,
e189501e
KS
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)
5869fd63 608}
48c88fde
KS
609
610impl NAStream {
e189501e
KS
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 }
48c88fde
KS
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() }
e189501e
KS
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 }
48c88fde
KS
625}
626
627impl fmt::Display for NAStream {
628 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
e189501e 629 write!(f, "({}#{} @ {}/{} - {})", self.media_type, self.id, self.tb_num, self.tb_den, self.info.get_properties())
48c88fde
KS
630 }
631}
632
633#[allow(dead_code)]
634pub struct NAPacket {
635 stream: Rc<NAStream>,
e189501e 636 ts: NATimeInfo,
48c88fde
KS
637 buffer: Rc<Vec<u8>>,
638 keyframe: bool,
639// options: HashMap<String, NAValue<'a>>,
640}
641
642impl NAPacket {
e189501e 643 pub fn new(str: Rc<NAStream>, ts: NATimeInfo, kf: bool, vec: Vec<u8>) -> Self {
48c88fde
KS
644// let mut vec: Vec<u8> = Vec::new();
645// vec.resize(size, 0);
e189501e 646 NAPacket { stream: str, ts: ts, keyframe: kf, buffer: Rc::new(vec) }
48c88fde
KS
647 }
648 pub fn get_stream(&self) -> Rc<NAStream> { self.stream.clone() }
e189501e
KS
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() }
48c88fde
KS
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());
e189501e
KS
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); }
48c88fde
KS
667 if self.keyframe { foo = format!("{} kf", foo); }
668 foo = foo + "]";
669 write!(f, "{}", foo)
670 }
671}
672
673pub trait FrameFromPacket {
22cb00db 674 fn new_from_pkt(pkt: &NAPacket, info: Rc<NACodecInfo>, buf: NABufferType) -> NAFrame;
48c88fde
KS
675 fn fill_timestamps(&mut self, pkt: &NAPacket);
676}
677
678impl FrameFromPacket for NAFrame {
22cb00db 679 fn new_from_pkt(pkt: &NAPacket, info: Rc<NACodecInfo>, buf: NABufferType) -> NAFrame {
e189501e 680 NAFrame::new(pkt.ts, FrameType::Other, pkt.keyframe, info, HashMap::new(), buf)
48c88fde
KS
681 }
682 fn fill_timestamps(&mut self, pkt: &NAPacket) {
e189501e 683 self.ts = pkt.get_time_information();
48c88fde
KS
684 }
685}
686