use std::process::ExitCode;
use dvb_si::demux::SiDemux;
use dvb_si::descriptors::{
AnyDescriptor, DescriptorLoop, DescriptorRegistry, PDS_EACEM, PDS_NORDIG,
};
use dvb_si::tables::AnyTableSection;
use crate::util::{for_each_packet, read_file};
fn table_name(table: &AnyTableSection<'_>) -> String {
match table {
AnyTableSection::Unknown { table_id, .. } => format!("UNKNOWN(0x{table_id:02X})"),
t => t.name().to_string(),
}
}
fn print_descriptors(loop_: &DescriptorLoop<'_>, reg: &DescriptorRegistry, indent: &str) {
for item in loop_.iter_with(reg) {
match item {
Ok(d) => {
let label = match &d {
AnyDescriptor::Unknown { tag, .. } => format!("UNKNOWN(0x{tag:02X})"),
AnyDescriptor::Other { tag, .. } => format!("{}(0x{tag:02X})", d.name()),
_ => d.name().to_string(),
};
println!("{indent}desc {label}");
}
Err(e) => println!("{indent}desc <parse error: {e}>"),
}
}
}
pub fn run(path: &str, json: bool) -> ExitCode {
let data = match read_file(path, "dvb-tools dump") {
Ok(d) => d,
Err(code) => return code,
};
let mut reg = DescriptorRegistry::new();
reg.with_logical_channel_for_pds(PDS_EACEM)
.with_logical_channel_for_pds(PDS_NORDIG);
let mut demux = SiDemux::builder().build();
for packet in for_each_packet(&data) {
for event in demux.feed(&packet) {
match event.table_section() {
Ok(table) => {
if json {
match serde_json::to_string_pretty(&table) {
Ok(s) => println!("{s}"),
Err(e) => {
eprintln!("dvb-tools dump: serialize {}: {e}", event.pid());
}
}
} else {
let name = table_name(&table);
match event.version() {
Some(v) => println!(
"pid={} {name} v{v} sn={}",
event.pid(),
event.section_number().unwrap_or(0)
),
None => println!("pid={} {name}", event.pid()),
}
match &table {
AnyTableSection::PmtSection(pmt) => {
print_descriptors(&pmt.program_info, ®, " ");
for st in &pmt.streams {
println!(
" es pid=0x{:04X} stream_type={}",
st.elementary_pid,
st.stream_type.name()
);
print_descriptors(&st.es_info, ®, " ");
}
}
AnyTableSection::SdtSection(sdt) => {
for s in &sdt.services {
println!(
" service 0x{:04X} running_status={}",
s.service_id,
s.running_status.name()
);
print_descriptors(&s.descriptors, ®, " ");
}
}
AnyTableSection::NitSection(nit) => {
print_descriptors(&nit.network_descriptors, ®, " ");
for ts in &nit.transport_streams {
println!(
" ts 0x{:04X} onid=0x{:04X}",
ts.transport_stream_id, ts.original_network_id
);
print_descriptors(&ts.descriptors, ®, " ");
}
}
_ => {}
}
}
}
Err(e) => eprintln!("pid={} parse error: {e}", event.pid()),
}
}
}
let s = demux.stats();
eprintln!(
"-- packets={} sections={} emitted={} suppressed={} crc_failures={} malformed={}",
s.packets,
s.sections_completed,
s.emitted,
s.suppressed,
s.crc_failures,
s.malformed_packets
);
ExitCode::SUCCESS
}