]>
Commit | Line | Data |
---|---|---|
6c9578be KS |
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. | |
ca8452f0 KS |
8 | use std::mem::swap; |
9 | pub use crate::frame::{FrameType, NAFrameRef}; | |
10 | ||
6c9578be | 11 | /// A trait for frame reorderer. |
ca8452f0 | 12 | pub trait FrameReorderer { |
6c9578be | 13 | /// Stores a newly decoded frame. |
ca8452f0 | 14 | fn add_frame(&mut self, fref: NAFrameRef) -> bool; |
6c9578be | 15 | /// Gets the next frame to be displayed (or `None` if that is not possible). |
ca8452f0 | 16 | fn get_frame(&mut self) -> Option<NAFrameRef>; |
6c9578be | 17 | /// Clears all stored frames. |
ca8452f0 | 18 | fn flush(&mut self); |
6c9578be | 19 | /// Retrieves the last frames stored by the reorderer. |
ca8452f0 KS |
20 | fn get_last_frames(&mut self) -> Option<NAFrameRef>; |
21 | } | |
22 | ||
6c9578be | 23 | /// Zero reorderer. |
ca8452f0 KS |
24 | pub struct NoReorderer { |
25 | fref: Option<NAFrameRef>, | |
26 | } | |
27 | ||
28 | impl NoReorderer { | |
6c9578be | 29 | /// Constructs a new instance of `NoReorderer`. |
ca8452f0 KS |
30 | pub fn new() -> Self { |
31 | Self { fref: None } | |
32 | } | |
33 | } | |
34 | ||
b36f412c KS |
35 | impl Default for NoReorderer { |
36 | fn default() -> Self { | |
37 | Self::new() | |
38 | } | |
39 | } | |
40 | ||
ca8452f0 KS |
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 | ||
6c9578be | 59 | /// Frame reorderer for codecs with I/P/B frames. |
f9c35397 | 60 | #[derive(Default)] |
ca8452f0 | 61 | pub struct IPBReorderer { |
f9c35397 KS |
62 | rframe: Option<NAFrameRef>, |
63 | bframe: Option<NAFrameRef>, | |
ca8452f0 KS |
64 | } |
65 | ||
66 | impl IPBReorderer { | |
6c9578be | 67 | /// Constructs a new instance of `IPBReorderer`. |
f9c35397 | 68 | pub fn new() -> Self { Self::default() } |
ca8452f0 KS |
69 | } |
70 | ||
71 | impl FrameReorderer for IPBReorderer { | |
72 | fn add_frame(&mut self, fref: NAFrameRef) -> bool { | |
f9c35397 KS |
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); | |
ca8452f0 | 78 | } else { |
f9c35397 KS |
79 | std::mem::swap(&mut self.bframe, &mut self.rframe); |
80 | self.rframe = Some(fref); | |
ca8452f0 | 81 | } |
f9c35397 | 82 | true |
ca8452f0 KS |
83 | } |
84 | fn get_frame(&mut self) -> Option<NAFrameRef> { | |
f9c35397 KS |
85 | let mut ret = None; |
86 | if self.bframe.is_some() { | |
87 | std::mem::swap(&mut ret, &mut self.bframe); | |
ca8452f0 | 88 | } |
f9c35397 | 89 | ret |
ca8452f0 KS |
90 | } |
91 | fn flush(&mut self) { | |
f9c35397 KS |
92 | self.rframe = None; |
93 | self.bframe = None; | |
ca8452f0 KS |
94 | } |
95 | fn get_last_frames(&mut self) -> Option<NAFrameRef> { | |
f9c35397 KS |
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 | |
ca8452f0 KS |
103 | } |
104 | } | |
105 | ||
8480761d KS |
106 | /// Frame reorderer for codecs with complex I/P/B frame structure like ITU H.26x. |
107 | #[derive(Default)] | |
108 | pub struct ComplexReorderer { | |
109 | last_ref_dts: Option<u64>, | |
110 | ready_idx: usize, | |
111 | frames: Vec<NAFrameRef>, | |
112 | } | |
113 | ||
114 | impl ComplexReorderer { | |
115 | /// Constructs a new instance of `IPBReorderer`. | |
116 | pub fn new() -> Self { Self::default() } | |
117 | } | |
118 | ||
119 | impl FrameReorderer for ComplexReorderer { | |
120 | fn add_frame(&mut self, fref: NAFrameRef) -> bool { | |
121 | if self.frames.len() >= 64 { | |
122 | return false; | |
123 | } | |
124 | let is_ref = fref.frame_type == FrameType::I || fref.frame_type == FrameType::P; | |
125 | if !is_ref { | |
126 | if self.frames.is_empty() || fref.get_dts().is_none() { | |
127 | self.frames.push(fref); | |
128 | } else if let Some(new_dts) = fref.get_dts() { | |
129 | let mut idx = 0; | |
130 | for (i, frm) in self.frames.iter().enumerate() { | |
131 | idx = i; | |
132 | if let Some(dts) = frm.get_dts() { | |
133 | if dts > new_dts { | |
134 | break; | |
135 | } | |
136 | } | |
137 | } | |
138 | self.frames.insert(idx, fref); | |
139 | } | |
140 | } else { | |
141 | for (i, frm) in self.frames.iter().enumerate() { | |
142 | if frm.get_dts() == self.last_ref_dts { | |
143 | self.ready_idx = i + 1; | |
144 | } | |
145 | } | |
146 | self.last_ref_dts = fref.get_dts(); | |
147 | self.frames.push(fref); | |
148 | } | |
149 | true | |
150 | } | |
151 | fn get_frame(&mut self) -> Option<NAFrameRef> { | |
152 | if self.ready_idx > 0 { | |
153 | self.ready_idx -= 1; | |
154 | Some(self.frames.remove(0)) | |
155 | } else { | |
156 | None | |
157 | } | |
158 | } | |
159 | fn flush(&mut self) { | |
160 | self.last_ref_dts = None; | |
161 | self.ready_idx = 0; | |
b191eef3 | 162 | self.frames.clear(); |
8480761d KS |
163 | } |
164 | fn get_last_frames(&mut self) -> Option<NAFrameRef> { | |
165 | if !self.frames.is_empty() { | |
166 | Some(self.frames.remove(0)) | |
167 | } else { | |
168 | None | |
169 | } | |
170 | } | |
171 | } | |
172 |