// Copyright 2026 Leo Cheng
// SPDX-License-Identifier: Apache-2.0
///|
/// Two hex digits.
fn hex(value : Int32) -> String {
let digits = "0123456789abcdef"
"0x" +
digits[value >> 4:(value >> 4) + 1].to_owned() +
digits[value & 0xF:(value & 0xF) + 1].to_owned()
}
///|
/// Build the tables and a frame of a transport stream, write them as packets,
/// then read the packets back.
///
/// moon run src/examples/04-transport
#coverage.skip
fn main raise {
let pat = @ts.Pat::new(transport_stream=1, programs=[
@ts.Program::new(1, 0x1000),
])
let pmt = @ts.Pmt::new(program=1, pcr_pid=0x100, streams=[
@ts.Stream::new(0x1B, 0x100),
@ts.Stream::new(0x0F, 0x101),
])
// A frame of five bytes, timed a quarter of a second in.
let frame = Bytes::from_array([b'\x00', b'\x00', b'\x00', b'\x01', b'\x09'])
let pes = @ts.Pes::new(0xE0, frame, pts=22500L)
let assembled : Array[@ts.Packet] = []
for i, packet in pat.section().packets(@ts.pat_pid) {
assembled.push({ ..packet, counter: i & 0xF, })
}
for i, packet in pmt.section().packets(0x1000) {
assembled.push({ ..packet, counter: i & 0xF, })
}
assembled.push(
@ts.Packet::new(0x100, pes.encode(), starts_unit=true, counter=0),
)
let buf = @buffer.Buffer()
for packet in assembled {
buf.write_bytes(packet.encode())
}
let stream = buf.contents()
println(
"packets: " +
assembled.length().to_string() +
", " +
stream.length().to_string() +
" bytes",
)
let packets = @ts.parse(stream[:])
let tables = @ts.sections(packets, @ts.pat_pid)
let read_pat = @ts.Pat::of(tables[0])
println(
"programme " +
read_pat.programs[0].number.to_string() +
" on pid " +
read_pat.programs[0].pid.to_string(),
)
let map = @ts.Pmt::of(@ts.sections(packets, 0x1000)[0])
println("programme clock on pid " + map.pcr_pid.to_string())
for stream_ in map.streams {
println(
" stream type " +
hex(stream_.stream_type) +
" on pid " +
stream_.pid.to_string(),
)
}
let frames = @ts.pes_packets(packets, 0x100)
println("frames: " + frames.length().to_string())
println(
"presentation time: " +
frames[0].pts().unwrap().to_string() +
" (1/90000 s)",
)
println("payload: " + frames[0].data.length().to_string() + " bytes")
println("checksum holds: " + tables[0].is_intact().to_string())
// Every packet is 188 bytes, and a packet written and read again is the same
// packet.
println("packet size: " + packets[0].encode().length().to_string())
println(
"round trip: " +
(packets[0].encode() == stream[0:188].to_owned()).to_string(),
)
}