1 use nihav_core::frame::*;
2 use nihav_core::codecs::*;
3 use nihav_core::io::byteio::*;
4 use nihav_core::compr::deflate::*;
8 lastframe: Option<NAVideoBufferRef<u8>>,
9 keyframe: Option<NAVideoBufferRef<u8>>,
13 fn new() -> Self { Self::default() }
16 self.lastframe = None;
18 fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
19 self.lastframe = Some(buf);
21 fn add_keyframe(&mut self, buf: NAVideoBufferRef<u8>) {
22 self.keyframe = Some(buf);
24 fn clone_ref(&mut self) -> Option<NAVideoBufferRef<u8>> {
25 if let Some(ref mut frm) = self.lastframe {
26 let newfrm = frm.copy_buffer();
27 *frm = newfrm.clone().into_ref();
28 Some(newfrm.into_ref())
33 fn has_last_frame(&self) -> bool { self.lastframe.is_some() }
34 fn get_key_frame(&mut self) -> Option<NAVideoBufferRef<u8>> {
35 self.keyframe.as_ref().cloned()
37 /*fn get_last_frame(&mut self) -> Option<NAVideoBufferRef<u8>> {
38 self.lastframe.as_ref().cloned()
63 fn new(ver1: bool) -> Self {
65 info: NACodecInfo::new_dummy(),
66 shuf: FSVShuffler::new(),
77 inflate: Inflate::new(),
83 fn decode_v1(&mut self, br: &mut dyn ByteIO, data: &mut [u8], stride: usize) -> DecoderResult<bool> {
84 let mut is_intra = true;
85 for (yy, row) in data.chunks_mut(stride * self.block_h).enumerate() {
86 let cur_h = (self.h - yy * self.block_h).min(self.block_h);
87 for x in (0..self.w).step_by(self.block_w) {
88 let cur_w = (self.w - x).min(self.block_w);
90 let data_size = br.read_u16be()? as usize;
92 br.read_buf(&mut self.cbuf[..data_size])?;
93 self.inflate = Inflate::new();
94 if self.inflate.decompress_block(&self.cbuf[..data_size], &mut self.tile[..cur_w * cur_h * 3]).is_err() {
95 return Err(DecoderError::InvalidData);
97 for (dst, src) in row[x * 3..].chunks_mut(stride).zip(self.tile.chunks(cur_w * 3)) {
98 dst[..cur_w * 3].copy_from_slice(src);
107 fn decode_v2(&mut self, br: &mut dyn ByteIO, data: &mut [u8], stride: usize, keyframe: bool) -> DecoderResult<bool> {
108 let mut is_intra = !self.has_ifrm;
109 let bstride = (self.w + self.block_w - 1) / self.block_w;
110 for y in (0..self.h).step_by(self.block_h) {
111 let cur_h = (self.h - y).min(self.block_h);
112 for x in (0..self.w).step_by(self.block_w) {
113 let cur_w = (self.w - x).min(self.block_w);
115 let mut data_size = br.read_u16be()? as usize;
116 validate!(!keyframe || data_size > 0);
121 let blk_start = br.tell();
122 let flags = br.read_byte()?;
123 let depth = (flags >> 3) & 3;
124 validate!(depth == 0 || depth == 2);
125 let has_diff = (flags & 4) != 0;
126 let cpriming = (flags & 2) != 0;
127 let ppriming = (flags & 1) != 0;
128 let (start, height) = if has_diff {
129 let start = br.read_byte()? as usize;
130 let height = br.read_byte()? as usize;
131 validate!(start + height <= cur_h);
137 let ret = self.shuf.get_key_frame();
139 return Err(DecoderError::MissingReference);
141 let src = ret.unwrap();
142 let src = src.get_data();
143 for (dst, src) in data[x * 3 + y * stride..].chunks_mut(stride).take(cur_h).zip(src[x * 3 + y * stride..].chunks(stride)) {
144 dst[..cur_w * 3].copy_from_slice(&src[..cur_w * 3]);
150 let ppos = if cpriming {
151 let xpos = br.read_byte()? as usize;
152 let ypos = br.read_byte()? as usize;
153 xpos + ypos * bstride
155 x / self.block_w + y / self.block_h * bstride
157 data_size -= (br.tell() - blk_start) as usize;
159 self.bpos.push(br.tell() as usize);
160 self.bsize.push(data_size);
163 br.read_buf(&mut self.cbuf[..data_size])?;
164 self.inflate = Inflate::new();
165 if cpriming || ppriming {
166 if self.bpos.is_empty() {
167 return Err(DecoderError::MissingReference);
169 let ret = self.inflate.decompress_block(&self.kdata[self.bpos[ppos]..][..self.bsize[ppos]], &mut self.tile);
171 return Err(DecoderError::InvalidData);
173 let ssize = ret.unwrap();
174 self.inflate = Inflate::new();
175 self.inflate.set_dict(&self.tile[..ssize]);
177 let ret = self.inflate.decompress_block(&self.cbuf[..data_size], &mut self.tile[..cur_w * height * 3]);
179 return Err(DecoderError::InvalidData);
181 let src_len = ret.unwrap();
183 let dst = &mut data[x * 3 + y * stride..];
186 validate!(src_len == cur_w * cur_h * 3);
187 for (dst, src) in dst.chunks_mut(stride).skip(start).take(height).zip(self.tile.chunks(cur_w * 3)) {
188 dst[..cur_w * 3].copy_from_slice(src);
192 let mut br = MemoryReader::new_read(&self.tile[..src_len]);
193 for line in dst.chunks_mut(stride).skip(start).take(height) {
194 for rgb in line.chunks_mut(3).take(cur_w) {
195 let b = br.read_byte()?;
197 rgb.copy_from_slice(&self.pal[(b as usize) * 3..][..3]);
199 let c = br.read_byte()?;
200 let clr = (u16::from(b & 0x7F) << 8) | u16::from(c);
201 let r = (clr >> 10) as u8;
202 let g = ((clr >> 5) & 0x1F) as u8;
203 let b = (clr & 0x1F) as u8;
204 rgb[0] = (r << 3) | (r >> 2);
205 rgb[1] = (g << 3) | (g >> 2);
206 rgb[2] = (b << 3) | (b >> 2);
225 impl NADecoder for FSVDecoder {
226 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
227 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
228 let w = vinfo.get_width();
229 let h = vinfo.get_height();
230 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, true, BGR24_FORMAT));
231 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
235 Err(DecoderError::InvalidData)
238 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
239 let src = pkt.get_buffer();
241 validate!(src.len() > 4);
242 let mut br = MemoryReader::new_read(&src);
244 let hdr0 = br.read_u16be()? as usize;
245 let hdr1 = br.read_u16be()? as usize;
246 let w = hdr0 & 0xFFF;
247 let h = hdr1 & 0xFFF;
248 let blk_w = (hdr0 >> 12) * 16 + 16;
249 let blk_h = (hdr1 >> 12) * 16 + 16;
250 validate!(w != 0 && h != 0 && blk_w != 0 && blk_h != 0);
253 let flags = br.read_byte()?;
254 self.has_pal = (flags & 1) != 0;
255 self.has_ifrm = (flags & 2) != 0;
257 let pal_sz = br.read_u16be()? as usize;
258 br.read_buf(&mut self.cbuf[..pal_sz])?;
259 self.inflate = Inflate::new();
260 if self.inflate.decompress_block(&self.cbuf[..pal_sz], &mut self.pal).is_err() {
261 return Err(DecoderError::InvalidData);
266 self.kdata.extend_from_slice(&src);
271 if self.w != w || self.h != h || self.block_w != blk_w || self.block_h != blk_h {
273 self.tile.resize(blk_w * blk_h * 3, 0);
276 self.block_w = blk_w;
277 self.block_h = blk_h;
280 let mut buf = if let Some(buffer) = self.shuf.clone_ref() {
283 let vinfo = self.info.get_properties().get_video_info().unwrap();
284 let bufinfo = alloc_video_buffer(vinfo, 0)?;
285 bufinfo.get_vbuf().unwrap()
287 let stride = buf.get_stride(0);
288 let data = buf.get_data_mut().unwrap();
289 let is_intra = if self.ver1 {
290 self.decode_v1(&mut br, data, stride)?
292 self.decode_v2(&mut br, data, stride, pkt.keyframe)?
295 if !is_intra && !self.shuf.has_last_frame() {
296 return Err(DecoderError::MissingReference);
299 if pkt.is_keyframe() {
300 self.shuf.add_keyframe(buf.clone());
302 self.shuf.add_frame(buf.clone());
304 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::VideoPacked(buf));
305 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
308 fn flush(&mut self) {
313 impl NAOptionHandler for FSVDecoder {
314 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
315 fn set_options(&mut self, _options: &[NAOption]) { }
316 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
319 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
320 Box::new(FSVDecoder::new(true))
323 pub fn get_decoder_v2() -> Box<dyn NADecoder + Send> {
324 Box::new(FSVDecoder::new(false))
329 use nihav_core::codecs::RegisteredDecoders;
330 use nihav_core::demuxers::RegisteredDemuxers;
331 use nihav_codec_support::test::dec_video::*;
332 use crate::flash_register_all_decoders;
333 use crate::flash_register_all_demuxers;
336 let mut dmx_reg = RegisteredDemuxers::new();
337 flash_register_all_demuxers(&mut dmx_reg);
338 let mut dec_reg = RegisteredDecoders::new();
339 flash_register_all_decoders(&mut dec_reg);
341 // sample: https://samples.mplayerhq.hu/FLV/flash_screen/screen.flv
342 test_decoding("flv", "flashsv", "assets/Flash/screen.flv",
343 Some(3000), &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
344 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
345 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
346 [0xb45b899e, 0x417b17d5, 0x7bfe898b, 0x026b289f],
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 [0xc04d4d1c, 0xbb1f4b4f, 0xe9f3d85e, 0xa40aff68],
353 [0x172e5bbe, 0xe44caba3, 0x6cb2a263, 0xcb79a89a]]));
357 let mut dmx_reg = RegisteredDemuxers::new();
358 flash_register_all_demuxers(&mut dmx_reg);
359 let mut dec_reg = RegisteredDecoders::new();
360 flash_register_all_decoders(&mut dec_reg);
362 // sample created from https://samples.mplayerhq.hu/FLV/flash_screen/screen.flv by recoding
363 test_decoding("flv", "flashsv2", "assets/Flash/screen2.flv",
364 Some(4700), &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
365 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
366 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
367 [0x55522afa, 0x9c7dd794, 0xdd67aa2e, 0x8b8c525e],
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 [0x9809efc2, 0xec5385aa, 0xb5eb9320, 0x4a47188e],
374 [0x40c77877, 0x58183722, 0x5700eb17, 0x27a00e33],
375 [0x802c2c6a, 0x3e08dd62, 0xa6c94df3, 0xc6318a6f],
376 [0x2aa70255, 0x652f0ca4, 0xe79817f9, 0x4f67e7ba],
377 [0x5cf34d91, 0xdfc54992, 0x4368180d, 0xfbe747d4],
378 [0x266d8bc4, 0x2b492ef4, 0xb42401a0, 0x23e530ec],
379 [0xa0e46b1c, 0x47d0620e, 0x0cbcb15b, 0x243e7f13]]));
383 const DEFAULT_PAL: [u8; 128 * 3] = [
384 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x66, 0x66, 0x66, 0x99, 0x99, 0x99,
385 0xCC, 0xCC, 0xCC, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x00, 0x66, 0x00, 0x00,
386 0x99, 0x00, 0x00, 0xCC, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x33, 0x00,
387 0x00, 0x66, 0x00, 0x00, 0x99, 0x00, 0x00, 0xCC, 0x00, 0x00, 0xFF, 0x00,
388 0x00, 0x00, 0x33, 0x00, 0x00, 0x66, 0x00, 0x00, 0x99, 0x00, 0x00, 0xCC,
389 0x00, 0x00, 0xFF, 0x33, 0x33, 0x00, 0x66, 0x66, 0x00, 0x99, 0x99, 0x00,
390 0xCC, 0xCC, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x33, 0x33, 0x00, 0x66, 0x66,
391 0x00, 0x99, 0x99, 0x00, 0xCC, 0xCC, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x33,
392 0x66, 0x00, 0x66, 0x99, 0x00, 0x99, 0xCC, 0x00, 0xCC, 0xFF, 0x00, 0xFF,
393 0xFF, 0xFF, 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC,
394 0xFF, 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC, 0xFF,
395 0x33, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF,
396 0xCC, 0xCC, 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xFF,
397 0xCC, 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xFF, 0xCC,
398 0x33, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0xFF, 0xCC, 0xCC,
399 0x99, 0x99, 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF,
400 0x99, 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF, 0x99,
401 0x33, 0x99, 0x99, 0x66, 0x99, 0x99, 0xCC, 0x99, 0x99, 0xFF, 0x99, 0x99,
402 0x66, 0x66, 0x33, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF,
403 0x66, 0x33, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF, 0x66,
404 0x33, 0x66, 0x66, 0x99, 0x66, 0x66, 0xCC, 0x66, 0x66, 0xFF, 0x66, 0x66,
405 0x33, 0x33, 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF,
406 0x33, 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF, 0x33,
407 0x66, 0x33, 0x33, 0x99, 0x33, 0x33, 0xCC, 0x33, 0x33, 0xFF, 0x33, 0x33,
408 0x00, 0x33, 0x66, 0x33, 0x66, 0x00, 0x66, 0x00, 0x33, 0x00, 0x66, 0x33,
409 0x33, 0x00, 0x66, 0x66, 0x33, 0x00, 0x33, 0x66, 0x99, 0x66, 0x99, 0x33,
410 0x99, 0x33, 0x66, 0x33, 0x99, 0x66, 0x66, 0x33, 0x99, 0x99, 0x66, 0x33,
411 0x66, 0x99, 0xCC, 0x99, 0xCC, 0x66, 0xCC, 0x66, 0x99, 0x66, 0xCC, 0x99,
412 0x99, 0x66, 0xCC, 0xCC, 0x99, 0x66, 0x99, 0xCC, 0xFF, 0xCC, 0xFF, 0x99,
413 0xFF, 0x99, 0xCC, 0x99, 0xFF, 0xCC, 0xCC, 0x99, 0xFF, 0xFF, 0xCC, 0x99,
414 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x55, 0x55, 0x55,
415 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xDD, 0xDD, 0xDD, 0xEE, 0xEE, 0xEE
418 const BGR24_FORMAT: NAPixelFormaton = NAPixelFormaton {
419 model: ColorModel::RGB(RGBSubmodel::RGB), components: 3,
421 Some(NAPixelChromaton{
422 h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 2, next_elem: 3 }),
423 Some(NAPixelChromaton{
424 h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 1, next_elem: 3 }),
425 Some(NAPixelChromaton{
426 h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 0, next_elem: 3 }),
428 elem_size: 3, be: false, alpha: false, palette: false