block_size: usize,
is_pcm: bool,
avg_bytes: u32,
+ duration: u64,
+
+ force_tb_num: u32,
+ force_tb_den: u32,
}
impl<'a> DemuxCore<'a> for WAVDemuxer<'a> {
fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
let riff = self.src.read_u32be()?;
let riff_size = self.src.read_u32le()? as usize;
- let riff_end = self.src.tell() + if riff_size > 0 { (riff_size as u64) } else { u64::from(std::u32::MAX) };
+ let riff_end = self.src.tell() + if riff_size > 0 { riff_size as u64 } else { u64::from(std::u32::MAX) };
let wave = self.src.read_u32be()?;
validate!(riff == mktag!(b"RIFF"));
validate!(wave == mktag!(b"WAVE"));
seek_index.mode = SeekIndexMode::Automatic;
let mut fmt_parsed = false;
- let mut _duration = 0;
+ let mut duration = 0;
while self.src.tell() < riff_end {
let ctype = self.src.read_tag()?;
let csize = self.src.read_u32le()? as usize;
},
b"fact" => {
validate!(csize == 4);
- _duration = self.src.read_u32le()? as usize;
+ duration = self.src.read_u32le()? as usize;
},
b"data" => {
validate!(fmt_parsed);
self.data_pos = self.src.tell();
self.data_end = self.data_pos + (csize as u64);
+
+ if duration != 0 {
+ self.duration = (duration as u64) * 1000 / u64::from(self.srate);
+ } else if self.avg_bytes > 0 {
+ self.duration = (self.data_end - self.data_pos) * 1000 / u64::from(self.avg_bytes);
+ } else {
+ self.duration = 0;
+ }
+
return Ok(());
},
_ => {
if self.src.tell() >= self.data_end {
return Err(DemuxerError::EOF);
}
- let str = strmgr.get_stream(0);
- if str.is_none() { return Err(InvalidData); }
- let stream = str.unwrap();
- let ts = NATimeInfo::new(None, None, None, 1, self.srate);
+ let strm = strmgr.get_stream(0);
+ if strm.is_none() { return Err(InvalidData); }
+ let stream = strm.unwrap();
+ let pts = if self.avg_bytes != 0 {
+ let pos = self.src.tell() - self.data_pos;
+ Some(pos * u64::from(self.srate) / u64::from(self.avg_bytes))
+ } else {
+ None
+ };
+ let ts = NATimeInfo::new(pts, None, None, 1, self.srate);
if self.is_pcm {
- let mut bsize = self.block_size;
- while bsize < 256 {
- bsize <<= 1;
- }
+ let bsize = if self.force_tb_num != 0 && self.force_tb_den != 0 {
+ let nbsize = u64::from(self.avg_bytes) * u64::from(self.force_tb_num) / u64::from(self.force_tb_den);
+ let mut nbsize = nbsize as usize + self.block_size - 1;
+ nbsize /= self.block_size;
+ nbsize *= self.block_size;
+ nbsize
+ } else {
+ let mut bsize = self.block_size;
+ while bsize < 256 {
+ bsize <<= 1;
+ }
+ bsize
+ };
let mut buf = vec![0; bsize];
- let size = self.src.read_buf_some(buf.as_mut_slice())?;
- buf.truncate(size);
+ let mut tot_size = 0;
+ while let Ok(psize) = self.src.read_buf_some(&mut buf[tot_size..]) {
+ tot_size += psize;
+ if tot_size == buf.len() {
+ break;
+ }
+ }
+ buf.truncate(tot_size);
Ok(NAPacket::new(stream, ts, true, buf))
} else {
self.src.read_packet(stream, ts, true, self.block_size)
}
}
- fn seek(&mut self, time: u64, _seek_index: &SeekIndex) -> DemuxerResult<()> {
+ fn seek(&mut self, time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> {
if self.block_size != 0 && self.avg_bytes != 0 {
- let seek_dst = u64::from(self.avg_bytes) * time / 1000;
- let seek_off = seek_dst / (self.block_size as u64) * (self.block_size as u64);
+ let seek_off = match time {
+ NATimePoint::Milliseconds(ms) => {
+ let seek_dst = u64::from(self.avg_bytes) * ms / 1000;
+ seek_dst / (self.block_size as u64) * (self.block_size as u64)
+ },
+ NATimePoint::PTS(pts) => (self.block_size as u64) * pts,
+ NATimePoint::None => return Ok(()),
+ };
self.src.seek(SeekFrom::Start(self.data_pos + seek_off))?;
Ok(())
} else {
Err(DemuxerError::NotImplemented)
}
}
+
+ fn get_duration(&self) -> u64 { self.duration }
}
+const WAV_OPTIONS: &[NAOptionDefinition] = &[
+ NAOptionDefinition {
+ name: "force_tb_num", description: "force timebase numerator for PCM blocks",
+ opt_type: NAOptionDefinitionType::Int(Some(1), None) },
+ NAOptionDefinition {
+ name: "force_tb_den", description: "force timebase denominator for PCM blocks",
+ opt_type: NAOptionDefinitionType::Int(Some(1), None) },
+];
+
impl<'a> NAOptionHandler for WAVDemuxer<'a> {
- fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
- fn set_options(&mut self, _options: &[NAOption]) { }
- fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
+ fn get_supported_options(&self) -> &[NAOptionDefinition] { WAV_OPTIONS }
+ fn set_options(&mut self, options: &[NAOption]) {
+ for option in options.iter() {
+ match (option.name, &option.value) {
+ ("force_tb_num", NAValue::Int(ref ival)) => {
+ self.force_tb_num = *ival as u32;
+ },
+ ("force_tb_den", NAValue::Int(ref ival)) => {
+ self.force_tb_den = *ival as u32;
+ },
+ _ => {},
+ };
+ }
+ }
+ fn query_option_value(&self, name: &str) -> Option<NAValue> {
+ match name {
+ "force_tb_num" => Some(NAValue::Int(i64::from(self.force_tb_num))),
+ "force_tb_den" => Some(NAValue::Int(i64::from(self.force_tb_den))),
+ _ => None,
+ }
+ }
}
impl<'a> WAVDemuxer<'a> {
block_size: 0,
is_pcm: false,
avg_bytes: 0,
+ duration: 0,
+ force_tb_num: 0,
+ force_tb_den: 0,
}
}
fn parse_fmt(&mut self, strmgr: &mut StreamManager, csize: usize) -> DemuxerResult<()> {
};
let ahdr = NAAudioInfo::new(samples_per_sec, channels as u8, soniton, block_align);
let ainfo = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
- let res = strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, 1, samples_per_sec));
+ let res = strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, 1, samples_per_sec, 0));
if res.is_none() { return Err(MemoryError); }
self.srate = samples_per_sec;
self.block_size = block_align;
self.avg_bytes = avg_bytes_per_sec;
self.is_pcm = cname == "pcm";
+ if self.is_pcm && self.avg_bytes == 0 {
+ self.avg_bytes = self.block_size as u32 * self.srate;
+ }
Ok(())
}
#[test]
fn test_wav_demux() {
+ // sample: https://samples.mplayerhq.hu/A-codecs/msadpcm-stereo/scatter.wav
let mut file = File::open("assets/MS/scatter.wav").unwrap();
let mut fr = FileReader::new_read(&mut file);
let mut br = ByteReader::new(&mut fr);