X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-core%2Fsrc%2Fframe.rs;h=31cf8e81991a519d26827e13913175a6d3cd1dd6;hp=f0794a86f9eeac3874bdfd2917c0aa3119304565;hb=a1298b7a5dcf1656dfc9bdbf3d6c80df89a70fc8;hpb=2c6462c81d1c18ccb26a6262400b33108e983820 diff --git a/nihav-core/src/frame.rs b/nihav-core/src/frame.rs index f0794a8..31cf8e8 100644 --- a/nihav-core/src/frame.rs +++ b/nihav-core/src/frame.rs @@ -150,6 +150,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 } @@ -251,6 +255,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 +390,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 { @@ -661,6 +682,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 +708,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() } @@ -927,23 +952,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,6 +998,33 @@ impl NATimeInfo { } } } + 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) + } + /// Checks whether the current time information is earler than provided reference time. + pub fn less_than(&self, time: NATimePoint) -> bool { + if self.pts.is_none() && self.dts.is_none() { + return true; + } + match time { + NATimePoint::PTS(rpts) => self.get_cur_ts() < rpts, + NATimePoint::Milliseconds(ms) => self.get_cur_millis() < ms, + NATimePoint::None => false, + } + } + /// Checks whether the current time information is the same as provided reference time. + pub fn equal(&self, time: NATimePoint) -> bool { + if self.pts.is_none() && self.dts.is_none() { + return time == NATimePoint::None; + } + match time { + NATimePoint::PTS(rpts) => self.get_cur_ts() == rpts, + NATimePoint::Milliseconds(ms) => self.get_cur_millis() == ms, + NATimePoint::None => false, + } + } } /// Time information for specifying durations or seek positions. @@ -978,6 +1034,14 @@ pub enum NATimePoint { Milliseconds(u64), /// Stream timestamp. PTS(u64), + /// No time information present. + None, +} + +impl Default for NATimePoint { + fn default() -> Self { + NATimePoint::None + } } impl fmt::Display for NATimePoint { @@ -1013,6 +1077,9 @@ impl fmt::Display for NATimePoint { NATimePoint::PTS(pts) => { write!(f, "{}pts", pts) }, + NATimePoint::None => { + write!(f, "none") + }, } } } @@ -1073,7 +1140,7 @@ impl FromStr for NATimePoint { let ret = parts.next().unwrap().parse::(); if ret.is_err() { return Err(FormatParseError {}); } let seconds = ret.unwrap(); - if seconds >= 60 { return Err(FormatParseError {}); } + if mins.is_some() && seconds >= 60 { return Err(FormatParseError {}); } let millis = if let Some(val) = parts.next() { let mut mval = 0; let mut base = 0; @@ -1241,12 +1308,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); } @@ -1264,9 +1334,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 } @@ -1286,6 +1356,8 @@ impl NAStream { self.tb_num = n; self.tb_den = d; } + /// Returns stream duration. + pub fn get_duration(&self) -> usize { self.num } /// Converts current instance into a reference-counted one. pub fn into_ref(self) -> NAStreamRef { Arc::new(self) } }