From 0a2bab5789cc5e6f4edcbfbd76449290d352c644 Mon Sep 17 00:00:00 2001 From: MattJackson <1085847+MattJackson@users.noreply.github.com> Date: Thu, 4 Jun 2026 19:28:34 -0700 Subject: [PATCH] mpls: resolve PID for sub-path / DV-EL stream entries (types 2/3/4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parse_stream_entry only read the PID for stream-entry type 1 (a stream in the PlayItem's own clip), returning PID 0 for every other type. The Dolby Vision enhancement layer uses type 4 (verified on Wicked + Dune: se_len=9 type=0x04 [00 10 15] -> PID 0x1015), so the EL fell through to PID 0x0000 and was silently dropped by the demux/mux — Dolby Vision lost. Now the PID offset is keyed off the entry type per the BD stream_entry() layout: type 1 -> +2, type 2 -> +4, type 3/4 -> +3. The DV EL now resolves to its real PID (0x1015) so it is demuxed and carried as a stream through the PES layer to every writer (M2TS carries dual-PID DV natively; the MKV writer's DV signaling is the format-specific piece). --- src/mpls.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/mpls.rs b/src/mpls.rs index 84bf4ce..d47881f 100644 --- a/src/mpls.rs +++ b/src/mpls.rs @@ -301,9 +301,21 @@ fn parse_stream_entry(item: &[u8], pos: usize, stream_type: u8) -> Option<(Strea return None; } - // PID from stream entry (type 0x01 = PlayItem stream: PID at bytes 2-3) - let pid = if item[pos + 1] == 0x01 && pos + 4 <= item.len() { - u16::from_be_bytes([item[pos + 2], item[pos + 3]]) + // PID location depends on the stream-entry type (BD spec stream_entry()): + // type 1 (stream in the PlayItem's Clip): PID at +2 + // type 2 (stream in a SubPath SubClip): +subpath_id(1)+subclip_id(1) → PID at +4 + // type 3 / 4 (SubPath clip; type 4 = Dolby Vision +subpath_id(1) → PID at +3 + // enhancement layer, e.g. PID 0x1015): + // Previously only type 1 was handled, so the DV EL (type 4) and any + // sub-path stream fell through to PID 0 and were dropped by the mux. + let pid_off = match item[pos + 1] { + 0x01 => 2, + 0x02 => 4, + 0x03 | 0x04 => 3, + _ => 0, + }; + let pid = if pid_off != 0 && pos + pid_off + 2 <= item.len() { + u16::from_be_bytes([item[pos + pid_off], item[pos + pid_off + 1]]) } else { 0 };