streaming

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

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:
Minternal/scte35/splice_info.go | 54+++++++++++++++++++++++++++++++++++++++++++++++++++++-
Minternal/scte35/splice_info_test.go | 30+++++++++++++++---------------
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))