introduce stream and container duration
[nihav.git] / nihav-commonfmt / src / demuxers / mov.rs
index 24431f9a7416e0a9fae179fd7256f005c942167b..9236baa1b0667d0132745e31e3465d959dafe193 100644 (file)
@@ -239,7 +239,7 @@ fn read_cmov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> Dem
     dmx.duration = ddmx.duration;
     dmx.tb_den = ddmx.tb_den;
     std::mem::swap(&mut dmx.pal, &mut ddmx.pal);
-    
+
     Ok(size)
 }
 
@@ -292,7 +292,7 @@ fn read_tkhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult
     let _mtime              = br.read_u32be()?;
     let track_id            = br.read_u32be()?;
                               br.read_skip(4)?;
-    let _duration           = br.read_u32be()?;
+    let duration            = br.read_u32be()?;
                               br.read_skip(8)?;
     let _layer              = br.read_u16be()?;
     let _alt_group          = br.read_u16be()?;
@@ -304,6 +304,7 @@ fn read_tkhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult
     track.width  = width  >> 16;
     track.height = height >> 16;
     track.track_id = track_id;
+    track.duration = duration;
 
     track.tkhd_found = true;
     Ok(KNOWN_TKHD_SIZE)
@@ -428,6 +429,14 @@ const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
 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 mut buf = [0; 8];
+                              br.peek_buf(&mut buf)?;
+        if &buf[4..8] != b"wave" {
+            let mut buf = vec![0; (size - read_part) as usize];
+                              br.read_buf(&mut buf)?;
+            return Ok(Some(buf));
+        }
+
         let csize           = br.read_u32be()? as u64;
         let ctag            = br.read_u32be()?;
         validate!(read_part + csize <= size);
@@ -554,7 +563,8 @@ fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult
             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 {
@@ -612,7 +622,7 @@ fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult
     };
     let read_size = br.tell() - start_pos;
     validate!(read_size <= size);
-    track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, 1, track.tb_den));
+    track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, 1, track.tb_den, u64::from(track.duration)));
     track.stsd_found = true;
     Ok(read_size)
 }
@@ -709,6 +719,7 @@ struct Track {
     track_str_id:   usize,
     track_no:       u32,
     tb_den:         u32,
+    duration:       u32,
     depth:          u8,
     tkhd_found:     bool,
     stsd_found:     bool,
@@ -742,6 +753,7 @@ impl Track {
             track_str_id:   0,
             track_no,
             tb_den,
+            duration:       0,
             stream_type:    StreamType::None,
             width:          0,
             height:         0,
@@ -845,8 +857,14 @@ impl Track {
             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 if self.frame_samples != 0 && self.bsize != 0 {
+                let nblocks = size / self.bsize;
+                if nblocks > 0 {
+                    let consumed = (nblocks * self.frame_samples).min(self.samples_left);
+                    self.samples_left -= consumed;
+                } else {
+                    self.samples_left = 0;
+                }
             } else {
                 self.samples_left = 0;
             }
@@ -947,7 +965,7 @@ impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
         Err(DemuxerError::EOF)
     }
 
-    fn seek(&mut self, time: u64, seek_index: &SeekIndex) -> DemuxerResult<()> {
+    fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
         let ret = seek_index.find_pos(time);
         if ret.is_none() {
             return Err(DemuxerError::SeekError);
@@ -958,6 +976,13 @@ impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
         }
         Ok(())
     }
+    fn get_duration(&self) -> u64 {
+        if self.tb_den != 0 {
+            u64::from(self.duration) * 1000 / u64::from(self.tb_den)
+        } else {
+            0
+        }
+    }
 }
 
 impl<'a> NAOptionHandler for MOVDemuxer<'a> {