core: fix or silence clippy warnings
[nihav.git] / nihav-core / src / reorder.rs
1 //! Output frame reordering.
2 //!
3 //! NihAV decoders output frames in the same order as they are put in.
4 //! In result if you want to have frames in display order you might need some frame reorderer.
5 //! This module provides such functionality depending on codec type: audio codecs and video codecs without B-frames do not need any reorderer and can use `NoReorderer` if the common interface is required. Codecs with B-frames should use `IPBReorderer`. For codecs with very complex reordering rules like H.264 or H.256 `PictureIDReorderer` will be added eventually.
6 //!
7 //! You can find out required reorderer by quering codec properties using `nihav_core::register` module.
8 use std::mem::swap;
9 pub use crate::frame::{FrameType, NAFrameRef};
10
11 /// A trait for frame reorderer.
12 pub trait FrameReorderer {
13 /// Stores a newly decoded frame.
14 fn add_frame(&mut self, fref: NAFrameRef) -> bool;
15 /// Gets the next frame to be displayed (or `None` if that is not possible).
16 fn get_frame(&mut self) -> Option<NAFrameRef>;
17 /// Clears all stored frames.
18 fn flush(&mut self);
19 /// Retrieves the last frames stored by the reorderer.
20 fn get_last_frames(&mut self) -> Option<NAFrameRef>;
21 }
22
23 /// Zero reorderer.
24 pub struct NoReorderer {
25 fref: Option<NAFrameRef>,
26 }
27
28 impl NoReorderer {
29 /// Constructs a new instance of `NoReorderer`.
30 pub fn new() -> Self {
31 Self { fref: None }
32 }
33 }
34
35 impl Default for NoReorderer {
36 fn default() -> Self {
37 Self::new()
38 }
39 }
40
41 impl FrameReorderer for NoReorderer {
42 fn add_frame(&mut self, fref: NAFrameRef) -> bool {
43 if self.fref.is_none() {
44 self.fref = Some(fref);
45 true
46 } else {
47 false
48 }
49 }
50 fn get_frame(&mut self) -> Option<NAFrameRef> {
51 let mut ret = None;
52 swap(&mut ret, &mut self.fref);
53 ret
54 }
55 fn flush(&mut self) { self.fref = None; }
56 fn get_last_frames(&mut self) -> Option<NAFrameRef> { None }
57 }
58
59 /// Frame reorderer for codecs with I/P/B frames.
60 #[derive(Default)]
61 pub struct IPBReorderer {
62 rframe: Option<NAFrameRef>,
63 bframe: Option<NAFrameRef>,
64 }
65
66 impl IPBReorderer {
67 /// Constructs a new instance of `IPBReorderer`.
68 pub fn new() -> Self { Self::default() }
69 }
70
71 impl FrameReorderer for IPBReorderer {
72 fn add_frame(&mut self, fref: NAFrameRef) -> bool {
73 if self.rframe.is_some() && self.bframe.is_some() { return false; }
74 let is_b = fref.get_frame_type() == FrameType::B;
75 if is_b && self.bframe.is_some() { return false; }
76 if is_b {
77 self.bframe = Some(fref);
78 } else {
79 std::mem::swap(&mut self.bframe, &mut self.rframe);
80 self.rframe = Some(fref);
81 }
82 true
83 }
84 fn get_frame(&mut self) -> Option<NAFrameRef> {
85 let mut ret = None;
86 if self.bframe.is_some() {
87 std::mem::swap(&mut ret, &mut self.bframe);
88 }
89 ret
90 }
91 fn flush(&mut self) {
92 self.rframe = None;
93 self.bframe = None;
94 }
95 fn get_last_frames(&mut self) -> Option<NAFrameRef> {
96 let mut ret = None;
97 if self.bframe.is_some() {
98 std::mem::swap(&mut ret, &mut self.bframe);
99 } else if self.rframe.is_some() {
100 std::mem::swap(&mut ret, &mut self.rframe);
101 }
102 ret
103 }
104 }
105