Skip to main content

motioncam_decoder/
raw_legacy.rs

1use crate::error::Result;
2
3const BLOCK_SIZE: usize = 16;
4const ENCODING_BLOCK: usize = BLOCK_SIZE * 2;
5const HEADER_LENGTH: usize = 2;
6const ENCODING_BLOCK_LENGTH: [usize; 17] = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 32, 32, 32, 32, 32, 32];
7
8#[inline(always)]
9fn decode_header(inp: &[u8]) -> (u8, u16) {
10    let b0 = inp[0];
11    let b1 = inp[1];
12    ((b0 >> 4) & 0x0F, ((b0 & 0x0F) as u16) << 8 | b1 as u16)
13}
14
15#[inline(always)]
16fn decode_block_legacy(out: &mut [u16], bits: u8, inp: &[u8]) -> usize {
17    match bits {
18        0 => out[..BLOCK_SIZE].fill(0),
19        1 => {
20            for i in 0..BLOCK_SIZE / 8 {
21                let b = inp[i] as u16;
22                out[i * 8] = (b >> 7) & 1;
23                out[i * 8 + 1] = (b >> 6) & 1;
24                out[i * 8 + 2] = (b >> 5) & 1;
25                out[i * 8 + 3] = (b >> 4) & 1;
26                out[i * 8 + 4] = (b >> 3) & 1;
27                out[i * 8 + 5] = (b >> 2) & 1;
28                out[i * 8 + 6] = (b >> 1) & 1;
29                out[i * 8 + 7] = b & 1;
30            }
31        }
32        2 => {
33            for i in 0..BLOCK_SIZE / 4 {
34                let b = inp[i] as u16;
35                out[i * 4] = (b >> 6) & 3;
36                out[i * 4 + 1] = (b >> 4) & 3;
37                out[i * 4 + 2] = (b >> 2) & 3;
38                out[i * 4 + 3] = b & 3;
39            }
40        }
41        3 => {
42            let mut o = 0;
43            let mut i = 0;
44            while o < BLOCK_SIZE {
45                let b0 = inp[i] as u16;
46                let b1 = inp[i + 1] as u16;
47                out[o] = (b0 >> 5) & 7;
48                out[o + 1] = (b0 >> 2) & 7;
49                out[o + 2] = ((b0 & 3) << 1) | ((b1 >> 7) & 1);
50                out[o + 3] = (b1 >> 4) & 7;
51                out[o + 4] = (b1 >> 1) & 7;
52                out[o + 5] = ((b1 & 1) << 2) | ((inp[i + 2] as u16 >> 6) & 3);
53                out[o + 6] = (inp[i + 2] as u16 >> 3) & 7;
54                out[o + 7] = inp[i + 2] as u16 & 7;
55                i += 3;
56                o += 8;
57            }
58        }
59        4 => {
60            for i in 0..BLOCK_SIZE / 2 {
61                let b = inp[i] as u16;
62                out[i * 2] = (b >> 4) & 0xF;
63                out[i * 2 + 1] = b & 0xF;
64            }
65        }
66        5 => {
67            let mut o = 0;
68            let mut i = 0;
69            while o < BLOCK_SIZE {
70                let b0 = inp[i] as u16;
71                let b1 = inp[i + 1] as u16;
72                let b2 = inp[i + 2] as u16;
73                let b3 = inp[i + 3] as u16;
74                let b4 = inp[i + 4] as u16;
75                out[o] = (b0 >> 3) & 0x1F;
76                out[o + 1] = ((b0 & 7) << 2) | ((b1 >> 6) & 3);
77                out[o + 2] = (b1 >> 1) & 0x1F;
78                out[o + 3] = ((b1 & 1) << 4) | ((b2 >> 4) & 0xF);
79                out[o + 4] = ((b2 & 0xF) << 1) | ((b3 >> 7) & 1);
80                out[o + 5] = (b3 >> 2) & 0x1F;
81                out[o + 6] = ((b3 & 3) << 3) | ((b4 >> 5) & 7);
82                out[o + 7] = b4 & 0x1F;
83                i += 5;
84                o += 8;
85            }
86        }
87        6 => {
88            let mut o = 0;
89            let mut i = 0;
90            while o < BLOCK_SIZE {
91                let b0 = inp[i] as u16;
92                let b1 = inp[i + 1] as u16;
93                let b2 = inp[i + 2] as u16;
94                let b3 = inp[i + 3] as u16;
95                out[o] = (b0 >> 2) & 0x3F;
96                out[o + 1] = ((b0 & 3) << 4) | ((b1 >> 4) & 0xF);
97                out[o + 2] = ((b1 & 0xF) << 2) | ((b2 >> 6) & 3);
98                out[o + 3] = b2 & 0x3F;
99                out[o + 4] = (b3 >> 2) & 0x3F;
100                out[o + 5] = ((b3 & 3) << 4) | ((inp[i + 4] as u16 >> 4) & 0xF);
101                out[o + 6] = ((inp[i + 4] as u16 & 0xF) << 2) | ((inp[i + 5] as u16 >> 6) & 3);
102                out[o + 7] = inp[i + 5] as u16 & 0x3F;
103                i += 6;
104                o += 8;
105            }
106        }
107        7 => {
108            let mut o = 0;
109            let mut i = 0;
110            while o < BLOCK_SIZE {
111                let b0 = inp[i] as u16;
112                let b1 = inp[i + 1] as u16;
113                out[o] = (b0 >> 1) & 0x7F;
114                out[o + 1] = ((b0 & 1) << 6) | ((b1 >> 2) & 0x3F);
115                out[o + 2] = ((b0 & 3) << 5) | ((b1 >> 3) & 0x1F);
116                out[o + 3] = ((b0 & 7) << 4) | ((b1 >> 4) & 0xF);
117                out[o + 4] = ((b0 & 0xF) << 3) | ((b1 >> 5) & 7);
118                out[o + 5] = ((b0 & 0x1F) << 2) | ((b1 >> 6) & 3);
119                out[o + 6] = ((b0 & 0x3F) << 1) | ((b1 >> 7) & 1);
120                out[o + 7] = b1 & 0x7F;
121                i += 2;
122                o += 8;
123            }
124        }
125        8 => {
126            for i in 0..BLOCK_SIZE {
127                out[i] = inp[i] as u16;
128            }
129        }
130        9 => {
131            let mut o = 0;
132            let mut i = 0;
133            while o < BLOCK_SIZE {
134                let b0 = inp[i] as u16;
135                let b1 = inp[i + 1] as u16;
136                out[o] = (b0 << 1) | ((b1 >> 7) & 1);
137                out[o + 1] = ((b0 & 0x7F) << 2) | ((inp[i + 2] as u16 >> 6) & 3);
138                out[o + 2] = ((inp[i + 2] as u16 & 0x3F) << 3) | ((inp[i + 3] as u16 >> 5) & 7);
139                out[o + 3] = ((inp[i + 3] as u16 & 0x1F) << 4) | ((inp[i + 4] as u16 >> 4) & 0xF);
140                out[o + 4] = ((inp[i + 4] as u16 & 0xF) << 5) | ((inp[i + 5] as u16 >> 3) & 0x1F);
141                out[o + 5] = ((inp[i + 5] as u16 & 7) << 6) | ((inp[i + 6] as u16 >> 2) & 0x3F);
142                out[o + 6] = ((inp[i + 6] as u16 & 3) << 7) | ((inp[i + 7] as u16 >> 1) & 0x7F);
143                out[o + 7] = ((inp[i + 7] as u16 & 1) << 8) | inp[i + 8] as u16;
144                i += 9;
145                o += 8;
146            }
147        }
148        10 => {
149            let mut o = 0;
150            let mut i = 0;
151            while o < BLOCK_SIZE {
152                let b0 = inp[i] as u16;
153                let b1 = inp[i + 1] as u16;
154                let b2 = inp[i + 2] as u16;
155                let b3 = inp[i + 3] as u16;
156                let b4 = inp[i + 4] as u16;
157                out[o] = (b0 << 2) | ((b1 >> 6) & 3);
158                out[o + 1] = ((b1 & 0x3F) << 4) | ((b2 >> 4) & 0xF);
159                out[o + 2] = ((b2 & 0xF) << 6) | ((b3 >> 2) & 0x3F);
160                out[o + 3] = ((b3 & 3) << 8) | b4;
161                i += 5;
162                o += 4;
163            }
164        }
165        _ => {
166            for i in 0..BLOCK_SIZE {
167                out[i] = ((inp[i * 2] as u16) << 8) | inp[i * 2 + 1] as u16;
168            }
169        }
170    }
171    ENCODING_BLOCK_LENGTH[bits as usize]
172}
173
174/// Decode a raw frame using compression type 6 (legacy).
175///
176/// Decodes the compressed `input` into `output` (row-major `u16` Bayer data).
177/// Returns the number of `u16` samples written.
178pub fn decode_legacy(output: &mut [u16], width: usize, height: usize, input: &[u8]) -> Result<usize> {
179    let padded_width = ENCODING_BLOCK * width.div_ceil(ENCODING_BLOCK);
180    let mut row = vec![0u16; padded_width];
181    let mut offset = 0;
182    let mut out_idx = 0;
183    let mut p = [0u16; ENCODING_BLOCK];
184    for _ in 0..height {
185        for x in (0..padded_width).step_by(ENCODING_BLOCK) {
186            if offset + HEADER_LENGTH >= input.len() {
187                break;
188            }
189            let (bits0, ref0) = decode_header(&input[offset..]);
190            offset += HEADER_LENGTH;
191            let (p0, p1) = p.split_at_mut(BLOCK_SIZE);
192            offset += decode_block_legacy(p0, bits0.min(16), &input[offset..]);
193            if offset + HEADER_LENGTH >= input.len() {
194                break;
195            }
196            let (bits1, ref1) = decode_header(&input[offset..]);
197            offset += HEADER_LENGTH;
198            offset += decode_block_legacy(p1, bits1.min(16), &input[offset..]);
199            for i in (0..ENCODING_BLOCK).step_by(2) {
200                row[x + i] = p[i / 2] + ref0;
201                row[x + i + 1] = p[BLOCK_SIZE + i / 2] + ref1;
202            }
203        }
204        let c = width.min(padded_width);
205        output[out_idx..out_idx + c].copy_from_slice(&row[..c]);
206        out_idx += width;
207    }
208    Ok(out_idx)
209}