use nihav_core::codecs::*;
use nihav_core::io::byteio::*;
use nihav_codec_support::codecs::HAMShuffler;
+use nihav_codec_support::codecs::imaadpcm::*;
use std::str::FromStr;
use std::sync::Arc;
let dst = &mut dst[dpos..][..len];
br.read_buf(dst)?;
} else {
- let val = br.read_byte()?;
- for i in 0..len {
- dst[dpos + i] = val;
+ let val1 = br.read_byte()?;
+ let val2 = br.read_byte()?;
+ for i in (0..len).step_by(2) {
+ dst[dpos + i] = val1;
+ dst[dpos + i + 1] = val2;
}
}
dpos += len;
buf: Vec<u8>,
width: usize,
height: usize,
+ xoff: usize,
+ yoff: usize,
hams: HAMShuffler,
}
buf: Vec::new(),
width: 0,
height: 0,
+ xoff: 0,
+ yoff: 0,
hams: HAMShuffler::default(),
}
}
if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
return Ok(false);
}
+ validate!(frame_x >= self.xoff && frame_y >= self.yoff);
validate!(frame_l >= frame_x && frame_d >= frame_y);
- validate!(frame_l < self.width && frame_d < self.height);
+ validate!(frame_l - self.xoff < self.width && frame_d - self.yoff < self.height);
if has_pal {
br.read_skip(2)?;
let w = frame_l + 1 - frame_x;
let h = frame_d + 1 - frame_y;
- let dpos = frame_x + frame_y * stride;
+ let dpos = frame_x - self.xoff + (frame_y - self.yoff) * stride;
let method = br.read_byte()?;
let is_intra;
if let Some(ref edata) = info.get_extradata() {
validate!(edata.len() == 0x330);
let unp_size = read_u32le(&edata[800..])? as usize;
- validate!(unp_size < self.width * self.height * 3 + 64); // just for sanity
+ validate!(unp_size < self.width * self.height * 4 + 64); // just for sanity
self.buf.resize(unp_size, 0);
for i in 0..768 {
let el = edata[28 + i];
self.pal[i] = (el << 2) | (el >> 4);
}
+ self.xoff = read_u16le(&edata[8..])? as usize;
+ self.yoff = read_u16le(&edata[10..])? as usize;
}
Ok(())
U8,
DPCM,
StereoDPCM,
+ ADPCM,
}
struct VMDAudioDecoder {
}
} else {
fmt = SND_S16P_FORMAT;
- self.blk_size = (ainfo.get_block_len() + 1) * channels;
self.blk_align = ainfo.get_block_len();
- self.mode = VMDAudioMode::DPCM;
+ if (flags & 0x10) == 0 {
+ self.blk_size = (ainfo.get_block_len() + 1) * channels;
+ self.mode = VMDAudioMode::DPCM;
+ } else {
+ self.blk_size = ainfo.get_block_len() / 2 + 3;
+ self.mode = VMDAudioMode::ADPCM;
+ }
};
self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone()));
}
self.ch = ch;
},
+ VMDAudioMode::ADPCM => {
+ let mut adata = abuf.get_abuf_i16().unwrap();
+ let dst = adata.get_data_mut().unwrap();
+ let mut doff = 0;
+ if self.chmap.num_channels() == 1 {
+ let mut mask = mask;
+ let mut ima = IMAState::new();
+ for _ in 0..nblocks {
+ if (mask & 1) != 0 {
+ doff += (self.blk_size - 3) * 2;
+ mask >>= 1;
+ continue;
+ }
+ let pred = br.read_u16le()? as i16;
+ let step = br.read_byte()?;
+ validate!((step as usize) < IMA_STEP_TABLE.len());
+ ima.reset(pred, step);
+ for _ in 3..self.blk_size {
+ let b = br.read_byte()?;
+ dst[doff] = ima.expand_sample(b >> 4);
+ doff += 1;
+ dst[doff] = ima.expand_sample(b & 0xF);
+ doff += 1;
+ }
+ mask >>= 1;
+ }
+ } else {
+ return Err(DecoderError::InvalidData);
+ }
+ },
};
let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);