]>
Commit | Line | Data |
---|---|---|
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 FrameReorderer for NoReorderer { | |
36 | fn add_frame(&mut self, fref: NAFrameRef) -> bool { | |
37 | if self.fref.is_none() { | |
38 | self.fref = Some(fref); | |
39 | true | |
40 | } else { | |
41 | false | |
42 | } | |
43 | } | |
44 | fn get_frame(&mut self) -> Option<NAFrameRef> { | |
45 | let mut ret = None; | |
46 | swap(&mut ret, &mut self.fref); | |
47 | ret | |
48 | } | |
49 | fn flush(&mut self) { self.fref = None; } | |
50 | fn get_last_frames(&mut self) -> Option<NAFrameRef> { None } | |
51 | } | |
52 | ||
53 | /// Frame reorderer for codecs with I/P/B frames. | |
54 | #[derive(Default)] | |
55 | pub struct IPBReorderer { | |
56 | rframe: Option<NAFrameRef>, | |
57 | bframe: Option<NAFrameRef>, | |
58 | } | |
59 | ||
60 | impl IPBReorderer { | |
61 | /// Constructs a new instance of `IPBReorderer`. | |
62 | pub fn new() -> Self { Self::default() } | |
63 | } | |
64 | ||
65 | impl FrameReorderer for IPBReorderer { | |
66 | fn add_frame(&mut self, fref: NAFrameRef) -> bool { | |
67 | if self.rframe.is_some() && self.bframe.is_some() { return false; } | |
68 | let is_b = fref.get_frame_type() == FrameType::B; | |
69 | if is_b && self.bframe.is_some() { return false; } | |
70 | if is_b { | |
71 | self.bframe = Some(fref); | |
72 | } else { | |
73 | std::mem::swap(&mut self.bframe, &mut self.rframe); | |
74 | self.rframe = Some(fref); | |
75 | } | |
76 | true | |
77 | } | |
78 | fn get_frame(&mut self) -> Option<NAFrameRef> { | |
79 | let mut ret = None; | |
80 | if self.bframe.is_some() { | |
81 | std::mem::swap(&mut ret, &mut self.bframe); | |
82 | } | |
83 | ret | |
84 | } | |
85 | fn flush(&mut self) { | |
86 | self.rframe = None; | |
87 | self.bframe = None; | |
88 | } | |
89 | fn get_last_frames(&mut self) -> Option<NAFrameRef> { | |
90 | let mut ret = None; | |
91 | if self.bframe.is_some() { | |
92 | std::mem::swap(&mut ret, &mut self.bframe); | |
93 | } else if self.rframe.is_some() { | |
94 | std::mem::swap(&mut ret, &mut self.rframe); | |
95 | } | |
96 | ret | |
97 | } | |
98 | } | |
99 |