Stamp the last frames that were still leaving without provenance
A real rip caught these. The warning added for a track placed from timestamps under a seam plan fired once, on one subtitle track of a 23-clip title, eighteen minutes in — a display set that arrives as a lone non-PCS segment is emitted straight through rather than accumulated, and that path still built its frame with source: None. Auditing the rest the same way found four more: flac, lpcm, mpegaudio and the passthrough parser. All are one-PES-one-frame, so the packet's own facts are the unit's facts. Every Frame construction in every codec parser now carries a source, checked by walking balanced braces rather than by eye — the earlier count was taken with a regex that cannot see a block containing nested braces, which is how these survived the first pass.
This commit is contained in:
@@ -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(),
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
|
||||
+27
-1
@@ -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"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user