core/frame: add proper function for audio frame truncation
[nihav.git] / nihav-core / src / frame.rs
index fbccfbee0a5d3106f0e14f323110548e669d202c..31cf8e81991a519d26827e13913175a6d3cd1dd6 100644 (file)
@@ -150,6 +150,10 @@ pub struct NAVideoBuffer<T> {
 }
 
 impl<T: Clone> NAVideoBuffer<T> {
+    /// Constructs video buffer from the provided components.
+    pub fn from_raw_parts(info: NAVideoInfo, data: NABufferRef<Vec<T>>, offs: Vec<usize>, strides: Vec<usize>) -> 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 }
@@ -386,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 {
@@ -693,7 +708,7 @@ pub fn alloc_data_buffer(size: usize) -> Result<NABufferType, AllocatorError> {
 }
 
 /// Creates a clone of current buffer.
-pub fn copy_buffer(buf: NABufferType) -> NABufferType {
+pub fn copy_buffer(buf: &NABufferType) -> NABufferType {
     buf.clone()
 }
 
@@ -937,23 +952,27 @@ impl NATimeInfo {
     pub fn set_duration(&mut self, dur: Option<u64>) { 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
                 }
             }
         }
@@ -1289,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<NAStream>;
 
 /// 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); }
@@ -1312,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 }
@@ -1334,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) }
 }