]> git.nihav.org Git - nihav.git/commitdiff
avi: improve non-interleaved case detection and handling
authorKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 18 Apr 2026 09:45:12 +0000 (11:45 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 18 Apr 2026 09:45:12 +0000 (11:45 +0200)
nihav-commonfmt/src/demuxers/avi.rs

index 35eddb45598b93dcbb29ad610b3697b6e0f145d5..35e02467877295dfa4fbb18469b5cc674c78c6be 100644 (file)
@@ -542,7 +542,7 @@ impl<'a> DemuxCore<'a> for AVIDemuxer<'a> {
     }
 
     fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
-        if self.state.movi_size == 0 {
+        if self.state.movi_size == 0 && self.state.demux_mode != DemuxingMode::NonInterleaved {
             if !self.state.odml {
                 return Err(EOF);
             }
@@ -927,6 +927,7 @@ fn parse_idx1(src: &mut dyn ByteIO, strmgr: &mut StreamManager, seek_idx: &mut S
     let mut tb_dens = [0u32; 100];
     let mut add_offset = 0;
     let mut set_offset = false;
+    let mut max_sizes = [0u32; 100];
     for _ in 0..num_entries {
                               src.read_buf(&mut tag)?;
         let flags           = src.read_u32le()?;
@@ -945,6 +946,8 @@ fn parse_idx1(src: &mut dyn ByteIO, strmgr: &mut StreamManager, seek_idx: &mut S
         }
         let stream_no = ((tag[0] - b'0') * 10 + (tag[1] - b'0')) as usize;
 
+        max_sizes[stream_no] = max_sizes[stream_no].max(length);
+
         if let Some(stream) = strmgr.get_stream(stream_no) {
             let (stb_num, stb_den) = stream.get_timebase();
             let pts = counter[stream_no];
@@ -1012,6 +1015,15 @@ fn parse_idx1(src: &mut dyn ByteIO, strmgr: &mut StreamManager, seek_idx: &mut S
                 non_interleaved = true;
                 break;
             }
+        } else if avi_str.index.len() == 1 {
+            // check for a case when whole audio track is stored as one large frame (at the end of file)
+            let max_frames = avi_streams.iter().fold(0usize, |acc, avistr| acc.max(avistr.index.len()));
+            let strm = strmgr.get_stream(avi_str.strm_no.into()).unwrap();
+            if strm.get_media_type() == StreamType::Audio && strm.get_info().get_name() == "pcm"
+                    && max_frames > 100 && max_sizes[usize::from(avi_str.strm_no)] > 64000 {
+                non_interleaved = true;
+                break;
+            }
         }
     }