diff --git a/src/mux/codec/flac.rs b/src/mux/codec/flac.rs index b903859..43c1f3b 100644 --- a/src/mux/codec/flac.rs +++ b/src/mux/codec/flac.rs @@ -118,7 +118,7 @@ impl CodecParser for FlacParser { vec![Frame { discontinuity: pes.discontinuity, coding: None, - source: None, + source: super::pesbuf::PesFacts::of(pes).source, pts_ns, keyframe: true, data: pes.data.clone(), diff --git a/src/mux/codec/lpcm.rs b/src/mux/codec/lpcm.rs index fa53638..e1dfc38 100644 --- a/src/mux/codec/lpcm.rs +++ b/src/mux/codec/lpcm.rs @@ -74,7 +74,7 @@ impl CodecParser for LpcmParser { vec![Frame { discontinuity: false, coding: None, - source: None, + source: super::pesbuf::PesFacts::of(pes).source, pts_ns, keyframe: true, data: pes.data[offset..].to_vec(), diff --git a/src/mux/codec/mod.rs b/src/mux/codec/mod.rs index 1b9a3c6..5784352 100644 --- a/src/mux/codec/mod.rs +++ b/src/mux/codec/mod.rs @@ -154,7 +154,7 @@ impl CodecParser for PassthroughParser { // parsers must instead defer the flag to the next emitted frame.) vec![Frame { coding: None, - source: None, + source: pesbuf::PesFacts::of(pes).source, pts_ns, keyframe: self.keyframe, discontinuity: pes.discontinuity, diff --git a/src/mux/codec/mpegaudio.rs b/src/mux/codec/mpegaudio.rs index dfe429b..cab0677 100644 --- a/src/mux/codec/mpegaudio.rs +++ b/src/mux/codec/mpegaudio.rs @@ -116,7 +116,7 @@ impl CodecParser for MpegAudioParser { vec![Frame { discontinuity: pes.discontinuity, coding: None, - source: None, + source: super::pesbuf::PesFacts::of(pes).source, pts_ns, keyframe: true, data: pes.data.clone(), diff --git a/src/mux/codec/pgs.rs b/src/mux/codec/pgs.rs index 6e95d9b..880e2de 100644 --- a/src/mux/codec/pgs.rs +++ b/src/mux/codec/pgs.rs @@ -366,7 +366,10 @@ impl CodecParser for PgsParser { out.push(Frame { discontinuity: false, coding: None, - source: None, + // Emitted straight from THIS packet, so its facts are + // this packet's -- the same rule as a pending set, + // which takes the facts of the packet that opened it. + source: super::pesbuf::PesFacts::of(pes).source, pts_ns: pts.unwrap_or(0), keyframe: true, data: pes.data.clone(), @@ -914,4 +917,27 @@ mod tests { assert_eq!(t.facts().displays, u32::MAX); assert_eq!(t.facts().forced_displays, u32::MAX); } + + /// A lone non-PCS segment with a PTS is emitted straight through rather + /// than accumulated, and it must still carry provenance. This path was + /// missed on the first pass and showed up on a real disc as a subtitle + /// track with no source offset -- the one track out of forty that could + /// not be placed by byte. + #[test] + fn a_lone_segment_emitted_directly_still_carries_provenance() { + let mut parser = PgsParser::new(); + // A non-PCS segment (type 0x15 = ODS) with a PTS and no pending set. + let mut p = make_pes(vec![0x15, 0x00, 0x00, 0x00, 0x04, 1, 2, 3, 4], Some(90_000)); + p.source = Some(crate::pes::SourcePos::at_byte(7_777)); + let frames = parser.parse(&p); + assert!( + !frames.is_empty(), + "a lone segment with a PTS is passed through" + ); + assert_eq!( + frames[0].source.map(|s| s.byte), + Some(7_777), + "emitted straight from this packet, so it carries this packet's offset" + ); + } }