diff --git a/src/data.rs b/src/data.rs index e741cae..3adb3fa 100644 --- a/src/data.rs +++ b/src/data.rs @@ -1,32 +1,36 @@ +use ascii::AsciiString; use deku::prelude::*; +use crate::{DeviceRestrictions}; #[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)] #[deku(endian = "big", type = "u8", bits = "1")] pub(crate) enum SpliceTime { #[deku(id = "1")] TimeSpecified { - #[deku(bits = "6", assert_eq = "0x3f")] - reserved: u8, + #[deku(bits = "6", assert_eq = "0x3f", update = "0x3f")] + _reserved: u8, + #[deku(bits = "33")] pts_time: u64, }, + #[deku(id = "0")] NoTimeSpecified { - #[deku(bits = "7", assert_eq = "0x7f")] - reserved: u8, + #[deku(bits = "7", assert_eq = "0x7f", update = "0x7f")] + _reserved: u8, }, } impl Default for SpliceTime { fn default() -> Self { - Self::NoTimeSpecified { reserved: 0x7f } + Self::NoTimeSpecified { _reserved: 0x7f } } } impl SpliceTime { fn new(pts_time: u64) -> Self { Self::TimeSpecified { - reserved: 0x3f, + _reserved: 0x3f, pts_time, } } @@ -35,21 +39,19 @@ impl SpliceTime { #[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)] #[deku(type = "u8")] pub(crate) enum SpliceDescriptor { - // #[deku(id = "0x02")] - // SegmentationDescriptor { - // #[deku(update = "deku::rest")] - // descriptor_length: u8, - // identifier: u32, - // - // }, + #[deku(id = "0x02")] + SegmentationDescriptor(SegmentationDescriptor), + #[deku(id_pat = "_")] Template(GenericDescriptor), } impl SpliceDescriptor { pub(crate) fn update(&mut self) -> Result<(), deku::DekuError> { + use SpliceDescriptor::*; match self { - SpliceDescriptor::Template(s) => s.update(), + Template(s) => s.update(), + SegmentationDescriptor(s) => s.update(), } } } @@ -58,13 +60,160 @@ impl SpliceDescriptor { #[deku(endian = "big")] pub(crate) struct GenericDescriptor { id: u8, + #[deku(update = "self.private_bytes.len() + 2")] descriptor_length: u8, + identifier: u32, + #[deku(count = "descriptor_length - 2")] private_bytes: Vec, } +#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)] +pub(crate) struct SegmentationDescriptor { + descriptor_length: u8, // TODO: need to calculate by hand the size based in `self.*` + + identifier: u32, + + segmentation_event_id: u32, + + #[deku(bits = "1")] + segmentation_event_cancel_indicator: bool, + + #[deku(bits = "7", assert_eq = "0x7f", update = "0x7f")] + _reserved: u8, + + #[deku( + skip, + cond = "*segmentation_event_cancel_indicator == false", + default = "None" + )] + segmentation: Option, +} + +#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)] +pub(crate) struct Segmentation { + #[deku(bits = "1")] + program_segmentation_flag: bool, + + #[deku(bits = "1")] + segmentation_duration_flag: bool, + + #[deku(bits = "1")] + delivery_not_restricted_flag: bool, + + #[deku(cond = "*delivery_not_restricted_flag == false")] + delivery_restriction: Option, + + #[deku(cond = "*delivery_not_restricted_flag", bits = "5")] + _reserved1: Option, + + #[deku(cond = "*program_segmentation_flag == false")] + program_components: Option, + + #[deku(cond = "*segmentation_duration_flag", bits = "40")] + segmentation_duration: u64, + + segmentation_upid: SegmentationUpid, +} + +#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)] +#[deku(type = "u8")] +#[non_exhaustive] +pub enum SegmentationUpid { + #[deku(id = "0x00")] + NotUsed, + + #[deku(id = "0x01")] + UserDefinedDeprecated(AsciiString), + + #[deku(id = "0x02")] + ISCI(AsciiString), + + #[deku(id = "0x03")] + AdID(AsciiString), + + #[deku(id = "0x04")] + UMID(AsciiString), + + #[deku(id = "0x05")] + ISANDeprecated(u64), + + #[deku(id = "0x06")] + ISAN(u128), + + #[deku(id = "0x07")] + TID(AsciiString), + + #[deku(id = "0x08")] + AiringID(u64), + + #[deku(id = "0x09")] + ADI(AsciiString), + + #[deku(id = "0x0a")] + EIDR(u128), + + #[deku(id = "0x0b")] + ATSCContentIdentifier(AsciiString), + + #[deku(id = "0x0c")] + MPU, + + #[deku(id = "0x0d")] + MID, + + #[deku(id = "0x0e")] + ADSInformation(AsciiString), + + #[deku(id = "0x0f")] + URI(AsciiString), + + #[deku(id = "0x10")] + UUID(u128), + + #[deku(id = "0x11")] + SCR(AsciiString), + + #[deku(id_pat = "_")] + Reserved(u8), +} + +#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)] +pub(crate) struct ProgramComponents { + #[deku(update = "self.components.len()")] + component_count: u8, + + #[deku(count = "component_count")] + components: Vec +} + +#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)] +pub(crate) struct SegmentationDescriptorComponent { + component_tag: u8, + + #[deku(bits = "7")] + _reserved: u8, + + #[deku(bits = "33")] + pts_offset: u64, +} + +#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)] +pub(crate) struct DeliveryRestriction { + #[deku(bits = "1")] + web_delivery_allowed_flag: bool, + + #[deku(bits = "1")] + no_regional_blackout_flag: bool, + + #[deku(bits = "1")] + archive_allowed_flag: bool, + + device_restrictions: DeviceRestrictions, +} + #[cfg(test)] mod tests { use super::*; @@ -75,6 +224,16 @@ mod tests { let data: Vec = st.try_into().unwrap(); assert_eq!(hex::encode(data.as_slice()), "7f"); + + // Check update is defined for missing value in field + let mut st = SpliceTime::NoTimeSpecified { + _reserved: 0 + }; + st.update().unwrap(); + + let data: Vec = st.try_into().unwrap(); + + assert_eq!(hex::encode(data.as_slice()), "7f"); } #[test] diff --git a/src/descriptors/segmentation.rs b/src/descriptors/segmentation.rs index 8b34a20..c9bad7f 100644 --- a/src/descriptors/segmentation.rs +++ b/src/descriptors/segmentation.rs @@ -1,3 +1,4 @@ +use deku::prelude::*; use crate::{BytesWritten, ClockTimeExt}; use ascii::AsciiString; use bitstream_io::{BigEndian, BitRecorder, BitWrite, BitWriter}; @@ -252,9 +253,10 @@ impl SpliceDescriptorExt for SegmentationDescriptor { } } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, DekuRead, DekuWrite)] #[cfg_attr(feature = "serde", derive(Serialize))] #[repr(u8)] +#[deku(type="u8", bits="2")] pub enum DeviceRestrictions { /// This Segment is restricted for a class of devices defined by an out of band message that /// describes which devices are excluded.