introduce stream and container duration
[nihav.git] / nihav-core / src / frame.rs
index f0794a86f9eeac3874bdfd2917c0aa3119304565..8c58e19b66756c2ebbcaf45fb981cc245ac37394 100644 (file)
@@ -251,6 +251,12 @@ impl<T: Clone> NAAudioBuffer<T> {
     }
     /// 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);
@@ -661,6 +667,10 @@ pub fn alloc_audio_buffer(ainfo: NAAudioInfo, nsamples: usize, chmap: NAChannelM
                 let data: Vec<i16> = vec![0; length];
                 let buf: NAAudioBuffer<i16> = 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<i32> = vec![0; length];
+                let buf: NAAudioBuffer<i32> = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride, step };
+                Ok(NABufferType::AudioI32(buf))
             } else {
                 Err(AllocatorError::TooLargeDimensions)
             }
@@ -969,6 +979,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 +1015,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 +1058,9 @@ impl fmt::Display for NATimePoint {
             NATimePoint::PTS(pts) => {
                 write!(f, "{}pts", pts)
             },
+            NATimePoint::None => {
+                write!(f, "none")
+            },
         }
     }
 }
@@ -1073,7 +1121,7 @@ impl FromStr for NATimePoint {
                     let ret = parts.next().unwrap().parse::<u64>();
                     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,6 +1289,8 @@ 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.
@@ -1264,9 +1314,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 +1336,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) }
 }