summaryrefslogtreecommitdiffstats
path: root/nihav-core/src/reorder.rs
blob: 54c0288e7e99355fa2d877ca0d18509b03f64b80 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use std::mem::swap;
pub use crate::frame::{FrameType, NAFrameRef};

pub trait FrameReorderer {
    fn add_frame(&mut self, fref: NAFrameRef) -> bool;
    fn get_frame(&mut self) -> Option<NAFrameRef>;
    fn flush(&mut self);
    fn get_last_frames(&mut self) -> Option<NAFrameRef>;
}

pub struct NoReorderer {
    fref:   Option<NAFrameRef>,
}

impl NoReorderer {
    pub fn new() -> Self {
        Self { fref: None }
    }
}

impl FrameReorderer for NoReorderer {
    fn add_frame(&mut self, fref: NAFrameRef) -> bool {
        if self.fref.is_none() {
            self.fref = Some(fref);
            true
        } else {
            false
        }
    }
    fn get_frame(&mut self) -> Option<NAFrameRef> {
        let mut ret = None;
        swap(&mut ret, &mut self.fref);
        ret
    }
    fn flush(&mut self) { self.fref = None; }
    fn get_last_frames(&mut self) -> Option<NAFrameRef> { None }
}

pub struct IPBReorderer {
    frames:     Vec<NAFrameRef>,
    max_depth:  usize,
    last_ft:    FrameType,
}

impl IPBReorderer {
    pub fn new(max_depth: usize) -> Self {
        Self {
            frames:     Vec::with_capacity(max_depth),
            max_depth,
            last_ft:    FrameType::Other,
        }
    }
}

impl FrameReorderer for IPBReorderer {
    fn add_frame(&mut self, fref: NAFrameRef) -> bool {
        if self.frames.len() < self.max_depth {
            let cur_ft = fref.get_frame_type();
            if cur_ft != FrameType::B {
                self.frames.push(fref);
                self.last_ft = cur_ft;
            } else {
                let pframe = self.frames.pop();
                if pframe.is_some() {
                    self.frames.push(fref);
                    self.frames.push(pframe.unwrap());
                } else {
                    self.last_ft = cur_ft;
                }
            }
            true
        } else {
            false
        }
    }
    fn get_frame(&mut self) -> Option<NAFrameRef> {
        if !self.frames.is_empty() {
            Some(self.frames.remove(0))
        } else {
            None
        }
    }
    fn flush(&mut self) {
        self.frames.clear();
        self.last_ft = FrameType::Other;
    }
    fn get_last_frames(&mut self) -> Option<NAFrameRef> {
        self.get_frame()
    }
}