diff --git a/src/mux/mkvstream.rs b/src/mux/mkvstream.rs index 3ca743d..39ccdf6 100644 --- a/src/mux/mkvstream.rs +++ b/src/mux/mkvstream.rs @@ -84,7 +84,11 @@ impl MkvStream { for s in &dt.streams { let (pid, track, parser) = match s { crate::disc::Stream::Video(v) => { - ws.video_pending += 1; + // Only count primary video as pending — secondary streams + // (Dolby Vision EL, PiP) may never produce codec headers + if !v.secondary { + ws.video_pending += 1; + } (v.pid, MkvTrack::video(v), codec::parser_for_codec(v.codec)) } crate::disc::Stream::Audio(a) => { diff --git a/src/mux/resolve.rs b/src/mux/resolve.rs index c79785d..d50c352 100644 --- a/src/mux/resolve.rs +++ b/src/mux/resolve.rs @@ -27,8 +27,10 @@ use std::path::Path; /// I/O buffer size for file streams. const IO_BUF_SIZE: usize = 4 * 1024 * 1024; -/// MKV lookahead buffer size. -const MKV_LOOKAHEAD: usize = 10 * 1024 * 1024; +/// Default MKV lookahead buffer size. +/// Dynamically increased for UHD content (many streams delay video codec headers). +const MKV_LOOKAHEAD_DEFAULT: usize = 10 * 1024 * 1024; +const MKV_LOOKAHEAD_UHD: usize = 100 * 1024 * 1024; /// Parsed stream URL. pub struct StreamUrl { @@ -231,7 +233,14 @@ pub fn open_output(url: &str, meta: &DiscTitle) -> io::Result> .map_err(|e| io::Error::new(e.kind(), format!("mkv://{}: {}", parsed.path, e)))?; let writer = BufWriter::with_capacity(IO_BUF_SIZE, file); - Ok(Box::new(MkvStream::new(writer).meta(meta).max_buffer(MKV_LOOKAHEAD))) + // Size lookahead based on content: UHD (many streams) needs larger buffer + // because HEVC SPS/PPS may not appear until well past 10 MB + let lookahead = if meta.streams.len() > 15 { + MKV_LOOKAHEAD_UHD + } else { + MKV_LOOKAHEAD_DEFAULT + }; + Ok(Box::new(MkvStream::new(writer).meta(meta).max_buffer(lookahead))) } "network" => { validate_network_addr(&parsed.path)?;