motioncam_decoder/
raw_legacy.rs1use 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
174pub 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}