core: add frame reordering functionality
authorKostya Shishkov <kostya.shishkov@gmail.com>
Tue, 12 Nov 2019 17:48:10 +0000 (18:48 +0100)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Tue, 12 Nov 2019 17:48:10 +0000 (18:48 +0100)
nihav-core/src/lib.rs
nihav-core/src/reorder.rs [new file with mode: 0644]

index 4b6729c861c74c98b43c01e2f928f0e40cefebe3..75dbc78d8101baeacb26537e8f565f9f7675bb52 100644 (file)
@@ -17,6 +17,7 @@ pub mod refs;
 pub mod register;
 #[allow(clippy::unreadable_literal)]
 pub mod detect;
+pub mod reorder;
 pub mod scale;
 
 #[cfg(feature="dsp")]
diff --git a/nihav-core/src/reorder.rs b/nihav-core/src/reorder.rs
new file mode 100644 (file)
index 0000000..54c0288
--- /dev/null
@@ -0,0 +1,91 @@
+use std::mem::swap;
+pub use crate::frame::{FrameType, NAFrameRef};
+
+pub trait FrameReorderer {
+    fn add_frame(&mut self, fref: NAFrameRef) -> bool;
+    fn get_frame(&mut self) -> Option<NAFrameRef>;
+    fn flush(&mut self);
+    fn get_last_frames(&mut self) -> Option<NAFrameRef>;
+}
+
+pub struct NoReorderer {
+    fref:   Option<NAFrameRef>,
+}
+
+impl NoReorderer {
+    pub fn new() -> Self {
+        Self { fref: None }
+    }
+}
+
+impl FrameReorderer for NoReorderer {
+    fn add_frame(&mut self, fref: NAFrameRef) -> bool {
+        if self.fref.is_none() {
+            self.fref = Some(fref);
+            true
+        } else {
+            false
+        }
+    }
+    fn get_frame(&mut self) -> Option<NAFrameRef> {
+        let mut ret = None;
+        swap(&mut ret, &mut self.fref);
+        ret
+    }
+    fn flush(&mut self) { self.fref = None; }
+    fn get_last_frames(&mut self) -> Option<NAFrameRef> { None }
+}
+
+pub struct IPBReorderer {
+    frames:     Vec<NAFrameRef>,
+    max_depth:  usize,
+    last_ft:    FrameType,
+}
+
+impl IPBReorderer {
+    pub fn new(max_depth: usize) -> Self {
+        Self {
+            frames:     Vec::with_capacity(max_depth),
+            max_depth,
+            last_ft:    FrameType::Other,
+        }
+    }
+}
+
+impl FrameReorderer for IPBReorderer {
+    fn add_frame(&mut self, fref: NAFrameRef) -> bool {
+        if self.frames.len() < self.max_depth {
+            let cur_ft = fref.get_frame_type();
+            if cur_ft != FrameType::B {
+                self.frames.push(fref);
+                self.last_ft = cur_ft;
+            } else {
+                let pframe = self.frames.pop();
+                if pframe.is_some() {
+                    self.frames.push(fref);
+                    self.frames.push(pframe.unwrap());
+                } else {
+                    self.last_ft = cur_ft;
+                }
+            }
+            true
+        } else {
+            false
+        }
+    }
+    fn get_frame(&mut self) -> Option<NAFrameRef> {
+        if !self.frames.is_empty() {
+            Some(self.frames.remove(0))
+        } else {
+            None
+        }
+    }
+    fn flush(&mut self) {
+        self.frames.clear();
+        self.last_ft = FrameType::Other;
+    }
+    fn get_last_frames(&mut self) -> Option<NAFrameRef> {
+        self.get_frame()
+    }
+}
+