X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-core%2Fsrc%2Fframe.rs;h=1bf5dec96cfcaec1ad2c5814e82321f308acef18;hb=e6aaad5c5273cd814b5748b7faf3751835a37217;hp=8c58e19b66756c2ebbcaf45fb981cc245ac37394;hpb=a480a0de101483d802a11e72d758dae00fa4860a;p=nihav.git diff --git a/nihav-core/src/frame.rs b/nihav-core/src/frame.rs index 8c58e19..1bf5dec 100644 --- a/nihav-core/src/frame.rs +++ b/nihav-core/src/frame.rs @@ -65,9 +65,9 @@ impl NAVideoInfo { NAVideoInfo { width: w, height: h, flipped: flip, format: fmt, bits } } /// Returns picture width. - pub fn get_width(&self) -> usize { self.width as usize } + pub fn get_width(&self) -> usize { self.width } /// Returns picture height. - pub fn get_height(&self) -> usize { self.height as usize } + pub fn get_height(&self) -> usize { self.height } /// Returns picture orientation. pub fn is_flipped(&self) -> bool { self.flipped } /// Returns picture pixel format. @@ -112,17 +112,11 @@ impl NACodecTypeInfo { } /// Reports whether the current stream is video stream. pub fn is_video(&self) -> bool { - match *self { - NACodecTypeInfo::Video(_) => true, - _ => false, - } + matches!(*self, NACodecTypeInfo::Video(_)) } /// Reports whether the current stream is audio stream. pub fn is_audio(&self) -> bool { - match *self { - NACodecTypeInfo::Audio(_) => true, - _ => false, - } + matches!(*self, NACodecTypeInfo::Audio(_)) } } @@ -150,6 +144,10 @@ pub struct NAVideoBuffer { } impl NAVideoBuffer { + /// Constructs video buffer from the provided components. + pub fn from_raw_parts(info: NAVideoInfo, data: NABufferRef>, offs: Vec, strides: Vec) -> Self { + Self { info, data, offs, strides } + } /// Returns the component offset (0 for all unavailable offsets). pub fn get_offset(&self, idx: usize) -> usize { if idx >= self.offs.len() { 0 } @@ -164,7 +162,7 @@ impl NAVideoBuffer { /// Returns the number of components in picture format. pub fn get_num_components(&self) -> usize { self.offs.len() } /// Creates a copy of current `NAVideoBuffer`. - pub fn copy_buffer(&mut self) -> Self { + pub fn copy_buffer(&self) -> Self { let mut data: Vec = Vec::with_capacity(self.data.len()); data.clone_from(self.data.as_ref()); let mut offs: Vec = Vec::with_capacity(self.offs.len()); @@ -273,7 +271,8 @@ impl NAAudioBuffer { impl NAAudioBuffer { /// Constructs a new `NAAudioBuffer` instance. pub fn new_from_buf(info: NAAudioInfo, data: NABufferRef>, chmap: NAChannelMap) -> Self { - let len = data.len(); + let len = data.len() * 8 / chmap.num_channels() / (info.format.bits as usize); + NAAudioBuffer { info, data, chmap, offs: Vec::new(), len, stride: 0, step: 0 } } } @@ -386,6 +385,17 @@ impl NABufferType { _ => 0, } } + /// Truncates audio frame duration if possible. + pub fn truncate_audio(&mut self, len: usize) { + match *self { + NABufferType::AudioU8(ref mut ab) => ab.truncate(len), + NABufferType::AudioI16(ref mut ab) => ab.truncate(len), + NABufferType::AudioI32(ref mut ab) => ab.truncate(len), + NABufferType::AudioF32(ref mut ab) => ab.truncate(len), + NABufferType::AudioPacked(ref mut ab) => ab.truncate(len), + _ => {}, + }; + } /// Returns the distance between starts of two channels. pub fn get_audio_stride(&self) -> usize { match *self { @@ -525,12 +535,12 @@ pub fn alloc_video_buffer(vinfo: NAVideoInfo, align: u8) -> Result = Vec::new(); for i in 0..fmt.get_num_comp() { - if fmt.get_chromaton(i) == None { return Err(AllocatorError::FormatError); } + if fmt.get_chromaton(i).is_none() { return Err(AllocatorError::FormatError); } } let align_mod = ((1 << align) as usize) - 1; - let width = ((vinfo.width as usize) + align_mod) & !align_mod; - let height = ((vinfo.height as usize) + align_mod) & !align_mod; + let width = (vinfo.width + align_mod) & !align_mod; + let height = (vinfo.height + align_mod) & !align_mod; let mut max_depth = 0; let mut all_packed = true; let mut all_bytealigned = true; @@ -545,20 +555,17 @@ pub fn alloc_video_buffer(vinfo: NAVideoInfo, align: u8) -> Result false, - _ => true, - }; + let unfit_elem_size = !matches!(fmt.get_elem_size(), 2 | 4); //todo semi-packed like NV12 if fmt.is_paletted() { //todo various-sized palettes? let stride = vinfo.get_format().get_chromaton(0).unwrap().get_linesize(width); let pic_sz = stride.checked_mul(height); - if pic_sz == None { return Err(AllocatorError::TooLargeDimensions); } + if pic_sz.is_none() { return Err(AllocatorError::TooLargeDimensions); } let pal_size = 256 * (fmt.get_elem_size() as usize); let new_size = pic_sz.unwrap().checked_add(pal_size); - if new_size == None { return Err(AllocatorError::TooLargeDimensions); } + if new_size.is_none() { return Err(AllocatorError::TooLargeDimensions); } offs.push(0); offs.push(stride * height); strides.push(stride); @@ -570,13 +577,13 @@ pub fn alloc_video_buffer(vinfo: NAVideoInfo, align: u8) -> Result Result = vec![0; new_size]; strides.push(line_sz.unwrap()); @@ -607,7 +614,7 @@ pub fn alloc_video_buffer(vinfo: NAVideoInfo, align: u8) -> Result { @@ -629,11 +636,12 @@ pub fn alloc_video_buffer(vinfo: NAVideoInfo, align: u8) -> Result Result { let mut offs: Vec = Vec::new(); 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); } + if len.is_none() { return Err(AllocatorError::TooLargeDimensions); } let length = len.unwrap(); let stride; let step; @@ -677,7 +685,7 @@ pub fn alloc_audio_buffer(ainfo: NAAudioInfo, nsamples: usize, chmap: NAChannelM } } else { let len = nsamples.checked_mul(ainfo.channels as usize); - if len == None { return Err(AllocatorError::TooLargeDimensions); } + if len.is_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, step: 0 }; @@ -693,7 +701,7 @@ pub fn alloc_data_buffer(size: usize) -> Result { } /// Creates a clone of current buffer. -pub fn copy_buffer(buf: NABufferType) -> NABufferType { +pub fn copy_buffer(buf: &NABufferType) -> NABufferType { buf.clone() } @@ -737,7 +745,23 @@ impl NAVideoBufferPool { } /// Clears the pool from all frames. pub fn reset(&mut self) { - self.pool.truncate(0); + self.pool.clear(); + } + /// Returns the number of frames currently in use. + pub fn get_num_used(&self) -> usize { + self.pool.iter().filter(|el| el.get_num_refs() != 1).count() + } + /// Adds a manually allocated frame to the pool. + pub fn add_frame(&mut self, buf: NAVideoBufferRef) { + self.pool.push(buf); + } + /// Returns current video format (if available). + pub fn get_info(&self) -> Option { + if !self.pool.is_empty() { + Some(self.pool[0].get_info()) + } else { + None + } } } @@ -812,11 +836,7 @@ pub type NACodecInfoRef = Arc; impl NACodecInfo { /// Constructs a new instance of `NACodecInfo`. pub fn new(name: &'static str, p: NACodecTypeInfo, edata: Option>) -> Self { - let extradata = match edata { - None => None, - Some(vec) => Some(Arc::new(vec)), - }; - NACodecInfo { name, properties: p, extradata } + NACodecInfo { name, properties: p, extradata: edata.map(Arc::new) } } /// Constructs a new reference-counted instance of `NACodecInfo`. pub fn new_ref(name: &'static str, p: NACodecTypeInfo, edata: Option>>) -> Self { @@ -937,23 +957,28 @@ impl NATimeInfo { pub fn set_duration(&mut self, dur: Option) { self.duration = dur; } /// Converts time in given scale into timestamp in given base. + #[allow(clippy::collapsible_if)] + #[allow(clippy::collapsible_else_if)] pub fn time_to_ts(time: u64, base: u64, tb_num: u32, tb_den: u32) -> u64 { let tb_num = u64::from(tb_num); let tb_den = u64::from(tb_den); - let tmp = time.checked_mul(tb_num); + let tmp = time.checked_mul(tb_den); if let Some(tmp) = tmp { - tmp / base / tb_den + tmp / base / tb_num } else { - let tmp = time.checked_mul(tb_num); - if let Some(tmp) = tmp { - tmp / base / tb_den + if tb_num < base { + let coarse = time / tb_num; + if let Some(tmp) = coarse.checked_mul(tb_den) { + tmp / base + } else { + (coarse / base) * tb_den + } } else { let coarse = time / base; - let tmp = coarse.checked_mul(tb_num); - if let Some(tmp) = tmp { - tmp / tb_den + if let Some(tmp) = coarse.checked_mul(tb_den) { + tmp / tb_num } else { - (coarse / tb_den) * tb_num + (coarse / tb_num) * tb_den } } } @@ -1009,22 +1034,17 @@ impl NATimeInfo { } /// Time information for specifying durations or seek positions. -#[derive(Clone,Copy,Debug,PartialEq)] +#[derive(Clone,Copy,Debug,PartialEq,Default)] pub enum NATimePoint { /// Time in milliseconds. Milliseconds(u64), /// Stream timestamp. PTS(u64), /// No time information present. + #[default] None, } -impl Default for NATimePoint { - fn default() -> Self { - NATimePoint::None - } -} - impl fmt::Display for NATimePoint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -1126,7 +1146,7 @@ impl FromStr for NATimePoint { let mut mval = 0; let mut base = 0; for ch in val.chars() { - if ch >= '0' && ch <= '9' { + if ch.is_ascii_digit() { mval = mval * 10 + u64::from((ch as u8) - b'0'); base += 1; if base > 3 { break; } @@ -1297,6 +1317,7 @@ pub struct NAStream { pub type NAStreamRef = Arc; /// Downscales the timebase by its greatest common denominator. +#[allow(clippy::comparison_chain)] pub fn reduce_timebase(tb_num: u32, tb_den: u32) -> (u32, u32) { if tb_num == 0 { return (tb_num, tb_den); } if (tb_den % tb_num) == 0 { return (1, tb_den / tb_num); } @@ -1337,7 +1358,11 @@ impl NAStream { self.tb_den = d; } /// Returns stream duration. - pub fn get_duration(&self) -> usize { self.num } + pub fn get_duration(&self) -> u64 { self.duration } + /// Constructs a new timestamp. + pub fn make_ts(&self, pts: Option, dts: Option, duration: Option) -> NATimeInfo { + NATimeInfo::new(pts, dts, duration, self.tb_num, self.tb_den) + } /// Converts current instance into a reference-counted one. pub fn into_ref(self) -> NAStreamRef { Arc::new(self) } } @@ -1376,14 +1401,14 @@ pub struct NAPacket { impl NAPacket { /// Constructs a new `NAPacket` instance. - pub fn new(str: NAStreamRef, ts: NATimeInfo, kf: bool, vec: Vec) -> Self { + pub fn new(stream: 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), side_data: Vec::new() } + NAPacket { stream, 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() } + pub fn new_from_refbuf(stream: NAStreamRef, ts: NATimeInfo, kf: bool, buffer: NABufferRef>) -> Self { + NAPacket { stream, 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() } @@ -1402,8 +1427,8 @@ impl NAPacket { /// 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; + pub fn reassign(&mut self, stream: NAStreamRef, ts: NATimeInfo) { + self.stream = stream; self.ts = ts; } } @@ -1424,6 +1449,37 @@ impl fmt::Display for NAPacket { } } +/// Packet with a piece of data for a raw stream. +pub struct NARawData { + stream: NAStreamRef, + buffer: NABufferRef>, +} + +impl NARawData { + /// Constructs a new `NARawData` instance. + pub fn new(stream: NAStreamRef, vec: Vec) -> Self { + Self { stream, buffer: NABufferRef::new(vec) } + } + /// Constructs a new `NARawData` instance reusing a buffer reference. + pub fn new_from_refbuf(stream: NAStreamRef, buffer: NABufferRef>) -> Self { + Self { stream, buffer } + } + /// Returns information about the stream this data belongs to. + pub fn get_stream(&self) -> NAStreamRef { self.stream.clone() } + /// Returns a reference to packet data. + pub fn get_buffer(&self) -> NABufferRef> { self.buffer.clone() } + /// Assigns raw data to a new stream. + pub fn reassign(&mut self, stream: NAStreamRef) { + self.stream = stream; + } +} + +impl fmt::Display for NARawData { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[raw data for {} size {}]", self.stream, self.buffer.len()) + } +} + #[cfg(test)] mod test { use super::*;