Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions pkg/scte35/splice_info_section.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ const (
SAPType3 = uint32(0x2)
// SAPTypeNotSpecified indicates the type of SAP, if any, is not signaled.
SAPTypeNotSpecified = uint32(0x3)

// MaxPTS is the maximum value for a 33-bit PTS value.
MaxPTS = 1<<33 - 1
)

// SpliceInfoSection shall be carried in transport packets whereby only one
Expand Down Expand Up @@ -210,6 +213,40 @@ func (sis *SpliceInfoSection) Durations() []Duration {
return durations
}

// TimeSpecifiedFlag returns true if the SpliceInfoSection contains a splice
// command for a splice event for which the splice time is specified.
func (sis *SpliceInfoSection) TimeSpecifiedFlag() bool {
switch sc := sis.SpliceCommand.(type) {
case *SpliceInsert:
return sc.TimeSpecifiedFlag()
case *TimeSignal:
return sc.SpliceTime.TimeSpecifiedFlag()
default:
return false
}
}

// SpliceTimePTS returns the final PTS time of the splice event, i.e. the
// splice time of the command adjusted by the PTS adjustment. If the splice
// command does not have a splice even for which splice time is specified,
// this method returns 0.
func (sis *SpliceInfoSection) SpliceTimePTS() uint64 {
switch sc := sis.SpliceCommand.(type) {
case *SpliceInsert:
if !sc.TimeSpecifiedFlag() {
return 0
}
return (*sc.Program.SpliceTime.PTSTime + sis.PTSAdjustment) & MaxPTS
case *TimeSignal:
if !sc.SpliceTime.TimeSpecifiedFlag() {
return 0
}
return (*sc.SpliceTime.PTSTime + sis.PTSAdjustment) & MaxPTS
default:
return 0
}
}

// Encode returns the binary representation of this SpliceInfoSection as a
// byte array.
func (sis *SpliceInfoSection) Encode() ([]byte, error) {
Expand Down
160 changes: 160 additions & 0 deletions pkg/scte35/splice_info_section_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,163 @@ func TestDurations(t *testing.T) {
})
}
}

func Test_TimeSpecifiedFlag(t *testing.T) {
cases := map[string]struct {
sis scte35.SpliceInfoSection
expected bool
}{
"SpliceInsert": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.SpliceInsert{
Program: &scte35.SpliceInsertProgram{
SpliceTime: scte35.SpliceTime{
PTSTime: ptr(uint64(90000)),
},
},
},
},
expected: true,
},
"SpliceInsertNoProgramSplice": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.SpliceInsert{},
},
expected: false,
},
"SpliceInsertNoSpliceTime": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.SpliceInsert{
Program: &scte35.SpliceInsertProgram{},
},
},
expected: false,
},
"TimeSignal": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.TimeSignal{
SpliceTime: scte35.SpliceTime{PTSTime: ptr(uint64(90000))},
},
},
expected: true,
},
"TimeSignalNoSpliceTime": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.TimeSignal{
SpliceTime: scte35.SpliceTime{},
},
},
expected: false,
},
}

for k, c := range cases {
t.Run(k, func(t *testing.T) {
require.Equal(t, c.expected, c.sis.TimeSpecifiedFlag())
})
}
}

func Test_SpliceTimePTS(t *testing.T) {
cases := map[string]struct {
sis scte35.SpliceInfoSection
expected uint64
}{
"SpliceInsert": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.SpliceInsert{
Program: &scte35.SpliceInsertProgram{
SpliceTime: scte35.SpliceTime{
PTSTime: ptr(uint64(90000)),
},
},
},
},
expected: 90000,
},
"SpliceInsertPtsAdjustment": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.SpliceInsert{
Program: &scte35.SpliceInsertProgram{
SpliceTime: scte35.SpliceTime{
PTSTime: ptr(uint64(90000)),
},
},
},
PTSAdjustment: 90000,
},
expected: 180000,
},
"SpliceInsertPtsAdjustmentWrapping": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.SpliceInsert{
Program: &scte35.SpliceInsertProgram{
SpliceTime: scte35.SpliceTime{
PTSTime: ptr(uint64(8589844592)),
},
},
},
PTSAdjustment: 180000,
},
expected: 90000,
},
"SpliceInsertNoProgramSplice": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.SpliceInsert{},
},
expected: 0,
},
"SpliceInsertNoSpliceTime": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.SpliceInsert{
Program: &scte35.SpliceInsertProgram{},
},
},
expected: 0,
},
"TimeSignal": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.TimeSignal{
SpliceTime: scte35.SpliceTime{PTSTime: ptr(uint64(90000))},
},
},
expected: 90000,
},
"TimeSingalPtsAdjustment": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.TimeSignal{
SpliceTime: scte35.SpliceTime{
PTSTime: ptr(uint64(90000)),
},
},
PTSAdjustment: 90000,
},
expected: 180000,
},
"TimeSignalPtsAdjustmentWrapping": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.TimeSignal{
SpliceTime: scte35.SpliceTime{
PTSTime: ptr(uint64(8589844592)),
},
},
PTSAdjustment: 180000,
},
expected: 90000,
},
"TimeSignalNoSpliceTime": {
sis: scte35.SpliceInfoSection{
SpliceCommand: &scte35.TimeSignal{
SpliceTime: scte35.SpliceTime{},
},
},
expected: 0,
},
}

for k, c := range cases {
t.Run(k, func(t *testing.T) {
require.Equal(t, c.expected, c.sis.SpliceTimePTS())
})
}
}
Loading