use crate::csa;
use crate::error::Error;
use crate::key::ControlWord;
use mpeg_ts::ts::{SCRAMBLING_MASK, TS_PACKET_SIZE, TsHeader};
const TSC_EVEN_KEY: u8 = 0x80;
const ADAPTATION_FIELD_LENGTH_SIZE: usize = 1;
pub fn scramble_ts_packet(
cw: &ControlWord,
packet: &mut [u8; TS_PACKET_SIZE],
) -> Result<(), Error> {
let payload = ts_payload_mut(packet)?;
csa::scramble(cw, payload);
packet[3] = (packet[3] & !SCRAMBLING_MASK) | TSC_EVEN_KEY;
Ok(())
}
pub fn descramble_ts_packet(
cw: &ControlWord,
packet: &mut [u8; TS_PACKET_SIZE],
) -> Result<(), Error> {
let payload = ts_payload_mut(packet)?;
csa::descramble(cw, payload);
packet[3] &= !SCRAMBLING_MASK;
Ok(())
}
fn ts_payload_mut(packet: &mut [u8; TS_PACKET_SIZE]) -> Result<&mut [u8], Error> {
let header = TsHeader::parse(&packet[..TsHeader::serialized_len()])
.expect("packet[..TsHeader::serialized_len()] is always exactly 4 bytes");
if !header.has_payload {
return Err(Error::BufferTooShort { need: 1, have: 0 });
}
let mut payload_start = TsHeader::serialized_len();
if header.has_adaptation {
let af_len = packet[payload_start] as usize; payload_start += ADAPTATION_FIELD_LENGTH_SIZE + af_len;
}
if payload_start >= TS_PACKET_SIZE {
return Err(Error::BufferTooShort { need: 1, have: 0 });
}
Ok(&mut packet[payload_start..TS_PACKET_SIZE])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn roundtrip_ts_packet() {
let cw = ControlWord::from_bytes([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
let mut packet = [0u8; 188];
packet[0] = 0x47; packet[1] = 0x41; packet[2] = 0x00; packet[3] = 0x10; for i in 0..184 {
packet[4 + i] = (i % 256) as u8;
}
let original = packet;
scramble_ts_packet(&cw, &mut packet).unwrap();
assert_ne!(packet[4..], original[4..]);
assert_eq!(packet[3] & 0xc0, 0x80);
descramble_ts_packet(&cw, &mut packet).unwrap();
assert_eq!(packet[4..], original[4..]);
assert_eq!(packet[3] & 0xc0, 0x00); }
}