Skip to content

A Rust implemented parser of SCTE-35 messages; in particular the Splice Info Section type.

License

Notifications You must be signed in to change notification settings

theRealRobG/scte35

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

scte35

scte35 is a SCTE35 parser that has been translated from Swift into Rust using my SCTE35Parser implementation as a base.

The 2020 SCTE-25 specification was used and can be found included in the Swift implementation repository.

Not all data fields from the SCTE35 message are included in the output struct; where the field is informational for parsing instruction only it is ommitted from inclusion in the public model.

Usage

The primary integration point to the framework is the SpliceInfoSection struct.

Given a hex encoded string SCTE35 message, the SpliceInfoSection offers the try_from_hex_string that returns Result<SpliceInfoSection, ParseError>:

use scte35::{
    splice_command::{time_signal::TimeSignal, SpliceCommand},
    splice_descriptor::{
        segmentation_descriptor::{
            DeliveryRestrictions, DeviceRestrictions, ScheduledEvent,
            SegmentationDescriptor, SegmentationTypeID, SegmentationUPID,
        },
        SpliceDescriptor,
    },
    splice_info_section::{SAPType, SpliceInfoSection},
    time::SpliceTime,
};

let hex_string = "0xFC3034000000000000FFFFF00506FE72BD0050001E021C435545494800008E7FCF0001A599B00808000000002CA0A18A3402009AC9D17E";
let splice_info_section = SpliceInfoSection::try_from_hex_string(hex_string).unwrap();
assert_eq!(
    SpliceInfoSection {
        table_id: 252,
        sap_type: SAPType::Unspecified,
        protocol_version: 0,
        encrypted_packet: None,
        pts_adjustment: 0,
        tier: 0xFFF,
        splice_command: SpliceCommand::TimeSignal(TimeSignal {
            splice_time: SpliceTime {
                pts_time: Some(1924989008),
            },
        }),
        splice_descriptors: vec![SpliceDescriptor::SegmentationDescriptor(
            SegmentationDescriptor {
                identifier: 1129661769,
                event_id: 1207959694,
                scheduled_event: Some(ScheduledEvent {
                    delivery_restrictions: Some(DeliveryRestrictions {
                        web_delivery_allowed: false,
                        no_regional_blackout: true,
                        archive_allowed: true,
                        device_restrictions: DeviceRestrictions::None,
                    }),
                    component_segments: None,
                    segmentation_duration: Some(27630000),
                    segmentation_upid: SegmentationUPID::TI(String::from("0x000000002CA0A18A")),
                    segmentation_type_id: SegmentationTypeID::ProviderPlacementOpportunityStart,
                    segment_num: 2,
                    segments_expected: 0,
                    sub_segment: None,
                }),
            },
        )],
        crc_32: 0x9AC9D17E,
        non_fatal_errors: vec![],
    },
    splice_info_section
);

Errors can be returned if there are some issues with the provided SCTE35 message that invalidate the parsing.

The parser also keeps a storage of non_fatal_errors. The idea here is that there may be some inconsistencies in the SCTE35 message (e.g. mis-match between declared SpliceCommand length and parsed length), but the message on the whole is still parsable, and so instead of killing the whole parse by throwing, the error is just logged to the non_fatal_errors instead.

There is also an initialiser provided for bytes &[u8]. This method can be used when you have a base64 string instead of hex by converting the string to bytes first, as the example below shows:

use base64::prelude::*;
use scte35::{
    splice_command::{time_signal::TimeSignal, SpliceCommand},
    splice_descriptor::{
        segmentation_descriptor::{
            DeliveryRestrictions, DeviceRestrictions, ScheduledEvent,
            SegmentationDescriptor, SegmentationTypeID, SegmentationUPID,
        },
        SpliceDescriptor,
    },
    splice_info_section::{SAPType, SpliceInfoSection},
    time::SpliceTime,
};

let base64_string = "/DA0AAAAAAAA///wBQb+cr0AUAAeAhxDVUVJSAAAjn/PAAGlmbAICAAAAAAsoKGKNAIAmsnRfg==";
let data = BASE64_STANDARD.decode(base64_string).expect("should be valid base64");
let splice_info_section = SpliceInfoSection::try_from_bytes(&data).unwrap();
assert_eq!(
    SpliceInfoSection {
        table_id: 252,
        sap_type: SAPType::Unspecified,
        protocol_version: 0,
        encrypted_packet: None,
        pts_adjustment: 0,
        tier: 0xFFF,
        splice_command: SpliceCommand::TimeSignal(TimeSignal {
            splice_time: SpliceTime {
                pts_time: Some(1924989008),
            },
        }),
        splice_descriptors: vec![SpliceDescriptor::SegmentationDescriptor(
            SegmentationDescriptor {
                identifier: 1129661769,
                event_id: 1207959694,
                scheduled_event: Some(ScheduledEvent {
                    delivery_restrictions: Some(DeliveryRestrictions {
                        web_delivery_allowed: false,
                        no_regional_blackout: true,
                        archive_allowed: true,
                        device_restrictions: DeviceRestrictions::None,
                    }),
                    component_segments: None,
                    segmentation_duration: Some(27630000),
                    segmentation_upid: SegmentationUPID::TI(String::from("0x000000002CA0A18A")),
                    segmentation_type_id: SegmentationTypeID::ProviderPlacementOpportunityStart,
                    segment_num: 2,
                    segments_expected: 0,
                    sub_segment: None,
                }),
            },
        )],
        crc_32: 0x9AC9D17E,
        non_fatal_errors: vec![],
    },
    splice_info_section
);

Both constructors are valid and should yield similar results:

use base64::prelude::*;
use scte35::splice_info_section::SpliceInfoSection;

let base64_string = "/DA0AAAAAAAA///wBQb+cr0AUAAeAhxDVUVJSAAAjn/PAAGlmbAICAAAAAAsoKGKNAIAmsnRfg==";
let base64_data = BASE64_STANDARD.decode(base64_string).expect("should be valid base64");
let hex_string = "0xFC3034000000000000FFFFF00506FE72BD0050001E021C435545494800008E7FCF0001A599B00808000000002CA0A18A3402009AC9D17E";
let splice_info_section_from_base64 = SpliceInfoSection::try_from_bytes(&base64_data).unwrap();
let splice_info_section_from_hex = SpliceInfoSection::try_from_hex_string(hex_string).unwrap();
assert_eq!(splice_info_section_from_base64, splice_info_section_from_hex);

About

A Rust implemented parser of SCTE-35 messages; in particular the Splice Info Section type.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages