use super::*;
mod ac3_audio;
mod adts_audio;
mod encrypted_guard;
mod framerate;
mod multi_program;
mod packet_layout;
fn ts_pkt(pid: u16, pusi: bool, adaptation: u8, payload: &[u8]) -> [u8; TS_PACKET] {
let mut p = [0xFFu8; TS_PACKET];
p[0] = TS_SYNC;
p[1] = if pusi { 0x40 } else { 0x00 } | ((pid >> 8) & 0x1F) as u8;
p[2] = (pid & 0xFF) as u8;
p[3] = (adaptation & 0x03) << 4;
let mut off = 4;
let pay_len = payload.len().min(TS_PACKET - off);
p[off..off + pay_len].copy_from_slice(&payload[..pay_len]);
off += pay_len;
let _ = off;
p
}
fn build_adts_header_7(profile: u8, sr_idx: u8, ch_cfg: u8, frame_length: usize) -> [u8; 7] {
let mut h = [0u8; 7];
h[0] = 0xFF;
h[1] = 0xF0 | 0x01; h[2] = ((profile & 0x03) << 6) | ((sr_idx & 0x0F) << 2) | ((ch_cfg >> 2) & 0x01);
h[3] = ((ch_cfg & 0x03) << 6) | (((frame_length >> 11) & 0x03) as u8);
h[4] = ((frame_length >> 3) & 0xFF) as u8;
h[5] = (((frame_length & 0x07) << 5) | 0x1F) as u8;
h[6] = 0xFC;
h
}
fn build_adts_header_9(profile: u8, sr_idx: u8, ch_cfg: u8, frame_length: usize) -> [u8; 9] {
let mut h = [0u8; 9];
h[0] = 0xFF;
h[1] = 0xF0; h[2] = ((profile & 0x03) << 6) | ((sr_idx & 0x0F) << 2) | ((ch_cfg >> 2) & 0x01);
h[3] = ((ch_cfg & 0x03) << 6) | (((frame_length >> 11) & 0x03) as u8);
h[4] = ((frame_length >> 3) & 0xFF) as u8;
h[5] = (((frame_length & 0x07) << 5) | 0x1F) as u8;
h[6] = 0xFC;
h
}
struct BitWriter {
bytes: Vec<u8>,
bit_pos: usize,
}
impl BitWriter {
fn new() -> Self {
Self {
bytes: Vec::new(),
bit_pos: 0,
}
}
fn put(&mut self, n: usize, v: u32) {
for i in (0..n).rev() {
let bit = ((v >> i) & 0x01) as u8;
if self.bit_pos % 8 == 0 {
self.bytes.push(0);
}
let byte_idx = self.bit_pos / 8;
let bit_idx = 7 - (self.bit_pos % 8);
self.bytes[byte_idx] |= bit << bit_idx;
self.bit_pos += 1;
}
}
fn flush(self) -> Vec<u8> {
self.bytes
}
}
fn synth_ac3_frame_stereo_48k_128k() -> Vec<u8> {
let mut bw = BitWriter::new();
bw.put(16, 0x0B77); bw.put(16, 0); bw.put(2, 0); bw.put(6, 8 << 1); bw.put(5, 8); bw.put(3, 0); bw.put(3, 2); bw.put(2, 0);
bw.put(1, 0); while bw.bytes.len() < 384 {
bw.put(8, 0);
}
bw.flush()
}
fn synth_eac3_frame_stereo_48k_192bytes() -> Vec<u8> {
let mut bw = BitWriter::new();
bw.put(16, 0x0B77);
bw.put(2, 0); bw.put(3, 0); bw.put(11, 0x5F); bw.put(2, 0); bw.put(2, 3); bw.put(3, 2); bw.put(1, 0); bw.put(5, 16); bw.put(5, 0); bw.put(1, 0); while bw.bytes.len() < 192 {
bw.put(8, 0);
}
bw.flush()
}
fn ts_pkt_continuation(pid: u16, payload: &[u8]) -> [u8; TS_PACKET] {
let mut p = [0xFFu8; TS_PACKET];
p[0] = TS_SYNC;
p[1] = ((pid >> 8) & 0x1F) as u8; p[2] = (pid & 0xFF) as u8;
p[3] = 0b01 << 4; let pay_len = payload.len().min(TS_PACKET - 4);
p[4..4 + pay_len].copy_from_slice(&payload[..pay_len]);
p
}
fn build_ts_with_audio(
audio_stream_type: u8,
audio_descriptors: &[u8],
audio_pid: u16,
audio_es: &[u8],
) -> Vec<u8> {
let mut pat = vec![0x00];
let pat_section_len: usize = 5 + 4 + 4;
pat.push(0xB0 | ((pat_section_len >> 8) & 0x0F) as u8);
pat.push((pat_section_len & 0xFF) as u8);
pat.extend_from_slice(&[0x00, 0x01, 0xC1, 0x00, 0x00]);
pat.extend_from_slice(&[0x00, 0x01, 0xE1, 0x00, 0u8, 0u8, 0u8, 0u8]);
let mut pat_payload = vec![0u8];
pat_payload.extend_from_slice(&pat);
let pat_pkt = ts_pkt(0x0000, true, 0b01, &pat_payload);
let mut pmt = vec![0x02];
let pmt_stream_entries = 5 + 5 + audio_descriptors.len(); let pmt_section_len: usize = 9 + pmt_stream_entries + 4;
pmt.push(0xB0 | ((pmt_section_len >> 8) & 0x0F) as u8);
pmt.push((pmt_section_len & 0xFF) as u8);
pmt.extend_from_slice(&[0x00, 0x01, 0xC1, 0x00, 0x00]);
pmt.extend_from_slice(&[0xE2, 0x00]); pmt.extend_from_slice(&[0xF0, 0x00]); pmt.extend_from_slice(&[STREAM_TYPE_MPEG2_VIDEO, 0xE2, 0x00, 0xF0, 0x00]);
pmt.push(audio_stream_type);
pmt.push(0xE0 | ((audio_pid >> 8) & 0x1F) as u8);
pmt.push((audio_pid & 0xFF) as u8);
let esi_len = audio_descriptors.len() as u16;
pmt.push(0xF0 | ((esi_len >> 8) & 0x0F) as u8);
pmt.push((esi_len & 0xFF) as u8);
pmt.extend_from_slice(audio_descriptors);
pmt.extend_from_slice(&[0u8; 4]); let mut pmt_payload = vec![0u8];
pmt_payload.extend_from_slice(&pmt);
let pmt_pkt = ts_pkt(0x0100, true, 0b01, &pmt_payload);
let video_pes = {
let mut pes = vec![
0u8, 0u8, 1u8, 0xE0, 0u8, 0u8, 0x80, 0x80, 5, 0x21, 0x00, 0x01, 0x00, 0x01,
];
pes.extend_from_slice(&[0xAAu8; 16]);
pes
};
let video_pkt = ts_pkt(0x0200, true, 0b01, &video_pes);
let mut audio_pes = vec![
0u8, 0u8, 1u8, 0xC0, 0u8, 0u8, 0x80, 0x80, 5, 0x21, 0x00, 0x01, 0x00, 0x01,
];
audio_pes.extend_from_slice(audio_es);
let first_chunk_max = TS_PACKET - 4; let mut audio_pkts: Vec<[u8; TS_PACKET]> = Vec::new();
let first_len = audio_pes.len().min(first_chunk_max);
audio_pkts.push(ts_pkt(audio_pid, true, 0b01, &audio_pes[..first_len]));
let mut cursor = first_len;
while cursor < audio_pes.len() {
let end = (cursor + first_chunk_max).min(audio_pes.len());
audio_pkts.push(ts_pkt_continuation(audio_pid, &audio_pes[cursor..end]));
cursor = end;
}
let mut buf = Vec::new();
buf.extend_from_slice(&pat_pkt);
buf.extend_from_slice(&pmt_pkt);
buf.extend_from_slice(&video_pkt);
for pkt in &audio_pkts {
buf.extend_from_slice(pkt);
}
buf.extend_from_slice(&ts_pkt(0x1FFF, false, 0b01, &[]));
buf
}
fn build_two_program_ts() -> Vec<u8> {
let mut pat = vec![0x00];
let pat_section_len: usize = 5 + 4 + 4 + 4; pat.push(0xB0 | ((pat_section_len >> 8) & 0x0F) as u8);
pat.push((pat_section_len & 0xFF) as u8);
pat.extend_from_slice(&[0x00, 0x01, 0xC1, 0x00, 0x00]);
pat.extend_from_slice(&[0x00, 0x01, 0xE1, 0x00]); pat.extend_from_slice(&[0x00, 0x02, 0xE1, 0x01]); pat.extend_from_slice(&[0u8; 4]);
let mut pat_payload = vec![0u8];
pat_payload.extend_from_slice(&pat);
let pat_pkt = ts_pkt(0x0000, true, 0b01, &pat_payload);
let mut pmt1 = vec![0x02];
let pmt1_section_len: usize = 9 + 5 + 4;
pmt1.push(0xB0 | ((pmt1_section_len >> 8) & 0x0F) as u8);
pmt1.push((pmt1_section_len & 0xFF) as u8);
pmt1.extend_from_slice(&[0x00, 0x01, 0xC1, 0x00, 0x00]); pmt1.extend_from_slice(&[0xE2, 0x00, 0xF0, 0x00]);
pmt1.extend_from_slice(&[STREAM_TYPE_MPEG2_VIDEO, 0xE2, 0x00, 0xF0, 0x00]);
pmt1.extend_from_slice(&[0u8; 4]);
let mut pmt1_payload = vec![0u8];
pmt1_payload.extend_from_slice(&pmt1);
let pmt1_pkt = ts_pkt(0x0100, true, 0b01, &pmt1_payload);
let mut pmt2 = vec![0x02];
let pmt2_section_len: usize = 9 + 5 + 4;
pmt2.push(0xB0 | ((pmt2_section_len >> 8) & 0x0F) as u8);
pmt2.push((pmt2_section_len & 0xFF) as u8);
pmt2.extend_from_slice(&[0x00, 0x02, 0xC1, 0x00, 0x00]); pmt2.extend_from_slice(&[0xE3, 0x00, 0xF0, 0x00]);
pmt2.extend_from_slice(&[STREAM_TYPE_H264, 0xE3, 0x00, 0xF0, 0x00]);
pmt2.extend_from_slice(&[0u8; 4]);
let mut pmt2_payload = vec![0u8];
pmt2_payload.extend_from_slice(&pmt2);
let pmt2_pkt = ts_pkt(0x0101, true, 0b01, &pmt2_payload);
let make_pes = |fill: u8| {
let mut pes = vec![
0u8, 0u8, 1u8, 0xE0, 0u8, 0u8, 0x80, 0x80, 5, 0x21, 0x00, 0x01, 0x00, 0x01,
];
pes.extend_from_slice(&[fill; 16]);
pes
};
let p1_pes = ts_pkt(0x0200, true, 0b01, &make_pes(0xAA));
let p2_pes = ts_pkt(0x0300, true, 0b01, &make_pes(0xBB));
let mut buf = Vec::new();
buf.extend_from_slice(&pat_pkt);
buf.extend_from_slice(&pmt1_pkt);
buf.extend_from_slice(&pmt2_pkt);
buf.extend_from_slice(&p1_pes);
buf.extend_from_slice(&p2_pes);
buf.extend_from_slice(&ts_pkt(0x0200, true, 0b01, &make_pes(0xAA)));
buf.extend_from_slice(&ts_pkt(0x0300, true, 0b01, &make_pes(0xBB)));
buf.extend_from_slice(&ts_pkt(0x1FFF, false, 0b01, &[]));
buf
}
fn build_encrypted_ts() -> Vec<u8> {
let mut pat = vec![0x00];
let pat_section_len: usize = 5 + 4 + 4;
pat.push(0xB0 | ((pat_section_len >> 8) & 0x0F) as u8);
pat.push((pat_section_len & 0xFF) as u8);
pat.extend_from_slice(&[0x00, 0x01, 0xC1, 0x00, 0x00]);
pat.extend_from_slice(&[0x00, 0x01, 0xE1, 0x00, 0u8, 0u8, 0u8, 0u8]);
let mut pat_payload = vec![0u8];
pat_payload.extend_from_slice(&pat);
let pat_pkt = ts_pkt(0x0000, true, 0b01, &pat_payload);
let mut pmt = vec![0x02];
let pmt_section_len: usize = 9 + 5 + 4;
pmt.push(0xB0 | ((pmt_section_len >> 8) & 0x0F) as u8);
pmt.push((pmt_section_len & 0xFF) as u8);
pmt.extend_from_slice(&[0x00, 0x01, 0xC1, 0x00, 0x00]);
pmt.extend_from_slice(&[0xE2, 0x00, 0xF0, 0x00]);
pmt.extend_from_slice(&[STREAM_TYPE_MPEG2_VIDEO, 0xE2, 0x00, 0xF0, 0x00]);
pmt.extend_from_slice(&[0u8; 4]);
let mut pmt_payload = vec![0u8];
pmt_payload.extend_from_slice(&pmt);
let pmt_pkt = ts_pkt(0x0100, true, 0b01, &pmt_payload);
let video_pes = {
let mut pes = vec![
0u8, 0u8, 1u8, 0xE0, 0u8, 0u8, 0x80, 0x80, 5, 0x21, 0x00, 0x01, 0x00, 0x01,
];
pes.extend_from_slice(&[0xAAu8; 16]);
pes
};
let mut video_pkt = ts_pkt(0x0200, true, 0b01, &video_pes);
video_pkt[3] = (video_pkt[3] & 0x3F) | (0x01 << 6);
let mut buf = Vec::new();
buf.extend_from_slice(&pat_pkt);
buf.extend_from_slice(&pmt_pkt);
buf.extend_from_slice(&video_pkt);
buf.extend_from_slice(&ts_pkt(0x1FFF, false, 0b01, &[]));
buf
}