cinepakenc: switch default quantisation mode to median cut
[nihav.git] / nihav-core / src / reorder.rs
... / ...
CommitLineData
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.
8use std::mem::swap;
9pub use crate::frame::{FrameType, NAFrameRef};
10
11/// A trait for frame reorderer.
12pub 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.
24pub struct NoReorderer {
25 fref: Option<NAFrameRef>,
26}
27
28impl NoReorderer {
29 /// Constructs a new instance of `NoReorderer`.
30 pub fn new() -> Self {
31 Self { fref: None }
32 }
33}
34
35impl 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)]
55pub struct IPBReorderer {
56 rframe: Option<NAFrameRef>,
57 bframe: Option<NAFrameRef>,
58}
59
60impl IPBReorderer {
61 /// Constructs a new instance of `IPBReorderer`.
62 pub fn new() -> Self { Self::default() }
63}
64
65impl 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