mov: do not skip deflate stream header, inflate can do it automatically now
[nihav.git] / nihav-commonfmt / src / demuxers / mov.rs
index 0c23b02c8adeee1e635ed170517a086ffbf5db56..1d2df514a7d9ad0cf4e3e31f92a9cec5933ca1e4 100644 (file)
@@ -1,5 +1,6 @@
 use nihav_core::demuxers::*;
 use nihav_registry::register::*;
+use nihav_core::compr::deflate::*;
 
 macro_rules! mktag {
     ($a:expr, $b:expr, $c:expr, $d:expr) => ({
@@ -169,6 +170,7 @@ fn read_moov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> Dem
 
 const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[
     RootChunkHandler { ctype: mktag!(b"mvhd"), parse: read_mvhd },
+    RootChunkHandler { ctype: mktag!(b"cmov"), parse: read_cmov },
     RootChunkHandler { ctype: mktag!(b"ctab"), parse: read_ctab },
     RootChunkHandler { ctype: mktag!(b"trak"), parse: read_trak },
     RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
@@ -202,6 +204,45 @@ fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> De
     Ok(KNOWN_MVHD_SIZE)
 }
 
+fn read_cmov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
+    let br = &mut dmx.src;
+    validate!(size > 24);
+    let dcom_size           = br.read_u32be()?;
+    let dcom_tag            = br.read_tag()?;
+    let compr_type          = br.read_tag()?;
+    validate!(&dcom_tag == b"dcom" && dcom_size == 12);
+    if &compr_type != b"zlib" {
+        return Err(DemuxerError::NotImplemented);
+    }
+    let cmvd_size           = u64::from(br.read_u32be()?);
+    let cmvd_tag            = br.read_tag()?;
+    validate!(&cmvd_tag == b"cmvd" && cmvd_size > 14 && cmvd_size == size - 12);
+    let comp_size = (cmvd_size - 12) as usize;
+    let uncomp_size         = br.read_u32be()? as usize;
+    validate!(uncomp_size > 8);
+    let mut sbuf = vec![0; comp_size];
+    let mut dbuf = vec![0; uncomp_size];
+                              br.read_buf(sbuf.as_mut_slice())?;
+    let ret = Inflate::uncompress(sbuf.as_slice(), dbuf.as_mut_slice());
+    if ret.is_err() {
+        return Err(DemuxerError::InvalidData);
+    }
+    let len = ret.unwrap();
+    validate!(len == uncomp_size);
+    let mut mr = MemoryReader::new_read(dbuf.as_slice());
+    let mut br = ByteReader::new(&mut mr);
+    let (ctype, csize) = read_chunk_header(&mut br)?;
+    validate!(ctype == mktag!(b"moov"));
+    let mut ddmx = MOVDemuxer::new(&mut br);
+    ddmx.read_moov(strmgr, csize)?;
+    std::mem::swap(&mut dmx.tracks, &mut ddmx.tracks);
+    dmx.duration = ddmx.duration;
+    dmx.tb_den = ddmx.tb_den;
+    std::mem::swap(&mut dmx.pal, &mut ddmx.pal);
+    
+    Ok(size)
+}
+
 fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
     let mut pal = [0; 1024];
     let size = read_palette(&mut dmx.src, size, &mut pal)?;
@@ -393,7 +434,7 @@ fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult
     let _flags              = br.read_u24be()?;
     let entries             = br.read_u32be()?;
     validate!(entries > 0);
-    let esize               = br.read_u32be()? as u64;
+    let esize               = u64::from(br.read_u32be()?);
     validate!(esize + 8 <= size);
     let mut fcc = [0u8; 4];
                               br.read_buf(&mut fcc)?;
@@ -421,13 +462,15 @@ fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult
                                   br.read_skip(31)?; // actual compressor name
             let depth           = br.read_u16be()?;
             let ctable_id       = br.read_u16be()?;
-            validate!(((depth & 0x1F) <= 8) || (ctable_id == 0xFFFF));
+            let grayscale = depth > 0x20 || depth == 1;
+            let depth = if grayscale { depth & 0x1F } else { depth };
+            validate!(depth <= 8 || (ctable_id == 0xFFFF));
             if ctable_id == 0 {
                 let max_pal_size = start_pos + size - br.tell();
                 let mut pal = [0; 1024];
                 read_palette(br, max_pal_size, &mut pal)?;
                 track.pal = Some(Arc::new(pal));
-            } else if (depth & 0x20) == 0 && (depth & 0x1F) <= 8 {
+            } else if (depth <= 8) && !grayscale {
                 match depth & 0x1F {
                     2 => {
                         let mut pal = [0; 1024];
@@ -444,12 +487,12 @@ fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult
                     },
                     _ => {},
                 };
-            } else if (depth & 0x1F) <= 8 {
+            } else if grayscale && ctable_id != 0xFFFF {
                 let mut pal = [0; 1024];
                 let cdepth = depth & 0x1F;
                 let size = 1 << cdepth;
                 for i in 0..size {
-                    let mut clr = (size - 1 - i) as u8;
+                    let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
                     let mut off = 8 - cdepth;
                     while off >= cdepth {
                         clr |= clr >> (8 - off);
@@ -473,17 +516,17 @@ fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult
                     "unknown"
                 };
             let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
-            let vhdr = NAVideoInfo::new(width, height, false, format);
-            let edata;
-            if br.tell() - start_pos + 4 < size {
+            let mut vhdr = NAVideoInfo::new(width, height, false, format);
+            vhdr.bits = depth as u8;
+            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];
+                    let edata_size  = br.read_u32be()? as usize;
+                    let mut buf = vec![0; edata_size];
                                   br.read_buf(buf.as_mut_slice())?;
-                edata = Some(buf);
-            } else {
-                edata = None;
-            }
+                    Some(buf)
+                } else {
+                    None
+                };
             codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
         },
         StreamType::Audio => {
@@ -676,7 +719,7 @@ impl Track {
     read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
     read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
     fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
-        if self.keyframes.len() > 0 {
+        if !self.keyframes.is_empty() {
             seek_index.mode = SeekIndexMode::Present;
         }
         for kf_time in self.keyframes.iter() {
@@ -760,9 +803,9 @@ impl Track {
         }
     }
     fn get_size(&self, sample_no: usize) -> usize {
-        if self.chunk_sizes.len() > 0 {
+        if !self.chunk_sizes.is_empty() {
             self.chunk_sizes[sample_no] as usize
-        } else if self.sample_map.len() > 0 {
+        } else if !self.sample_map.is_empty() {
             let mut nsamp = 0;
             for (idx, samples) in self.sample_map.iter() {
                 if *idx as usize <= self.cur_chunk {
@@ -781,7 +824,7 @@ impl Track {
         self.samples_left = 0;
         if self.stream_type == StreamType::Audio {
             self.cur_chunk = self.cur_sample;
-        } else if self.chunk_offsets.len() != self.chunk_sizes.len() && self.sample_map.len() > 0{
+        } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
             let mut csamp = 0;
             self.cur_chunk = 0;
             let mut cmap = self.sample_map.iter();
@@ -816,7 +859,7 @@ impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
     fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
         self.read_root(strmgr)?;
         validate!(self.mdat_pos > 0);
-        validate!(self.tracks.len() > 0);
+        validate!(!self.tracks.is_empty());
         for track in self.tracks.iter() {
             track.fill_seek_index(seek_index);
         }
@@ -826,7 +869,7 @@ impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
     }
 
     fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
-        if self.tracks.len() == 0 {
+        if self.tracks.is_empty() {
             return Err(DemuxerError::EOF);
         }
         for _ in 0..self.tracks.len() {
@@ -849,7 +892,7 @@ impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
                 return Ok(pkt);
             }
         }
-        return Err(DemuxerError::EOF);
+        Err(DemuxerError::EOF)
     }
 
     fn seek(&mut self, time: u64, seek_index: &SeekIndex) -> DemuxerResult<()> {