scte35_reader/
lib.rs

1//! Parser data formatted according to
2//! [SCTE-35](http://www.scte.org/SCTEDocs/Standards/SCTE%2035%202016.pdf).
3//!
4//! Intended to be used in conjunction with the
5//! [mpeg2ts-reader](https://crates.io/crates/mpeg2ts-reader) crate's facilities for processing
6//! the Transport Stream structures within which SCTE-35 data is usually embedded.
7//!
8//! ## Example
9//!
10//! ```
11//! # use hex_literal::*;
12//! # use scte35_reader::Scte35SectionProcessor;
13//! # use mpeg2ts_reader::psi::WholeCompactSyntaxPayloadParser;
14//! # use mpeg2ts_reader::{ psi, demultiplex };
15//! # mpeg2ts_reader::demux_context!(
16//! #        NullDemuxContext,
17//! #        demultiplex::NullPacketFilter<NullDemuxContext>
18//! #    );
19//! # impl NullDemuxContext {
20//! #    fn do_construct(
21//! #        &mut self,
22//! #        _req: demultiplex::FilterRequest<'_, '_>,
23//! #    ) -> demultiplex::NullPacketFilter<NullDemuxContext> {
24//! #        unimplemented!();
25//! #    }
26//! # }
27//! pub struct DumpSpliceInfoProcessor;
28//! impl scte35_reader::SpliceInfoProcessor for DumpSpliceInfoProcessor {
29//!     fn process(
30//!         &self,
31//!         header: scte35_reader::SpliceInfoHeader<'_>,
32//!         command: scte35_reader::SpliceCommand,
33//!         descriptors: scte35_reader::SpliceDescriptors<'_>,
34//!     ) {
35//!         println!("{:?} {:#?}", header, command);
36//!         for d in &descriptors {
37//!             println!(" - {:?}", d);
38//!         }
39//!     }
40//! }
41//!
42//! let data = hex!(
43//!             "fc302500000000000000fff01405000000017feffe2d142b00fe0123d3080001010100007f157a49"
44//!         );
45//! let mut parser = Scte35SectionProcessor::new(DumpSpliceInfoProcessor);
46//! let header = psi::SectionCommonHeader::new(&data[..psi::SectionCommonHeader::SIZE]);
47//! let mut ctx = NullDemuxContext::new();
48//! parser.section(&mut ctx, &header, &data[..]);
49//! ```
50//!
51//! Output:
52//!
53//! ```plain
54//! SpliceInfoHeader { protocol_version: 0, encrypted_packet: false, encryption_algorithm: None, pts_adjustment: 0, cw_index: 0, tier: 4095 } SpliceInsert {
55//!     splice_event_id: 1,
56//!     reserved: 127,
57//!     splice_detail: Insert {
58//!         network_indicator: Out,
59//!         splice_mode: Program(
60//!             Timed(
61//!                 Some(
62//!                     756296448
63//!                 )
64//!             )
65//!         ),
66//!         duration: Some(
67//!             SpliceDuration {
68//!                 return_mode: Automatic,
69//!                 duration: 19125000
70//!             }
71//!         ),
72//!         unique_program_id: 1,
73//!         avail_num: 1,
74//!         avails_expected: 1
75//!     }
76//! }
77//! ```
78
79#![forbid(unsafe_code)]
80#![deny(rust_2018_idioms, future_incompatible)]
81
82pub mod upid;
83
84use bitreader::BitReaderError;
85use log::error;
86use mpeg2ts_reader::demultiplex;
87use mpeg2ts_reader::psi;
88use mpeg2ts_reader::smptera::FormatIdentifier;
89use serde::ser::{SerializeSeq, SerializeStruct};
90use std::convert::TryInto;
91use std::marker;
92
93/// The StreamType which might be used for `SCTE-35` data
94pub const SCTE35_STREAM_TYPE: mpeg2ts_reader::StreamType = mpeg2ts_reader::StreamType(0x86);
95
96/// Utility function to search the PTM section for a `CUEI` registration descriptor per
97/// _SCTE-35, section 8.1_, which indicates that streams with `stream_type` equal to the private
98/// value `0x86` within this PMT section are formatted according to SCTE-35.
99///
100/// Returns `true` if the descriptor is attached to the given PMT section and `false` otherwise.
101pub fn is_scte35(pmt: &mpeg2ts_reader::psi::pmt::PmtSection<'_>) -> bool {
102    for d in pmt.descriptors().flatten() {
103        if let mpeg2ts_reader::descriptor::CoreDescriptors::Registration(reg) = d {
104            if reg.is_format(FormatIdentifier::CUEI) {
105                return true;
106            }
107        }
108    }
109    false
110}
111#[derive(Debug, PartialEq, serde_derive::Serialize)]
112pub enum EncryptionAlgorithm {
113    None,
114    DesEcb,
115    DesCbc,
116    TripleDesEde3Ecb,
117    Reserved(u8),
118    Private(u8),
119}
120impl EncryptionAlgorithm {
121    pub fn from_id(id: u8) -> EncryptionAlgorithm {
122        match id {
123            0 => EncryptionAlgorithm::None,
124            1 => EncryptionAlgorithm::DesEcb,
125            2 => EncryptionAlgorithm::DesCbc,
126            3 => EncryptionAlgorithm::TripleDesEde3Ecb,
127            _ => {
128                if id < 32 {
129                    EncryptionAlgorithm::Reserved(id)
130                } else {
131                    EncryptionAlgorithm::Private(id)
132                }
133            }
134        }
135    }
136}
137
138#[derive(Debug, PartialEq, serde_derive::Serialize)]
139pub enum SpliceCommandType {
140    SpliceNull,
141    Reserved(u8),
142    SpliceSchedule,
143    SpliceInsert,
144    TimeSignal,
145    BandwidthReservation,
146    PrivateCommand,
147}
148impl SpliceCommandType {
149    pub fn from_id(id: u8) -> SpliceCommandType {
150        match id {
151            0x00 => SpliceCommandType::SpliceNull,
152            0x04 => SpliceCommandType::SpliceSchedule,
153            0x05 => SpliceCommandType::SpliceInsert,
154            0x06 => SpliceCommandType::TimeSignal,
155            0x07 => SpliceCommandType::BandwidthReservation,
156            0xff => SpliceCommandType::PrivateCommand,
157            _ => SpliceCommandType::Reserved(id),
158        }
159    }
160}
161
162/// Header element within a SCTE-43 _splice_info_section_ containing metadata generic across all kinds of _splice-command_.
163///
164/// This is a wrapper around a byte-slice that will extract requested fields on demand, as its
165/// methods are called.
166pub struct SpliceInfoHeader<'a> {
167    buf: &'a [u8],
168}
169impl<'a> SpliceInfoHeader<'a> {
170    const HEADER_LENGTH: usize = 11;
171
172    /// Splits the given buffer into a `SpliceInfoHeader` element, and a remainder which will
173    /// include the _splice-command_ itself, plus any _descriptor_loop_.
174    pub fn new(buf: &'a [u8]) -> (SpliceInfoHeader<'a>, &'a [u8]) {
175        if buf.len() < 11 {
176            panic!("buffer too short: {} (expected 11)", buf.len());
177        }
178        let (head, tail) = buf.split_at(11);
179        (SpliceInfoHeader { buf: head }, tail)
180        // TODO: change this to return Err if the protocol_version or encrypted_packet values are
181        //       unsupported
182    }
183
184    /// The version of the SCTE-35 data structures carried in this _splice_info_section_ (only
185    /// version `0` is supported by this library).
186    pub fn protocol_version(&self) -> u8 {
187        self.buf[0]
188    }
189
190    /// Indicates that portions of this _splice_info_section_ are encrypted (only un-encrypted
191    /// data is supported by this library).
192    pub fn encrypted_packet(&self) -> bool {
193        self.buf[1] & 0b1000_0000 != 0
194    }
195    /// The algorithm by which portions of this _splice_info_section_ are encrypted (only
196    /// un-encrypted data is supported by this library).
197    pub fn encryption_algorithm(&self) -> EncryptionAlgorithm {
198        EncryptionAlgorithm::from_id((self.buf[1] & 0b0111_1110) >> 1)
199    }
200    /// A 33-bit adjustment value to be applied to any PTS value in a _splice-command_ within this
201    /// _splice_info_section_.
202    pub fn pts_adjustment(&self) -> u64 {
203        u64::from(self.buf[1] & 1) << 32
204            | u64::from(self.buf[2]) << 24
205            | u64::from(self.buf[3]) << 16
206            | u64::from(self.buf[4]) << 8
207            | u64::from(self.buf[5])
208    }
209    /// Identifier for the 'control word' (key) used to encrypt the message, if `encrypted_packet`
210    /// is true.
211    pub fn cw_index(&self) -> u8 {
212        self.buf[6]
213    }
214    /// 12-bit authorization tier.
215    pub fn tier(&self) -> u16 {
216        u16::from(self.buf[7]) << 4 | u16::from(self.buf[8]) >> 4
217    }
218    /// Length in bytes of the _splice-command_ data within this message.
219    pub fn splice_command_length(&self) -> u16 {
220        u16::from(self.buf[8] & 0b0000_1111) << 8 | u16::from(self.buf[9])
221    }
222    /// Type of _splice-command_ within this message.
223    pub fn splice_command_type(&self) -> SpliceCommandType {
224        SpliceCommandType::from_id(self.buf[10])
225    }
226}
227impl<'a> serde::Serialize for SpliceInfoHeader<'a> {
228    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
229    where
230        S: serde::Serializer,
231    {
232        let mut s = serializer.serialize_struct("SpliceInfoHeader", 6)?;
233        s.serialize_field("protocol_version", &self.protocol_version())?;
234        s.serialize_field("encrypted_packet", &self.encrypted_packet())?;
235        s.serialize_field("encryption_algorithm", &self.encryption_algorithm())?;
236        s.serialize_field("pts_adjustment", &self.pts_adjustment())?;
237        s.serialize_field("cw_index", &self.cw_index())?;
238        s.serialize_field("tier", &self.tier())?;
239        s.end()
240    }
241}
242impl<'a> std::fmt::Debug for SpliceInfoHeader<'a> {
243    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
244        let mut s = f.debug_struct("SpliceInfoHeader");
245        s.field("protocol_version", &self.protocol_version());
246        s.field("encrypted_packet", &self.encrypted_packet());
247        s.field("encryption_algorithm", &self.encryption_algorithm());
248        s.field("pts_adjustment", &self.pts_adjustment());
249        s.field("cw_index", &self.cw_index());
250        s.field("tier", &self.tier());
251        s.finish()
252    }
253}
254
255#[non_exhaustive]
256#[derive(Debug, serde_derive::Serialize)]
257pub enum SpliceCommand {
258    SpliceNull {},
259    SpliceInsert {
260        splice_event_id: u32,
261        reserved: u8,
262        splice_detail: SpliceInsert,
263    },
264    TimeSignal {
265        splice_time: SpliceTime,
266    },
267    BandwidthReservation {},
268    PrivateCommand {
269        identifier: u32,
270        private_bytes: Vec<u8>,
271    }
272}
273
274#[derive(Debug, serde_derive::Serialize)]
275pub enum NetworkIndicator {
276    Out,
277    In,
278}
279impl NetworkIndicator {
280    /// panics if `id` is something other than `0` or `1`
281    pub fn from_flag(id: u8) -> NetworkIndicator {
282        match id {
283            0 => NetworkIndicator::In,
284            1 => NetworkIndicator::Out,
285            _ => panic!(
286                "Invalid out_of_network_indicator value: {} (expected 0 or 1)",
287                id
288            ),
289        }
290    }
291}
292
293#[derive(Debug, serde_derive::Serialize)]
294pub enum SpliceInsert {
295    Cancel,
296    Insert {
297        network_indicator: NetworkIndicator,
298        splice_mode: SpliceMode,
299        duration: Option<SpliceDuration>,
300        unique_program_id: u16,
301        avail_num: u8,
302        avails_expected: u8,
303    },
304}
305
306#[derive(Debug, serde_derive::Serialize)]
307pub enum SpliceTime {
308    Immediate,
309    Timed(Option<u64>),
310}
311
312#[derive(Debug, serde_derive::Serialize)]
313pub struct ComponentSplice {
314    component_tag: u8,
315    splice_time: SpliceTime,
316}
317
318#[derive(Debug, serde_derive::Serialize)]
319pub enum SpliceMode {
320    Program(SpliceTime),
321    Components(Vec<ComponentSplice>),
322}
323
324#[derive(Debug, serde_derive::Serialize)]
325pub enum ReturnMode {
326    Automatic,
327    Manual,
328}
329impl ReturnMode {
330    pub fn from_flag(flag: u8) -> ReturnMode {
331        match flag {
332            0 => ReturnMode::Manual,
333            1 => ReturnMode::Automatic,
334            _ => panic!("Invalid auto_return value: {} (expected 0 or 1)", flag),
335        }
336    }
337}
338
339#[derive(Debug, PartialEq, serde_derive::Serialize, Copy, Clone)]
340pub enum SegmentationUpidType {
341    NotUsed,
342    UserDefinedDeprecated,
343    /// _Industry Standard Commercial Identifier_
344    ISCIDeprecated,
345    /// Defined by the _Advertising Digital Identification_ group
346    AdID,
347    UMID,
348    ISANDeprecated,
349    ISAN,
350    TID,
351    TI,
352    ADI,
353    EIDR,
354    ATSC,
355    MPU,
356    MID,
357    ADS,
358    URI,
359    Reserved(u8),
360}
361impl SegmentationUpidType {
362    pub fn from_type(id: u8) -> SegmentationUpidType {
363        match id {
364            0 => SegmentationUpidType::NotUsed,
365            1 => SegmentationUpidType::UserDefinedDeprecated,
366            2 => SegmentationUpidType::ISCIDeprecated,
367            3 => SegmentationUpidType::AdID,
368            4 => SegmentationUpidType::UMID,
369            5 => SegmentationUpidType::ISANDeprecated,
370            6 => SegmentationUpidType::ISAN,
371            7 => SegmentationUpidType::TID,
372            8 => SegmentationUpidType::TI,
373            9 => SegmentationUpidType::ADI,
374            10 => SegmentationUpidType::EIDR,
375            11 => SegmentationUpidType::ATSC,
376            12 => SegmentationUpidType::MPU,
377            13 => SegmentationUpidType::MID,
378            14 => SegmentationUpidType::ADS,
379            15 => SegmentationUpidType::URI,
380            _ => SegmentationUpidType::Reserved(id),
381        }
382    }
383}
384
385#[derive(Debug, PartialEq, serde_derive::Serialize)]
386pub enum SegmentationTypeId {
387    NotIndicated,
388    ContentIdentification,
389    ProgramStart,
390    ProgramEnd,
391    ProgramEarlyTermination,
392    ProgramBreakaway,
393    ProgramResumption,
394    ProgramRunoverPlanned,
395    ProgramRunoverUnplanned,
396    ProgramOverlapStart,
397    ProgramBlackoutOverride,
398    ProgramStartInProgress,
399    ChapterStart,
400    ChapterEnd,
401    BreakStart,
402    BreakEnd,
403    ProviderAdvertisementStart,
404    ProviderAdvertisementEnd,
405    DistributorAdvertisementStart,
406    DistributorAdvertisementEnd,
407    ProviderPlacementOpportunityStart,
408    ProviderPlacementOpportunityEnd,
409    DistributorPlacementOpportunityStart,
410    DistributorPlacementOpportunityEnd,
411    UnscheduledEventStart,
412    UnscheduledEventEnd,
413    NetworkStart,
414    NetworkEnd,
415    Reserved(u8),
416}
417impl SegmentationTypeId {
418    pub fn from_id(id: u8) -> SegmentationTypeId {
419        match id {
420            0 => SegmentationTypeId::NotIndicated,
421            1 => SegmentationTypeId::ContentIdentification,
422            16 => SegmentationTypeId::ProgramStart,
423            17 => SegmentationTypeId::ProgramEnd,
424            18 => SegmentationTypeId::ProgramEarlyTermination,
425            19 => SegmentationTypeId::ProgramBreakaway,
426            20 => SegmentationTypeId::ProgramResumption,
427            21 => SegmentationTypeId::ProgramRunoverPlanned,
428            22 => SegmentationTypeId::ProgramRunoverUnplanned,
429            23 => SegmentationTypeId::ProgramOverlapStart,
430            24 => SegmentationTypeId::ProgramBlackoutOverride,
431            25 => SegmentationTypeId::ProgramStartInProgress,
432            32 => SegmentationTypeId::ChapterStart,
433            33 => SegmentationTypeId::ChapterEnd,
434            34 => SegmentationTypeId::BreakStart,
435            35 => SegmentationTypeId::BreakEnd,
436            48 => SegmentationTypeId::ProviderAdvertisementStart,
437            49 => SegmentationTypeId::ProviderAdvertisementEnd,
438            50 => SegmentationTypeId::DistributorAdvertisementStart,
439            51 => SegmentationTypeId::DistributorAdvertisementEnd,
440            52 => SegmentationTypeId::ProviderPlacementOpportunityStart,
441            53 => SegmentationTypeId::ProviderPlacementOpportunityEnd,
442            54 => SegmentationTypeId::DistributorPlacementOpportunityStart,
443            55 => SegmentationTypeId::DistributorPlacementOpportunityEnd,
444            64 => SegmentationTypeId::UnscheduledEventStart,
445            65 => SegmentationTypeId::UnscheduledEventEnd,
446            80 => SegmentationTypeId::NetworkStart,
447            81 => SegmentationTypeId::NetworkEnd,
448            _ => SegmentationTypeId::Reserved(id),
449        }
450    }
451}
452
453#[derive(Debug, serde_derive::Serialize)]
454pub enum SegmentationUpid {
455    None,
456    UserDefined(upid::UserDefinedDeprecated),
457    Isci(upid::IsciDeprecated),
458    AdID(upid::AdID),
459    IsanDeprecated(upid::IsanDeprecated),
460    Umid(upid::Umid),
461    TID(upid::TID),
462    TI(upid::TI),
463    ADI(upid::ADI),
464    EIDR(upid::EIDR),
465    ATSC(upid::ATSC),
466    MPU(upid::MPU),
467    MID(Vec<SegmentationUpid>),
468    ADS(upid::ADSInformation),
469    URI(upid::Url),
470    Reserved(SegmentationUpidType, Vec<u8>),
471}
472impl SegmentationUpid {
473    fn parse(
474        r: &mut bitreader::BitReader<'_>,
475        segmentation_upid_type: SegmentationUpidType,
476        segmentation_upid_length: u8,
477    ) -> Result<SegmentationUpid, SpliceDescriptorErr> {
478        if segmentation_upid_length > 0 {
479            let upid_result: Result<Vec<u8>, bitreader::BitReaderError> = (0
480                ..segmentation_upid_length)
481                .map(|_| r.read_u8(8))
482                .collect();
483            let upid = upid_result.named("segmentation_descriptor.segmentation_upid")?;
484            SegmentationUpid::parse_payload(segmentation_upid_type, upid)
485        } else {
486            Ok(SegmentationUpid::None)
487        }
488    }
489
490    // TODO: rework 'upid' param from Vec<u8> into &[u8]
491    fn parse_payload(
492        segmentation_upid_type: SegmentationUpidType,
493        upid: Vec<u8>,
494    ) -> Result<SegmentationUpid, SpliceDescriptorErr> {
495        match segmentation_upid_type {
496            SegmentationUpidType::NotUsed => Err(
497                SpliceDescriptorErr::SegmentationUpidLengthTypeMismatch(segmentation_upid_type),
498            ),
499            SegmentationUpidType::UserDefinedDeprecated => Self::parse_user_defined(upid),
500            SegmentationUpidType::ISCIDeprecated => Self::parse_isci(upid),
501            SegmentationUpidType::AdID => Self::parse_adid(upid),
502            SegmentationUpidType::UMID => Self::parse_umid(upid),
503            SegmentationUpidType::ISANDeprecated => Self::parse_isan_deprecated(upid),
504            SegmentationUpidType::ISAN => Self::parse_isan(upid),
505            SegmentationUpidType::TID => Self::parse_tid(upid),
506            SegmentationUpidType::TI => Self::parse_ti(upid),
507            SegmentationUpidType::ADI => Self::parse_adi(upid),
508            SegmentationUpidType::EIDR => Self::parse_eidr(upid),
509            SegmentationUpidType::ATSC => Self::parse_atsc(upid),
510            SegmentationUpidType::MPU => Self::parse_mpu(upid),
511            SegmentationUpidType::MID => Self::parse_mid(upid),
512            SegmentationUpidType::ADS => Self::parse_ads(upid),
513            SegmentationUpidType::URI => Self::parse_url(upid),
514            SegmentationUpidType::Reserved(_) => Self::parse_reserved(segmentation_upid_type, upid),
515        }
516    }
517
518    pub fn segmentation_upid_length(&self) -> usize {
519        match self {
520            SegmentationUpid::None => 0,
521            SegmentationUpid::UserDefined(v) => v.0.len(),
522            SegmentationUpid::Isci(_) => 8,
523            SegmentationUpid::AdID(_) => 12,
524            SegmentationUpid::IsanDeprecated(_) => 8,
525            SegmentationUpid::Umid(_) => 32,
526            SegmentationUpid::TID(_) => 12,
527            SegmentationUpid::TI(_) => 8,
528            SegmentationUpid::ADI(adi) => adi.0.len(),
529            SegmentationUpid::EIDR(_) => 12,
530            SegmentationUpid::ATSC(atsc) => atsc.0.len(),
531            SegmentationUpid::MPU(m) => m.0.len(),
532            SegmentationUpid::MID(v) => {
533                v.len() * 2
534                    + v.iter()
535                        .map(|upid| upid.segmentation_upid_length())
536                        .sum::<usize>()
537            }
538            SegmentationUpid::ADS(a) => a.0.len(),
539            SegmentationUpid::URI(u) => u.0.as_str().len(),
540            SegmentationUpid::Reserved(_, r) => r.len(),
541        }
542    }
543
544    pub fn segmentation_upid_type(&self) -> SegmentationUpidType {
545        match self {
546            SegmentationUpid::None => SegmentationUpidType::NotUsed,
547            SegmentationUpid::UserDefined(_) => SegmentationUpidType::UserDefinedDeprecated,
548            SegmentationUpid::Isci(_) => SegmentationUpidType::ISCIDeprecated,
549            SegmentationUpid::AdID(_) => SegmentationUpidType::AdID,
550            SegmentationUpid::IsanDeprecated(_) => SegmentationUpidType::ISAN,
551            SegmentationUpid::Umid(_) => SegmentationUpidType::UMID,
552            SegmentationUpid::TID(_) => SegmentationUpidType::TID,
553            SegmentationUpid::TI(_) => SegmentationUpidType::TI,
554            SegmentationUpid::ADI(_) => SegmentationUpidType::ADI,
555            SegmentationUpid::EIDR(_) => SegmentationUpidType::EIDR,
556            SegmentationUpid::ATSC(_) => SegmentationUpidType::ATSC,
557            SegmentationUpid::MPU(_) => SegmentationUpidType::MPU,
558            SegmentationUpid::MID(_) => SegmentationUpidType::MID,
559            SegmentationUpid::ADS(_) => SegmentationUpidType::ADS,
560            SegmentationUpid::URI(_) => SegmentationUpidType::URI,
561            SegmentationUpid::Reserved(t, _) => *t,
562        }
563    }
564
565    fn parse_user_defined(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
566        Ok(SegmentationUpid::UserDefined(upid::UserDefinedDeprecated(
567            upid,
568        )))
569    }
570    fn parse_isci(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
571        chk_upid(&upid, 8, SegmentationUpidType::ISCIDeprecated)?;
572        upid_from_utf8(upid, SegmentationUpidType::ISCIDeprecated)
573            .map(|s| SegmentationUpid::Isci(upid::IsciDeprecated(s)))
574    }
575    fn parse_adid(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
576        chk_upid(&upid, 12, SegmentationUpidType::AdID)?;
577        upid_from_utf8(upid, SegmentationUpidType::AdID)
578            .map(|s| SegmentationUpid::AdID(upid::AdID(s)))
579    }
580    fn parse_umid(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
581        chk_upid(&upid, 32, SegmentationUpidType::UMID)?;
582        Ok(SegmentationUpid::Umid(upid::Umid(upid)))
583    }
584    fn parse_isan_deprecated(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
585        chk_upid(&upid, 8, SegmentationUpidType::ISANDeprecated)?;
586        Ok(SegmentationUpid::IsanDeprecated(upid::IsanDeprecated(upid)))
587    }
588    fn parse_isan(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
589        chk_upid(&upid, 12, SegmentationUpidType::ISAN)?;
590        Ok(SegmentationUpid::IsanDeprecated(upid::IsanDeprecated(upid)))
591    }
592    fn parse_tid(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
593        chk_upid(&upid, 12, SegmentationUpidType::TID)?;
594        upid_from_utf8(upid, SegmentationUpidType::TID).map(|s| SegmentationUpid::TID(upid::TID(s)))
595    }
596    fn parse_ti(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
597        chk_upid(&upid, 8, SegmentationUpidType::TI)?;
598        Ok(SegmentationUpid::TI(upid::TI(upid)))
599    }
600    fn parse_adi(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
601        upid_from_utf8(upid, SegmentationUpidType::ADI).map(|s| SegmentationUpid::ADI(upid::ADI(s)))
602    }
603    fn parse_eidr(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
604        chk_upid(&upid, 12, SegmentationUpidType::EIDR)?;
605        Ok(SegmentationUpid::EIDR(upid::EIDR(
606            upid.as_slice().try_into().unwrap(),
607        )))
608    }
609    fn parse_atsc(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
610        Ok(SegmentationUpid::ATSC(upid::ATSC(upid)))
611    }
612    fn parse_mpu(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
613        Ok(SegmentationUpid::MPU(upid::MPU(upid)))
614    }
615    fn parse_mid(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
616        let mut data = &upid[..];
617        let mut result = vec![];
618        while !data.is_empty() {
619            if data.len() < 2 {
620                return Err(SpliceDescriptorErr::not_enough_data("MID.length", 1, 0));
621            }
622            let segmentation_upid_type = SegmentationUpidType::from_type(data[0]);
623            let length = data[1] as usize;
624            let payload_end = 2 + length;
625            if data.len() < payload_end {
626                return Err(SpliceDescriptorErr::not_enough_data(
627                    "MID.segmentation_upid",
628                    length,
629                    data.len() - 2,
630                ));
631            }
632            let payload = &data[2..payload_end];
633            result.push(Self::parse_payload(
634                segmentation_upid_type,
635                payload.to_vec(),
636            )?);
637            data = &data[payload_end..];
638        }
639        Ok(SegmentationUpid::MID(result))
640    }
641    fn parse_ads(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
642        Ok(SegmentationUpid::ADS(upid::ADSInformation(upid)))
643    }
644    fn parse_url(upid: Vec<u8>) -> Result<SegmentationUpid, SpliceDescriptorErr> {
645        upid_from_utf8(upid, SegmentationUpidType::URI)
646            .and_then(|s| {
647                url::Url::parse(&s).map_err(|_| SpliceDescriptorErr::InvalidUpidContent {
648                    upid_type: SegmentationUpidType::URI,
649                    bytes: s.into_bytes(),
650                })
651            })
652            .map(|u| SegmentationUpid::URI(upid::Url(u)))
653    }
654    fn parse_reserved(
655        segmentation_upid_type: SegmentationUpidType,
656        upid: Vec<u8>,
657    ) -> Result<SegmentationUpid, SpliceDescriptorErr> {
658        Ok(SegmentationUpid::Reserved(segmentation_upid_type, upid))
659    }
660}
661
662/// helper wrapping String::from_utf8() and producing a useful error type
663fn upid_from_utf8(
664    upid: Vec<u8>,
665    upid_type: SegmentationUpidType,
666) -> Result<String, SpliceDescriptorErr> {
667    String::from_utf8(upid).map_err(|e| SpliceDescriptorErr::InvalidUpidContent {
668        upid_type,
669        bytes: e.into_bytes(),
670    })
671}
672
673fn chk_upid(
674    upid: &[u8],
675    expected: usize,
676    upid_type: SegmentationUpidType,
677) -> Result<(), SpliceDescriptorErr> {
678    if upid.len() == expected {
679        Ok(())
680    } else {
681        Err(SpliceDescriptorErr::InvalidUpidLength {
682            upid_type,
683            expected,
684            actual: upid.len(),
685        })
686    }
687}
688
689#[derive(Debug, serde_derive::Serialize)]
690pub enum DeviceRestrictions {
691    RestrictGroup0,
692    RestrictGroup1,
693    RestrictGroup2,
694    None,
695}
696impl DeviceRestrictions {
697    /// panics if `id` is something other than `0`, `1`, `2` or `3`
698    pub fn from_bits(restriction: u8) -> DeviceRestrictions {
699        match restriction {
700            0 => DeviceRestrictions::RestrictGroup0,
701            1 => DeviceRestrictions::RestrictGroup1,
702            2 => DeviceRestrictions::RestrictGroup2,
703            3 => DeviceRestrictions::None,
704            _ => panic!(
705                "Invalid device_restrictions value: {} (expected 0, 1, 2, 3)",
706                restriction
707            ),
708        }
709    }
710}
711
712#[derive(Debug, serde_derive::Serialize)]
713pub enum DeliveryRestrictionFlags {
714    None,
715    DeliveryRestrictions {
716        web_delivery_allowed_flag: bool,
717        no_regional_blackout_flag: bool,
718        archive_allowed_flag: bool,
719        device_restrictions: DeviceRestrictions,
720    },
721}
722
723#[derive(Debug, serde_derive::Serialize)]
724pub enum SegmentationMode {
725    Program,
726    Component {
727        components: Vec<SegmentationModeComponent>,
728    },
729}
730
731#[derive(Debug, serde_derive::Serialize)]
732pub struct SegmentationModeComponent {
733    component_tag: u8,
734    pts_offset: u64,
735}
736
737#[derive(Debug, serde_derive::Serialize)]
738pub enum SegmentationDescriptor {
739    Cancel,
740    Insert {
741        program_segmentation_flag: bool,
742        segmentation_duration_flag: bool,
743        delivery_not_restricted_flag: bool,
744        delivery_restrictions: DeliveryRestrictionFlags,
745        segmentation_mode: SegmentationMode,
746        segmentation_duration: Option<u64>,
747        segmentation_upid: SegmentationUpid,
748        segmentation_type_id: SegmentationTypeId,
749        segment_num: u8,
750        segments_expected: u8,
751        sub_segments: Option<SubSegments>,
752    },
753}
754
755#[derive(Debug, serde_derive::Serialize)]
756pub struct SubSegments {
757    sub_segment_num: u8,
758    sub_segments_expected: u8,
759}
760
761#[derive(Debug, serde_derive::Serialize)]
762pub struct SpliceDuration {
763    return_mode: ReturnMode,
764    duration: u64,
765}
766
767pub trait SpliceInfoProcessor {
768    fn process(
769        &self,
770        header: SpliceInfoHeader<'_>,
771        command: SpliceCommand,
772        descriptors: SpliceDescriptors<'_>,
773    );
774}
775
776#[derive(Debug, serde_derive::Serialize)]
777pub enum SpliceDescriptor {
778    AvailDescriptor {
779        provider_avail_id: u32,
780    },
781    DTMFDescriptor {
782        preroll: u8,
783        dtmf_chars: Vec<u8>,
784    },
785    SegmentationDescriptor {
786        segmentation_event_id: u32,
787        descriptor_detail: SegmentationDescriptor,
788    },
789    TimeDescriptor {
790        tai_seconds: u64,
791        tai_nanoseconds: u32,
792        utc_offset: u16,
793    },
794    Reserved {
795        tag: u8,
796        identifier: [u8; 4],
797        private_bytes: Vec<u8>,
798    },
799}
800impl SpliceDescriptor {
801    fn parse_segmentation_descriptor_details(
802        r: &mut bitreader::BitReader<'_>,
803        cancelled: bool,
804    ) -> Result<SegmentationDescriptor, SpliceDescriptorErr> {
805        if cancelled {
806            Ok(SegmentationDescriptor::Cancel)
807        } else {
808            let program_segmentation_flag = r
809                .read_bool()
810                .named("segmentation_descriptor.program_segmentation_flag")?;
811            let segmentation_duration_flag = r
812                .read_bool()
813                .named("segmentation_descriptor.segmentation_duration_flag")?;
814            let delivery_not_restricted_flag = r
815                .read_bool()
816                .named("segmentation_descriptor.delivery_not_restricted_flag")?;
817            let delivery_restrictions;
818            if !delivery_not_restricted_flag {
819                delivery_restrictions = DeliveryRestrictionFlags::DeliveryRestrictions {
820                    web_delivery_allowed_flag: r
821                        .read_bool()
822                        .named("segmentation_descriptor.web_delivery_allowed_flag")?,
823                    no_regional_blackout_flag: r
824                        .read_bool()
825                        .named("segmentation_descriptor.no_regional_blackout_flag")?,
826                    archive_allowed_flag: r
827                        .read_bool()
828                        .named("segmentation_descriptor.archive_allowed_flag")?,
829                    device_restrictions: DeviceRestrictions::from_bits(
830                        r.read_u8(2)
831                            .named("segmentation_descriptor.device_restrictions")?,
832                    ),
833                }
834            } else {
835                delivery_restrictions = DeliveryRestrictionFlags::None;
836                r.skip(5).named("segmentation_descriptor.reserved")?;
837            }
838            let segmentation_mode = if !program_segmentation_flag {
839                let component_count = r
840                    .read_u8(8)
841                    .named("segmentation_descriptor.component_count")?;
842                let mut components = Vec::with_capacity(component_count as usize);
843
844                for _ in 0..component_count {
845                    let component_tag = r
846                        .read_u8(8)
847                        .named("segmentation_descriptor.component.component_tag")?;
848                    r.skip(7)
849                        .named("segmentation_descriptor.component.reserved")?;
850                    let pts_offset = r
851                        .read_u64(33)
852                        .named("segmentation_descriptor.component.pts_offset")?;
853                    components.push(SegmentationModeComponent {
854                        component_tag,
855                        pts_offset,
856                    })
857                }
858
859                SegmentationMode::Component { components }
860            } else {
861                SegmentationMode::Program
862            };
863
864            let segmentation_duration = if segmentation_duration_flag {
865                Some(
866                    r.read_u64(40)
867                        .named("segmentation_descriptor.segmentation_duration")?,
868                )
869            } else {
870                None
871            };
872
873            let segmentation_upid_type = SegmentationUpidType::from_type(
874                r.read_u8(8)
875                    .named("segmentation_descriptor.segmentation_upid_type")?,
876            );
877            let segmentation_upid_length = r
878                .read_u8(8)
879                .named("segmentation_descriptor.segmentation_upid_length")?;
880            let segmentation_upid =
881                SegmentationUpid::parse(r, segmentation_upid_type, segmentation_upid_length)?;
882
883            let segmentation_type_id =
884                SegmentationTypeId::from_id(r.read_u8(8).named("segmentation_type_id")?);
885            let segment_num = r.read_u8(8).named("segment_num")?;
886            let segments_expected = r.read_u8(8).named("segments_expected")?;
887
888            // The spec notes: "sub_segment_num and sub_segments_expected can form an optional
889            // appendix to the segmentation descriptor. The presence or absence of this optional
890            // data block is determined by the descriptor loop's descriptor_length."
891            let sub_segments = if r.relative_reader().skip(1).is_ok() {
892                Some(SubSegments {
893                    sub_segment_num: r.read_u8(8).named("sub_segment_num")?,
894                    sub_segments_expected: r.read_u8(8).named("sub_segments_expected")?,
895                })
896            } else {
897                None
898            };
899
900            Ok(SegmentationDescriptor::Insert {
901                program_segmentation_flag,
902                segmentation_duration_flag,
903                delivery_not_restricted_flag,
904                delivery_restrictions,
905                segmentation_mode,
906                segmentation_duration,
907                segmentation_upid,
908                segmentation_type_id,
909                segment_num,
910                segments_expected,
911                sub_segments,
912            })
913        }
914    }
915
916    fn parse_segmentation_descriptor(buf: &[u8]) -> Result<SpliceDescriptor, SpliceDescriptorErr> {
917        let mut r = bitreader::BitReader::new(buf);
918        let id = r.read_u32(32).named("segmentation_descriptor.id")?;
919        let cancel = r.read_bool().named("segmentation_descriptor.cancel")?;
920        r.skip(7).named("segmentation_descriptor.reserved")?;
921
922        let result = SpliceDescriptor::SegmentationDescriptor {
923            segmentation_event_id: id,
924            descriptor_detail: Self::parse_segmentation_descriptor_details(&mut r, cancel)?,
925        };
926
927        // if we end up without reading to the end of a byte, this must indicate a bug in the
928        // parsing routine,
929        assert!(r.is_aligned(1));
930
931        if buf.len() > (r.position() / 8) as usize {
932            error!(
933                "only {} bytes consumed data in segmentation_descriptor of {} bytes",
934                r.position() / 8,
935                buf.len()
936            );
937        }
938        Ok(result)
939    }
940
941    fn parse_dtmf_descriptor(buf: &[u8]) -> Result<SpliceDescriptor, SpliceDescriptorErr> {
942        let mut r = bitreader::BitReader::new(buf);
943        let preroll = r.read_u8(8).named("dtmf_descriptor.preroll")?;
944        let dtmf_count = r.read_u8(3).named("dtmf_descriptor.dtmf_count")?;
945        r.skip(5).named("dtmf_descriptor.reserved")?;
946        let dtmf_chars_result: Result<Vec<u8>, BitReaderError> =
947            (0..dtmf_count).map(|_| r.read_u8(8)).collect();
948        let dtmf_chars = dtmf_chars_result.named("dtmf_descriptor")?;
949
950        // if we end up without reading to the end of a byte, this must indicate a bug in the
951        // parsing routine,
952        assert!(r.is_aligned(1));
953
954        if buf.len() > (r.position() / 8) as usize {
955            error!(
956                "only {} bytes consumed data in segmentation_descriptor of {} bytes",
957                r.position() / 8,
958                buf.len()
959            );
960        }
961
962        Ok(SpliceDescriptor::DTMFDescriptor {
963            preroll,
964            dtmf_chars,
965        })
966    }
967    fn parse(buf: &[u8]) -> Result<SpliceDescriptor, SpliceDescriptorErr> {
968        if buf.len() < 6 {
969            return Err(SpliceDescriptorErr::NotEnoughData {
970                field_name: "splice_descriptor",
971                actual: buf.len(),
972                expected: 6,
973            });
974        }
975        let splice_descriptor_tag = buf[0];
976        let splice_descriptor_len = buf[1] as usize;
977        if splice_descriptor_len < 4 {
978            // descriptor must at least be big enough to hold the 4-byte id value
979            return Err(SpliceDescriptorErr::InvalidDescriptorLength(
980                splice_descriptor_len,
981            ));
982        }
983        let splice_descriptor_end = splice_descriptor_len + 2;
984        if splice_descriptor_end > buf.len() {
985            return Err(SpliceDescriptorErr::NotEnoughData {
986                field_name: "splice_descriptor.private_byte",
987                actual: buf.len(),
988                expected: splice_descriptor_end,
989            });
990        }
991        let id = &buf[2..6];
992        let payload = &buf[6..splice_descriptor_end];
993        if id == b"CUEI" {
994            match splice_descriptor_tag {
995                0x00 => Self::parse_avail_descriptor(payload),
996                0x01 => Self::parse_dtmf_descriptor(payload),
997                0x02 => Self::parse_segmentation_descriptor(payload),
998                0x03 => Self::parse_time_descriptor(payload),
999                _ => Self::parse_reserved(payload, splice_descriptor_tag, id),
1000            }
1001        } else {
1002            Self::parse_reserved(payload, splice_descriptor_tag, id)
1003        }
1004    }
1005
1006    fn parse_reserved(
1007        buf: &[u8],
1008        splice_descriptor_tag: u8,
1009        id: &[u8],
1010    ) -> Result<SpliceDescriptor, SpliceDescriptorErr> {
1011        Ok(SpliceDescriptor::Reserved {
1012            tag: splice_descriptor_tag,
1013            identifier: [id[0], id[1], id[2], id[3]],
1014            private_bytes: buf.to_owned(),
1015        })
1016    }
1017
1018    fn parse_avail_descriptor(buf: &[u8]) -> Result<SpliceDescriptor, SpliceDescriptorErr> {
1019        if buf.len() < 4 {
1020            return Err(SpliceDescriptorErr::NotEnoughData {
1021                field_name: "avail_descriptor",
1022                expected: 4,
1023                actual: buf.len(),
1024            });
1025        }
1026        Ok(SpliceDescriptor::AvailDescriptor {
1027            provider_avail_id: u32::from(buf[0]) << 24
1028                | u32::from(buf[1]) << 16
1029                | u32::from(buf[2]) << 8
1030                | u32::from(buf[3]),
1031        })
1032    }
1033
1034    fn parse_time_descriptor(buf: &[u8]) -> Result<SpliceDescriptor, SpliceDescriptorErr> {
1035        if buf.len() < 12 {
1036            return Err(SpliceDescriptorErr::NotEnoughData {
1037                field_name: "time_descriptor",
1038                expected: 12,
1039                actual: buf.len(),
1040            });
1041        }
1042        Ok(SpliceDescriptor::TimeDescriptor {
1043            tai_seconds: u64::from(buf[0]) << 40
1044                | u64::from(buf[1]) << 32
1045                | u64::from(buf[2]) << 24
1046                | u64::from(buf[3]) << 16
1047                | u64::from(buf[4]) << 8
1048                | u64::from(buf[5]),
1049            tai_nanoseconds: u32::from(buf[6]) << 24
1050                | u32::from(buf[7]) << 16
1051                | u32::from(buf[8]) << 8
1052                | u32::from(buf[9]),
1053            utc_offset: u16::from(buf[10]) << 8 | u16::from(buf[11]),
1054        })
1055    }
1056}
1057
1058#[derive(Debug, serde_derive::Serialize)]
1059pub enum SpliceDescriptorErr {
1060    InvalidDescriptorLength(usize),
1061    NotEnoughData {
1062        field_name: &'static str,
1063        expected: usize,
1064        actual: usize,
1065    },
1066    /// The segmentation_upid_length field value was `0`, but the segmentation_upid_type value was
1067    /// non-`0` (as indicated by the given `SegmentationUpidType` enum variant)
1068    SegmentationUpidLengthTypeMismatch(SegmentationUpidType),
1069    /// The UPID field contained byte values that are invalid for the given UPID type
1070    InvalidUpidContent {
1071        upid_type: SegmentationUpidType,
1072        bytes: Vec<u8>,
1073    },
1074    /// The UPID field had a length invalid for its type
1075    InvalidUpidLength {
1076        upid_type: SegmentationUpidType,
1077        expected: usize,
1078        actual: usize,
1079    },
1080}
1081impl SpliceDescriptorErr {
1082    fn not_enough_data(
1083        field_name: &'static str,
1084        expected: usize,
1085        actual: usize,
1086    ) -> SpliceDescriptorErr {
1087        SpliceDescriptorErr::NotEnoughData {
1088            field_name,
1089            expected,
1090            actual,
1091        }
1092    }
1093}
1094
1095trait ErrorFieldNamed<T> {
1096    fn named(self, field_name: &'static str) -> Result<T, SpliceDescriptorErr>;
1097}
1098impl<T> ErrorFieldNamed<T> for Result<T, bitreader::BitReaderError> {
1099    fn named(self, field_name: &'static str) -> Result<T, SpliceDescriptorErr> {
1100        match self {
1101            Err(bitreader::BitReaderError::NotEnoughData {
1102                position,
1103                length,
1104                requested,
1105            }) => {
1106                // TODO: round numbers up to nearest byte,
1107                Err(SpliceDescriptorErr::NotEnoughData {
1108                    field_name,
1109                    expected: (requested / 8) as usize,
1110                    actual: ((length - position) / 8) as usize,
1111                })
1112            }
1113            Err(e) => {
1114                panic!("scte35-reader bug: {:?}", e)
1115            }
1116            Ok(v) => Ok(v),
1117        }
1118    }
1119}
1120
1121pub struct SpliceDescriptors<'buf> {
1122    buf: &'buf [u8],
1123}
1124impl<'buf> IntoIterator for &SpliceDescriptors<'buf> {
1125    type Item = Result<SpliceDescriptor, SpliceDescriptorErr>;
1126    type IntoIter = SpliceDescriptorIter<'buf>;
1127
1128    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
1129        SpliceDescriptorIter::new(self.buf)
1130    }
1131}
1132impl<'a> serde::Serialize for SpliceDescriptors<'a> {
1133    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1134    where
1135        S: serde::Serializer,
1136    {
1137        let mut s = serializer.serialize_seq(None)?;
1138        for elem in self.into_iter().flatten() {
1139            s.serialize_element(&elem)?;
1140        }
1141        s.end()
1142    }
1143}
1144
1145pub struct SpliceDescriptorIter<'buf> {
1146    buf: &'buf [u8],
1147}
1148impl<'buf> SpliceDescriptorIter<'buf> {
1149    fn new(buf: &'buf [u8]) -> SpliceDescriptorIter<'buf> {
1150        SpliceDescriptorIter { buf }
1151    }
1152}
1153impl<'buf> Iterator for SpliceDescriptorIter<'buf> {
1154    type Item = Result<SpliceDescriptor, SpliceDescriptorErr>;
1155
1156    fn next(&mut self) -> Option<Self::Item> {
1157        if self.buf.is_empty() {
1158            return None;
1159        }
1160        if self.buf.len() < 6 {
1161            self.buf = &self.buf[0..0];
1162            return Some(Err(SpliceDescriptorErr::NotEnoughData {
1163                field_name: "splice_descriptor",
1164                expected: 2,
1165                actual: self.buf.len(),
1166            }));
1167        }
1168        let descriptor_length = self.buf[1] as usize;
1169        if self.buf.len() < descriptor_length + 2 {
1170            self.buf = &self.buf[0..0];
1171            return Some(Err(SpliceDescriptorErr::NotEnoughData {
1172                field_name: "splice_descriptor",
1173                expected: descriptor_length + 2,
1174                actual: self.buf.len(),
1175            }));
1176        }
1177        if descriptor_length > 254 {
1178            self.buf = &self.buf[0..0];
1179            return Some(Err(SpliceDescriptorErr::InvalidDescriptorLength(
1180                descriptor_length,
1181            )));
1182        }
1183        let (desc, rest) = self.buf.split_at(2 + descriptor_length);
1184        let result = SpliceDescriptor::parse(desc);
1185        self.buf = rest;
1186        Some(result)
1187    }
1188}
1189
1190pub struct Scte35SectionProcessor<P, Ctx: demultiplex::DemuxContext>
1191where
1192    P: SpliceInfoProcessor,
1193{
1194    processor: P,
1195    phantom: marker::PhantomData<Ctx>,
1196}
1197impl<P, Ctx: demultiplex::DemuxContext> psi::WholeCompactSyntaxPayloadParser
1198    for Scte35SectionProcessor<P, Ctx>
1199where
1200    P: SpliceInfoProcessor,
1201{
1202    type Context = Ctx;
1203
1204    fn section(
1205        &mut self,
1206        _ctx: &mut Self::Context,
1207        header: &psi::SectionCommonHeader,
1208        data: &[u8],
1209    ) {
1210        if header.table_id == 0xfc {
1211            // no CRC while fuzz-testing, to make it more likely to find parser bugs,
1212            if !cfg!(fuzzing) {
1213                let crc = mpeg2ts_reader::mpegts_crc::sum32(data);
1214                if crc != 0 {
1215                    error!("section CRC check failed {:#08x}", crc);
1216                    return;
1217                }
1218            }
1219            let section_data = &data[psi::SectionCommonHeader::SIZE..];
1220            if section_data.len() < SpliceInfoHeader::HEADER_LENGTH + 4 {
1221                error!(
1222                    "section data too short: {} (must be at least {})",
1223                    section_data.len(),
1224                    SpliceInfoHeader::HEADER_LENGTH + 4
1225                );
1226                return;
1227            }
1228            // trim off the 32-bit CRC
1229            let section_data = &section_data[..section_data.len() - 4];
1230            let (splice_header, rest) = SpliceInfoHeader::new(section_data);
1231            if splice_header.encrypted_packet() {
1232                error!("encrypted SCTE-35 data not supoprted");
1233                return;
1234            }
1235            let command_len = splice_header.splice_command_length() as usize;
1236            if command_len > rest.len() {
1237                error!("splice_command_length of {} bytes is too long to fit in remaining {} bytes of section data", command_len, rest.len());
1238                return;
1239            }
1240            let (payload, rest) = rest.split_at(command_len);
1241            if rest.len() < 2 {
1242                error!("end of section data while trying to read descriptor_loop_length");
1243                return;
1244            }
1245            let descriptor_loop_length = (u16::from(rest[0]) << 8 | u16::from(rest[1])) as usize;
1246            if descriptor_loop_length + 2 > rest.len() {
1247                error!("descriptor_loop_length of {} bytes is too long to fit in remaining {} bytes of section data", descriptor_loop_length, rest.len());
1248                return;
1249            }
1250            let descriptors = &rest[2..2 + descriptor_loop_length];
1251            let splice_command = match splice_header.splice_command_type() {
1252                SpliceCommandType::SpliceNull => Some(Self::splice_null(payload)),
1253                SpliceCommandType::SpliceInsert => Some(Self::splice_insert(payload)),
1254                SpliceCommandType::TimeSignal => Some(Self::time_signal(payload)),
1255                SpliceCommandType::BandwidthReservation => {
1256                    Some(Self::bandwidth_reservation(payload))
1257                }
1258                SpliceCommandType::PrivateCommand => Some(Self::private_command(payload)),
1259                _ => None,
1260            };
1261            match splice_command {
1262                Some(Ok(splice_command)) => {
1263                    self.processor.process(
1264                        splice_header,
1265                        splice_command,
1266                        SpliceDescriptors { buf: descriptors },
1267                    );
1268                }
1269                Some(Err(e)) => {
1270                    error!("parse error: {:?}", e);
1271                }
1272                None => {
1273                    error!(
1274                        "unhandled command {:?}",
1275                        splice_header.splice_command_type()
1276                    );
1277                }
1278            }
1279        } else {
1280            error!(
1281                "bad table_id for scte35: {:#x} (expected 0xfc)",
1282                header.table_id
1283            );
1284        }
1285    }
1286}
1287impl<P, Ctx: demultiplex::DemuxContext> Scte35SectionProcessor<P, Ctx>
1288where
1289    P: SpliceInfoProcessor,
1290{
1291    pub fn new(processor: P) -> Scte35SectionProcessor<P, Ctx> {
1292        Scte35SectionProcessor {
1293            processor,
1294            phantom: marker::PhantomData,
1295        }
1296    }
1297    fn splice_null(payload: &[u8]) -> Result<SpliceCommand, SpliceDescriptorErr> {
1298        if payload.is_empty() {
1299            Ok(SpliceCommand::SpliceNull {})
1300        } else {
1301            Err(SpliceDescriptorErr::InvalidDescriptorLength(payload.len()))
1302        }
1303    }
1304
1305    fn splice_insert(payload: &[u8]) -> Result<SpliceCommand, SpliceDescriptorErr> {
1306        let mut r = bitreader::BitReader::new(payload);
1307
1308        let splice_event_id = r.read_u32(32).named("splice_insert.splice_event_id")?;
1309        let splice_event_cancel_indicator = r
1310            .read_bool()
1311            .named("splice_insert.splice_event_cancel_indicator")?;
1312        let reserved = r.read_u8(7).named("splice_insert.reserved")?;
1313        let result = SpliceCommand::SpliceInsert {
1314            splice_event_id,
1315            reserved,
1316            splice_detail: Self::read_splice_detail(&mut r, splice_event_cancel_indicator)?,
1317        };
1318
1319        // if we end up without reading to the end of a byte, this must indicate a bug in the
1320        // parsing routine,
1321        assert!(r.is_aligned(1));
1322
1323        if payload.len() > (r.position() / 8) as usize {
1324            error!(
1325                "only {} bytes consumed data in splice_insert of {} bytes",
1326                r.position() / 8,
1327                payload.len()
1328            );
1329        }
1330        Ok(result)
1331    }
1332
1333    fn time_signal(payload: &[u8]) -> Result<SpliceCommand, SpliceDescriptorErr> {
1334        let mut r = bitreader::BitReader::new(payload);
1335
1336        let result = SpliceCommand::TimeSignal {
1337            splice_time: SpliceTime::Timed(Self::read_splice_time(&mut r)?),
1338        };
1339
1340        // if we end up without reading to the end of a byte, this must indicate a bug in the
1341        // parsing routine,
1342        assert!(r.is_aligned(1));
1343
1344        if payload.len() > (r.position() / 8) as usize {
1345            error!(
1346                "only {} bytes consumed data in time_signal of {} bytes",
1347                r.position() / 8,
1348                payload.len()
1349            );
1350        }
1351        Ok(result)
1352    }
1353
1354    fn bandwidth_reservation(payload: &[u8]) -> Result<SpliceCommand, SpliceDescriptorErr> {
1355        if payload.is_empty() {
1356            Ok(SpliceCommand::BandwidthReservation {})
1357        } else {
1358            Err(SpliceDescriptorErr::InvalidDescriptorLength(payload.len()))
1359        }
1360    }
1361
1362    fn private_command(payload: &[u8]) -> Result<SpliceCommand, SpliceDescriptorErr> {
1363        let mut r = bitreader::BitReader::new(payload);
1364        let identifier = r.read_u32(32).named("private_command.identifier")?;
1365        Ok(SpliceCommand::PrivateCommand {
1366            identifier,
1367            private_bytes: payload[4..].to_vec(),
1368        })
1369    }
1370
1371    fn read_splice_detail(
1372        r: &mut bitreader::BitReader<'_>,
1373        splice_event_cancel_indicator: bool,
1374    ) -> Result<SpliceInsert, SpliceDescriptorErr> {
1375        if splice_event_cancel_indicator {
1376            Ok(SpliceInsert::Cancel)
1377        } else {
1378            r.relative_reader().skip(1).named("splice_insert.flags")?;
1379            let network_indicator =
1380                NetworkIndicator::from_flag(r.read_u8(1).named("splice_insert.network_indicator")?);
1381            let program_splice_flag = r.read_bool().named("splice_insert.program_splice_flag")?;
1382            let duration_flag = r.read_bool().named("splice_insert.duration_flag")?;
1383            let splice_immediate_flag =
1384                r.read_bool().named("splice_insert.splice_immediate_flag")?;
1385            r.skip(4).named("splice_insert.reserved")?;
1386
1387            Ok(SpliceInsert::Insert {
1388                network_indicator,
1389                splice_mode: Self::read_splice_mode(r, program_splice_flag, splice_immediate_flag)?,
1390                duration: if duration_flag {
1391                    Some(Self::read_duration(r)?)
1392                } else {
1393                    None
1394                },
1395                unique_program_id: r.read_u16(16).named("unique_program_id")?,
1396                avail_num: r.read_u8(8).named("avail_num")?,
1397                avails_expected: r.read_u8(8).named("avails_expected")?,
1398            })
1399        }
1400    }
1401
1402    fn read_splice_mode(
1403        r: &mut bitreader::BitReader<'_>,
1404        program_splice_flag: bool,
1405        splice_immediate_flag: bool,
1406    ) -> Result<SpliceMode, SpliceDescriptorErr> {
1407        if program_splice_flag {
1408            let time = if splice_immediate_flag {
1409                SpliceTime::Immediate
1410            } else {
1411                SpliceTime::Timed(Self::read_splice_time(r)?)
1412            };
1413            Ok(SpliceMode::Program(time))
1414        } else {
1415            let component_count = r.read_u8(8).named("component_count")? as usize;
1416            let mut components = Vec::with_capacity(component_count);
1417            for _ in 0..component_count {
1418                let component_tag = r.read_u8(8).named("component_tag")?;
1419                let splice_time = if splice_immediate_flag {
1420                    SpliceTime::Immediate
1421                } else {
1422                    SpliceTime::Timed(Self::read_splice_time(r)?)
1423                };
1424                components.push(ComponentSplice {
1425                    component_tag,
1426                    splice_time,
1427                });
1428            }
1429            Ok(SpliceMode::Components(components))
1430        }
1431    }
1432
1433    fn read_splice_time(
1434        r: &mut bitreader::BitReader<'_>,
1435    ) -> Result<Option<u64>, SpliceDescriptorErr> {
1436        Ok(if r.read_bool().named("splice_time.time_specified_flag")? {
1437            r.skip(6).named("splice_time.reserved")?; // reserved
1438            Some(r.read_u64(33).named("splice_time.pts_time")?)
1439        } else {
1440            r.skip(7).named("splice_time.reserved")?; // reserved
1441            None
1442        })
1443    }
1444
1445    fn read_duration(
1446        r: &mut bitreader::BitReader<'_>,
1447    ) -> Result<SpliceDuration, SpliceDescriptorErr> {
1448        let return_mode = ReturnMode::from_flag(r.read_u8(1).named("break_duration.auto_return")?);
1449        r.skip(6).named("break_duration.reserved")?;
1450        Ok(SpliceDuration {
1451            return_mode,
1452            duration: r.read_u64(33).named("break_duration.duration")?,
1453        })
1454    }
1455}
1456
1457#[cfg(test)]
1458mod tests {
1459    use super::*;
1460    use hex_literal::*;
1461    use matches::*;
1462    use mpeg2ts_reader::demultiplex;
1463    use mpeg2ts_reader::psi;
1464    use mpeg2ts_reader::psi::WholeCompactSyntaxPayloadParser;
1465
1466    mpeg2ts_reader::demux_context!(
1467        NullDemuxContext,
1468        demultiplex::NullPacketFilter<NullDemuxContext>
1469    );
1470    impl NullDemuxContext {
1471        fn do_construct(
1472            &mut self,
1473            _req: demultiplex::FilterRequest<'_, '_>,
1474        ) -> demultiplex::NullPacketFilter<NullDemuxContext> {
1475            unimplemented!();
1476        }
1477    }
1478
1479    struct MockSpliceInsertProcessor;
1480    impl SpliceInfoProcessor for MockSpliceInsertProcessor {
1481        fn process(
1482            &self,
1483            header: SpliceInfoHeader<'_>,
1484            command: SpliceCommand,
1485            descriptors: SpliceDescriptors<'_>,
1486        ) {
1487            assert_eq!(header.encryption_algorithm(), EncryptionAlgorithm::None);
1488            assert_matches!(command, SpliceCommand::SpliceInsert { .. });
1489            for d in &descriptors {
1490                d.unwrap();
1491            }
1492        }
1493    }
1494
1495    #[test]
1496    fn it_works() {
1497        let data = hex!(
1498            "fc302500000000000000fff01405000000017feffe2d142b00fe0123d3080001010100007f157a49"
1499        );
1500        let mut parser = Scte35SectionProcessor::new(MockSpliceInsertProcessor);
1501        let header = psi::SectionCommonHeader::new(&data[..psi::SectionCommonHeader::SIZE]);
1502        let mut ctx = NullDemuxContext::new();
1503        parser.section(&mut ctx, &header, &data[..]);
1504    }
1505
1506    struct MockTimeSignalProcessor;
1507    impl SpliceInfoProcessor for MockTimeSignalProcessor {
1508        fn process(
1509            &self,
1510            header: SpliceInfoHeader<'_>,
1511            command: SpliceCommand,
1512            descriptors: SpliceDescriptors<'_>,
1513        ) {
1514            assert_eq!(header.encryption_algorithm(), EncryptionAlgorithm::None);
1515            assert_matches!(command, SpliceCommand::TimeSignal { .. });
1516            for d in &descriptors {
1517                d.unwrap();
1518            }
1519        }
1520    }
1521
1522    #[test]
1523    fn it_understands_time_signal() {
1524        let data = hex!(
1525            "fc302700000000000000fff00506ff592d03c00011020f43554549000000017fbf000010010112ce0e6b"
1526        );
1527        let mut parser = Scte35SectionProcessor::new(MockTimeSignalProcessor);
1528        let header = psi::SectionCommonHeader::new(&data[..psi::SectionCommonHeader::SIZE]);
1529        let mut ctx = NullDemuxContext::new();
1530        parser.section(&mut ctx, &header, &data[..]);
1531    }
1532
1533    #[test]
1534    fn splice_descriptor() {
1535        let data = [];
1536        assert_matches!(
1537            SpliceDescriptor::parse(&data[..]),
1538            Err(SpliceDescriptorErr::NotEnoughData { .. })
1539        );
1540        let data = hex!("01084D5949440000"); // descriptor payload too short
1541        assert_matches!(
1542            SpliceDescriptor::parse(&data[..]),
1543            Err(SpliceDescriptorErr::NotEnoughData { .. })
1544        );
1545        let data = hex!("01034D59494400000003");
1546        assert_matches!(
1547            SpliceDescriptor::parse(&data[..]),
1548            Err(SpliceDescriptorErr::InvalidDescriptorLength { .. })
1549        );
1550        let data = hex!("01084D59494400000003");
1551        assert_matches!(
1552            SpliceDescriptor::parse(&data[..]),
1553            Ok(SpliceDescriptor::Reserved {
1554                tag: 01,
1555                identifier: [0x4D, 0x59, 0x49, 0x44],
1556                private_bytes: _,
1557            })
1558        );
1559
1560        let data = hex!("020f43554549000000017fbf0000100101");
1561        assert_matches!(
1562            SpliceDescriptor::parse(&data[..]),
1563            Ok(SpliceDescriptor::SegmentationDescriptor {
1564                segmentation_event_id: 1,
1565                descriptor_detail: SegmentationDescriptor::Insert {
1566                    program_segmentation_flag: true,
1567                    segmentation_duration_flag: false,
1568                    delivery_not_restricted_flag: true,
1569                    delivery_restrictions: DeliveryRestrictionFlags::None,
1570                    segmentation_mode: SegmentationMode::Program,
1571                    segmentation_duration: None,
1572                    segmentation_upid: SegmentationUpid::None,
1573                    segmentation_type_id: SegmentationTypeId::ProgramStart,
1574                    segment_num: 1,
1575                    segments_expected: 1,
1576                    sub_segments: None,
1577                }
1578            })
1579        );
1580    }
1581
1582    #[test]
1583    fn segmentation_descriptor() {
1584        let data = hex!("480000ad7f9f0808000000002cb2d79d350200");
1585        let desc = SpliceDescriptor::parse_segmentation_descriptor(&data[..]).unwrap();
1586        match desc {
1587            SpliceDescriptor::SegmentationDescriptor {
1588                descriptor_detail:
1589                    SegmentationDescriptor::Insert {
1590                        segmentation_upid: SegmentationUpid::TI(ti),
1591                        ..
1592                    },
1593                ..
1594            } => {
1595                // TODO: assert_eq!(upid.len(), 8);
1596                assert_eq!(ti, upid::TI(hex!("000000002cb2d79d").to_vec()));
1597            }
1598            _ => panic!("unexpected {:?}", desc),
1599        };
1600    }
1601
1602    #[test]
1603    fn no_sub_segment_num() {
1604        // This segmentation_descriptor() does not include sub_segment_num or
1605        // sub_segments_expected fields.  Their absence should not cause parsing problems.
1606        let data = hex!("480000bf7fcf0000f8fa630d110e054c413330390808000000002e538481340000");
1607        SpliceDescriptor::parse_segmentation_descriptor(&data[..]).unwrap();
1608    }
1609
1610    #[test]
1611    fn too_large_segment_descriptor() {
1612        // there are more bytes than expected; this should not panic
1613        let data = hex!("480000ad7f9f0808000000002cb2d79d350200000000");
1614        SpliceDescriptor::parse_segmentation_descriptor(&data[..]).unwrap();
1615    }
1616}