]>
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 |