Flash support
[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 test_decoding("flv", "flashsv", "assets/Flash/screen.flv",
351 Some(3000), &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
352 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
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 [0xc04d4d1c, 0xbb1f4b4f, 0xe9f3d85e, 0xa40aff68],
361 [0x172e5bbe, 0xe44caba3, 0x6cb2a263, 0xcb79a89a]]));
362 }
363 #[test]
364 fn test_flashsv2() {
365 let mut dmx_reg = RegisteredDemuxers::new();
366 flash_register_all_demuxers(&mut dmx_reg);
367 let mut dec_reg = RegisteredDecoders::new();
368 flash_register_all_decoders(&mut dec_reg);
369
370 test_decoding("flv", "flashsv2", "assets/Flash/screen2.flv",
371 Some(4700), &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
372 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
373 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
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 [0x9809efc2, 0xec5385aa, 0xb5eb9320, 0x4a47188e],
381 [0x40c77877, 0x58183722, 0x5700eb17, 0x27a00e33],
382 [0x802c2c6a, 0x3e08dd62, 0xa6c94df3, 0xc6318a6f],
383 [0x2aa70255, 0x652f0ca4, 0xe79817f9, 0x4f67e7ba],
384 [0x5cf34d91, 0xdfc54992, 0x4368180d, 0xfbe747d4],
385 [0x266d8bc4, 0x2b492ef4, 0xb42401a0, 0x23e530ec],
386 [0xa0e46b1c, 0x47d0620e, 0x0cbcb15b, 0x243e7f13]]));
387 }
388 }
389
390 const DEFAULT_PAL: [u8; 128 * 3] = [
391 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x66, 0x66, 0x66, 0x99, 0x99, 0x99,
392 0xCC, 0xCC, 0xCC, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x00, 0x66, 0x00, 0x00,
393 0x99, 0x00, 0x00, 0xCC, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x33, 0x00,
394 0x00, 0x66, 0x00, 0x00, 0x99, 0x00, 0x00, 0xCC, 0x00, 0x00, 0xFF, 0x00,
395 0x00, 0x00, 0x33, 0x00, 0x00, 0x66, 0x00, 0x00, 0x99, 0x00, 0x00, 0xCC,
396 0x00, 0x00, 0xFF, 0x33, 0x33, 0x00, 0x66, 0x66, 0x00, 0x99, 0x99, 0x00,
397 0xCC, 0xCC, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x33, 0x33, 0x00, 0x66, 0x66,
398 0x00, 0x99, 0x99, 0x00, 0xCC, 0xCC, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x33,
399 0x66, 0x00, 0x66, 0x99, 0x00, 0x99, 0xCC, 0x00, 0xCC, 0xFF, 0x00, 0xFF,
400 0xFF, 0xFF, 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC,
401 0xFF, 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC, 0xFF,
402 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF,
403 0xCC, 0xCC, 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xFF,
404 0xCC, 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xFF, 0xCC,
405 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xFF, 0xCC, 0xCC,
406 0x99, 0x99, 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF,
407 0x99, 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF, 0x99,
408 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF, 0x99, 0x99,
409 0x66, 0x66, 0x33, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF,
410 0x66, 0x33, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF, 0x66,
411 0x33, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF, 0x66, 0x66,
412 0x33, 0x33, 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF,
413 0x33, 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF, 0x33,
414 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF, 0x33, 0x33,
415 0x00, 0x33, 0x66, 0x33, 0x66, 0x00, 0x66, 0x00, 0x33, 0x00, 0x66, 0x33,
416 0x33, 0x00, 0x66, 0x66, 0x33, 0x00, 0x33, 0x66, 0x99, 0x66, 0x99, 0x33,
417 0x99, 0x33, 0x66, 0x33, 0x99, 0x66, 0x66, 0x33, 0x99, 0x99, 0x66, 0x33,
418 0x66, 0x99, 0xCC, 0x99, 0xCC, 0x66, 0xCC, 0x66, 0x99, 0x66, 0xCC, 0x99,
419 0x99, 0x66, 0xCC, 0xCC, 0x99, 0x66, 0x99, 0xCC, 0xFF, 0xCC, 0xFF, 0x99,
420 0xFF, 0x99, 0xCC, 0x99, 0xFF, 0xCC, 0xCC, 0x99, 0xFF, 0xFF, 0xCC, 0x99,
421 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x55, 0x55, 0x55,
422 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xDD, 0xDD, 0xDD, 0xEE, 0xEE, 0xEE
423 ];