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

     1  package pes
     2  
     3  import (
     4  	"bytes"
     5  
     6  	"github.com/pkg/errors"
     7  )
     8  
     9  type packet struct {
    10  	stream *Stream
    11  
    12  	payload []byte
    13  }
    14  
    15  var startCodePrefix = []byte{0, 0, 1}
    16  
    17  func (p *packet) preUnmarshal(b []byte) (int, error) {
    18  	if !bytes.HasPrefix(b, startCodePrefix) {
    19  		return 0, errors.Errorf("bad start prefix [% 2X]", b[:3])
    20  	}
    21  
    22  	if p.stream == nil {
    23  		p.stream = new(Stream)
    24  	}
    25  
    26  	p.stream.ID = b[3]
    27  	return (int(b[4]) << 8) | int(b[5]), nil
    28  }
    29  
    30  func (p *packet) unmarshal(b []byte) error {
    31  	switch p.stream.ID {
    32  	case idPaddingStream, idPrivateStream2:
    33  		// Optional PES Header not present for these streams.
    34  
    35  	default:
    36  		hlen, err := p.stream.unmarshalHeader(b)
    37  		if err != nil {
    38  			return err
    39  		}
    40  
    41  		b = b[hlen:]
    42  	}
    43  
    44  	p.payload = append([]byte{}, b...)
    45  
    46  	return nil
    47  }
    48  
    49  func (p *packet) Unmarshal(b []byte) error {
    50  	l, err := p.preUnmarshal(b)
    51  	if err != nil {
    52  		return err
    53  	}
    54  
    55  	// trim mandatory header (already consumed by preMarshal)
    56  	b = b[mandatoryHeaderLength:]
    57  
    58  	return p.unmarshal(b[:l]) // enforce length with slice boundaries.
    59  }
    60  
    61  func (p *packet) Marshal() ([]byte, error) {
    62  	var h []byte
    63  
    64  	switch p.stream.ID {
    65  	case idPaddingStream, idPrivateStream2:
    66  		// Optional PES Header not present for these streams.
    67  
    68  	default:
    69  		var err error
    70  
    71  		h, err = p.stream.marshalHeader()
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  	}
    76  
    77  	l := len(h) + len(p.payload)
    78  
    79  	if l > 0xffff {
    80  		return nil, errors.Errorf("packet size too big: header:%d payload:%d", len(h), len(p.payload))
    81  	}
    82  
    83  	out := make([]byte, mandatoryHeaderLength+l)
    84  
    85  	copy(out, startCodePrefix)
    86  
    87  	out[3] = p.stream.ID
    88  	out[4] = byte((l >> 8) & 0xff)
    89  	out[5] = byte(l & 0xff)
    90  
    91  	start := mandatoryHeaderLength
    92  	start += copy(out[start:], h)
    93  
    94  	copy(out[start:], p.payload)
    95  
    96  	return out, nil
    97  }