diff --git a/ebp/baseebp.go b/ebp/baseebp.go index 8af5d08..5467c28 100644 --- a/ebp/baseebp.go +++ b/ebp/baseebp.go @@ -146,10 +146,10 @@ func (ebp *baseEbp) SetIsEmpty(value bool) { // but Stream Sync and SCTE-35 were the only two ever to get implemented. MK was the only Transcoder to implement SCTE-35 within the // Grouping ID section and we never leveraged that data on any downstream devices. func (ebp *baseEbp) StreamSyncSignal() uint8 { - // The first byte is Grouping ID, the second byte is the sync signal - if len(ebp.Grouping) == 2 && ebp.Grouping[0] == 0x80 { - return ebp.Grouping[1] + for _, groupID := range ebp.Grouping { + if groupID == StreamSynchronized || groupID == StreamNotSynchronized { + return groupID + } } - return InvalidStreamSyncSignal } diff --git a/ebp/cablelabsebp.go b/ebp/cablelabsebp.go index c5b2f1a..1ed0992 100644 --- a/ebp/cablelabsebp.go +++ b/ebp/cablelabsebp.go @@ -122,12 +122,15 @@ func readCableLabsEbp(data []byte) (ebp *cableLabsEbp, err error) { if ebp.GroupingFlag() { var group byte - group = data[index] + var groupExtFlag bool + groupExtFlag = data[index]&0x80 != 0 + group = data[index] & 0x7F ebp.Grouping = append(ebp.Grouping, group) index += uint8(1) - for group&0x80 != 0 { - group = data[index] + for groupExtFlag { + groupExtFlag = data[index]&0x80 != 0 + group = data[index] & 0x7F ebp.Grouping = append(ebp.Grouping, group) index += uint8(1) } @@ -182,11 +185,15 @@ func (ebp *cableLabsEbp) Data() []byte { if ebp.GroupingFlag() { for i := range ebp.Grouping { - ebp.Grouping[i] |= 0x80 // set flag because this is not the last ID - if i == len(ebp.Grouping)-1 { - ebp.Grouping[i] &= 0x7F // last index does not have this flag set + var group byte + if i < len(ebp.Grouping)-1 { + // add the ext flag for all but the last group + group = ebp.Grouping[i] | 0x80 + } else { + // last group - no ext flag + group = ebp.Grouping[i] } - binary.Write(data, ebpEncoding, ebp.Grouping[i]) + binary.Write(data, ebpEncoding, group) } } diff --git a/ebp/cablelabsebp_test.go b/ebp/cablelabsebp_test.go index 7b317b0..b652d52 100644 --- a/ebp/cablelabsebp_test.go +++ b/ebp/cablelabsebp_test.go @@ -1,7 +1,7 @@ /* MIT License -Copyright 2016 Comcast Cable Communications Management, LLC +# Copyright 2016 Comcast Cable Communications Management, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -110,3 +110,49 @@ func TestCableLabsEBP(t *testing.T) { ) } } + +func TestParseCableLabsEBPWithMultipleGroups(t *testing.T) { + var ebpBytes = []byte{0xdf, 0x11, 0x45, 0x42, 0x50, 0x30, 0x98, 0x80, 0xa3, 0xfe, 0x1d, 0xe6, 0xa1, 0x45, 0x18, 0xb8, 0x51, 0x00, 0x00} + ebp, err := readCableLabsEbp(ebpBytes) + if err != nil { + t.Logf("failed to parse CableLabs-style EBP: #{err}") + t.FailNow() + } + if ebp.StreamSyncSignal() != StreamSynchronized { + t.Errorf("Wrong stream sync signal (expected 0x1D, got #{ebp.StreamSyncSignal()})") + } + var expectedGroups = []uint8{0x00, 0x23, 0x7E, 0x1D} + if len(ebp.Grouping) != len(expectedGroups) { + t.Logf("Wrong number of group IDs (expected #{len(expectedGroups)}, got #{len(ebp.Grouping)}") + t.FailNow() + } + for i, gid := range expectedGroups { + other := ebp.Grouping[i] + if gid != other { + t.Errorf("Wrong group ID (expected #{gid}, got #{other})") + } + } +} + +func TestParseCableLabsEBPWithSyncInMiddle(t *testing.T) { + var ebpBytes = []byte{0xdf, 0x12, 0x45, 0x42, 0x50, 0x30, 0x98, 0x80, 0xa3, 0xfe, 0x9d, 0x05, 0xe6, 0xa1, 0x45, 0x18, 0xb8, 0x51, 0x00, 0x00} + ebp, err := readCableLabsEbp(ebpBytes) + if err != nil { + t.Logf("failed to parse CableLabs-style EBP: #{err}") + t.FailNow() + } + if ebp.StreamSyncSignal() != StreamSynchronized { + t.Errorf("Wrong stream sync signal (expected 0x1D, got #{ebp.StreamSyncSignal()})") + } + var expectedGroups = []uint8{0x00, 0x23, 0x7E, 0x1D, 0x05} + if len(ebp.Grouping) != len(expectedGroups) { + t.Logf("Wrong number of group IDs (expected #{len(expectedGroups)}, got #{len(ebp.Grouping)}") + t.FailNow() + } + for i, gid := range expectedGroups { + other := ebp.Grouping[i] + if gid != other { + t.Errorf("Wrong group ID (expected #{gid}, got #{other})") + } + } +} diff --git a/v2/ebp/baseebp.go b/v2/ebp/baseebp.go index 8af5d08..5467c28 100644 --- a/v2/ebp/baseebp.go +++ b/v2/ebp/baseebp.go @@ -146,10 +146,10 @@ func (ebp *baseEbp) SetIsEmpty(value bool) { // but Stream Sync and SCTE-35 were the only two ever to get implemented. MK was the only Transcoder to implement SCTE-35 within the // Grouping ID section and we never leveraged that data on any downstream devices. func (ebp *baseEbp) StreamSyncSignal() uint8 { - // The first byte is Grouping ID, the second byte is the sync signal - if len(ebp.Grouping) == 2 && ebp.Grouping[0] == 0x80 { - return ebp.Grouping[1] + for _, groupID := range ebp.Grouping { + if groupID == StreamSynchronized || groupID == StreamNotSynchronized { + return groupID + } } - return InvalidStreamSyncSignal } diff --git a/v2/ebp/cablelabsebp.go b/v2/ebp/cablelabsebp.go index f25870b..a2a043e 100644 --- a/v2/ebp/cablelabsebp.go +++ b/v2/ebp/cablelabsebp.go @@ -122,12 +122,15 @@ func readCableLabsEbp(data []byte) (ebp *cableLabsEbp, err error) { if ebp.GroupingFlag() { var group byte - group = data[index] + var groupExtFlag bool + groupExtFlag = data[index]&0x80 != 0 + group = data[index] & 0x7F ebp.Grouping = append(ebp.Grouping, group) index += uint8(1) - for group&0x80 != 0 { - group = data[index] + for groupExtFlag { + groupExtFlag = data[index]&0x80 != 0 + group = data[index] & 0x7F ebp.Grouping = append(ebp.Grouping, group) index += uint8(1) } @@ -182,11 +185,15 @@ func (ebp *cableLabsEbp) Data() []byte { if ebp.GroupingFlag() { for i := range ebp.Grouping { - ebp.Grouping[i] |= 0x80 // set flag because this is not the last ID - if i == len(ebp.Grouping)-1 { - ebp.Grouping[i] &= 0x7F // last index does not have this flag set + var group byte + if i < len(ebp.Grouping)-1 { + // add the ext flag for all but the last group + group = ebp.Grouping[i] | 0x80 + } else { + // last group - no ext flag + group = ebp.Grouping[i] } - binary.Write(data, ebpEncoding, ebp.Grouping[i]) + binary.Write(data, ebpEncoding, group) } } diff --git a/v2/ebp/cablelabsebp_test.go b/v2/ebp/cablelabsebp_test.go index 7b317b0..b652d52 100644 --- a/v2/ebp/cablelabsebp_test.go +++ b/v2/ebp/cablelabsebp_test.go @@ -1,7 +1,7 @@ /* MIT License -Copyright 2016 Comcast Cable Communications Management, LLC +# Copyright 2016 Comcast Cable Communications Management, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -110,3 +110,49 @@ func TestCableLabsEBP(t *testing.T) { ) } } + +func TestParseCableLabsEBPWithMultipleGroups(t *testing.T) { + var ebpBytes = []byte{0xdf, 0x11, 0x45, 0x42, 0x50, 0x30, 0x98, 0x80, 0xa3, 0xfe, 0x1d, 0xe6, 0xa1, 0x45, 0x18, 0xb8, 0x51, 0x00, 0x00} + ebp, err := readCableLabsEbp(ebpBytes) + if err != nil { + t.Logf("failed to parse CableLabs-style EBP: #{err}") + t.FailNow() + } + if ebp.StreamSyncSignal() != StreamSynchronized { + t.Errorf("Wrong stream sync signal (expected 0x1D, got #{ebp.StreamSyncSignal()})") + } + var expectedGroups = []uint8{0x00, 0x23, 0x7E, 0x1D} + if len(ebp.Grouping) != len(expectedGroups) { + t.Logf("Wrong number of group IDs (expected #{len(expectedGroups)}, got #{len(ebp.Grouping)}") + t.FailNow() + } + for i, gid := range expectedGroups { + other := ebp.Grouping[i] + if gid != other { + t.Errorf("Wrong group ID (expected #{gid}, got #{other})") + } + } +} + +func TestParseCableLabsEBPWithSyncInMiddle(t *testing.T) { + var ebpBytes = []byte{0xdf, 0x12, 0x45, 0x42, 0x50, 0x30, 0x98, 0x80, 0xa3, 0xfe, 0x9d, 0x05, 0xe6, 0xa1, 0x45, 0x18, 0xb8, 0x51, 0x00, 0x00} + ebp, err := readCableLabsEbp(ebpBytes) + if err != nil { + t.Logf("failed to parse CableLabs-style EBP: #{err}") + t.FailNow() + } + if ebp.StreamSyncSignal() != StreamSynchronized { + t.Errorf("Wrong stream sync signal (expected 0x1D, got #{ebp.StreamSyncSignal()})") + } + var expectedGroups = []uint8{0x00, 0x23, 0x7E, 0x1D, 0x05} + if len(ebp.Grouping) != len(expectedGroups) { + t.Logf("Wrong number of group IDs (expected #{len(expectedGroups)}, got #{len(ebp.Grouping)}") + t.FailNow() + } + for i, gid := range expectedGroups { + other := ebp.Grouping[i] + if gid != other { + t.Errorf("Wrong group ID (expected #{gid}, got #{other})") + } + } +}