aboutsummaryrefslogtreecommitdiff
path: root/lvc/src/main.rs
blob: 9d8a6cb3b5ee33b4de13cdcd5295ee75b41b8582 (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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use bincode::config::standard;
use clap::{Parser, Subcommand};
use lvc::{
    debug::draw_debug,
    decode::decode,
    encode::{encode, EncodeConfig},
    Block, Frame, Pixel, PixelValue, View, P2,
};
use std::{
    io::{stdin, stdout, BufReader, BufWriter, Read, Write},
    time::Instant,
};

#[derive(Parser)]
#[clap(about, version)]
struct Args {
    // Width of the video signal
    #[arg(short, long)]
    width: u16,
    // Height of the video signal
    #[arg(short, long)]
    height: u16,
    #[clap(subcommand)]
    action: Action,
}
#[derive(Clone, Subcommand)]
enum Action {
    // Compress video
    Encode {
        #[arg(short, long, default_value_t = 400)]
        max_block_size: usize,
        #[arg(short, long, default_value_t = 10)]
        iters: usize,
        #[arg(short, long, default_value_t = 5_000)]
        threshold: u32,
    },
    // Decompress video
    Decode {
        #[arg(short, long)]
        debug: bool,
    },
}

fn main() {
    let args = Args::parse();

    let size = P2 {
        x: args.width as i32,
        y: args.height as i32,
    };
    match args.action {
        Action::Decode { debug } => {
            let mut frame = Frame::new(size);
            let mut last_frame = Frame::new(size);
            let mut debug_frame = if debug { Some(Frame::new(size)) } else { None };

            let mut stdin = BufReader::new(stdin());
            let mut stdout = BufWriter::new(stdout());

            loop {
                let b: Block = bincode::decode_from_std_read(&mut stdin, standard()).unwrap();
                decode(&last_frame, &mut frame, View::all(size), &b);

                if let Some(debug_frame) = &mut debug_frame {
                    debug_frame.pixels.copy_from_slice(&frame.pixels);
                    draw_debug(debug_frame, View::all(size), &b);
                    write_frame(&mut stdout, &debug_frame);
                } else {
                    write_frame(&mut stdout, &frame);
                }

                last_frame.pixels.copy_from_slice(&frame.pixels);
            }
        }
        Action::Encode {
            max_block_size,
            threshold,
            iters,
        } => {
            let config = EncodeConfig {
                threshold,
                max_block_size,
                iters,
            };

            let mut last_frame = Frame::new(size);

            let mut stdin = BufReader::new(stdin());
            let mut stdout = BufWriter::new(stdout());

            for frame_number in 0.. {
                let mut frame = read_frame(&mut stdin, size);

                let t = Instant::now();
                let b: Block = encode(&last_frame, &frame, View::all(size), &config);
                eprintln!("frame {frame_number} took {:?}", t.elapsed());

                bincode::encode_into_std_write(&b, &mut stdout, standard()).unwrap();

                decode(&last_frame, &mut frame, View::all(size), &b);
                last_frame = frame;
            }
        }
    }
}

fn read_frame(inp: &mut impl Read, size: P2) -> Frame {
    let mut f = Frame::new(size);

    for y in 0..size.y {
        for x in 0..size.x {
            let mut cc = [0u8; 3];
            inp.read_exact(&mut cc).unwrap();
            f[P2 { x, y }] = Pixel {
                r: cc[0] as PixelValue,
                g: cc[1] as PixelValue,
                b: cc[2] as PixelValue,
            };
        }
    }
    f
}

fn write_frame(out: &mut impl Write, frame: &Frame) {
    for y in 0..frame.size.y {
        for x in 0..frame.size.x {
            let p = frame[P2 { x, y }];
            let mut cc = [0u8; 3];
            cc[0] = p.r as u8;
            cc[1] = p.g as u8;
            cc[2] = p.b as u8;
            out.write_all(&mut cc).unwrap();
        }
    }
}