github.com/puellanivis/breton@v0.2.16/lib/mpeg/ts/dvb/table.go (about) 1 package dvb 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/pkg/errors" 8 "github.com/puellanivis/breton/lib/mpeg/ts/psi" 9 ) 10 11 // ServiceDescriptorTable defines a Service Descriptor Table from the DVB standard for MPEG-TS. 12 // It is a PSI. 13 type ServiceDescriptorTable struct { 14 Syntax *psi.SectionSyntax 15 16 OriginalNetworkID uint16 17 18 Services []*Service 19 20 crc uint32 21 } 22 23 const ( 24 tableidSDT = 0x42 25 ) 26 27 func init() { 28 psi.Register(tableidSDT, func() psi.PSI { return new(ServiceDescriptorTable) }) 29 } 30 31 // TableID implements mpeg/ts/psi.PSI. 32 func (sdt *ServiceDescriptorTable) TableID() uint8 { 33 return tableidSDT 34 } 35 36 // SectionSyntax returns the embedded SectionSyntax, and implements mpeg/ts/psi.PSI. 37 func (sdt *ServiceDescriptorTable) SectionSyntax() *psi.SectionSyntax { 38 return sdt.Syntax 39 } 40 41 func (sdt *ServiceDescriptorTable) String() string { 42 out := []string{ 43 "DVB:SDT", 44 } 45 46 if sdt.Syntax != nil { 47 out = append(out, fmt.Sprint(sdt.Syntax)) 48 } 49 50 out = append(out, fmt.Sprintf("OrigNetID:%04X", sdt.OriginalNetworkID)) 51 52 for _, s := range sdt.Services { 53 out = append(out, s.String()) 54 } 55 56 return fmt.Sprintf("{%s}", strings.Join(out, " ")) 57 } 58 59 // Unmarshal decodes a byte slice into the ServiceDescriptorTable. 60 func (sdt *ServiceDescriptorTable) Unmarshal(b []byte) error { 61 if b[0] != tableidSDT { 62 return errors.Errorf("table_id mismatch: x%02X != x%02X", b[0], tableidSDT) 63 } 64 65 syn, data, crc, err := psi.CommonUnmarshal(b) 66 if err != nil { 67 return err 68 } 69 70 sdt.Syntax = syn 71 sdt.crc = crc 72 73 sdt.OriginalNetworkID = uint16(data[0])<<8 | uint16(data[1]) 74 75 start := 3 // original_network_id uint16 + reserved_future_use uint8 76 for start < len(data) { 77 s := new(Service) 78 79 l, err := s.unmarshal(data[start:]) 80 if err != nil { 81 return err 82 } 83 84 sdt.Services = append(sdt.Services, s) 85 86 start += l 87 } 88 89 return nil 90 } 91 92 // Marshal encodes a ServiceDescriptorTable into a byte slice. 93 func (sdt *ServiceDescriptorTable) Marshal() ([]byte, error) { 94 data := make([]byte, 3) 95 96 data[0] = byte(sdt.OriginalNetworkID >> 8 & 0xFF) 97 data[1] = byte(sdt.OriginalNetworkID & 0xFF) 98 data[2] = 0xFF // reserved_future_use 99 100 for _, s := range sdt.Services { 101 sb, err := s.marshal() 102 if err != nil { 103 return nil, err 104 } 105 106 data = append(data, sb...) 107 } 108 109 return psi.CommonMarshal(tableidSDT, true, sdt.Syntax, data) 110 }