github.com/puellanivis/breton@v0.2.16/lib/mpeg/ts/dvb/descriptor.go (about)

     1  package dvb
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/pkg/errors"
     7  	desc "github.com/puellanivis/breton/lib/mpeg/ts/descriptor"
     8  )
     9  
    10  // ServiceType is an enum encoding DVB standards indicating service types for MPEG-TS.
    11  type ServiceType uint8
    12  
    13  // SesrviceType enum values.
    14  const (
    15  	ServiceTypeTV ServiceType = iota + 1
    16  	ServiceTypeRadio
    17  	ServiceTypeTeletext
    18  	ServiceTypeHDTV     = 0x11
    19  	ServiceTypeH264SDTV = 0x16
    20  	ServiceTypeH264HDTV = 0x19
    21  	ServiceTypeHEVCTV   = 0x1F
    22  )
    23  
    24  var dvbServiceTypeNames = map[ServiceType]string{
    25  	ServiceTypeTV:       "TV",
    26  	ServiceTypeRadio:    "Radio",
    27  	ServiceTypeTeletext: "Teletext",
    28  	ServiceTypeHDTV:     "HDTV",
    29  	ServiceTypeH264SDTV: "H.264-SDTV",
    30  	ServiceTypeH264HDTV: "H.264-HDTV",
    31  	ServiceTypeHEVCTV:   "HEVC-TV",
    32  }
    33  
    34  func (t ServiceType) String() string {
    35  	if s, ok := dvbServiceTypeNames[t]; ok {
    36  		return s
    37  	}
    38  
    39  	return fmt.Sprintf("x%02X", uint8(t))
    40  }
    41  
    42  // ServiceDescriptor defines a DVB Service Descriptor for the MPEG-TS standard.
    43  type ServiceDescriptor struct {
    44  	Type ServiceType
    45  
    46  	Provider string
    47  	Name     string
    48  }
    49  
    50  func (d *ServiceDescriptor) String() string {
    51  	return fmt.Sprintf("{DVB:ServiceDesc %v P:%q N:%q}", d.Type, d.Provider, d.Name)
    52  }
    53  
    54  const (
    55  	tagDVBService uint8 = 0x48
    56  )
    57  
    58  func init() {
    59  	desc.Register(tagDVBService, func() desc.Descriptor { return new(ServiceDescriptor) })
    60  }
    61  
    62  // Tag implements mpeg/ts/descriptor.Descriptor.
    63  func (d *ServiceDescriptor) Tag() uint8 {
    64  	return tagDVBService
    65  }
    66  
    67  // Len returns the length in bytes that the ServiceDescriptor would encode into, and implements mpeg/ts/descriptor.Descriptor.
    68  func (d *ServiceDescriptor) Len() int {
    69  	return 5 + len(d.Provider) + len(d.Name)
    70  }
    71  
    72  // Unmarshal decodes a byte slice into the ServiceDescriptor.
    73  func (d *ServiceDescriptor) Unmarshal(b []byte) error {
    74  	if b[0] != tagDVBService {
    75  		return errors.Errorf("descriptor_tag mismatch: x%02X != x%02X", b[0], tagDVBService)
    76  	}
    77  
    78  	l := int(b[1])
    79  
    80  	b = b[2:]
    81  	if len(b) < l {
    82  		return errors.Errorf("unexpected end of byte-slice: %d < %d", len(b), l)
    83  	}
    84  
    85  	d.Type = ServiceType(b[0])
    86  	b = b[1:]
    87  
    88  	n := int(b[0])
    89  	d.Provider = string(b[1 : 1+n])
    90  
    91  	b = b[1+n:]
    92  
    93  	n = int(b[0])
    94  	d.Name = string(b[1 : 1+n])
    95  
    96  	return nil
    97  }
    98  
    99  // Marshal encodes the ServiceDescriptor into a byte slice.
   100  func (d *ServiceDescriptor) Marshal() ([]byte, error) {
   101  	l := 3 + len(d.Provider) + len(d.Name)
   102  	if l > 0xFF {
   103  		return nil, errors.Errorf("descriptor data field too large: %d", l)
   104  	}
   105  
   106  	b := make([]byte, d.Len())
   107  
   108  	b[0] = tagDVBService
   109  	b[1] = byte(l)
   110  	b[2] = byte(d.Type)
   111  
   112  	b[3] = byte(len(d.Provider))
   113  	n := copy(b[4:], d.Provider)
   114  
   115  	b[4+n] = byte(len(d.Name))
   116  	copy(b[5+n:], d.Name)
   117  
   118  	return b, nil
   119  }