streaming

Media streaming and broadcast systems in Go
Log | Files | Refs | README | LICENSE

commit ccb2bb2323ba704025fe9ee71679e9a112be7c77
parent a27f2f8b5d1de78c44c630ce88566d59176ed413
Author: Oliver Lowe <o@olowe.co>
Date:   Thu,  2 May 2024 16:28:48 +1000

internal/scte35: remove custom table serialisation

Lots of code, but I'm not sure that we're getting much apart from
being able to being able to visually check values against a PDF.

Diffstat:
Minternal/scte35/README.md | 1+
Minternal/scte35/audio_descriptor.go | 20--------------------
Minternal/scte35/avail_descriptor.go | 10----------
Minternal/scte35/bandwidth_reservation.go | 7+------
Minternal/scte35/dtmf_descriptor.go | 12------------
Minternal/scte35/private_command.go | 8--------
Minternal/scte35/private_descriptor.go | 10----------
Minternal/scte35/segmentation_descriptor.go | 62--------------------------------------------------------------
Minternal/scte35/splice_command.go | 1-
Minternal/scte35/splice_descriptor.go | 1-
Minternal/scte35/splice_info_section.go | 32--------------------------------
Minternal/scte35/splice_insert.go | 42------------------------------------------
Minternal/scte35/splice_null.go | 5-----
Minternal/scte35/splice_schedule.go | 39+--------------------------------------
Dinternal/scte35/table.go | 91-------------------------------------------------------------------------------
Minternal/scte35/time_descriptor.go | 14--------------
Minternal/scte35/time_signal.go | 10----------
17 files changed, 3 insertions(+), 362 deletions(-)

diff --git a/internal/scte35/README.md b/internal/scte35/README.md @@ -6,6 +6,7 @@ Notable differences from the original works are: - third party dependencies removed - refactored test code +- supports only binary/base64 encoding, decoding ## License diff --git a/internal/scte35/audio_descriptor.go b/internal/scte35/audio_descriptor.go @@ -18,7 +18,6 @@ package scte35 import ( "fmt" - "strconv" "github.com/bamiaux/iobit" ) @@ -95,25 +94,6 @@ func (sd *AudioDescriptor) length() int { return length / 8 } -// writeTo the given table. -func (sd *AudioDescriptor) writeTo(t *table) { - t.row(0, "audio_descriptor() {", nil) - t.row(1, "splice_descriptor_tag", fmt.Sprintf("%#02x", sd.Tag())) - t.row(1, "descriptor_length", sd.length()) - t.row(1, "identifier", fmt.Sprintf("%#08x, (%s)", CUEIdentifier, CUEIASCII)) - t.row(1, "audio_count", len(sd.AudioChannels)) - for i, ac := range sd.AudioChannels { - t.row(1, "audio_channel["+strconv.Itoa(i)+"] {", nil) - t.row(2, "component_tag", ac.ComponentTag) - t.row(2, "iso_code", ac.ISOCode) - t.row(2, "bit_stream_mode", ac.BitStreamMode) - t.row(2, "num_channels", ac.NumChannels) - t.row(2, "full_srvc_audio", ac.FullSrvcAudio) - t.row(1, "}", nil) - } - t.row(0, "}", nil) -} - // AudioChannel collects the audio PID details. type AudioChannel struct { ComponentTag uint32 diff --git a/internal/scte35/avail_descriptor.go b/internal/scte35/avail_descriptor.go @@ -39,16 +39,6 @@ type AvailDescriptor struct { // Tag returns the splice_descriptor_tag. func (sd *AvailDescriptor) Tag() uint32 { return AvailDescriptorTag } -// writeTo the given table. -func (sd *AvailDescriptor) writeTo(t *table) { - t.row(0, "avail_descriptor() {", nil) - t.row(1, "splice_descriptor_tag", fmt.Sprintf("%#02x", AvailDescriptorTag)) - t.row(1, "descriptor_length", sd.length()) - t.row(1, "identifier", fmt.Sprintf("%#08x, (%s)", CUEIdentifier, CUEIASCII)) - t.row(1, "provider_avail_id", sd.ProviderAvailID) - t.row(0, "}", nil) -} - // decode updates this splice_descriptor from binary. func (sd *AvailDescriptor) decode(b []byte) error { r := iobit.NewReader(b) diff --git a/internal/scte35/bandwidth_reservation.go b/internal/scte35/bandwidth_reservation.go @@ -32,7 +32,7 @@ const BandwidthReservationType = 0x07 // expected that it will be carried through the entire transmission chain and it // should be a private descriptor that is utilized only by the bandwidth // reservation process. -type BandwidthReservation struct {} +type BandwidthReservation struct{} // Type returns the splice_command_type. func (cmd *BandwidthReservation) Type() uint32 { return BandwidthReservationType } @@ -50,8 +50,3 @@ func (cmd *BandwidthReservation) encode() ([]byte, error) { return nil, nil } // commandLength returns the splice_command_length func (cmd *BandwidthReservation) length() int { return 0 } - -// writeTo the given table. -func (cmd *BandwidthReservation) writeTo(t *table) { - t.row(0, "bandwidth_reservation() {}", nil) -} diff --git a/internal/scte35/dtmf_descriptor.go b/internal/scte35/dtmf_descriptor.go @@ -34,18 +34,6 @@ type DTMFDescriptor struct { DTMFChars string } -// writeTo the given table. -func (sd *DTMFDescriptor) writeTo(t *table) { - t.row(0, "dtmf_descriptor() {", nil) - t.row(1, "splice_descriptor_tag", fmt.Sprintf("%#02x", DTMFDescriptorTag)) - t.row(1, "descriptor_length", sd.length()) - t.row(1, "identifier", fmt.Sprintf("%#08x (%s)", CUEIdentifier, CUEIASCII)) - t.row(1, "preroll", float32(sd.Preroll/10)) - t.row(1, "dtmf_count", len(sd.DTMFChars)) - t.row(1, "dtmf_chars", sd.DTMFChars) - t.row(0, "}", nil) -} - // Tag returns the splice_descriptor_tag. func (sd *DTMFDescriptor) Tag() uint32 { return DTMFDescriptorTag } diff --git a/internal/scte35/private_command.go b/internal/scte35/private_command.go @@ -80,11 +80,3 @@ func (cmd *PrivateCommand) length() int { length += len(cmd.PrivateBytes) * 8 // private_bytes return length / 8 } - -// writeTo the given table. -func (cmd *PrivateCommand) writeTo(t *table) { - t.row(0, "private_command() {", nil) - t.row(1, "identifier", fmt.Sprintf("%#08x, (%s)", cmd.Identifier, cmd.IdentifierString())) - t.row(1, "private_byte", fmt.Sprintf("%#0x", cmd.PrivateBytes)) - t.row(0, "}", nil) -} diff --git a/internal/scte35/private_descriptor.go b/internal/scte35/private_descriptor.go @@ -80,13 +80,3 @@ func (sd *PrivateDescriptor) length() int { length += len(sd.PrivateBytes) * 8 // private_bytes return length / 8 } - -// table returns the tabular description of this PrivateDescriptor. -func (sd *PrivateDescriptor) writeTo(t *table) { - t.row(0, "private_descriptor() {", nil) - t.row(1, "splice_descriptor_tag", fmt.Sprintf("%#02x", sd.Tag())) - t.row(1, "descriptor_length", sd.length()) - t.row(1, "identifier", fmt.Sprintf("%#08x, (%s)", sd.Identifier, sd.IdentifierString())) - t.row(1, "private_bytes", fmt.Sprintf("%#0x", sd.PrivateBytes)) - t.row(0, "}", nil) -} diff --git a/internal/scte35/segmentation_descriptor.go b/internal/scte35/segmentation_descriptor.go @@ -18,7 +18,6 @@ package scte35 import ( "fmt" - "strconv" "github.com/bamiaux/iobit" ) @@ -535,67 +534,6 @@ func (sd *SegmentationDescriptor) length() int { return length / 8 } -// table returns the tabular description of this SegmentationDescriptor. -func (sd *SegmentationDescriptor) writeTo(t *table) { - t.row(0, "segmentation_descriptor() {", nil) - t.row(1, "splice_descriptor_tag", fmt.Sprintf("%#02x", sd.Tag())) - t.row(1, "descriptor_length", sd.length()) - t.row(1, "identifier", fmt.Sprintf("%#08x (%s)", CUEIdentifier, CUEIASCII)) - t.row(1, "segmentation_event_id", sd.SegmentationEventID) - t.row(1, "segmentation_event_cancel_indicator", sd.SegmentationEventCancelIndicator) - if !sd.SegmentationEventCancelIndicator { - t.row(1, "program_segmentation_flag", sd.ProgramSegmentationFlag()) - t.row(1, "segmentation_duration_flag", sd.SegmentationDurationFlag()) - t.row(1, "delivery_not_restricted_flag", sd.DeliveryNotRestrictedFlag()) - if sd.DeliveryRestrictions != nil { - t.row(1, "web_delivery_allowed_flag", sd.DeliveryRestrictions.WebDeliveryAllowedFlag) - t.row(1, "no_regional_blackout_flag", sd.DeliveryRestrictions.NoRegionalBlackoutFlag) - t.row(1, "archive_allowed_flag", sd.DeliveryRestrictions.ArchiveAllowedFlag) - t.row(1, "device_restrictions", fmt.Sprintf("%d (%s)", sd.DeliveryRestrictions.DeviceRestrictions, sd.DeliveryRestrictions.deviceRestrictionsName())) - } - if len(sd.Components) > 0 { - t.row(1, "component_count", len(sd.Components)) - for i, c := range sd.Components { - t.row(1, "component["+strconv.Itoa(i)+"] {", nil) - t.row(2, "component_tag", c.Tag) - t.row(2, "pts_offset", c.PTSOffset) - t.row(1, "}", nil) - } - } - if sd.SegmentationDurationFlag() { - t.row(1, "segmentation_duration", sd.SegmentationDuration) - } - - t.row(1, "segmentation_upid_length", sd.SegmentationUpidLength()) - for i, u := range sd.SegmentationUPIDs { - t.row(1, "segmentation_upid["+strconv.Itoa(i)+"] {", nil) - t.row(2, "segmentation_upid_type", fmt.Sprintf("%#02x (%s)", u.Type, u.Name())) - if u.Type == SegmentationUPIDTypeMPU { - t.row(2, "format_identifier", u.formatIdentifierString()) - } - t.row(2, "segmentation_upid", u.Value) - t.row(1, "}", nil) - } - } - - t.row(1, "segmentation_type_id", fmt.Sprintf("%#02x (%s)", sd.SegmentationTypeID, sd.Name())) - t.row(1, "segment_num", sd.SegmentNum) - t.row(1, "segments_expected", sd.SegmentsExpected) - switch sd.SegmentationTypeID { - case SegmentationTypeProviderPOStart, - SegmentationTypeDistributorPOStart, - SegmentationTypeProviderOverlayPOStart, - SegmentationTypeDistributorOverlayPOStart: - if sd.SubSegmentNum != nil { - t.row(1, "sub_segment_num", sd.SubSegmentNum) - } - if sd.SubSegmentsExpected != nil { - t.row(1, "sub_segments_expected", sd.SubSegmentsExpected) - } - } - t.row(0, "}", nil) -} - // SegmentationDescriptorComponent describes the Component element contained // within the SegmentationDescriptorType XML schema definition. type SegmentationDescriptorComponent struct { diff --git a/internal/scte35/splice_command.go b/internal/scte35/splice_command.go @@ -40,7 +40,6 @@ type SpliceCommand interface { decode(b []byte) error encode() ([]byte, error) length() int - writeTo(t *table) } // decodeSpliceCommand decodes the supplied byte array into the desired diff --git a/internal/scte35/splice_descriptor.go b/internal/scte35/splice_descriptor.go @@ -64,7 +64,6 @@ type SpliceDescriptor interface { decode(b []byte) error encode() ([]byte, error) length() int // named to differentiate from splice_command - writeTo(t *table) } // SpliceDescriptors is a slice of SpliceDescriptor. diff --git a/internal/scte35/splice_info_section.go b/internal/scte35/splice_info_section.go @@ -249,38 +249,6 @@ func (sis *SpliceInfoSection) SAPTypeName() string { } } -// Table returns the tabular description of this SpliceInfoSection as described -// in ANSI/SCTE 35 Table 5. -func (sis *SpliceInfoSection) Table(prefix, indent string) string { - // top level table is not indented - t := newTable(prefix, indent) - - t.row(0, "splice_info_section() {", nil) - t.row(1, "table_id", fmt.Sprintf("%#02x", TableID)) - t.row(1, "section_syntax_indicator", SectionSyntaxIndicator) - t.row(1, "private_indicator", PrivateIndicator) - t.row(1, "sap_type", fmt.Sprintf("%d (%s)", sis.SAPType, sis.SAPTypeName())) - t.row(1, "section_length", sis.sectionLength()) - t.row(0, "}", nil) - t.row(0, "protocol_version", sis.ProtocolVersion) - t.row(0, "encryption_algorithm", fmt.Sprintf("%d (%s)", sis.EncryptedPacket.EncryptionAlgorithm, cipher(sis.EncryptedPacket.EncryptionAlgorithm))) - t.row(0, "pts_adjustment", sis.PTSAdjustment) - t.row(0, "cw_index", sis.EncryptedPacket.CWIndex) - t.row(0, "tier", sis.Tier) - - if sis.SpliceCommand != nil { - t.row(0, "splice_command_length", sis.SpliceCommand.length()) - t.row(0, "splice_command_type", fmt.Sprintf("%#02x", sis.SpliceCommand.Type())) - sis.SpliceCommand.writeTo(t) - } - - t.row(0, "descriptor_loop_length", sis.descriptorLoopLength()) - for _, sd := range sis.SpliceDescriptors { - sd.writeTo(t) - } - return t.String() -} - // length returns the expected length of the encoded splice_info_section, in // bytes. func (sis *SpliceInfoSection) length() int { diff --git a/internal/scte35/splice_insert.go b/internal/scte35/splice_insert.go @@ -18,7 +18,6 @@ package scte35 import ( "fmt" - "strconv" "github.com/bamiaux/iobit" ) @@ -59,47 +58,6 @@ func (cmd *SpliceInsert) TimeSpecifiedFlag() bool { // Type returns the splice_command_type. func (cmd *SpliceInsert) Type() uint32 { return SpliceInsertType } -// writeTo the given table. -func (cmd *SpliceInsert) writeTo(t *table) { - t.row(0, "splice_insert() {", nil) - t.row(1, "splice_event_id", cmd.SpliceEventID) - t.row(1, "splice_event_cancel_indicator", cmd.SpliceEventCancelIndicator) - if !cmd.SpliceEventCancelIndicator { - t.row(1, "out_of_network_indicator", cmd.OutOfNetworkIndicator) - t.row(1, "program_splice_flag", cmd.ProgramSpliceFlag()) - t.row(1, "duration_flag", cmd.DurationFlag()) - t.row(1, "splice_immediate_flag", cmd.SpliceImmediateFlag) - if cmd.ProgramSpliceFlag() && !cmd.SpliceImmediateFlag { - t.row(1, "time_specified_flag", cmd.TimeSpecifiedFlag()) - if cmd.TimeSpecifiedFlag() { - t.row(1, "pts_time", cmd.Program.SpliceTime.PTSTime) - } - } - if !cmd.ProgramSpliceFlag() { - t.row(1, "component_count", len(cmd.Components)) - for i, c := range cmd.Components { - t.row(1, "component["+strconv.Itoa(i)+"]", nil) - t.row(2, "component_tag", c.Tag) - if !cmd.SpliceImmediateFlag { - t.row(2, "time_specified_flag", c.TimeSpecifiedFlag()) - if c.TimeSpecifiedFlag() { - t.row(2, "pts_time", c.SpliceTime.PTSTime) - } - } - t.row(1, "}", nil) - } - } - if cmd.DurationFlag() { - t.row(1, "auto_return", cmd.BreakDuration.AutoReturn) - t.row(1, "duration", cmd.BreakDuration.Duration) - } - t.row(1, "unique_program_id", cmd.UniqueProgramID) - t.row(1, "avail_num", cmd.AvailNum) - t.row(1, "avails_expected", cmd.AvailsExpected) - } - t.row(0, "}", nil) -} - // decode a binary splice_insert. func (cmd *SpliceInsert) decode(b []byte) error { r := iobit.NewReader(b) diff --git a/internal/scte35/splice_null.go b/internal/scte35/splice_null.go @@ -43,8 +43,3 @@ func (cmd *SpliceNull) encode() ([]byte, error) { return []byte{}, nil } // commandLength returns the splice_command_length. func (cmd *SpliceNull) length() int { return 0 } - -// writeTo the given table. -func (cmd *SpliceNull) writeTo(t *table) { - t.row(0, "splice_null() {}", nil) -} diff --git a/internal/scte35/splice_schedule.go b/internal/scte35/splice_schedule.go @@ -18,7 +18,6 @@ package scte35 import ( "fmt" - "strconv" "github.com/bamiaux/iobit" ) @@ -30,7 +29,7 @@ const SpliceScheduleType = 0x04 // SpliceSchedule is provided to allow a schedule of splice events to be // conveyed in advance. type SpliceSchedule struct { - Events []Event + Events []Event } // Type returns the splice_command_type @@ -166,42 +165,6 @@ func (cmd SpliceSchedule) length() int { return length / 8 } -// writeTo the given table. -func (cmd *SpliceSchedule) writeTo(t *table) { - t.row(0, "splice_schedule() {", nil) - t.row(1, "splice_count", strconv.Itoa(len(cmd.Events))) - for i, e := range cmd.Events { - t.row(1, "event["+strconv.Itoa(i)+"]", nil) - t.row(2, "splice_event_id", e.SpliceEventID) - t.row(2, "splice_event_cancel_indicator", e.SpliceEventCancelIndicator) - if !e.SpliceEventCancelIndicator { - t.row(2, "out_of_network_indicator", e.OutOfNetworkIndicator) - t.row(2, "program_splice_flag", e.ProgramSpliceFlag()) - t.row(2, "duration_flag", e.DurationFlag()) - if e.ProgramSpliceFlag() { - t.row(2, "utc_splice_time", e.Program.UTCSpliceTime) - } else { - t.row(2, "component_count", len(e.Components)) - for j, c := range e.Components { - t.row(2, "component["+strconv.Itoa(j)+"]", nil) - t.row(3, "component_tag", c.Tag) - t.row(3, "utc_splice_time", c.UTCSpliceTime) - t.row(2, "}", nil) - } - } - if e.DurationFlag() { - t.row(1, "auto_return", e.BreakDuration.AutoReturn) - t.row(1, "duration", e.BreakDuration.Duration) - } - t.row(1, "unique_program_id", e.UniqueProgramID) - t.row(1, "avail_num", e.AvailNum) - t.row(1, "avails_expected", e.AvailsExpected) - } - t.row(1, "}", nil) - } - t.row(0, "}", nil) -} - // Event is a single event within a splice_schedule. type Event struct { Program *EventProgram diff --git a/internal/scte35/table.go b/internal/scte35/table.go @@ -1,91 +0,0 @@ -package scte35 - -import ( - "fmt" - "strconv" - "strings" - "time" -) - -// newTable creates a new table with the given parameters. -func newTable(prefix, indent string) *table { - return &table{ - prefix: prefix, - indent: indent, - b: &strings.Builder{}, - } -} - -// table simplifies construction of splice_info_section tables. -type table struct { - prefix string - indent string - b *strings.Builder -} - -// row0 writes a new row with 0 indents. -func (t *table) row(indents int, key string, value any) { - _, _ = t.b.WriteString(t.prefix) - for i := 0; i < indents; i++ { - _, _ = t.b.WriteString(t.indent) - } - _, _ = t.b.WriteString(key) - if value != nil { - _, _ = t.b.WriteString(": ") - _, _ = t.b.WriteString(valueString(value)) - } - _, _ = t.b.WriteRune('\n') -} - -// String returns the table string. -func (t *table) String() string { - return t.b.String() -} - -// valueString converts the given value to a string -func valueString(value any) string { - switch vt := value.(type) { - case string: - return vt - case int: - return strconv.FormatInt(int64(vt), 10) - case int8: - return strconv.FormatInt(int64(vt), 10) - case int16: - return strconv.FormatInt(int64(vt), 10) - case int32: - return strconv.FormatInt(int64(vt), 10) - case int64: - return strconv.FormatInt(vt, 10) - case uint: - return strconv.FormatUint(uint64(vt), 10) - case uintptr: - return strconv.FormatUint(uint64(vt), 10) - case uint8: - return strconv.FormatUint(uint64(vt), 10) - case uint16: - return strconv.FormatUint(uint64(vt), 10) - case uint32: - return strconv.FormatUint(uint64(vt), 10) - case uint64: - return strconv.FormatUint(vt, 10) - case *uint64: - if vt == nil { - return "" - } - return strconv.FormatUint(*vt, 10) - case bool: - if vt { - return "true" - } - return "false" - case time.Time: - return vt.Format(time.RFC3339) - case float32: - return fmt.Sprintf("%.2f", vt) - case []byte: - return fmt.Sprintf("%#02x", vt) - default: - return fmt.Sprintf("%s", vt) - } -} diff --git a/internal/scte35/time_descriptor.go b/internal/scte35/time_descriptor.go @@ -17,8 +17,6 @@ package scte35 import ( - "fmt" - "github.com/bamiaux/iobit" ) @@ -40,18 +38,6 @@ type TimeDescriptor struct { // Tag returns the splice_descriptor_tag. func (sd *TimeDescriptor) Tag() uint32 { return TimeDescriptorTag } -// table returns the tabular description of this TimeDescriptor. -func (sd *TimeDescriptor) writeTo(t *table) { - t.row(0, "time_descriptor() {", nil) - t.row(1, "splice_descriptor_tag", fmt.Sprintf("%#02x", TimeDescriptorTag)) - t.row(1, "descriptor_length", sd.length()) - t.row(1, "identifier", fmt.Sprintf("%#08x, (%s)", CUEIdentifier, CUEIASCII)) - t.row(1, "tai_seconds", sd.TAISeconds) - t.row(1, "tai_ns", sd.TAINS) - t.row(1, "utc_offset", sd.UTCOffset) - t.row(0, "}", nil) -} - // decode updates this splice_descriptor from binary. func (sd *TimeDescriptor) decode(b []byte) error { r := iobit.NewReader(b) diff --git a/internal/scte35/time_signal.go b/internal/scte35/time_signal.go @@ -96,16 +96,6 @@ func (cmd *TimeSignal) length() int { return length / 8 } -// writeTo the given table. -func (cmd *TimeSignal) writeTo(t *table) { - t.row(0, "time_signal() {", nil) - t.row(1, "time_specified_flag", cmd.timeSpecifiedFlag()) - if cmd.timeSpecifiedFlag() { - t.row(1, "pts_time", cmd.SpliceTime.PTSTime) - } - t.row(0, "}", nil) -} - // timeSpecifiedFlag return the time_specified_flag. func (cmd *TimeSignal) timeSpecifiedFlag() bool { return cmd != nil && cmd.SpliceTime.PTSTime != nil