commit 4c6c6fb4e1c15a64c498ef85c044882c2e86bbfe
parent fdfd601c2abd8099cd091daa80763ba6926aa8be
Author: Oliver Lowe <o@olowe.co>
Date: Sat, 11 May 2024 19:21:56 +1000
internal/scte35: implement SpliceInsert decode
Diffstat:
2 files changed, 68 insertions(+), 16 deletions(-)
diff --git a/internal/scte35/splice_info.go b/internal/scte35/splice_info.go
@@ -222,8 +222,60 @@ func decodeCommand(buf []byte) (*Command, error) {
t := binary.BigEndian.Uint64(b)
cmd.TimeSignal = &t
}
+ case SpliceInsert:
+ var ins Insert
+ ins.ID = binary.BigEndian.Uint32(buf[1:5])
+ if buf[5]&0x80 > 0 {
+ ins.Cancel = true
+ cmd.Insert = &ins
+ // rebelelder told us to do this.
+ return &cmd, nil
+ }
+ if buf[6]&(1<<7) > 0 {
+ ins.OutOfNetwork = true
+ }
+
+ // assume program_splice is set at bit 6;
+
+ var durflag bool
+ if buf[6]&(1<<5) > 0 {
+ durflag = true
+ }
+ // we don't support deprecated component mode.
+ if buf[6]&(1<<4) > 0 {
+ ins.Immediate = true
+ }
+ if buf[6]&(1<<3) > 0 {
+ ins.EventIDCompliance = true
+ }
+ // next 3 bits are reserved.
+
+ if !ins.Immediate {
+ // is time_specified_flag set? if so, read the 33-bit time.
+ if buf[7]&(1<<7) > 0 {
+ b := make([]byte, 3)
+ b = append(b, buf[7]&0x01) // skip reserved bits.
+ b = append(b, buf[8:12]...) // read remaining 32 bits.
+ dur := binary.BigEndian.Uint64(b)
+ ins.SpliceTime = newuint64(dur)
+ buf = buf[12:]
+ } else {
+ buf = buf[8:]
+ }
+ }
+
+ if durflag {
+ a := [5]byte{buf[0], buf[1], buf[2], buf[3], buf[4]}
+ ins.Duration = readBreakDuration(a)
+ buf = buf[5:]
+ }
+
+ ins.ProgramID = binary.BigEndian.Uint16([]byte{buf[0], buf[1]})
+ ins.AvailNum = uint8(buf[2])
+ ins.AvailExpected = uint8(buf[3])
+ cmd.Insert = &ins
default:
- return nil, fmt.Errorf("cannot decode command type %s", cmd.Type)
+ return nil, fmt.Errorf("TODO: cannot decode command type %s", cmd.Type)
}
return &cmd, nil
}
diff --git a/internal/scte35/splice_info_test.go b/internal/scte35/splice_info_test.go
@@ -131,24 +131,24 @@ func TestDecodeSpliceInfo(t *testing.T) {
if err != nil {
t.Fatalf("decode splice info: %v", err)
}
- if tt.want.SAPType != info.SAPType {
- t.Errorf("want SAPType %s, got %s", tt.want.SAPType, info.SAPType)
- }
- if tt.want.Tier != info.Tier {
- t.Errorf("want tier %#x, got %#x", tt.want.Tier, info.Tier)
- }
- if *tt.want.Command.TimeSignal != *info.Command.TimeSignal {
- t.Errorf("want timesig %x, got %x", *tt.want.Command.TimeSignal, *info.Command.TimeSignal)
+
+ // test each possible command
+ if tt.want.Command.TimeSignal != nil {
+ if *tt.want.Command.TimeSignal != *info.Command.TimeSignal {
+ t.Errorf("want timesig %x, got %x", *tt.want.Command.TimeSignal, *info.Command.TimeSignal)
+ }
}
- wd := info.Descriptors[0].(SegmentationDescriptor)
- d, ok := info.Descriptors[0].(SegmentationDescriptor)
- if !ok {
- t.Errorf("want %T, got %T", wd, info.Descriptors[0])
- } else {
- if wd.UPID.Type != d.UPID.Type {
- t.Errorf("want upid type %d, got %d", wd.UPID.Type, d.UPID.Type)
+ if tt.want.Command.Insert != nil {
+ want := *tt.want.Command.Insert
+ got := *info.Command.Insert
+ if !reflect.DeepEqual(&want, got) {
+ t.Errorf("info command: want %+v, got %+v", want, got)
+ if *want.SpliceTime != *got.SpliceTime {
+ t.Logf("want splice time %d, got %d", want.SpliceTime, got.SpliceTime)
+ }
}
}
+
if !reflect.DeepEqual(tt.want, *info) {
t.Errorf("decode splice info: want %+v, got %+v", tt.want, info)
t.Log(diffInfo(tt.want, *info))