aboutsummaryrefslogtreecommitdiff
path: root/test2/src/encode.rs
blob: b024c1791434978543583f364217196790084d60 (plain)
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
use crate::{BLOCK_SIZE, Frame};
use framework::BitstreamFilter;
use glam::{IVec2, ivec2};

pub struct Enc {
    res: IVec2,
    last: Frame,
}
impl BitstreamFilter for Enc {
    const INPUT_CODEC_ID: &str = "V_UNCOMPRESSED";
    const OUTPUT_CODEC_ID: &str = "V_VCETEST2";

    fn new(width: u32, height: u32) -> Self {
        let res = ivec2(width as i32, height as i32);
        Self {
            res,
            last: Frame::new(res),
        }
    }

    fn process_block(&mut self, a: Vec<u8>) -> Vec<u8> {
        let mut frame = Frame {
            data: a,
            res: self.res,
        };

        let mut out = Vec::new();
        let mut savblock = Vec::new();
        let mut refblock = Vec::new();

        for by in 0..frame.res.y / BLOCK_SIZE {
            for bx in 0..frame.res.x / BLOCK_SIZE {
                let boff = ivec2(bx * BLOCK_SIZE, by * BLOCK_SIZE);

                let mut best_d = Frame::compare_block(&frame, &self.last, boff, boff);
                let mut best_off = boff;

                for granularity in [8, 4, 2, 1] {
                    for dir in [
                        ivec2(1, 0),
                        ivec2(1, 1),
                        ivec2(0, 1),
                        ivec2(-1, 1),
                        ivec2(-1, 0),
                        ivec2(-1, -1),
                        ivec2(0, -1),
                        ivec2(1, -1),
                    ] {
                        let roff = boff + dir * granularity;
                        if roff.x >= 0
                            && roff.y >= 0
                            && roff.x + BLOCK_SIZE < frame.res.x
                            && roff.y + BLOCK_SIZE < frame.res.y
                        {
                            let d = Frame::compare_block(&frame, &self.last, boff, roff);
                            if d < best_d {
                                best_d = d;
                                best_off = roff;
                            }
                        }
                    }
                }

                savblock.clear();
                frame.export_block(boff, &mut savblock);

                refblock.clear();
                self.last.export_block(best_off, &mut refblock);

                let reloff = best_off - boff;
                out.push((reloff.x + 127) as u8);
                out.push((reloff.y + 127) as u8);

                for i in 0..(BLOCK_SIZE * BLOCK_SIZE + BLOCK_SIZE * BLOCK_SIZE / 2) {
                    out.push(savblock[i as usize] - refblock[i as usize])
                }
            }
        }

        self.last = frame.clone();
        out
    }
}