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

     1  package packet
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/pkg/errors"
     9  	"github.com/puellanivis/breton/lib/mpeg/ts/pcr"
    10  )
    11  
    12  // AdaptationField defines the MPEG-TS Adaptation Field structure of a packet.
    13  type AdaptationField struct {
    14  	Discontinuity bool
    15  	RandomAccess  bool
    16  	Priority      bool
    17  
    18  	PCR  *pcr.PCR
    19  	OPCR *pcr.PCR
    20  
    21  	SpliceCountdown *byte
    22  
    23  	PrivateData []byte
    24  
    25  	LegalTimeWindow struct {
    26  		Valid bool
    27  		Value *uint16
    28  	}
    29  
    30  	PiecewiseRate *uint32
    31  
    32  	SeamlessSplice struct {
    33  		Type uint8
    34  		DTS  *uint64
    35  	}
    36  
    37  	Stuffing int
    38  }
    39  
    40  func (af *AdaptationField) String() string {
    41  	if af == nil {
    42  		return "{}"
    43  	}
    44  
    45  	var out []string
    46  
    47  	if af.Discontinuity {
    48  		out = append(out, "DISCONT")
    49  	}
    50  
    51  	if af.RandomAccess {
    52  		out = append(out, "RAND")
    53  	}
    54  
    55  	if af.Priority {
    56  		out = append(out, "PRI")
    57  	}
    58  
    59  	if af.PCR != nil {
    60  		out = append(out, fmt.Sprintf("PCR:%v", af.PCR))
    61  	}
    62  
    63  	if af.OPCR != nil {
    64  		out = append(out, fmt.Sprintf("OPCR:%v", af.OPCR))
    65  	}
    66  
    67  	if af.SpliceCountdown != nil {
    68  		out = append(out, fmt.Sprintf("SpliceCountdown:%d", *af.SpliceCountdown))
    69  	}
    70  
    71  	if len(af.PrivateData) > 0 {
    72  		out = append(out, fmt.Sprintf("priv[%d]", len(af.PrivateData)))
    73  	}
    74  
    75  	if af.LegalTimeWindow.Value != nil {
    76  		valid := ""
    77  		if af.LegalTimeWindow.Valid {
    78  			valid = "(VALID)"
    79  		}
    80  		out = append(out, fmt.Sprintf("LTW%s:x%04X", valid, *af.LegalTimeWindow.Value))
    81  	}
    82  
    83  	if af.PiecewiseRate != nil {
    84  		out = append(out, fmt.Sprintf("PWR:x%06X", *af.PiecewiseRate))
    85  	}
    86  
    87  	if af.SeamlessSplice.DTS != nil {
    88  		out = append(out, fmt.Sprintf("SeamlessSplice(%02X):x%09X", af.SeamlessSplice.Type, *af.SeamlessSplice.DTS))
    89  	}
    90  
    91  	if af.Stuffing > 0 {
    92  		out = append(out, fmt.Sprintf("Stuffing[%d]", af.Stuffing))
    93  	}
    94  
    95  	return fmt.Sprintf("{%s}", strings.Join(out, " "))
    96  }
    97  
    98  const (
    99  	flagAFDiscontinuity = 0x80
   100  	flagAFRandomAccess  = 0x40
   101  	flagAFPriority      = 0x20
   102  	flagAFPCR           = 0x10
   103  	flagAFOPCR          = 0x08
   104  	flagAFSplicePoint   = 0x04
   105  	flagAFPrivateData   = 0x02
   106  	flagAFExtension     = 0x01
   107  
   108  	flagAFExtLTW            = 0x80
   109  	flagAFExtPiecewiseRate  = 0x40
   110  	flagAFExtSeamlessSplice = 0x20
   111  
   112  	flagAFExtLTWValid = 0x80
   113  
   114  	// AdaptationFieldMinLength is the minimum length (in bytes) that an Adaptation Field can encode into.
   115  	AdaptationFieldMinLength = 2
   116  )
   117  
   118  // Len returns the actual length in bytes that the AdaptationField would encode into.
   119  func (af *AdaptationField) Len() int {
   120  	if af == nil {
   121  		return 0
   122  	}
   123  
   124  	l := 2
   125  
   126  	if af.PCR != nil {
   127  		l += 6
   128  	}
   129  
   130  	if af.OPCR != nil {
   131  		l += 6
   132  	}
   133  
   134  	if af.SpliceCountdown != nil {
   135  		l++
   136  	}
   137  
   138  	l += len(af.PrivateData)
   139  
   140  	if af.LegalTimeWindow.Value != nil || af.PiecewiseRate != nil || af.SeamlessSplice.DTS != nil {
   141  		l += 2
   142  
   143  		if af.LegalTimeWindow.Value != nil {
   144  			l += 2
   145  		}
   146  
   147  		if af.PiecewiseRate != nil {
   148  			l += 3
   149  		}
   150  
   151  		if af.SeamlessSplice.DTS != nil {
   152  			l += 5
   153  		}
   154  	}
   155  
   156  	return l + af.Stuffing
   157  }
   158  
   159  func (af *AdaptationField) marshal() ([]byte, error) {
   160  	if af == nil {
   161  		// If we got here, we already set that there is an AdaptationField…
   162  		// If so, return an empty AdaptationField, not a not-there AdaptationField.
   163  		return []byte{1, 0}, nil
   164  	}
   165  
   166  	b := make([]byte, 2)
   167  
   168  	if af.Discontinuity {
   169  		b[1] |= flagAFDiscontinuity
   170  	}
   171  	if af.RandomAccess {
   172  		b[1] |= flagAFRandomAccess
   173  	}
   174  	if af.Priority {
   175  		b[1] |= flagAFPriority
   176  	}
   177  
   178  	if af.PCR != nil {
   179  		b[1] |= flagAFPCR
   180  
   181  		pcr, err := af.PCR.Marshal()
   182  		if err != nil {
   183  			return nil, err
   184  		}
   185  
   186  		b = append(b, pcr...)
   187  	}
   188  
   189  	if af.OPCR != nil {
   190  		b[1] |= flagAFOPCR
   191  
   192  		opcr, err := af.OPCR.Marshal()
   193  		if err != nil {
   194  			return nil, err
   195  		}
   196  
   197  		b = append(b, opcr...)
   198  	}
   199  
   200  	if af.SpliceCountdown != nil {
   201  		b[1] |= flagAFSplicePoint
   202  		b = append(b, *af.SpliceCountdown)
   203  	}
   204  
   205  	if af.PrivateData != nil {
   206  		if len(af.PrivateData) > 0xFF {
   207  			return nil, errors.Errorf("private_data length exceeds 255: %d", len(af.PrivateData))
   208  		}
   209  
   210  		b[1] |= flagAFPrivateData
   211  		b = append(b, byte(len(af.PrivateData)&0xFF))
   212  		b = append(b, af.PrivateData...)
   213  	}
   214  
   215  	if af.LegalTimeWindow.Value != nil || af.PiecewiseRate != nil || af.SeamlessSplice.DTS != nil {
   216  		ext := make([]byte, 2)
   217  
   218  		if af.LegalTimeWindow.Value != nil {
   219  			ext[1] |= flagAFExtLTW
   220  
   221  			ext = append(ext,
   222  				byte((*af.LegalTimeWindow.Value>>8)&0x7F),
   223  				byte(*af.LegalTimeWindow.Value&0xFF),
   224  			)
   225  
   226  			if af.LegalTimeWindow.Valid {
   227  				ext[2] |= flagAFExtLTWValid
   228  			}
   229  		}
   230  
   231  		if af.PiecewiseRate != nil {
   232  			ext[1] |= flagAFExtPiecewiseRate
   233  
   234  			ext = append(ext,
   235  				byte((*af.PiecewiseRate>>16)&0x3F),
   236  				byte((*af.PiecewiseRate>>8)&0xFF),
   237  				byte(*af.PiecewiseRate&0xFF),
   238  			)
   239  		}
   240  
   241  		if af.SeamlessSplice.DTS != nil {
   242  			ext[1] |= flagAFExtSeamlessSplice
   243  
   244  			ext = append(ext,
   245  				byte((af.SeamlessSplice.Type&0x0F)<<4)|byte((*af.SeamlessSplice.DTS>>29)&0xE)|1,
   246  				byte((*af.SeamlessSplice.DTS>>23)&0xFF),
   247  				byte((*af.SeamlessSplice.DTS>>14)&0xFE)|1,
   248  				byte((*af.SeamlessSplice.DTS>>7)&0xFF),
   249  				byte((*af.SeamlessSplice.DTS<<1)&0xFE)|1,
   250  			)
   251  		}
   252  
   253  		ext[0] = byte(len(ext) - 1)
   254  
   255  		b = append(b, ext...)
   256  	}
   257  
   258  	if af.Stuffing > 0 {
   259  		b = append(b, bytes.Repeat([]byte{0xFF}, af.Stuffing)...)
   260  	}
   261  
   262  	b[0] = byte(len(b) - 1)
   263  	return b, nil
   264  }
   265  
   266  func (af *AdaptationField) unmarshal(b []byte) (int, error) {
   267  	if b[0] == 0 {
   268  		return 1, nil
   269  	}
   270  
   271  	length := int(b[0]) + 1
   272  
   273  	// trim so that OOB access will panic
   274  	b = b[:length]
   275  
   276  	af.Discontinuity = b[1]&flagAFDiscontinuity != 0
   277  	af.RandomAccess = b[1]&flagAFRandomAccess != 0
   278  	af.Priority = b[1]&flagAFPriority != 0
   279  
   280  	start := 2
   281  
   282  	if b[1]&flagAFPCR != 0 {
   283  		af.PCR = new(pcr.PCR)
   284  
   285  		_ = af.PCR.Unmarshal(b[start : start+6])
   286  
   287  		start += 6
   288  	}
   289  
   290  	if b[1]&flagAFOPCR != 0 {
   291  		af.OPCR = new(pcr.PCR)
   292  
   293  		_ = af.OPCR.Unmarshal(b[start : start+6])
   294  
   295  		start += 6
   296  	}
   297  
   298  	if b[1]&flagAFSplicePoint != 0 {
   299  		sc := b[start]
   300  		af.SpliceCountdown = &sc
   301  		start++
   302  	}
   303  
   304  	if b[1]&flagAFPrivateData != 0 {
   305  		l := int(b[start])
   306  		start++
   307  
   308  		af.PrivateData = append([]byte{}, b[start:start+l]...)
   309  		start += l
   310  	}
   311  
   312  	if b[1]&flagAFExtension != 0 {
   313  		l := int(b[start])
   314  		start++
   315  
   316  		ext := b[start : start+l]
   317  		start += l
   318  
   319  		if ext[0]&flagAFExtLTW != 0 {
   320  			b := ext[start:]
   321  
   322  			af.LegalTimeWindow.Valid = b[0]&0x80 != 0
   323  
   324  			ltw := uint16(b[0]&0x7F)<<8 | uint16(b[1])
   325  			af.LegalTimeWindow.Value = &ltw
   326  
   327  			start += 2
   328  		}
   329  
   330  		if ext[0]&flagAFExtPiecewiseRate != 0 {
   331  			b := ext[start:]
   332  
   333  			pwr := uint32(b[0]&0x3F)<<16 | uint32(b[1])<<8 | uint32(b[2])
   334  			af.PiecewiseRate = &pwr
   335  
   336  			start += 3
   337  		}
   338  
   339  		if ext[0]&flagAFExtSeamlessSplice != 0 {
   340  			b := ext[start:]
   341  
   342  			af.SeamlessSplice.Type = (b[0] >> 4) & 0x0F
   343  
   344  			ts := uint64(b[start]>>1) & 0x07
   345  			ts = (ts << 8) | uint64(b[1])
   346  			ts = (ts << 7) | uint64((b[2]>>1)&0x7F)
   347  			ts = (ts << 8) | uint64(b[3])
   348  			ts = (ts << 7) | uint64((b[4]>>1)&0x7F)
   349  
   350  			af.SeamlessSplice.DTS = &ts
   351  
   352  			start += 5
   353  		}
   354  	}
   355  
   356  	af.Stuffing = len(b) - start
   357  
   358  	return length, nil
   359  }