]> git.nihav.org Git - nihav.git/blobdiff - src/demuxers/avi.rs
fix an error in AVI demuxer
[nihav.git] / src / demuxers / avi.rs
index 56cf023e50309c71f71ae2863ae9b1d09e82e106..c00df25ad8682626d4ebdfcb94377f3f934590bd 100644 (file)
@@ -81,12 +81,20 @@ impl<'a> Demux<'a> for AVIDemuxer<'a> {
             if (self.src.tell() & 1) == 1 {
                 self.src.read_skip(1)?;
                 self.movi_size -= 1;
+                if self.movi_size == 0 { return Err(EOF); }
             }
             self.src.read_buf(&mut tag)?;
             let size = self.src.read_u32le()? as usize;
             if mktag!(tag) == mktag!(b"JUNK") {
                 self.movi_size -= size + 8;
                 self.src.read_skip(size)?;
+                if self.movi_size == 0 { return Err(EOF); }
+                continue;
+            }
+            if mktag!(tag) == mktag!(b"LIST") {
+                self.movi_size -= 12;
+                self.src.read_skip(4)?;
+                if self.movi_size == 0 { return Err(EOF); }
                 continue;
             }
             if tag[0] < b'0' || tag[0] > b'9' || tag[1] < b'0' || tag[1] > b'9' {
@@ -139,7 +147,8 @@ impl<'a> AVIDemuxer<'a> {
         if RIFFTag::Chunk(tag) == end_tag {
             return Ok((size, true));
         }
-        let ltag = if is_list_tag(tag) { self.src.read_u32be()? } else { 0 };
+        let is_list = is_list_tag(tag);
+        let ltag = if is_list { self.src.read_u32be()? } else { 0 };
         if RIFFTag::List(tag, ltag) == end_tag {
             return Ok((size, true));
         }
@@ -148,6 +157,7 @@ impl<'a> AVIDemuxer<'a> {
             if RIFFTag::Chunk(tag) == CHUNKS[i].tag {
                 let psize = (CHUNKS[i].parse)(self, size)?;
                 if psize != size { return Err(InvalidData); }
+                if (psize & 1) == 1 { self.src.read_skip(1)?; }
                 return Ok((size + 8, false));
             }
             if RIFFTag::List(tag, ltag) == CHUNKS[i].tag {
@@ -159,12 +169,23 @@ impl<'a> AVIDemuxer<'a> {
                     let (psize, _) = self.parse_chunk(end_tag, rest_size, depth+1)?;
                     if psize > rest_size { return Err(InvalidData); }
                     rest_size -= psize;
+                    if (psize & 1) == 1 {
+                        if rest_size > 0 {
+                            rest_size -= 1;
+                        }
+                    }
                 }
 
                 return Ok((size + 8, false));
             }
         }
-        self.src.read_skip(size)?;
+        if !is_list {
+            self.src.read_skip(size)?;
+        } else {
+            if size < 4 { return Err(InvalidData); }
+            self.src.read_skip(size - 4)?;
+        }
+        if (size & 1) == 1 { self.src.read_skip(1)?; }
         return Ok((size + 8, false));
     }
 
@@ -315,7 +336,7 @@ fn parse_strf_auds(dmx: &mut AVIDemuxer, size: usize) -> DemuxerResult<usize> {
     let samplespersec       = dmx.src.read_u32le()?;
     let avgbytespersec      = dmx.src.read_u32le()?;
     let block_align         = dmx.src.read_u16le()?;
-    let bits_per_sample     = dmx.src.read_u16le()?;
+    let bits_per_sample     = dmx.src.read_u16le()? * 8;
 
     let soniton = NASoniton::new(bits_per_sample as u8, SONITON_FLAG_SIGNED);
     let ahdr = NAAudioInfo::new(samplespersec, channels as u8, soniton, block_align as usize);