34de8943bc946605f2e033dbf29ad620c71f6b40
[nihav.git] / nihav-ms / src / codecs / msvideo1.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 use nihav_codec_support::codecs::HAMShuffler;
4
5 struct HAMShuffler16 {
6 lastframe: Option<NAVideoBufferRef<u16>>,
7 }
8
9 impl HAMShuffler16 {
10 fn clear(&mut self) { self.lastframe = None; }
11 fn add_frame(&mut self, buf: NAVideoBufferRef<u16>) {
12 self.lastframe = Some(buf);
13 }
14 fn clone_ref(&mut self) -> Option<NAVideoBufferRef<u16>> {
15 if let Some(ref mut frm) = self.lastframe {
16 let newfrm = frm.copy_buffer();
17 *frm = newfrm.clone().into_ref();
18 Some(newfrm.into_ref())
19 } else {
20 None
21 }
22 }
23 fn get_output_frame(&mut self) -> Option<NAVideoBufferRef<u16>> {
24 match self.lastframe {
25 Some(ref frm) => Some(frm.clone()),
26 None => None,
27 }
28 }
29 }
30
31 impl Default for HAMShuffler16 {
32 fn default() -> Self { Self { lastframe: None } }
33 }
34
35 const RGB555_FORMAT: NAPixelFormaton = NAPixelFormaton {
36 model: ColorModel::RGB(RGBSubmodel::RGB), components: 3,
37 comp_info: [
38 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 10, comp_offs: 0, next_elem: 2 }),
39 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 5, comp_offs: 0, next_elem: 2 }),
40 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 0, comp_offs: 0, next_elem: 2 }),
41 None, None],
42 elem_size: 2, be: false, alpha: false, palette: false };
43
44 #[derive(Default)]
45 struct Video1Decoder {
46 info: NACodecInfoRef,
47 hams: HAMShuffler,
48 hams16: HAMShuffler16,
49 width: usize,
50 height: usize,
51 is_16bit: bool,
52 }
53
54 impl Video1Decoder {
55 fn new() -> Self {
56 Self::default()
57 }
58 fn decode_frame(&self, br: &mut ByteReader, frm: &mut NASimpleVideoFrame<u8>) -> DecoderResult<FrameType> {
59 let off = frm.offset[0];
60 let stride = frm.stride[0];
61 let mut skip_count = 0;
62 let blk_w = (self.width + 3) >> 2;
63 let blk_h = (self.height + 3) >> 2;
64 let mut cur_x = 0;
65 let mut cur_y = 0;
66 while cur_x < blk_w && cur_y < blk_h {
67 let op = br.read_u16le()?;
68 let advance;
69 if op < 0x8000 {
70 let mut clr = [0; 2];
71 br.read_buf(&mut clr)?;
72 let mut flags = !op as usize;
73 let cur_off = off + cur_x * 4 + cur_y * 4 * stride;
74 for j in 0..4 {
75 for i in 0..4 {
76 frm.data[cur_off + i + j * stride] = clr[flags & 1];
77 flags >>= 1;
78 }
79 }
80 advance = 1;
81 } else if op < 0x8400 {
82 let cur_off = off + cur_x * 4 + cur_y * 4 * stride;
83 let clr = op as u8;
84 for j in 0..4 {
85 for i in 0..4 {
86 frm.data[cur_off + i + j * stride] = clr;
87 }
88 }
89 advance = 1;
90 } else if op < 0x8800 {
91 advance = (op & 0x3FF) as usize;
92 validate!(advance > 0);
93 skip_count += advance;
94 } else {
95 let mut clr = [0; 8];
96 br.read_buf(&mut clr)?;
97 let mut flags = !op as usize;
98 let cur_off = off + cur_x * 4 + cur_y * 4 * stride;
99 for j in 0..4 {
100 for i in 0..4 {
101 frm.data[cur_off + i + j * stride] = clr[(i >> 1) * 2 + (j >> 1) * 4 + (flags & 1)];
102 flags >>= 1;
103 }
104 }
105 advance = 1;
106 }
107 cur_x += advance;
108 while cur_x >= blk_w {
109 cur_x -= blk_w;
110 cur_y += 1;
111 }
112 }
113 validate!(cur_x == 0 && cur_y == blk_h);
114 if skip_count == 0 {
115 Ok(FrameType::I)
116 } else if skip_count < blk_w * blk_h {
117 Ok(FrameType::P)
118 } else {
119 Ok(FrameType::Skip)
120 }
121 }
122 fn decode_frame16(&self, br: &mut ByteReader, frm: &mut NASimpleVideoFrame<u16>) -> DecoderResult<FrameType> {
123 let off = frm.offset[0];
124 let stride = frm.stride[0];
125 let mut skip_count = 0;
126 let blk_w = (self.width + 3) >> 2;
127 let blk_h = (self.height + 3) >> 2;
128 let mut cur_x = 0;
129 let mut cur_y = 0;
130 while cur_x < blk_w && cur_y < blk_h {
131 let op = br.read_u16le()?;
132 let advance;
133 if (op & 0x8000) == 0 {
134 let mut clr = [0; 8];
135 clr[0] = br.read_u16le()?;
136 clr[1] = br.read_u16le()?;
137 let mut flags = !op as usize;
138 let cur_off = off + cur_x * 4 + cur_y * 4 * stride;
139 if (clr[0] & 0x8000) == 0 {
140 for j in 0..4 {
141 for i in 0..4 {
142 frm.data[cur_off + i + j * stride] = clr[flags & 1];
143 flags >>= 1;
144 }
145 }
146 } else {
147 clr[2] = br.read_u16le()?;
148 clr[3] = br.read_u16le()?;
149 clr[4] = br.read_u16le()?;
150 clr[5] = br.read_u16le()?;
151 clr[6] = br.read_u16le()?;
152 clr[7] = br.read_u16le()?;
153 for j in 0..4 {
154 for i in 0..4 {
155 frm.data[cur_off + i + j * stride] = clr[(i >> 1) * 2 + (j >> 1) * 4 + (flags & 1)];
156 flags >>= 1;
157 }
158 }
159 }
160 advance = 1;
161 } else if (op & 0xFC00) == 0x8400 {
162 advance = (op & 0x3FF) as usize;
163 validate!(advance > 0);
164 skip_count += advance;
165 } else {
166 let cur_off = off + cur_x * 4 + cur_y * 4 * stride;
167 let clr = op & 0x7FFF;
168 for j in 0..4 {
169 for i in 0..4 {
170 frm.data[cur_off + i + j * stride] = clr;
171 }
172 }
173 advance = 1;
174 }
175 cur_x += advance;
176 while cur_x >= blk_w {
177 cur_x -= blk_w;
178 cur_y += 1;
179 }
180 }
181 validate!((cur_x == 0 || cur_x == 1) && cur_y == blk_h);
182 if skip_count == 0 {
183 Ok(FrameType::I)
184 } else if skip_count < blk_w * blk_h {
185 Ok(FrameType::P)
186 } else {
187 Ok(FrameType::Skip)
188 }
189 }
190 }
191
192 impl NADecoder for Video1Decoder {
193 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
194 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
195 self.is_16bit = !vinfo.get_format().palette;
196 let fmt = if !self.is_16bit { PAL8_FORMAT } else { RGB555_FORMAT };
197 self.width = vinfo.get_width();
198 self.height = vinfo.get_height();
199 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, true, fmt));
200 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
201
202 Ok(())
203 } else {
204 Err(DecoderError::InvalidData)
205 }
206 }
207 #[allow(clippy::identity_op)]
208 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
209 let src = pkt.get_buffer();
210 validate!(src.len() >= 2);
211 let mut mr = MemoryReader::new_read(src.as_slice());
212 let mut br = ByteReader::new(&mut mr);
213
214 let buftype;
215 let ftype;
216 if !self.is_16bit {
217 let bufret = self.hams.clone_ref();
218 let mut buf;
219 if let Some(bbuf) = bufret {
220 buf = bbuf;
221 } else {
222 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 2)?;
223 buf = bufinfo.get_vbuf().unwrap();
224 self.hams.add_frame(buf);
225 buf = self.hams.get_output_frame().unwrap();
226 }
227 let mut frm = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
228 ftype = self.decode_frame(&mut br, &mut frm)?;
229 let paloff = frm.offset[1];
230 let dpal = &mut frm.data[paloff..];
231 let mut found_pal = false;
232 for sd in pkt.side_data.iter() {
233 match *sd {
234 NASideData::Palette(_, ref pal) => {
235 for (dst, src) in dpal.chunks_mut(3).zip(pal.chunks(4)) {
236 dst[0] = src[0];
237 dst[1] = src[1];
238 dst[2] = src[2];
239 }
240 found_pal = true;
241 break;
242 },
243 _ => {},
244 };
245 }
246 if !found_pal {
247 for i in 0..256 {
248 dpal[i * 3 + 0] = i as u8;
249 dpal[i * 3 + 1] = i as u8;
250 dpal[i * 3 + 2] = i as u8;
251 }
252 }
253 buftype = NABufferType::Video(buf);
254 } else {
255 let bufret = self.hams16.clone_ref();
256 let mut buf;
257 if let Some(bbuf) = bufret {
258 buf = bbuf;
259 } else {
260 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 2)?;
261 buf = bufinfo.get_vbuf16().unwrap();
262 self.hams16.add_frame(buf);
263 buf = self.hams16.get_output_frame().unwrap();
264 }
265 let mut frm = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
266 ftype = self.decode_frame16(&mut br, &mut frm)?;
267 buftype = NABufferType::Video16(buf);
268 }
269
270 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buftype);
271 frm.set_keyframe(ftype == FrameType::I);
272 frm.set_frame_type(ftype);
273 Ok(frm.into_ref())
274 }
275 fn flush(&mut self) {
276 self.hams.clear();
277 self.hams16.clear();
278 }
279 }
280
281 impl NAOptionHandler for Video1Decoder {
282 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
283 fn set_options(&mut self, _options: &[NAOption]) { }
284 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
285 }
286
287 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
288 Box::new(Video1Decoder::new())
289 }
290
291 #[cfg(test)]
292 mod test {
293 use nihav_core::codecs::RegisteredDecoders;
294 use nihav_core::demuxers::RegisteredDemuxers;
295 use nihav_codec_support::test::dec_video::*;
296 use crate::ms_register_all_codecs;
297 use nihav_commonfmt::generic_register_all_demuxers;
298 #[test]
299 fn test_ms_video1_8bit() {
300 let mut dmx_reg = RegisteredDemuxers::new();
301 generic_register_all_demuxers(&mut dmx_reg);
302 let mut dec_reg = RegisteredDecoders::new();
303 ms_register_all_codecs(&mut dec_reg);
304
305 test_decoding("avi", "msvideo1", "assets/MS/toon.avi", Some(66), &dmx_reg, &dec_reg,
306 ExpectedTestResult::MD5([0x0c26ec42, 0xb75bfea7, 0x1e6342ae, 0xb14dcfa3]));
307 }
308 #[test]
309 fn test_ms_video1_16bit() {
310 let mut dmx_reg = RegisteredDemuxers::new();
311 generic_register_all_demuxers(&mut dmx_reg);
312 let mut dec_reg = RegisteredDecoders::new();
313 ms_register_all_codecs(&mut dec_reg);
314
315 test_decoding("avi", "msvideo1", "assets/MS/clock-cram16.avi", None, &dmx_reg, &dec_reg,
316 ExpectedTestResult::MD5([0x03381fa4, 0x5b294fec, 0xb97a7575, 0xa1a3ffe9]));
317 }
318 }