X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-core%2Fsrc%2Fframe.rs;h=8944f45bf5de6453c0990aec892f283cfc778b68;hb=b36f412c24813b14cb2b1f8fd151863e2a49c1e2;hp=95bad262b9ae94e927543d191db4138c1466d4a1;hpb=2b8bf9a03242bbd6e80091082a50ec13b1a95143;p=nihav.git diff --git a/nihav-core/src/frame.rs b/nihav-core/src/frame.rs index 95bad26..8944f45 100644 --- a/nihav-core/src/frame.rs +++ b/nihav-core/src/frame.rs @@ -2,7 +2,7 @@ use std::cmp::max; //use std::collections::HashMap; use std::fmt; -use std::sync::Arc; +pub use std::sync::Arc; pub use crate::formats::*; pub use crate::refs::*; @@ -53,12 +53,15 @@ pub struct NAVideoInfo { pub flipped: bool, /// Picture pixel format. pub format: NAPixelFormaton, + /// Declared bits per sample. + pub bits: u8, } impl NAVideoInfo { /// Constructs a new `NAVideoInfo` instance. pub fn new(w: usize, h: usize, flip: bool, fmt: NAPixelFormaton) -> Self { - NAVideoInfo { width: w, height: h, flipped: flip, format: fmt } + let bits = fmt.get_total_depth(); + NAVideoInfo { width: w, height: h, flipped: flip, format: fmt, bits } } /// Returns picture width. pub fn get_width(&self) -> usize { self.width as usize } @@ -182,6 +185,21 @@ impl NAVideoBuffer { pub fn into_ref(self) -> NABufferRef { NABufferRef::new(self) } + + fn print_contents(&self, datatype: &str) { + println!("{} video buffer size {}", datatype, self.data.len()); + println!(" format {}", self.info); + print!(" offsets:"); + for off in self.offs.iter() { + print!(" {}", *off); + } + println!(); + print!(" strides:"); + for stride in self.strides.iter() { + print!(" {}", *stride); + } + println!(); + } } /// A specialised type for reference-counted `NAVideoBuffer`. @@ -197,6 +215,7 @@ pub struct NAAudioBuffer { data: NABufferRef>, offs: Vec, stride: usize, + step: usize, chmap: NAChannelMap, len: usize, } @@ -209,12 +228,16 @@ impl NAAudioBuffer { } /// Returns the distance between the start of one channel and the next one. pub fn get_stride(&self) -> usize { self.stride } + /// Returns the distance between the samples in one channel. + pub fn get_step(&self) -> usize { self.step } /// Returns audio format information. pub fn get_info(&self) -> NAAudioInfo { self.info } /// Returns channel map. pub fn get_chmap(&self) -> &NAChannelMap { &self.chmap } /// Returns an immutable reference to the data. pub fn get_data(&self) -> &Vec { self.data.as_ref() } + /// Returns reference to the data. + pub fn get_data_ref(&self) -> NABufferRef> { self.data.clone() } /// Returns a mutable reference to the data. pub fn get_data_mut(&mut self) -> Option<&mut Vec> { self.data.as_mut() } /// Clones current `NAAudioBuffer` into a new one. @@ -223,17 +246,28 @@ impl NAAudioBuffer { data.clone_from(self.data.as_ref()); let mut offs: Vec = Vec::with_capacity(self.offs.len()); offs.clone_from(&self.offs); - NAAudioBuffer { info: self.info, data: NABufferRef::new(data), offs, chmap: self.get_chmap().clone(), len: self.len, stride: self.stride } + NAAudioBuffer { info: self.info, data: NABufferRef::new(data), offs, chmap: self.get_chmap().clone(), len: self.len, stride: self.stride, step: self.step } } /// Return the length of frame in samples. pub fn get_length(&self) -> usize { self.len } + + fn print_contents(&self, datatype: &str) { + println!("Audio buffer with {} data, stride {}, step {}", datatype, self.stride, self.step); + println!(" format {}", self.info); + println!(" channel map {}", self.chmap); + print!(" offsets:"); + for off in self.offs.iter() { + print!(" {}", *off); + } + println!(); + } } impl NAAudioBuffer { /// Constructs a new `NAAudioBuffer` instance. pub fn new_from_buf(info: NAAudioInfo, data: NABufferRef>, chmap: NAChannelMap) -> Self { let len = data.len(); - NAAudioBuffer { info, data, chmap, offs: Vec::new(), len, stride: 0 } + NAAudioBuffer { info, data, chmap, offs: Vec::new(), len, stride: 0, step: 0 } } } @@ -274,6 +308,7 @@ impl NABufferType { NABufferType::VideoPacked(ref vb) => vb.get_offset(idx), NABufferType::AudioU8(ref ab) => ab.get_offset(idx), NABufferType::AudioI16(ref ab) => ab.get_offset(idx), + NABufferType::AudioI32(ref ab) => ab.get_offset(idx), NABufferType::AudioF32(ref ab) => ab.get_offset(idx), NABufferType::AudioPacked(ref ab) => ab.get_offset(idx), _ => 0, @@ -355,6 +390,17 @@ impl NABufferType { _ => 0, } } + /// Returns the distance between two samples in one channel. + pub fn get_audio_step(&self) -> usize { + match *self { + NABufferType::AudioU8(ref ab) => ab.get_step(), + NABufferType::AudioI16(ref ab) => ab.get_step(), + NABufferType::AudioI32(ref ab) => ab.get_step(), + NABufferType::AudioF32(ref ab) => ab.get_step(), + NABufferType::AudioPacked(ref ab) => ab.get_step(), + _ => 0, + } + } /// Returns reference to 8-bit (or packed) audio buffer. pub fn get_abuf_u8(&self) -> Option> { match *self { @@ -384,6 +430,22 @@ impl NABufferType { _ => None, } } + /// Prints internal buffer layout. + pub fn print_buffer_metadata(&self) { + match *self { + NABufferType::Video(ref buf) => buf.print_contents("8-bit"), + NABufferType::Video16(ref buf) => buf.print_contents("16-bit"), + NABufferType::Video32(ref buf) => buf.print_contents("32-bit"), + NABufferType::VideoPacked(ref buf) => buf.print_contents("packed"), + NABufferType::AudioU8(ref buf) => buf.print_contents("8-bit unsigned integer"), + NABufferType::AudioI16(ref buf) => buf.print_contents("16-bit integer"), + NABufferType::AudioI32(ref buf) => buf.print_contents("32-bit integer"), + NABufferType::AudioF32(ref buf) => buf.print_contents("32-bit float"), + NABufferType::AudioPacked(ref buf) => buf.print_contents("packed"), + NABufferType::Data(ref buf) => { println!("Data buffer, len = {}", buf.len()); }, + NABufferType::None => { println!("No buffer"); }, + }; + } } const NA_SIMPLE_VFRAME_COMPONENTS: usize = 4; @@ -562,18 +624,29 @@ pub fn alloc_video_buffer(vinfo: NAVideoInfo, align: u8) -> Result Result { let mut offs: Vec = Vec::new(); - if ainfo.format.is_planar() || (ainfo.channels == 1 && (ainfo.format.get_bits() % 8) == 0) { + if ainfo.format.is_planar() || ((ainfo.format.get_bits() % 8) == 0) { let len = nsamples.checked_mul(ainfo.channels as usize); if len == None { return Err(AllocatorError::TooLargeDimensions); } let length = len.unwrap(); - let stride = nsamples; - for i in 0..ainfo.channels { - offs.push((i as usize) * stride); + let stride; + let step; + if ainfo.format.is_planar() { + stride = nsamples; + step = 1; + for i in 0..ainfo.channels { + offs.push((i as usize) * stride); + } + } else { + stride = 1; + step = ainfo.channels as usize; + for i in 0..ainfo.channels { + offs.push(i as usize); + } } if ainfo.format.is_float() { if ainfo.format.get_bits() == 32 { let data: Vec = vec![0.0; length]; - let buf: NAAudioBuffer = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride }; + let buf: NAAudioBuffer = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride, step }; Ok(NABufferType::AudioF32(buf)) } else { Err(AllocatorError::TooLargeDimensions) @@ -581,11 +654,11 @@ pub fn alloc_audio_buffer(ainfo: NAAudioInfo, nsamples: usize, chmap: NAChannelM } else { if ainfo.format.get_bits() == 8 && !ainfo.format.is_signed() { let data: Vec = vec![0; length]; - let buf: NAAudioBuffer = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride }; + let buf: NAAudioBuffer = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride, step }; Ok(NABufferType::AudioU8(buf)) } else if ainfo.format.get_bits() == 16 && ainfo.format.is_signed() { let data: Vec = vec![0; length]; - let buf: NAAudioBuffer = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride }; + let buf: NAAudioBuffer = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride, step }; Ok(NABufferType::AudioI16(buf)) } else { Err(AllocatorError::TooLargeDimensions) @@ -596,7 +669,7 @@ pub fn alloc_audio_buffer(ainfo: NAAudioInfo, nsamples: usize, chmap: NAChannelM if len == None { return Err(AllocatorError::TooLargeDimensions); } let length = ainfo.format.get_audio_size(len.unwrap() as u64); let data: Vec = vec![0; length]; - let buf: NAAudioBuffer = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride: 0 }; + let buf: NAAudioBuffer = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride: 0, step: 0 }; Ok(NABufferType::AudioPacked(buf)) } } @@ -789,21 +862,6 @@ pub const DUMMY_CODEC_INFO: NACodecInfo = NACodecInfo { properties: NACodecTypeInfo::None, extradata: None }; -/// A list of accepted option values. -#[derive(Debug,Clone)] -pub enum NAValue { - /// Empty value. - None, - /// Integer value. - Int(i32), - /// Long integer value. - Long(i64), - /// String value. - String(String), - /// Binary data value. - Data(Arc>), -} - /// A list of recognized frame types. #[derive(Debug,Clone,Copy,PartialEq)] #[allow(dead_code)] @@ -869,8 +927,8 @@ impl NATimeInfo { /// Converts time in given scale into timestamp in given base. pub fn time_to_ts(time: u64, base: u64, tb_num: u32, tb_den: u32) -> u64 { - let tb_num = tb_num as u64; - let tb_den = tb_den as u64; + let tb_num = u64::from(tb_num); + let tb_den = u64::from(tb_den); let tmp = time.checked_mul(tb_num); if let Some(tmp) = tmp { tmp / base / tb_den @@ -891,8 +949,8 @@ impl NATimeInfo { } /// Converts timestamp in given base into time in given scale. pub fn ts_to_time(ts: u64, base: u64, tb_num: u32, tb_den: u32) -> u64 { - let tb_num = tb_num as u64; - let tb_den = tb_den as u64; + let tb_num = u64::from(tb_num); + let tb_den = u64::from(tb_den); let tmp = ts.checked_mul(base); if let Some(tmp) = tmp { let tmp2 = tmp.checked_mul(tb_num); @@ -1099,6 +1157,18 @@ impl fmt::Display for NAStream { } } +/// Side data that may accompany demuxed data. +#[derive(Clone)] +pub enum NASideData { + /// Palette information. + /// + /// This side data contains a flag signalling that palette has changed since previous time and a reference to the current palette. + /// Palette is stored in 8-bit RGBA format. + Palette(bool, Arc<[u8; 1024]>), + /// Generic user data. + UserData(Arc>), +} + /// Packet with compressed data. #[allow(dead_code)] pub struct NAPacket { @@ -1109,6 +1179,8 @@ pub struct NAPacket { /// Keyframe flag. pub keyframe: bool, // options: HashMap>, + /// Packet side data (e.g. palette for paletted formats). + pub side_data: Vec, } impl NAPacket { @@ -1116,7 +1188,11 @@ impl NAPacket { pub fn new(str: NAStreamRef, ts: NATimeInfo, kf: bool, vec: Vec) -> Self { // let mut vec: Vec = Vec::new(); // vec.resize(size, 0); - NAPacket { stream: str, ts, keyframe: kf, buffer: NABufferRef::new(vec) } + NAPacket { stream: str, ts, keyframe: kf, buffer: NABufferRef::new(vec), side_data: Vec::new() } + } + /// Constructs a new `NAPacket` instance reusing a buffer reference. + pub fn new_from_refbuf(str: NAStreamRef, ts: NATimeInfo, kf: bool, buffer: NABufferRef>) -> Self { + NAPacket { stream: str, ts, keyframe: kf, buffer, side_data: Vec::new() } } /// Returns information about the stream packet belongs to. pub fn get_stream(&self) -> NAStreamRef { self.stream.clone() } @@ -1132,6 +1208,13 @@ impl NAPacket { pub fn is_keyframe(&self) -> bool { self.keyframe } /// Returns a reference to packet data. pub fn get_buffer(&self) -> NABufferRef> { self.buffer.clone() } + /// Adds side data for a packet. + pub fn add_side_data(&mut self, side_data: NASideData) { self.side_data.push(side_data); } + /// Assigns packet to a new stream. + pub fn reassign(&mut self, str: NAStreamRef, ts: NATimeInfo) { + self.stream = str; + self.ts = ts; + } } impl Drop for NAPacket {