fix: assorted correctness fixes and dead-code cleanup
- aacs/resolve: a media-keys-only provider missing the VID classifies as VidUnavailable, not NoMaterial (an MK derives the VUK once the VID arrives). - disc/bluray: mark a clip seen only after its .clpi parses, so a transient parse failure on the first PlayItem cannot suppress the clip's extents for a later PlayItem referencing it that succeeds. - disc/patch: log rather than swallow mapfile record/flush failures on a reverify downgrade, so a failed persist cannot silently mismark a bad unit good on resume. - mux/ts: flag a discontinuity when a partial PES is dropped, matching the other partial-drop paths. - mux/demux_thread: the no-demuxer branch forwards an empty batch for early consumer-disconnect detection instead of reading the whole disc. - io/pipeline: correct the send-timing log (as_secs_f64, not as_micros printed as ms). - aacs/derive, aacs/variant, disc/read_error, keysource: comment/doc accuracy. sector/prefetched, udf: remove dead fields/functions. - mux/disc: assert unit-aligned read counts in the test.
This commit is contained in:
+19
-3
@@ -204,6 +204,14 @@ impl DemuxThread {
|
||||
}
|
||||
} else {
|
||||
let _ = recycle_tx.send(buf);
|
||||
// No demuxer (a BdTs title with zero streams): still send
|
||||
// an empty batch so an early consumer disconnect is
|
||||
// detected here too, exactly like the ts/ps branches above.
|
||||
// Without it this worker reads the whole disc even after
|
||||
// the consumer has dropped.
|
||||
if tx.send(DemuxBatch::Ts(Vec::new())).is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Flush tail packets at EOF.
|
||||
@@ -479,7 +487,7 @@ mod tests {
|
||||
#[test]
|
||||
fn no_demuxer_configured_still_recycles_and_eofs() {
|
||||
// With neither ts nor ps set, the worker must still recycle buffers
|
||||
// and terminate with Eof — never emit a spurious Ts/Ps batch.
|
||||
// and terminate with Eof — also forward an empty batch per buffer for disconnect detection.
|
||||
let (pf_tx, pf_rx) = bounded::<std::io::Result<Vec<u8>>>(4);
|
||||
let (rc_tx, rc_rx) = bounded::<Vec<u8>>(4);
|
||||
let (_dt, rx) = DemuxThread::spawn_zero_copy(pf_rx, rc_tx, (), None, None, None).unwrap();
|
||||
@@ -492,8 +500,16 @@ mod tests {
|
||||
drop(pf_tx);
|
||||
|
||||
let batches = collect_batches(&rx, Duration::from_secs(5));
|
||||
assert_eq!(batches.len(), 1, "only the Eof sentinel");
|
||||
assert!(matches!(batches[0], DemuxBatch::Eof));
|
||||
// The no-demuxer branch now forwards an empty Ts batch per buffer for
|
||||
// early consumer-disconnect detection (same rationale as the ts/ps
|
||||
// branches), then the Eof sentinel.
|
||||
assert_eq!(
|
||||
batches.len(),
|
||||
2,
|
||||
"empty Ts disconnect-probe batch, then Eof"
|
||||
);
|
||||
assert!(matches!(batches[0], DemuxBatch::Ts(ref v) if v.is_empty()));
|
||||
assert!(matches!(batches[1], DemuxBatch::Eof));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+9
-5
@@ -1520,11 +1520,15 @@ mod tests {
|
||||
"read at lba {lba} is not unit-aligned (offset {} % {ALIGN} != 0)",
|
||||
lba - ext_start
|
||||
);
|
||||
// Non-tail reads must be a whole number of units; the only
|
||||
// permitted short read is the final partial unit (here COUNT is a
|
||||
// multiple of ALIGN, so every read should be unit-multiple unless
|
||||
// it shrank below one unit — which is itself a single unit).
|
||||
let _ = count;
|
||||
// Non-tail reads must be a whole number of units; the only permitted
|
||||
// short read is a final partial unit (below one unit). Assert it
|
||||
// rather than documenting it — a mid-stream non-unit-multiple read
|
||||
// would straddle AACS unit boundaries and decrypt under the wrong
|
||||
// alignment.
|
||||
assert!(
|
||||
count as u32 % ALIGN == 0 || (count as u32) < ALIGN,
|
||||
"read count {count} is neither a whole number of units nor a sub-unit tail"
|
||||
);
|
||||
}
|
||||
|
||||
// At least one error was skipped (the bad unit) and a SectorSkipped
|
||||
|
||||
@@ -167,6 +167,10 @@ impl PesAssembler {
|
||||
self.buffer.clear();
|
||||
self.active = false;
|
||||
self.header_remaining = 0;
|
||||
// A dropped partial PES is a gap in the elementary stream — flag
|
||||
// it so the NEXT completed PES carries a discontinuity, matching
|
||||
// every other partial-drop path in this file (lines 395/479/504).
|
||||
self.pending_discontinuity = true;
|
||||
return;
|
||||
}
|
||||
self.buffer.extend_from_slice(data);
|
||||
|
||||
Reference in New Issue
Block a user