#![cfg(feature = "ts")]
use dvb_t2mi::payload::AnyPayload;
use dvb_t2mi::payload::fef_null::S1Field;
use dvb_t2mi::payload::{
GuardInterval, L1Modulation, PilotPattern, PlpPayloadType, PlpType, T2Version,
TxInputStreamType,
};
use dvb_t2mi::pump::T2miPump;
const T2MI_PID: u16 = 0x0040;
const TS_PACKET: usize = 188;
fn fixture() -> Vec<u8> {
let path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../fixtures/dvb-t2mi/colombia-capital-t2mi.ts"
);
std::fs::read(path).expect("fixture present")
}
#[test]
fn l1_current_fixture_oracle() {
let data = fixture();
let mut pump = T2miPump::new(T2MI_PID);
let mut first_l1 = None;
'outer: for pkt in data.chunks(TS_PACKET) {
for event in pump.feed_ts(pkt) {
if let Ok(AnyPayload::L1Current(payload)) = event.payload() {
first_l1 = Some(payload.l1_current_data.to_vec());
break 'outer;
}
}
}
let l1_data = first_l1.expect("at least one L1Current packet in fixture");
assert_eq!(
l1_data.len(),
67,
"l1_current_data must be 67 bytes (21 L1PRE + 2+24 CONF + 2+16 DYN + 2+0 EXT)"
);
let payload = dvb_t2mi::payload::L1CurrentPayload {
frame_idx: 0,
freq_source: dvb_t2mi::payload::FrequencySource::UseL1CurrentData,
l1_current_data: &l1_data,
};
let pre = payload.l1_pre().expect("l1_pre() must succeed");
assert_eq!(pre.type_, TxInputStreamType::TsOnly, "TYPE");
assert_eq!(pre.s1, S1Field::V0, "S1 (T2_SISO)");
assert_eq!(pre.guard_interval, GuardInterval::G1_8, "GUARD_INTERVAL");
assert_eq!(pre.l1_mod, L1Modulation::Qam16, "L1_MOD");
assert_eq!(pre.l1_post_size, 376, "L1_POST_SIZE");
assert_eq!(pre.l1_post_info_size, 318, "L1_POST_INFO_SIZE");
assert_eq!(pre.pilot_pattern, PilotPattern::Pp3, "PILOT_PATTERN");
assert_eq!(pre.network_id, 0x3003, "NETWORK_ID");
assert_eq!(pre.t2_system_id, 0x3003, "T2_SYSTEM_ID");
assert_eq!(pre.num_t2_frames, 2, "NUM_T2_FRAMES");
assert_eq!(pre.num_data_symbols, 41, "NUM_DATA_SYMBOLS");
assert_eq!(pre.num_rf, 1, "NUM_RF");
assert_eq!(pre.current_rf_idx, 0, "CURRENT_RF_IDX");
assert_eq!(pre.t2_version, T2Version::V1_3_1, "T2_VERSION");
assert!(!pre.l1_post_extension, "L1_POST_EXTENSION must be false");
let post = payload.l1_post().expect("l1_post() must succeed");
let conf = &post.configurable;
assert_eq!(conf.num_plp, 1, "NUM_PLP");
assert_eq!(conf.num_aux, 0, "NUM_AUX");
assert_eq!(conf.rf.len(), 1, "RF loop length");
assert!(conf.fef.is_none(), "FEF block absent (S2 LSB=0)");
assert_eq!(conf.plps.len(), 1, "PLP loop length");
assert!(post.extension.is_empty(), "extension blocks absent");
let plp = &conf.plps[0];
assert_eq!(plp.plp_type, PlpType::DataType1, "PLP_TYPE");
assert_eq!(plp.plp_payload_type, PlpPayloadType::Ts, "PLP_PAYLOAD_TYPE");
let conf_bits = conf.len_bits();
assert_eq!(conf_bits, 191, "L1CONF declared bit length must be 191");
let dyn_bits = post.dynamic_current.len_bits();
assert_eq!(dyn_bits, 127, "L1DYN_CURR declared bit length must be 127");
let total = 21 + 2 + conf_bits.div_ceil(8) + 2 + dyn_bits.div_ceil(8) + 2; assert_eq!(
total,
l1_data.len(),
"framing byte totals must equal l1_current_data length"
);
let mut reser = pre.to_bytes().to_vec();
reser.extend_from_slice(&post.to_l1_current_framed().expect("framed serialize"));
assert_eq!(
reser, l1_data,
"parse→serialize of the real L1-current data must be byte-identical"
);
}