From f0f60ebdfc63cd0cb1ace213a8dca8d3298bc5c6 Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Thu, 12 May 2022 08:59:17 +0200 Subject: [PATCH] Roadblock on Deku usage Here we hit a road block on using Deku for the SCTE35 spec. The Upid type is more complex in terms of serialization which makes it very complicated to use Deku. Besides the problem above. It seems like using Deku will make maintainance more complicated due to the externsive use of magic macros. Which also does impact development. I still believe Deku is a great project to be used in more straight forward binary formats. --- src/data.rs | 187 +++++++++++++++++++++++++++++--- src/descriptors/segmentation.rs | 4 +- 2 files changed, 176 insertions(+), 15 deletions(-) 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.