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