///|
fn Inspector::rebuild_media(
self : Inspector,
emit : (InspectEvent) -> Unit,
) -> Unit {
let wanted = FixedArray::make(8192, false)
let pcrs = FixedArray::make(8192, false)
let mut count = 0
for slot in self.slots {
if slot.section is Some(section) {
if parse_pmt(section) is Ok(pmt) {
if pmt.pcr_pid != 8191 {
pcrs[pmt.pcr_pid] = true
}
for stream in pmt.streams {
if is_pes_stream(stream.stream_type) && !wanted[stream.pid] {
if count >= 256 {
emit(
Issue(
fault(
"elementary_stream_limit",
section.offset,
Some(stream.pid),
),
),
)
} else {
wanted[stream.pid] = true
count = count + 1
}
}
}
}
}
}
for pid = 0; pid < 8192; pid = pid + 1 {
// Table changes deliberately reset PES headers, preventing cross-version assembly.
self.pes[pid] = if wanted[pid] { Some(PesAssembler::new()) } else { None }
if !pcrs[pid] {
self.clocks[pid] = None
}
self.known_pcr[pid] = pcrs[pid]
}
}
///|
fn Inspector::observe_media(
self : Inspector,
p : Packet,
event : ContinuityEvent,
emit : (InspectEvent) -> Unit,
) -> Unit {
if event == IgnoredNull {
return
}
let lost = match event {
Gap(..) | Discontinuity | TransportError => true
_ => false
}
if lost {
if self.pes[p.pid] is Some(a) {
a.reset()
}
if self.clocks[p.pid] is Some(c) {
c.reset()
}
}
if event == TransportError {
return
}
// Duplicates may carry a refreshed valid PCR, but their PES bytes must not be replayed.
if self.known_pcr[p.pid] {
match p.adaptation() {
Ok(Some(a)) =>
if a.pcr is Some(ticks) {
let clock = match self.clocks[p.pid] {
Some(c) => c
None => {
let c = PcrClock::new()
self.clocks[p.pid] = Some(c)
c
}
}
match clock.observe(ticks) {
Ok(sample) => emit(MediaClock(pid=p.pid, offset=p.offset, sample))
Err(e) => emit(Issue(fault(e.code, p.offset, Some(p.pid))))
}
}
_ => ()
}
}
if event == Duplicate {
return
}
if p.scrambling != 0 {
if self.pes[p.pid] is Some(a) {
a.reset()
emit(Issue(fault("scrambled_pes", p.offset, Some(p.pid))))
}
return
}
if p.payload.is_empty() {
return
}
if self.pes[p.pid] is Some(a) {
a.feed(
p.payload,
p.payload_start,
p.offset + (188 - p.payload.length()).to_int64(),
fn(r) {
match r {
Ok(header) => emit(PesTimestamp(pid=p.pid, header))
Err(e) => emit(Issue(fault(e.code, e.offset, Some(p.pid))))
}
},
)
}
}
///|
// Only declared PES families are routed to PES parsing. Private sections (5),
// DSM-CC sections and unknown future stream types remain inventory-only.
fn is_pes_stream(kind : Int) -> Bool {
match kind {
1 | 2 | 3 | 4 | 6 | 15 | 16 | 17 | 27 | 36 | 0x81 => true
_ => false
}
}