fix clippy warnings
[nihav.git] / nihav-flash / src / codecs / flashsv.rs
CommitLineData
92d9fb69
KS
1use nihav_core::frame::*;
2use nihav_core::codecs::*;
3use nihav_core::io::byteio::*;
4use nihav_core::compr::deflate::*;
5
6#[derive(Default)]
7struct FSVShuffler {
8 lastframe: Option<NAVideoBufferRef<u8>>,
9 keyframe: Option<NAVideoBufferRef<u8>>,
10}
11
12#[allow(dead_code)]
13impl FSVShuffler {
14 fn new() -> Self { Self::default() }
15 fn clear(&mut self) {
16 self.keyframe = None;
17 self.lastframe = None;
18 }
19 fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
20 self.lastframe = Some(buf);
21 }
22 fn add_keyframe(&mut self, buf: NAVideoBufferRef<u8>) {
23 self.keyframe = Some(buf);
24 }
25 fn clone_ref(&mut self) -> Option<NAVideoBufferRef<u8>> {
26 if let Some(ref mut frm) = self.lastframe {
27 let newfrm = frm.copy_buffer();
28 *frm = newfrm.clone().into_ref();
29 Some(newfrm.into_ref())
30 } else {
31 None
32 }
33 }
34 fn has_last_frame(&self) -> bool { self.lastframe.is_some() }
35 fn get_key_frame(&mut self) -> Option<NAVideoBufferRef<u8>> {
e6aaad5c 36 self.keyframe.as_ref().cloned()
92d9fb69
KS
37 }
38 fn get_last_frame(&mut self) -> Option<NAVideoBufferRef<u8>> {
e6aaad5c 39 self.lastframe.as_ref().cloned()
92d9fb69
KS
40 }
41}
42
43
44struct FSVDecoder {
45 info: NACodecInfoRef,
46 shuf: FSVShuffler,
47 w: usize,
48 h: usize,
49 block_w: usize,
50 block_h: usize,
51 ver1: bool,
52 has_pal: bool,
53 has_ifrm: bool,
54 tile: Vec<u8>,
55 cbuf: [u8; 65536],
56 pal: [u8; 128 * 3],
57 inflate: Inflate,
58 kdata: Vec<u8>,
59 bpos: Vec<usize>,
60 bsize: Vec<usize>,
61}
62
63impl FSVDecoder {
64 fn new(ver1: bool) -> Self {
65 Self {
66 info: NACodecInfo::new_dummy(),
67 shuf: FSVShuffler::new(),
68 w: 0,
69 h: 0,
70 block_w: 0,
71 block_h: 0,
72 ver1,
73 has_pal: false,
74 has_ifrm: false,
75 tile: Vec::new(),
76 cbuf: [0; 65536],
77 pal: DEFAULT_PAL,
78 inflate: Inflate::new(),
79 kdata: Vec::new(),
80 bpos: Vec::new(),
81 bsize: Vec::new(),
82 }
83 }
84 fn decode_v1(&mut self, br: &mut ByteReader, data: &mut [u8], stride: usize) -> DecoderResult<bool> {
85 let mut is_intra = true;
86 for (yy, row) in data.chunks_mut(stride * self.block_h).enumerate() {
87 let cur_h = (self.h - yy * self.block_h).min(self.block_h);
88 for x in (0..self.w).step_by(self.block_w) {
89 let cur_w = (self.w - x).min(self.block_w);
90
91 let data_size = br.read_u16be()? as usize;
92 if data_size > 0 {
93 br.read_buf(&mut self.cbuf[..data_size])?;
94 self.inflate = Inflate::new();
95 if self.inflate.decompress_block(&self.cbuf[..data_size], &mut self.tile[..cur_w * cur_h * 3]).is_err() {
96 return Err(DecoderError::InvalidData);
97 }
98 for (dst, src) in row[x * 3..].chunks_mut(stride).zip(self.tile.chunks(cur_w * 3)) {
99 dst[..cur_w * 3].copy_from_slice(src);
100 }
101 } else {
102 is_intra = false;
103 }
104 }
105 }
106 Ok(is_intra)
107 }
108 fn decode_v2(&mut self, br: &mut ByteReader, data: &mut [u8], stride: usize, keyframe: bool) -> DecoderResult<bool> {
109 let mut is_intra = !self.has_ifrm;
110 let bstride = (self.w + self.block_w - 1) / self.block_w;
111 for y in (0..self.h).step_by(self.block_h) {
112 let cur_h = (self.h - y).min(self.block_h);
113 for x in (0..self.w).step_by(self.block_w) {
114 let cur_w = (self.w - x).min(self.block_w);
115
116 let mut data_size = br.read_u16be()? as usize;
117 validate!(!keyframe || data_size > 0);
118 if data_size == 0 {
119 is_intra = false;
120 continue;
121 }
122 let blk_start = br.tell();
123 let flags = br.read_byte()?;
124 let depth = (flags >> 3) & 3;
125 validate!(depth == 0 || depth == 2);
126 let has_diff = (flags & 4) != 0;
127 let cpriming = (flags & 2) != 0;
128 let ppriming = (flags & 1) != 0;
129 let (start, height) = if has_diff {
130 let start = br.read_byte()? as usize;
131 let height = br.read_byte()? as usize;
132 validate!(start + height <= cur_h);
133 (start, height)
134 } else {
135 (0, cur_h)
136 };
137 if has_diff {
138 let ret = self.shuf.get_key_frame();
139 if ret.is_none() {
140 return Err(DecoderError::MissingReference);
141 }
142 let src = ret.unwrap();
143 let src = src.get_data();
144 for (dst, src) in data[x * 3 + y * stride..].chunks_mut(stride).take(cur_h).zip(src[x * 3 + y * stride..].chunks(stride)) {
145 dst[..cur_w * 3].copy_from_slice(&src[..cur_w * 3]);
146 }
147 }
148 if height != cur_h {
149 is_intra = false;
150 }
151 let ppos = if cpriming {
152 let xpos = br.read_byte()? as usize;
153 let ypos = br.read_byte()? as usize;
154 xpos + ypos * bstride
155 } else {
156 x / self.block_w + y / self.block_h * bstride
157 };
158 data_size -= (br.tell() - blk_start) as usize;
159 if keyframe {
160 self.bpos.push(br.tell() as usize);
161 self.bsize.push(data_size);
162 }
163 if data_size > 0 {
164 br.read_buf(&mut self.cbuf[..data_size])?;
165 self.inflate = Inflate::new();
166 if cpriming || ppriming {
167 if self.bpos.is_empty() {
168 return Err(DecoderError::MissingReference);
169 }
170 let ret = self.inflate.decompress_block(&self.kdata[self.bpos[ppos]..][..self.bsize[ppos]], &mut self.tile);
171 if ret.is_err() {
172 return Err(DecoderError::InvalidData);
173 }
174 let ssize = ret.unwrap();
175 self.inflate = Inflate::new();
176 self.inflate.set_dict(&self.tile[..ssize]);
177 }
178 let ret = self.inflate.decompress_block(&self.cbuf[..data_size], &mut self.tile[..cur_w * height * 3]);
179 if ret.is_err() {
180 return Err(DecoderError::InvalidData);
181 }
182 let src_len = ret.unwrap();
183
184 let dst = &mut data[x * 3 + y * stride..];
185 match depth {
186 0 => {
187 validate!(src_len == cur_w * cur_h * 3);
188 for (dst, src) in dst.chunks_mut(stride).skip(start).take(height).zip(self.tile.chunks(cur_w * 3)) {
189 dst[..cur_w * 3].copy_from_slice(src);
190 }
191 },
192 2 => {
193 let mut mr = MemoryReader::new_read(&self.tile[..src_len]);
194 let mut br = ByteReader::new(&mut mr);
195 for line in dst.chunks_mut(stride).skip(start).take(height) {
196 for rgb in line.chunks_mut(3).take(cur_w) {
197 let b = br.read_byte()?;
198 if (b & 0x80) == 0 {
199 rgb.copy_from_slice(&self.pal[(b as usize) * 3..][..3]);
200 } else {
201 let c = br.read_byte()?;
202 let clr = (u16::from(b & 0x7F) << 8) | u16::from(c);
203 let r = (clr >> 10) as u8;
204 let g = ((clr >> 5) & 0x1F) as u8;
205 let b = (clr & 0x1F) as u8;
206 rgb[0] = (r << 3) | (r >> 2);
207 rgb[1] = (g << 3) | (g >> 2);
208 rgb[2] = (b << 3) | (b >> 2);
209 }
210 }
211 }
212 },
213 _ => unreachable!(),
214 };
215 } else {
216 is_intra = false;
217 }
218 }
219 }
220 if self.has_ifrm {
221unimplemented!();
222 }
223 Ok(is_intra)
224 }
225}
226
227impl NADecoder for FSVDecoder {
228 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
229 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
230 let w = vinfo.get_width();
231 let h = vinfo.get_height();
232 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, true, RGB24_FORMAT));
233 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
234
235 Ok(())
236 } else {
237 Err(DecoderError::InvalidData)
238 }
239 }
240 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
241 let src = pkt.get_buffer();
242
243 validate!(src.len() > 4);
244 let mut mr = MemoryReader::new_read(&src);
245 let mut br = ByteReader::new(&mut mr);
246
247 let hdr0 = br.read_u16be()? as usize;
248 let hdr1 = br.read_u16be()? as usize;
249 let w = hdr0 & 0xFFF;
250 let h = hdr1 & 0xFFF;
251 let blk_w = (hdr0 >> 12) * 16 + 16;
252 let blk_h = (hdr1 >> 12) * 16 + 16;
253 validate!(w != 0 && h != 0 && blk_w != 0 && blk_h != 0);
254
255 if !self.ver1 {
256 let flags = br.read_byte()?;
257 self.has_pal = (flags & 1) != 0;
258 self.has_ifrm = (flags & 2) != 0;
259 if self.has_pal {
260 let pal_sz = br.read_u16be()? as usize;
261 br.read_buf(&mut self.cbuf[..pal_sz])?;
262 self.inflate = Inflate::new();
263 if self.inflate.decompress_block(&self.cbuf[..pal_sz], &mut self.pal).is_err() {
264 return Err(DecoderError::InvalidData);
265 }
266 }
267 if pkt.keyframe {
268 self.kdata.clear();
269 self.kdata.extend_from_slice(&src);
270 self.bpos.clear();
271 self.bsize.clear();
272 }
273 }
274 if self.w != w || self.h != h || self.block_w != blk_w || self.block_h != blk_h {
275 self.flush();
276 self.tile.resize(blk_w * blk_h * 3, 0);
277 self.w = w;
278 self.h = h;
279 self.block_w = blk_w;
280 self.block_h = blk_h;
281 }
282
283 let mut buf = if let Some(buffer) = self.shuf.clone_ref() {
284 buffer
285 } else {
286 let vinfo = self.info.get_properties().get_video_info().unwrap();
287 let bufinfo = alloc_video_buffer(vinfo, 0)?;
288 bufinfo.get_vbuf().unwrap()
289 };
290 let stride = buf.get_stride(0);
291 let data = buf.get_data_mut().unwrap();
292 let is_intra = if self.ver1 {
293 self.decode_v1(&mut br, data, stride)?
294 } else {
295 self.decode_v2(&mut br, data, stride, pkt.keyframe)?
296 };
297
298 if !is_intra && !self.shuf.has_last_frame() {
299 return Err(DecoderError::MissingReference);
300 }
301
302 if pkt.is_keyframe() {
303 self.shuf.add_keyframe(buf.clone());
304 }
305 self.shuf.add_frame(buf.clone());
306
307 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::VideoPacked(buf));
308 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
309 Ok(frm.into_ref())
310 }
311 fn flush(&mut self) {
312 self.shuf.clear();
313 }
314}
315
316impl NAOptionHandler for FSVDecoder {
317 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
318 fn set_options(&mut self, _options: &[NAOption]) { }
319 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
320}
321
322pub fn get_decoder() -> Box<dyn NADecoder + Send> {
323 Box::new(FSVDecoder::new(true))
324}
325
326pub fn get_decoder_v2() -> Box<dyn NADecoder + Send> {
327 Box::new(FSVDecoder::new(false))
328}
329
330#[cfg(test)]
331mod test {
332 use nihav_core::codecs::RegisteredDecoders;
333 use nihav_core::demuxers::RegisteredDemuxers;
334 use nihav_codec_support::test::dec_video::*;
335 use crate::flash_register_all_decoders;
336 use crate::flash_register_all_demuxers;
337 #[test]
338 fn test_flashsv1() {
339 let mut dmx_reg = RegisteredDemuxers::new();
340 flash_register_all_demuxers(&mut dmx_reg);
341 let mut dec_reg = RegisteredDecoders::new();
342 flash_register_all_decoders(&mut dec_reg);
343
886cde48 344 // sample: https://samples.mplayerhq.hu/FLV/flash_screen/screen.flv
92d9fb69
KS
345 test_decoding("flv", "flashsv", "assets/Flash/screen.flv",
346 Some(3000), &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
347 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
348 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
349 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
350 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
351 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
352 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
353 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
354 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
355 [0xc04d4d1c, 0xbb1f4b4f, 0xe9f3d85e, 0xa40aff68],
356 [0x172e5bbe, 0xe44caba3, 0x6cb2a263, 0xcb79a89a]]));
357 }
358 #[test]
359 fn test_flashsv2() {
360 let mut dmx_reg = RegisteredDemuxers::new();
361 flash_register_all_demuxers(&mut dmx_reg);
362 let mut dec_reg = RegisteredDecoders::new();
363 flash_register_all_decoders(&mut dec_reg);
364
886cde48 365 // sample created from https://samples.mplayerhq.hu/FLV/flash_screen/screen.flv by recoding
92d9fb69
KS
366 test_decoding("flv", "flashsv2", "assets/Flash/screen2.flv",
367 Some(4700), &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
368 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
369 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
370 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
371 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
372 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
373 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
374 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
375 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
376 [0x9809efc2, 0xec5385aa, 0xb5eb9320, 0x4a47188e],
377 [0x40c77877, 0x58183722, 0x5700eb17, 0x27a00e33],
378 [0x802c2c6a, 0x3e08dd62, 0xa6c94df3, 0xc6318a6f],
379 [0x2aa70255, 0x652f0ca4, 0xe79817f9, 0x4f67e7ba],
380 [0x5cf34d91, 0xdfc54992, 0x4368180d, 0xfbe747d4],
381 [0x266d8bc4, 0x2b492ef4, 0xb42401a0, 0x23e530ec],
382 [0xa0e46b1c, 0x47d0620e, 0x0cbcb15b, 0x243e7f13]]));
383 }
384}
385
386const DEFAULT_PAL: [u8; 128 * 3] = [
387 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x66, 0x66, 0x66, 0x99, 0x99, 0x99,
388 0xCC, 0xCC, 0xCC, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x00, 0x66, 0x00, 0x00,
389 0x99, 0x00, 0x00, 0xCC, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x33, 0x00,
390 0x00, 0x66, 0x00, 0x00, 0x99, 0x00, 0x00, 0xCC, 0x00, 0x00, 0xFF, 0x00,
391 0x00, 0x00, 0x33, 0x00, 0x00, 0x66, 0x00, 0x00, 0x99, 0x00, 0x00, 0xCC,
392 0x00, 0x00, 0xFF, 0x33, 0x33, 0x00, 0x66, 0x66, 0x00, 0x99, 0x99, 0x00,
393 0xCC, 0xCC, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x33, 0x33, 0x00, 0x66, 0x66,
394 0x00, 0x99, 0x99, 0x00, 0xCC, 0xCC, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x33,
395 0x66, 0x00, 0x66, 0x99, 0x00, 0x99, 0xCC, 0x00, 0xCC, 0xFF, 0x00, 0xFF,
396 0xFF, 0xFF, 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC,
397 0xFF, 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC, 0xFF,
398 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF,
399 0xCC, 0xCC, 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xFF,
400 0xCC, 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xFF, 0xCC,
401 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xFF, 0xCC, 0xCC,
402 0x99, 0x99, 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF,
403 0x99, 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF, 0x99,
404 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF, 0x99, 0x99,
405 0x66, 0x66, 0x33, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF,
406 0x66, 0x33, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF, 0x66,
407 0x33, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF, 0x66, 0x66,
408 0x33, 0x33, 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF,
409 0x33, 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF, 0x33,
410 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF, 0x33, 0x33,
411 0x00, 0x33, 0x66, 0x33, 0x66, 0x00, 0x66, 0x00, 0x33, 0x00, 0x66, 0x33,
412 0x33, 0x00, 0x66, 0x66, 0x33, 0x00, 0x33, 0x66, 0x99, 0x66, 0x99, 0x33,
413 0x99, 0x33, 0x66, 0x33, 0x99, 0x66, 0x66, 0x33, 0x99, 0x99, 0x66, 0x33,
414 0x66, 0x99, 0xCC, 0x99, 0xCC, 0x66, 0xCC, 0x66, 0x99, 0x66, 0xCC, 0x99,
415 0x99, 0x66, 0xCC, 0xCC, 0x99, 0x66, 0x99, 0xCC, 0xFF, 0xCC, 0xFF, 0x99,
416 0xFF, 0x99, 0xCC, 0x99, 0xFF, 0xCC, 0xCC, 0x99, 0xFF, 0xFF, 0xCC, 0x99,
417 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x55, 0x55, 0x55,
418 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xDD, 0xDD, 0xDD, 0xEE, 0xEE, 0xEE
419];