Skip to content

Instantly share code, notes, and snippets.

@sbowman
Created March 12, 2014 17:52
Show Gist options
  • Save sbowman/9512354 to your computer and use it in GitHub Desktop.
Save sbowman/9512354 to your computer and use it in GitHub Desktop.
SCTE35 Parsing with iobit
package main
import (
"encoding/base64"
"fmt"
"github.com/bamiaux/iobit"
)
type SpliceInfoSection struct {
TableID uint32
SectionSyntaxIndicator bool
PrivateIndicator bool
SectionLength uint32
ProtocolVersion uint32
EncryptedPacket bool
EncryptionAlgorithm uint32
PTSAdjustment uint64
CWIndex uint32
Tier uint32
SpliceCommandLength uint32
SpliceCommandType uint32
DescriptorLoopLength uint32
AlignmentStuffing []int
EncryptedCRC uint32
CRC32 uint32
// SpliceCommand interface{}
// SpliceDescriptors []*SpliceDescriptor
}
// Create an iobit reader to parse the Base64 SCTE35 string.
func NewReader(base64str string) (*iobit.Reader, error) {
decoded, err := base64.StdEncoding.DecodeString(base64str)
if err != nil {
return nil, err
}
return iobit.NewReader(decoded), nil
}
func ParseSpliceInfoSection(base64str string) (*SpliceInfoSection, error) {
r, err := NewReader(base64str)
if err != nil {
return nil, err
}
sis := new(SpliceInfoSection)
sis.TableID = r.Uint32Le(8)
sis.SectionSyntaxIndicator = r.IsBit()
sis.PrivateIndicator = r.IsBit()
// Reserved
r.Skip(2)
sis.SectionLength = r.Uint32(12)
sis.ProtocolVersion = r.Uint32(8)
sis.EncryptedPacket = r.IsBit()
sis.EncryptionAlgorithm = r.Uint32(6)
sis.PTSAdjustment = r.Uint64(33)
sis.CWIndex = r.Uint32(8)
sis.Tier = r.Uint32Le(12)
sis.SpliceCommandLength = r.Uint32(12)
sis.SpliceCommandType = r.Uint32(8)
sis.DescriptorLoopLength = r.Uint32(16)
spliceDescriptor := make([]byte, sis.DescriptorLoopLength)
for i, _ := range spliceDescriptor {
spliceDescriptor[i] = byte(r.Uint32Le(8))
}
// TODO: Pass the spliceDescriptor along to be read into
// SegmentationDescriptor, etc.
if sis.EncryptedPacket {
if r.Bits() > 64 {
r.Skip(64 - r.Bits())
}
sis.EncryptedCRC = r.Uint32Le(32)
} else if r.Bits() > 32 {
r.Skip(32 - r.Bits())
}
sis.CRC32 = r.Uint32Le(32)
return sis, nil
}
// Convert the Base64 string into it's binary representation manually.
func showBinary(base64str string) {
decoded, err := base64.StdEncoding.DecodeString(base64str)
if err != nil {
fmt.Println(err)
return
}
bin := ""
for i := 0; i < len(decoded); i += 16 {
for offset := 0; offset < 16 && offset+i < len(decoded); offset++ {
bin += fmt.Sprintf("%b", decoded[i+offset])
}
}
fmt.Println(bin)
}
// Cycle through the bits in the Base64 string using the iobit library.
func showBits(base64str string) {
r, err := NewReader(base64str)
if err != nil {
fmt.Println(err)
return
}
for r.Bits() != 0 {
if r.IsBit() {
fmt.Print("1")
} else {
fmt.Print("0")
}
}
fmt.Println()
}
func main() {
// Test string
base64str := "/ABVAAAAAAAAAAAABQaAZPXfAAA/Aj1DVUVJQUJDRH/fAAD3MUAJKUJMQUNLT1VUOlRXdEhLMDFNU0VKRlpVdFpNM2RMV0RCaE5rbFJkejA5NAAAZ6usxA=="
fmt.Println("Manually parsing:")
showBinary(base64str)
fmt.Println()
fmt.Println("Using iobit:")
showBits(base64str)
}
@sbowman
Copy link
Author

sbowman commented Mar 18, 2014

That showBinary function is a trimmed down version of my production one, hence the weird loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment