TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
];
+fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
+ let read_part = br.tell() - start_pos;
+ if read_part + 8 < size {
+ let csize = br.read_u32be()? as u64;
+ let ctag = br.read_u32be()?;
+ validate!(read_part + csize <= size);
+ validate!(ctag == mktag!(b"wave"));
+ if csize == 8 {
+ return Ok(None);
+ }
+ let mut buf = [0; 8];
+ br.peek_buf(&mut buf)?;
+ if &buf[4..8] == b"frma" {
+ br.read_skip(12)?;
+ if csize > 20 {
+ let mut buf = vec![0; (csize - 20) as usize];
+ br.read_buf(&mut buf)?;
+ Ok(Some(buf))
+ } else {
+ Ok(None)
+ }
+ } else if csize > 8 {
+ let mut buf = vec![0; (csize as usize) - 8];
+ br.read_buf(&mut buf)?;
+ Ok(Some(buf))
+ } else {
+ Ok(None)
+ }
+ } else {
+ Ok(None)
+ }
+}
+
fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
const KNOWN_STSD_SIZE: u64 = 24;
validate!(size >= KNOWN_STSD_SIZE);
let edata = if br.tell() - start_pos + 4 < size {
//todo skip various common atoms
let edata_size = br.read_u32be()? as usize;
- let mut buf = vec![0; edata_size];
+ validate!(edata_size >= 4);
+ let mut buf = vec![0; edata_size - 4];
br.read_buf(buf.as_mut_slice())?;
Some(buf)
} else {
codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
},
StreamType::Audio => {
- let _ver = br.read_u16be()?;
+ let sver = br.read_u16be()?;
let _revision = br.read_u16le()?;
let _vendor = br.read_u32be()?;
let nchannels = br.read_u16be()?;
//todo adjust format for various PCM kinds
let soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
let block_align = 1;
+ if sver == 1 {
+ let samples_per_packet = br.read_u32be()?;
+ let _bytes_per_packet = br.read_u32be()?;
+ let bytes_per_frame = br.read_u32be()?;
+ let _bytes_per_sample = br.read_u32be()?;
+ track.bsize = bytes_per_frame as usize;
+ track.frame_samples = samples_per_packet as usize;
+ } else {
+ track.bsize = sample_size as usize;
+ }
let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
- let edata = None;
+ let edata = parse_audio_edata(br, start_pos, size)?;
codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
track.channels = nchannels as usize;
track.bits = sample_size as usize;
let sample_size = br.read_u32be()?;
if sample_size != 0 {
track.sample_size = sample_size;
+ if track.sample_size != 1 || track.bsize == 0 {
+ track.bsize = sample_size as usize;
+ }
Ok(8)
} else {
let entries = br.read_u32be()? as usize;
height: usize,
channels: usize,
bits: usize,
+ bsize: usize,
fcc: [u8; 4],
keyframes: Vec<u32>,
chunk_sizes: Vec<u32>,
chunk_offsets: Vec<u64>,
sample_map: Vec<(u32, u32)>,
sample_size: u32,
+ frame_samples: usize,
stream: Option<NAStream>,
cur_chunk: usize,
cur_sample: usize,
height: 0,
channels: 0,
bits: 0,
+ bsize: 0,
fcc: [0; 4],
keyframes: Vec::new(),
chunk_sizes: Vec::new(),
chunk_offsets: Vec::new(),
sample_map: Vec::new(),
sample_size: 0,
+ frame_samples: 0,
stream: None,
depth: 0,
cur_chunk: 0,
}
fn calculate_chunk_size(&self, nsamp: usize) -> usize {
if nsamp == 0 {
- self.sample_size as usize
+ self.bsize
} else {
match &self.fcc {
b"NONE" | b"raw " | b"twos" | b"sowt" => {
b"ms\x00\x21" => { //IMA ADPCM
(nsamp / 2 + 4) * self.channels
},
- _ => self.sample_size as usize,
+ _ => self.bsize,
}
}
}
self.last_offset += size as u64;
if self.stream_type == StreamType::Video {
self.samples_left -= 1;
+ } else if self.frame_samples != 0 {
+ self.samples_left -= self.frame_samples.min(self.samples_left);
} else {
self.samples_left = 0;
}
}
self.calculate_chunk_size(nsamp as usize)
} else {
- self.sample_size as usize
+ self.bsize
}
}
fn seek(&mut self, pts: u64) {