]> git.nihav.org Git - nihav.git/commitdiff
mov: support version 1 of common boxes (with 64-bit time and duration)
authorKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 4 Nov 2026 03:49:00 +0000 (04:49 +0100)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 4 Nov 2026 03:49:00 +0000 (04:49 +0100)
nihav-commonfmt/src/demuxers/mov/mod.rs
nihav-commonfmt/src/demuxers/mov/pktread.rs
nihav-commonfmt/src/demuxers/mov/track.rs

index 7742be992423b45ff2b4f5bf243bee409c706858..826746adf9899088a1193895c1efa21fa2f50c2a 100644 (file)
@@ -252,16 +252,26 @@ const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[
 
 fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
     const KNOWN_MVHD_SIZE: u64 = 100;
+    const KNOWN_MVHD_SIZE1: u64 = 112;
     let br = &mut dmx.src;
-    validate!(size >= KNOWN_MVHD_SIZE);
     let version             = br.read_byte()?;
-    validate!(version == 0 || version == 0xFF);
+    validate!(matches!(version, 0 | 1 | 0xFF));
+    if version != 1 {
+        validate!(size >= KNOWN_MVHD_SIZE);
+    } else {
+        validate!(size >= KNOWN_MVHD_SIZE1);
+    }
     dmx.ver_m1 = version == 0xFF;
     let _flags              = br.read_u24be()?;
-    let _ctime              = br.read_u32be()?;
-    let _mtime              = br.read_u32be()?;
+    if version != 1 {
+        let _ctime          = br.read_u32be()?;
+        let _mtime          = br.read_u32be()?;
+    } else {
+        let _ctime          = br.read_u64be()?;
+        let _mtime          = br.read_u64be()?;
+    }
     let tscale              = br.read_u32be()?;
-    let duration            = br.read_u32be()?;
+    let duration            = if version != 1 { u64::from(br.read_u32be()?) } else { br.read_u64be()? };
     let _pref_rate          = br.read_u32be()?;
     let _pref_volume        = br.read_u16be()?;
                               br.read_skip(10)?;
@@ -276,7 +286,7 @@ fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> De
     dmx.duration = duration;
     dmx.tb_den = tscale;
 
-    Ok(KNOWN_MVHD_SIZE)
+    Ok(if version != 1 { KNOWN_MVHD_SIZE } else { KNOWN_MVHD_SIZE1 })
 }
 
 fn read_cmov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
@@ -417,7 +427,7 @@ struct MOVDemuxer<'a> {
     tracks:         Vec<Track>,
     cur_track:      usize,
     tb_den:         u32,
-    duration:       u32,
+    duration:       u64,
     pal:            Option<Arc<[u8; 1024]>>,
     ver_m1:         bool,
     file_size:      u64,
@@ -696,7 +706,7 @@ impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
     }
     fn get_duration(&self) -> u64 {
         if self.tb_den != 0 {
-            u64::from(self.duration) * 1000 / u64::from(self.tb_den)
+            self.duration * 1000 / u64::from(self.tb_den)
         } else {
             0
         }
index 68c887a1166a4d7fce41437cc5fcbfe97fe2d25f..cd534a0baf18001eb1b8e57d46b449171fee5e78 100644 (file)
@@ -131,7 +131,7 @@ pub struct QTPacketDemuxer {
     pub cur_ts:         Option<u64>,
     pub samples_left:   usize,
     pub last_offset:    u64,
-    pub duration:       u32,
+    pub duration:       u64,
     pub channels:       usize,
     pub bits:           usize,
     pub bsize:          usize,
@@ -447,7 +447,7 @@ impl QTPacketDemuxer {
             },
             PacketMode::AudioCBR | PacketMode::AudioVBR => {
                 if self.chunk_offsets.len() == self.chunk_sizes.len() && self.duration != 0 {
-                    let new_sample = (self.chunk_sizes.len() as u64 * tgt_pts / u64::from(self.duration)) as usize;
+                    let new_sample = (self.chunk_sizes.len() as u64 * tgt_pts / self.duration) as usize;
                     self.cur_sample = new_sample;
                     self.cur_chunk = self.cur_sample;
                 } else {
index 7d7a15db3fec8164e3658ca269256a1e800439d1..7e7672e664fa9b26b37d12ca2b486b82d3c26b9b 100644 (file)
@@ -53,15 +53,25 @@ const TRAK_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
 
 fn read_tkhd(track: &mut Track, br: &mut dyn ByteIO, size: u64) -> DemuxerResult<u64> {
     const KNOWN_TKHD_SIZE: u64 = 84;
-    validate!(size >= KNOWN_TKHD_SIZE);
+    const KNOWN_TKHD_SIZE1: u64 = 96;
     let version             = br.read_byte()?;
-    validate!(version == 0);
+    validate!(version == 0 || version == 1);
+    if version != 1 {
+        validate!(size >= KNOWN_TKHD_SIZE);
+    } else {
+        validate!(size >= KNOWN_TKHD_SIZE1);
+    }
     let _flags              = br.read_u24be()?;
-    let _ctime              = br.read_u32be()?;
-    let _mtime              = br.read_u32be()?;
+    if version != 1 {
+        let _ctime          = br.read_u32be()?;
+        let _mtime          = br.read_u32be()?;
+    } else {
+        let _ctime          = br.read_u64be()?;
+        let _mtime          = br.read_u64be()?;
+    }
     let track_id            = br.read_u32be()?;
                               br.read_skip(4)?;
-    let duration            = br.read_u32be()?;
+    let duration            = if version == 0 { u64::from(br.read_u32be()?) } else { br.read_u64be()? };
                               br.read_skip(8)?;
     let _layer              = br.read_u16be()?;
     let _alt_group          = br.read_u16be()?;
@@ -76,7 +86,7 @@ fn read_tkhd(track: &mut Track, br: &mut dyn ByteIO, size: u64) -> DemuxerResult
     track.pkt_demux.duration = duration;
 
     track.tkhd_found = true;
-    Ok(KNOWN_TKHD_SIZE)
+    Ok(if version == 0 { KNOWN_TKHD_SIZE } else { KNOWN_TKHD_SIZE1 })
 }
 
 fn read_mdia(track: &mut Track, br: &mut dyn ByteIO, size: u64) -> DemuxerResult<u64> {
@@ -94,21 +104,31 @@ const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
 
 fn read_mdhd(track: &mut Track, br: &mut dyn ByteIO, size: u64) -> DemuxerResult<u64> {
     const KNOWN_MDHD_SIZE: u64 = 24;
-    validate!(size >= KNOWN_MDHD_SIZE);
+    const KNOWN_MDHD_SIZE1: u64 = 36;
     let version             = br.read_byte()?;
-    validate!(version == 0);
+    validate!(version == 0 || version == 1);
+    if version != 1 {
+        validate!(size >= KNOWN_MDHD_SIZE);
+    } else {
+        validate!(size >= KNOWN_MDHD_SIZE1);
+    }
     let flags               = br.read_u24be()?;
     validate!(flags == 0);
-    let _ctime              = br.read_u32be()?;
-    let _mtime              = br.read_u32be()?;
+    if version != 1 {
+        let _ctime          = br.read_u32be()?;
+        let _mtime          = br.read_u32be()?;
+    } else {
+        let _ctime          = br.read_u64be()?;
+        let _mtime          = br.read_u64be()?;
+    }
     track.tb_den            = br.read_u32be()?;
     validate!(track.tb_den != 0);
     track.pkt_demux.tb_den = track.tb_den;
-    track.pkt_demux.duration = br.read_u32be()?;
+    track.pkt_demux.duration = if version == 0 { u64::from(br.read_u32be()?) } else { br.read_u64be()? };
     let _language           = br.read_u16be()?;
     let _quality            = br.read_u16be()?;
 
-    Ok(KNOWN_MDHD_SIZE)
+    Ok(if version == 0 { KNOWN_MDHD_SIZE } else { KNOWN_MDHD_SIZE1 })
 }
 
 fn read_hdlr(track: &mut Track, br: &mut dyn ByteIO, size: u64) -> DemuxerResult<u64> {
@@ -163,7 +183,7 @@ fn read_udta_mdia(track: &mut Track, br: &mut dyn ByteIO, size: u64) -> DemuxerR
                 let info = ref_info.get_properties();
                 let cinfo = NACodecInfo::new(name, info, Some(edata));
                 let strm_id = ref_strm.get_id();
-                track.streams[0] = NAStream::new(track.stream_type, strm_id, cinfo, track.tb_num, track.tb_den, u64::from(track.pkt_demux.duration));
+                track.streams[0] = NAStream::new(track.stream_type, strm_id, cinfo, track.tb_num, track.tb_den, track.pkt_demux.duration);
                 return Ok(size);
             }
         }
@@ -614,7 +634,7 @@ fn read_stsd(track: &mut Track, br: &mut dyn ByteIO, size: u64) -> DemuxerResult
         track.pkt_demux.tb_den = track.tb_den;
         validate!(br.tell() <= end_pos);
         br.seek(SeekFrom::Start(end_pos))?;
-        track.streams.push(NAStream::new(track.stream_type, track.track_no | ((desc_no as u32) << 16), codec_info, track.tb_num, track.tb_den, u64::from(track.pkt_demux.duration)));
+        track.streams.push(NAStream::new(track.stream_type, track.track_no | ((desc_no as u32) << 16), codec_info, track.tb_num, track.tb_den, track.pkt_demux.duration));
     }
     let read_size = br.tell() - start_pos;
     track.stsd_found = true;
@@ -1050,7 +1070,7 @@ impl Track {
             self.tb_den = tb_den;
             self.pkt_demux.tb_num = tb_num;
             self.pkt_demux.tb_den = tb_den;
-            self.pkt_demux.duration /= self.tb_div;
+            self.pkt_demux.duration /= u64::from(self.tb_div);
         }
     }
 }