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