1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
4 const DICT_SIZE: usize = 4096;
5 const MAX_BITS: u8 = 12;
6 const INVALID_POS: usize = 65536;
16 impl<'a> BitReader<'a> {
17 fn new(src: &'a [u8]) -> Self {
26 fn read(&mut self, nbits: u8) -> DecoderResult<u32> {
27 while self.bits < nbits {
28 while self.left > 0 && self.bits <= 24 {
29 self.bitbuf |= u32::from(self.src[self.pos]) << self.bits;
34 if self.bits < nbits {
35 if self.pos >= self.src.len() {
36 return Err(DecoderError::ShortData);
38 self.left = self.src[self.pos];
40 validate!(self.left > 0);
41 if self.pos + usize::from(self.left) > self.src.len() {
42 return Err(DecoderError::ShortData);
46 let ret = self.bitbuf & ((1 << nbits) - 1);
47 self.bitbuf >>= nbits;
54 dict_sym: [u8; DICT_SIZE],
55 dict_prev: [u16; DICT_SIZE],
65 dict_sym: [0; DICT_SIZE],
66 dict_prev: [0; DICT_SIZE],
73 fn reset(&mut self, bits: u8) {
74 self.nsyms = (1 << bits) + 2;
75 self.dict_pos = self.nsyms;
76 self.dict_lim = 1 << (bits + 1);
77 self.idx_bits = bits + 1;
79 fn add(&mut self, prev: usize, sym: u8) {
80 if self.dict_pos < self.dict_lim {
81 self.dict_sym [self.dict_pos] = sym;
82 self.dict_prev[self.dict_pos] = prev as u16;
86 fn decode_idx(&self, dst: &mut [u8], pos: usize, idx: usize) -> DecoderResult<usize> {
89 while tidx >= self.nsyms {
90 tidx = self.dict_prev[tidx] as usize;
93 validate!(pos + tot_len <= dst.len());
95 let mut end = pos + tot_len - 1;
97 while tidx >= self.nsyms {
98 dst[end] = self.dict_sym[tidx];
100 tidx = self.dict_prev[tidx] as usize;
102 dst[end] = tidx as u8;
106 fn unpack(&mut self, src: &[u8], dst: &mut [u8]) -> DecoderResult<()> {
107 validate!(src.len() >= 4);
108 let mut br = BitReader::new(&src[1..]);
112 let reset_sym = 1 << bits;
113 let end_sym = reset_sym + 1;
118 let mut lastidx = INVALID_POS;
120 let idx = br.read(self.idx_bits)? as usize;
121 if idx == reset_sym {
123 lastidx = INVALID_POS;
129 validate!(idx <= self.dict_pos);
130 if idx != self.dict_pos {
131 let len = self.decode_idx(dst, pos, idx)?;
132 if lastidx != INVALID_POS {
133 self.add(lastidx, dst[pos]);
137 validate!(lastidx != INVALID_POS);
138 let len = self.decode_idx(dst, pos, lastidx)?;
139 let lastsym = dst[pos];
141 validate!(pos < dst.len());
144 self.add(lastidx, lastsym);
148 if self.dict_pos == self.dict_lim && self.idx_bits < MAX_BITS {
153 validate!(pos == dst.len());
154 validate!(br.pos + 2 == src.len());
160 info: NACodecInfoRef,
174 info: NACodecInfoRef::default(),
181 lzw: LZWState::new(),
187 impl NADecoder for GIFDecoder {
188 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
189 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
190 self.width = vinfo.width;
191 self.height = vinfo.height;
193 self.gpal = [0; 768];
194 if let Some(ref edata) = info.get_extradata() {
195 validate!(edata.len() >= 3);
197 self.transp = Some(edata[1]);
199 self.gpal[..edata.len() - 3].copy_from_slice(&edata[3..]);
201 self.frame = vec![0; self.width * self.height];
202 self.dbuf = vec![0; self.width * self.height];
203 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT));
204 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
208 Err(DecoderError::InvalidData)
211 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
212 let src = pkt.get_buffer();
213 validate!(src.len() > 0);
215 for sd in pkt.side_data.iter() {
216 if let NASideData::Palette(true, ref pal) = sd {
217 for (dst, src) in self.gpal.chunks_mut(3).zip(pal.chunks(4)) {
226 let mut mr = MemoryReader::new_read(&src);
227 let mut br = ByteReader::new(&mut mr);
228 let tag = br.read_byte()?;
229 validate!(tag == 0x2C);
230 let left = usize::from(br.read_u16le()?);
231 let top = usize::from(br.read_u16le()?);
232 let width = usize::from(br.read_u16le()?);
233 let height = usize::from(br.read_u16le()?);
234 validate!(width > 0 && height > 0);
235 validate!(left + width <= self.width && top + height <= self.height);
236 let flags = br.read_byte()?;
237 let local_pal = (flags & 0x80) != 0;
239 let csize = 3 << ((flags & 7) + 1);
240 br.read_buf(&mut self.lpal[..csize])?;
243 let start = br.tell() as usize;
244 self.dbuf.resize(width * height, 0);
245 self.lzw.unpack(&src[start..], &mut self.dbuf)?;
247 if let Some(tpix) = self.transp {
248 for (dline, sline) in self.frame.chunks_exact_mut(self.width).skip(top)
249 .zip(self.dbuf.chunks_exact(width)) {
250 for (dst, &src) in dline[left..][..width].iter_mut().zip(sline.iter()) {
257 for (dline, sline) in self.frame.chunks_exact_mut(self.width).skip(top)
258 .zip(self.dbuf.chunks_exact(width)) {
259 dline[left..][..width].copy_from_slice(sline);
263 let buf = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?;
264 let mut vbuf = buf.get_vbuf().unwrap();
265 let paloff = vbuf.get_offset(1);
266 let stride = vbuf.get_stride(0);
267 let data = vbuf.get_data_mut().unwrap();
269 for (drow, srow) in data.chunks_exact_mut(stride).zip(self.frame.chunks_exact(self.width)) {
270 drow[..self.width].copy_from_slice(srow);
272 data[paloff..][..768].copy_from_slice(if local_pal { &self.lpal } else { &self.gpal });
274 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buf);
275 let ftype = if pkt.keyframe { FrameType::I } else { FrameType::P };
276 frm.set_frame_type(ftype);
279 fn flush(&mut self) {
283 impl NAOptionHandler for GIFDecoder {
284 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
285 fn set_options(&mut self, _options: &[NAOption]) { }
286 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
289 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
290 Box::new(GIFDecoder::new())
295 use nihav_core::codecs::RegisteredDecoders;
296 use nihav_core::demuxers::RegisteredDemuxers;
297 use nihav_codec_support::test::dec_video::*;
300 // sample: https://samples.mplayerhq.hu/image-samples/GIF/3D.gif
302 fn test_gif_decoder() {
303 let mut dmx_reg = RegisteredDemuxers::new();
304 generic_register_all_demuxers(&mut dmx_reg);
305 let mut dec_reg = RegisteredDecoders::new();
306 generic_register_all_decoders(&mut dec_reg);
308 test_decoding("gif", "gif", "assets/Misc/3D.gif",
309 Some(2), &dmx_reg, &dec_reg,
310 ExpectedTestResult::MD5Frames(vec![
311 [0x95e68f8f, 0xe899ac86, 0x0af66a0a, 0x34a4a00e],
312 [0xdf920e8c, 0xeb57c5f8, 0xd862507e, 0xd733fca3],
313 [0x75bee5cb, 0xefb2076c, 0xfce61f8a, 0x2d2b30df]]));