X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-core%2Fsrc%2Fframe.rs;h=fbdbdf5e391f533e5c75c2fb90b4cd5f11d07248;hb=6f2630992fe340ad1a122ec10c649f756e478185;hp=e6757cf51c0592a48efe2fcf53a48dcf9a1fcc1b;hpb=dcabdfd2eea01174f46548a8e2166ab88d0de96b;p=nihav.git diff --git a/nihav-core/src/frame.rs b/nihav-core/src/frame.rs index e6757cf..fbdbdf5 100644 --- a/nihav-core/src/frame.rs +++ b/nihav-core/src/frame.rs @@ -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()); @@ -251,6 +249,12 @@ impl NAAudioBuffer { } /// Return the length of frame in samples. pub fn get_length(&self) -> usize { self.len } + /// Truncates buffer length if possible. + /// + /// In case when new length is larger than old length nothing is done. + pub fn truncate(&mut self, new_len: usize) { + self.len = self.len.min(new_len); + } fn print_contents(&self, datatype: &str) { println!("Audio buffer with {} data, stride {}, step {}", datatype, self.stride, self.step); @@ -380,6 +384,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 { @@ -539,10 +554,7 @@ 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() { @@ -661,6 +673,10 @@ pub fn alloc_audio_buffer(ainfo: NAAudioInfo, nsamples: usize, chmap: NAChannelM let data: Vec = vec![0; length]; let buf: NAAudioBuffer = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride, step }; Ok(NABufferType::AudioI16(buf)) + } else if ainfo.format.get_bits() == 32 && 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, step }; + Ok(NABufferType::AudioI32(buf)) } else { Err(AllocatorError::TooLargeDimensions) } @@ -683,7 +699,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() } @@ -727,7 +743,7 @@ impl NAVideoBufferPool { } /// Clears the pool from all frames. pub fn reset(&mut self) { - self.pool.truncate(0); + self.pool.clear(); } } @@ -802,11 +818,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 { @@ -927,23 +939,27 @@ 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)] 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 } } } @@ -969,7 +985,7 @@ impl NATimeInfo { } } } - fn get_cur_ts(&self) -> u64 { self.pts.unwrap_or(self.dts.unwrap_or(0)) } + fn get_cur_ts(&self) -> u64 { self.pts.unwrap_or_else(|| self.dts.unwrap_or(0)) } fn get_cur_millis(&self) -> u64 { let ts = self.get_cur_ts(); Self::ts_to_time(ts, 1000, self.tb_num, self.tb_den) @@ -1009,6 +1025,12 @@ pub enum NATimePoint { 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 { @@ -1110,7 +1132,7 @@ impl FromStr for NATimePoint { let mut mval = 0; let mut base = 0; for ch in val.chars() { - if ch >= '0' && ch <= '9' { + if ('0'..='9').contains(&ch) { mval = mval * 10 + u64::from((ch as u8) - b'0'); base += 1; if base > 3 { break; } @@ -1273,12 +1295,15 @@ pub struct NAStream { pub tb_num: u32, /// Timebase denominator. pub tb_den: u32, + /// Duration in timebase units (zero if not available). + pub duration: u64, } /// A specialised reference-counted `NAStream` type. 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); } @@ -1296,9 +1321,9 @@ pub fn reduce_timebase(tb_num: u32, tb_den: u32) -> (u32, u32) { impl NAStream { /// Constructs a new `NAStream` instance. - pub fn new(mt: StreamType, id: u32, info: NACodecInfo, tb_num: u32, tb_den: u32) -> Self { + pub fn new(mt: StreamType, id: u32, info: NACodecInfo, tb_num: u32, tb_den: u32, duration: u64) -> Self { let (n, d) = reduce_timebase(tb_num, tb_den); - NAStream { media_type: mt, id, num: 0, info: info.into_ref(), tb_num: n, tb_den: d } + NAStream { media_type: mt, id, num: 0, info: info.into_ref(), tb_num: n, tb_den: d, duration } } /// Returns stream id. pub fn get_id(&self) -> u32 { self.id } @@ -1318,6 +1343,8 @@ impl NAStream { self.tb_num = n; self.tb_den = d; } + /// Returns stream duration. + pub fn get_duration(&self) -> u64 { self.duration } /// Converts current instance into a reference-counted one. pub fn into_ref(self) -> NAStreamRef { Arc::new(self) } } @@ -1404,6 +1431,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::*;