| 1 | use nihav_core::codecs::*; |
| 2 | use nihav_core::io::byteio::*; |
| 3 | use nihav_codec_support::codecs::HAMShuffler; |
| 4 | |
| 5 | #[derive(Default)] |
| 6 | struct RleDecoder { |
| 7 | info: NACodecInfoRef, |
| 8 | hams: HAMShuffler<u8>, |
| 9 | width: usize, |
| 10 | height: usize, |
| 11 | is_4bit: bool, |
| 12 | } |
| 13 | |
| 14 | impl RleDecoder { |
| 15 | fn new() -> Self { |
| 16 | Self::default() |
| 17 | } |
| 18 | fn decode_8bit(&self, br: &mut ByteReader, frm: &mut NASimpleVideoFrame<u8>) -> DecoderResult<FrameType> { |
| 19 | let mut has_skips = false; |
| 20 | |
| 21 | if (br.left() as usize) == self.width * self.height { |
| 22 | for line in frm.data.chunks_mut(frm.stride[0]).take(self.height) { |
| 23 | br.read_buf(&mut line[..self.width])?; |
| 24 | } |
| 25 | return Ok(FrameType::I); |
| 26 | } |
| 27 | let mut x = 0; |
| 28 | let mut y = 0; |
| 29 | let mut doff = 0; |
| 30 | loop { |
| 31 | let a = br.read_byte()?; |
| 32 | let b = br.read_byte()?; |
| 33 | if a > 0 { |
| 34 | let len = a as usize; |
| 35 | validate!(y < self.height); |
| 36 | validate!(x + len <= self.width); |
| 37 | for _ in 0..len { |
| 38 | frm.data[doff] = b; |
| 39 | doff += 1; |
| 40 | } |
| 41 | x += len; |
| 42 | } else { |
| 43 | match b { |
| 44 | 0 => { |
| 45 | if x != self.width { |
| 46 | has_skips = true; |
| 47 | } |
| 48 | x = 0; |
| 49 | y += 1; |
| 50 | }, |
| 51 | 1 => { |
| 52 | if x != 0 || y != self.height { |
| 53 | has_skips = true; |
| 54 | } |
| 55 | break; |
| 56 | }, |
| 57 | 2 => { |
| 58 | let xoff = br.read_byte()? as usize; |
| 59 | let yoff = br.read_byte()? as usize; |
| 60 | validate!(x + xoff <= self.width); |
| 61 | validate!(y + yoff <= self.height); |
| 62 | x += xoff; |
| 63 | y += yoff; |
| 64 | has_skips = true; |
| 65 | }, |
| 66 | _ => { |
| 67 | let len = b as usize; |
| 68 | validate!(y < self.height); |
| 69 | validate!(x + len <= self.width); |
| 70 | for _ in 0..len { |
| 71 | frm.data[doff] = br.read_byte()?; |
| 72 | doff += 1; |
| 73 | } |
| 74 | x += len; |
| 75 | if (len & 1) != 0 { |
| 76 | br.read_byte()?; // padding |
| 77 | } |
| 78 | }, |
| 79 | }; |
| 80 | if b < 3 { |
| 81 | doff = x + y * frm.stride[0]; |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | |
| 87 | Ok(if has_skips { FrameType::P } else { FrameType::I }) |
| 88 | } |
| 89 | fn decode_4bit(&self, br: &mut ByteReader, frm: &mut NASimpleVideoFrame<u8>) -> DecoderResult<FrameType> { |
| 90 | let mut has_skips = false; |
| 91 | |
| 92 | if (br.left() as usize) == (self.width + 1) / 2 * self.height { |
| 93 | for line in frm.data.chunks_mut(frm.stride[0]).take(self.height) { |
| 94 | for i in 0..self.width/2 { |
| 95 | let clr = br.read_byte()?; |
| 96 | line[i * 2] = clr >> 4; |
| 97 | line[i * 2 + 1] = clr & 0xF; |
| 98 | } |
| 99 | if (self.width & 1) == 1 { |
| 100 | let clr = br.read_byte()?; |
| 101 | line[self.width - 1] = clr >> 4; |
| 102 | } |
| 103 | } |
| 104 | return Ok(FrameType::I); |
| 105 | } |
| 106 | let mut x = 0; |
| 107 | let mut y = 0; |
| 108 | let mut doff = 0; |
| 109 | loop { |
| 110 | let a = br.read_byte()?; |
| 111 | let b = br.read_byte()?; |
| 112 | if a > 0 { |
| 113 | let len = a as usize; |
| 114 | validate!(y < self.height); |
| 115 | validate!(x + len <= self.width); |
| 116 | for _ in 0..len / 2 { |
| 117 | frm.data[doff] = b >> 4; |
| 118 | doff += 1; |
| 119 | frm.data[doff] = b & 0xF; |
| 120 | doff += 1; |
| 121 | } |
| 122 | if (len & 1) != 0 { |
| 123 | frm.data[doff] = b >> 4; |
| 124 | doff += 1; |
| 125 | } |
| 126 | x += len; |
| 127 | } else { |
| 128 | match b { |
| 129 | 0 => { |
| 130 | if x != self.width { |
| 131 | has_skips = true; |
| 132 | } |
| 133 | x = 0; |
| 134 | y += 1; |
| 135 | }, |
| 136 | 1 => { |
| 137 | if x != 0 || y != self.height { |
| 138 | has_skips = true; |
| 139 | } |
| 140 | break; |
| 141 | }, |
| 142 | 2 => { |
| 143 | let xoff = br.read_byte()? as usize; |
| 144 | let yoff = br.read_byte()? as usize; |
| 145 | validate!(x + xoff <= self.width); |
| 146 | validate!(y + yoff <= self.height); |
| 147 | x += xoff; |
| 148 | y += yoff; |
| 149 | has_skips = true; |
| 150 | }, |
| 151 | _ => { |
| 152 | let len = b as usize; |
| 153 | validate!(y < self.height); |
| 154 | validate!(x + len <= self.width); |
| 155 | for _ in 0..len / 2 { |
| 156 | let clr = br.read_byte()?; |
| 157 | frm.data[doff] = clr >> 4; |
| 158 | doff += 1; |
| 159 | frm.data[doff] = clr & 0xF; |
| 160 | doff += 1; |
| 161 | } |
| 162 | if (len & 1) != 0 { |
| 163 | let clr = br.read_byte()?; |
| 164 | frm.data[doff] = clr >> 4; |
| 165 | doff += 1; |
| 166 | } |
| 167 | x += len; |
| 168 | if ((len + 1) & 2) != 0 { |
| 169 | br.read_byte()?; // padding |
| 170 | } |
| 171 | }, |
| 172 | }; |
| 173 | if b < 3 { |
| 174 | doff = x + y * frm.stride[0]; |
| 175 | } |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | |
| 180 | Ok(if has_skips { FrameType::P } else { FrameType::I }) |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | impl NADecoder for RleDecoder { |
| 185 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { |
| 186 | if let NACodecTypeInfo::Video(vinfo) = info.get_properties() { |
| 187 | self.width = vinfo.get_width(); |
| 188 | self.height = vinfo.get_height(); |
| 189 | let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, true, PAL8_FORMAT)); |
| 190 | self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); |
| 191 | self.is_4bit = vinfo.bits == 4; |
| 192 | |
| 193 | Ok(()) |
| 194 | } else { |
| 195 | Err(DecoderError::InvalidData) |
| 196 | } |
| 197 | } |
| 198 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
| 199 | let src = pkt.get_buffer(); |
| 200 | validate!(src.len() >= 2); |
| 201 | let mut mr = MemoryReader::new_read(src.as_slice()); |
| 202 | let mut br = ByteReader::new(&mut mr); |
| 203 | |
| 204 | let ftype; |
| 205 | let bufret = self.hams.clone_ref(); |
| 206 | let mut buf; |
| 207 | if let Some(bbuf) = bufret { |
| 208 | buf = bbuf; |
| 209 | } else { |
| 210 | let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?; |
| 211 | buf = bufinfo.get_vbuf().unwrap(); |
| 212 | self.hams.add_frame(buf); |
| 213 | buf = self.hams.get_output_frame().unwrap(); |
| 214 | } |
| 215 | let mut frm = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap(); |
| 216 | if !self.is_4bit { |
| 217 | ftype = self.decode_8bit(&mut br, &mut frm)?; |
| 218 | } else { |
| 219 | ftype = self.decode_4bit(&mut br, &mut frm)?; |
| 220 | } |
| 221 | let paloff = frm.offset[1]; |
| 222 | let dpal = &mut frm.data[paloff..]; |
| 223 | for sd in pkt.side_data.iter() { |
| 224 | match *sd { |
| 225 | NASideData::Palette(_, ref pal) => { |
| 226 | for (dst, src) in dpal.chunks_mut(3).zip(pal.chunks(4)) { |
| 227 | dst[0] = src[0]; |
| 228 | dst[1] = src[1]; |
| 229 | dst[2] = src[2]; |
| 230 | } |
| 231 | break; |
| 232 | }, |
| 233 | _ => {}, |
| 234 | }; |
| 235 | } |
| 236 | let buftype = NABufferType::Video(buf); |
| 237 | |
| 238 | let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buftype); |
| 239 | frm.set_keyframe(ftype == FrameType::I); |
| 240 | frm.set_frame_type(ftype); |
| 241 | Ok(frm.into_ref()) |
| 242 | } |
| 243 | fn flush(&mut self) { |
| 244 | self.hams.clear(); |
| 245 | } |
| 246 | } |
| 247 | |
| 248 | impl NAOptionHandler for RleDecoder { |
| 249 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } |
| 250 | fn set_options(&mut self, _options: &[NAOption]) { } |
| 251 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } |
| 252 | } |
| 253 | |
| 254 | pub fn get_decoder() -> Box<dyn NADecoder + Send> { |
| 255 | Box::new(RleDecoder::new()) |
| 256 | } |
| 257 | |
| 258 | #[cfg(test)] |
| 259 | mod test { |
| 260 | use nihav_core::codecs::RegisteredDecoders; |
| 261 | use nihav_core::demuxers::RegisteredDemuxers; |
| 262 | use nihav_codec_support::test::dec_video::*; |
| 263 | use crate::ms_register_all_decoders; |
| 264 | use nihav_commonfmt::generic_register_all_demuxers; |
| 265 | #[test] |
| 266 | fn test_ms_rle_8bit() { |
| 267 | let mut dmx_reg = RegisteredDemuxers::new(); |
| 268 | generic_register_all_demuxers(&mut dmx_reg); |
| 269 | let mut dec_reg = RegisteredDecoders::new(); |
| 270 | ms_register_all_decoders(&mut dec_reg); |
| 271 | |
| 272 | test_decoding("avi", "msrle", "assets/MS/workcycl-64color.avi", Some(6), &dmx_reg, &dec_reg, |
| 273 | ExpectedTestResult::MD5Frames(vec![ |
| 274 | [0xdd030d70, 0x0b6140ff, 0xdd01823e, 0x27c18f12], |
| 275 | [0xd592aa63, 0x97bafa10, 0x380787ed, 0x71da30c4], |
| 276 | [0x78596af1, 0x8c21fa09, 0xd914131b, 0x04e3e176], |
| 277 | [0xcfe091d7, 0xccd513d5, 0x5bd3caa3, 0xcc388e4a], |
| 278 | [0xbea60252, 0x1e493c7d, 0x9996b50c, 0x8f7a1c24], |
| 279 | [0xfab23365, 0xe8070819, 0xa2ce974e, 0x15dcabba], |
| 280 | [0xd1cdf200, 0x9c2e6d33, 0xbe3270d1, 0x1dede547]])); |
| 281 | } |
| 282 | #[test] |
| 283 | fn test_ms_rle_8bit_raw() { |
| 284 | let mut dmx_reg = RegisteredDemuxers::new(); |
| 285 | generic_register_all_demuxers(&mut dmx_reg); |
| 286 | let mut dec_reg = RegisteredDecoders::new(); |
| 287 | ms_register_all_decoders(&mut dec_reg); |
| 288 | |
| 289 | test_decoding("avi", "msrle", "assets/MS/suzie_appl_rle8.avi", Some(2), &dmx_reg, &dec_reg, |
| 290 | ExpectedTestResult::MD5Frames(vec![ |
| 291 | [0xe4d5ad8d, 0x50e8bd7e, 0x0d602ece, 0x3631a8b4], |
| 292 | [0x3301ba0e, 0x281c3e54, 0xbd961d44, 0xc352845b], |
| 293 | [0x3ed7881d, 0x86acadf7, 0x2922d8bc, 0x8ec9b17e]])); |
| 294 | } |
| 295 | #[test] |
| 296 | fn test_ms_rle_4bit() { |
| 297 | let mut dmx_reg = RegisteredDemuxers::new(); |
| 298 | generic_register_all_demuxers(&mut dmx_reg); |
| 299 | let mut dec_reg = RegisteredDecoders::new(); |
| 300 | ms_register_all_decoders(&mut dec_reg); |
| 301 | |
| 302 | test_decoding("avi", "msrle", "assets/MS/mplayer-msrle-4bit.avi", Some(2), &dmx_reg, &dec_reg, |
| 303 | ExpectedTestResult::MD5Frames(vec![ |
| 304 | [0x9898c473, 0x80362654, 0xdb40513a, 0xb0c60fd9], |
| 305 | [0x281e1531, 0x368a71cb, 0x9dd02f8d, 0xdfe630d9], |
| 306 | [0x6faac693, 0x1856d0fd, 0x47933bb2, 0xb2fb02b0]])); |
| 307 | } |
| 308 | #[test] |
| 309 | fn test_ms_rle_4bit_raw() { |
| 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_decoders(&mut dec_reg); |
| 314 | |
| 315 | test_decoding("avi", "msrle", "assets/MS/suzie_appl_rle4.avi", Some(2), &dmx_reg, &dec_reg, |
| 316 | ExpectedTestResult::MD5([0xb5d38296, 0xdae25407, 0x985973f0, 0xb1da9c94])); |
| 317 | } |
| 318 | } |