Skip to content

Commit

Permalink
Merge pull request #84 from kortschak/arraypackets
Browse files Browse the repository at this point in the history
packet: use [188]byte as Packet type
  • Loading branch information
WillGunther authored Aug 3, 2018
2 parents b412433 + 94115b6 commit b075ace
Show file tree
Hide file tree
Showing 13 changed files with 253 additions and 312 deletions.
12 changes: 6 additions & 6 deletions cli/parsefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func main() {
}
}

pkt := make(packet.Packet, packet.PacketSize)
var pkt packet.Packet
var numPackets uint64
ebps := make(map[uint64]ebp.EncoderBoundaryPoint)
scte35PIDs := make(map[uint16]bool)
Expand All @@ -107,7 +107,7 @@ func main() {
}

for {
if _, err := io.ReadFull(reader, pkt); err != nil {
if _, err := io.ReadFull(reader, pkt[:]); err != nil {
if err == io.EOF || err == io.ErrUnexpectedEOF {
break
}
Expand All @@ -116,13 +116,13 @@ func main() {
}
numPackets++
if *dumpSCTE35 {
currPID, err := packet.Pid(pkt)
currPID, err := packet.Pid(&pkt)
if err != nil {
fmt.Printf("Cannot get packet PID for %d\n", currPID)
continue
}
if scte35PIDs[currPID] {
pay, err := packet.Payload(pkt)
pay, err := packet.Payload(&pkt)
if err != nil {
fmt.Printf("Cannot get payload for packet number %d on PID %d Error=%s\n", numPackets, currPID, err)
continue
Expand All @@ -138,7 +138,7 @@ func main() {

}
if *showEbp {
ebpBytes, err := adaptationfield.EncoderBoundaryPoint(pkt)
ebpBytes, err := adaptationfield.EncoderBoundaryPoint(&pkt)
if err != nil {
// Not an EBP
continue
Expand All @@ -154,7 +154,7 @@ func main() {
}
if *showPacketNumberOfPID != 0 {
pid := uint16(*showPacketNumberOfPID)
pktPid, err := packet.Pid(pkt)
pktPid, err := packet.Pid(&pkt)
if err != nil {
continue
}
Expand Down
39 changes: 14 additions & 25 deletions packet/accumulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,48 +30,37 @@ import (
"github.com/Comcast/gots"
)

var (
emptyByteArray []byte
)

type doneFunc func([]byte) (bool, error)

type accumulator struct {
f doneFunc
packets []Packet
f func([]byte) (bool, error)
packets []*Packet
}

// NewAccumulator creates a new packet accumulator
// that is done when the provided doneFunc returns true.
// PacketAccumulator is not thread safe
func NewAccumulator(f doneFunc) Accumulator {
// NewAccumulator creates a new packet accumulator that is done when
// the provided function returns done as true.
func NewAccumulator(f func(data []byte) (done bool, err error)) Accumulator {
return &accumulator{f: f}
}

// Add a packet to the accumulator. If the added packet completes
// the accumulation, based on the provided doneFunc, true is returned.
// Returns an error if the packet is not valid.
func (a *accumulator) Add(pkt Packet) (bool, error) {
func (a *accumulator) Add(pkt []byte) (bool, error) {
if badLen(pkt) {
return false, gots.ErrInvalidPacketLength
}
var pp Packet
copy(pp[:], pkt)
// technically we could get a packet without a payload. Check this and
// return false if we get one
p, err := ContainsPayload(pkt)
if err != nil {
p, err := ContainsPayload(&pp)
if !p || err != nil {
return false, err
} else if !p {
return false, nil
}
if payloadUnitStartIndicator(pkt) {
a.packets = make([]Packet, 0)
} else if len(a.packets) == 0 {
if !payloadUnitStartIndicator(&pp) && len(a.packets) == 0 {
// First packet must have payload unit start indicator
return false, gots.ErrNoPayloadUnitStartIndicator
}
pktCopy := make(Packet, PacketSize)
copy(pktCopy, pkt)
a.packets = append(a.packets, pktCopy)
a.packets = append(a.packets, &pp)
b, err := a.Parse()
if err != nil {
return false, err
Expand All @@ -91,14 +80,14 @@ func (a *accumulator) Parse() ([]byte, error) {
for _, pkt := range a.packets {
pay, err := Payload(pkt)
if err != nil {
return emptyByteArray, err
return nil, err
}
buf.Write(pay)
}
return buf.Bytes(), nil
}

func (a *accumulator) Packets() []Packet {
func (a *accumulator) Packets() []*Packet {
return a.packets
}

Expand Down
10 changes: 6 additions & 4 deletions packet/accumulator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func ExamplePacketAccumulator() {

secondPacket, _ := hex.DecodeString("47006411f0002b59bc22ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")

packets := []Packet{firstPacket, secondPacket}
packets := [][]byte{firstPacket, secondPacket}
// Just a simple func to accumulate two packets
dFunc := func(b []byte) (bool, error) {
if len(b) <= PacketSize {
Expand All @@ -48,9 +48,11 @@ func ExamplePacketAccumulator() {
}

acc := NewAccumulator(dFunc)
done, err := acc.Add(packets[0])
for i := 1; !done; i++ {
done, err = acc.Add(packets[i])
for _, pkt := range packets {
done, err := acc.Add(pkt)
if done {
break
}
if err != nil {
fmt.Printf("%v\n", err)
}
Expand Down
106 changes: 42 additions & 64 deletions packet/adaptationfield/adaptationfield.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,64 +5,59 @@ import (
"github.com/Comcast/gots/packet"
)

var emptyByteSlice []byte

// Length returns the length of the adaptation field in bytes
func Length(packet packet.Packet) uint8 {
return uint8(packet[4])
func Length(pkt *packet.Packet) uint8 {
return uint8(pkt[4])
}

// IsDiscontinuous returns the discontinuity indicator for this adaptation field
func IsDiscontinuous(packet packet.Packet) bool {
return (packet[5] & 0x80) != 0
func IsDiscontinuous(pkt *packet.Packet) bool {
return pkt[5]&0x80 != 0
}

// IsRandomAccess returns the random access indicator for this adaptation field
func IsRandomAccess(packet packet.Packet) bool {
return (packet[5] & 0x40) != 0
func IsRandomAccess(pkt *packet.Packet) bool {
return pkt[5]&0x40 != 0
}

// IsESHigherPriority returns true if this elementary stream is
// high priority. Corresponds to the elementary stream
// priority indicator.
func IsESHigherPriority(packet packet.Packet) bool {
return (packet[5] & 0x20) != 0
func IsESHigherPriority(pkt *packet.Packet) bool {
return pkt[5]&0x20 != 0
}

// HasPCR returns true when the PCR flag is set
func HasPCR(packet packet.Packet) bool {
return (packet[5] & 0x10) != 0
func HasPCR(pkt *packet.Packet) bool {
return pkt[5]&0x10 != 0
}

// HasOPCR returns true when the OPCR flag is set
func HasOPCR(packet packet.Packet) bool {
return (packet[5] & 0x08) != 0
func HasOPCR(pkt *packet.Packet) bool {
return pkt[5]&0x08 != 0
}

// HasSplicingPoint returns true when the splicing countdown field is present
func HasSplicingPoint(packet packet.Packet) bool {
return (packet[5] & 0x04) != 0
func HasSplicingPoint(pkt *packet.Packet) bool {
return pkt[5]&0x04 != 0
}

// HasTransportPrivateData returns true when the private data field is present
func HasTransportPrivateData(packet packet.Packet) bool {
return (packet[5] & 0x02) != 0
func HasTransportPrivateData(pkt *packet.Packet) bool {
return pkt[5]&0x02 != 0
}

// HasAdaptationFieldExtension returns true if this adaptation field contains an extension field
func HasAdaptationFieldExtension(packet packet.Packet) bool {
return (packet[5] & 0x01) != 0
func HasAdaptationFieldExtension(pkt *packet.Packet) bool {
return pkt[5]&0x01 != 0
}

// EncoderBoundaryPoint returns the byte array located in the optional TransportPrivateData of the (also optional)
// AdaptationField of the Packet. If either of these optional fields are missing an empty byte array is returned with an error
func EncoderBoundaryPoint(pkt packet.Packet) ([]byte, error) {
if badLen(pkt) {
return emptyByteSlice, gots.ErrInvalidPacketLength
}
func EncoderBoundaryPoint(pkt *packet.Packet) ([]byte, error) {
hasAdapt, err := packet.ContainsAdaptationField(pkt)
if err != nil {
return emptyByteSlice, nil
return nil, nil
}
if hasAdapt && Length(pkt) > 0 && HasTransportPrivateData(pkt) {
ebp, err := TransportPrivateData(pkt)
Expand All @@ -78,81 +73,64 @@ func EncoderBoundaryPoint(pkt packet.Packet) ([]byte, error) {
// First 33 bits are PCR base.
// Next 6 bits are reserved.
// Final 9 bits are PCR extension.
func PCR(packet packet.Packet) ([]byte, error) {
if !HasPCR(packet) {
return emptyByteSlice, gots.ErrNoPCR
func PCR(pkt *packet.Packet) ([]byte, error) {
if !HasPCR(pkt) {
return nil, gots.ErrNoPCR
}
offset := 6
return packet[offset : offset+6], nil
return pkt[offset : offset+6], nil
}

// OPCR is the Original Program Clock Reference.
// First 33 bits are original PCR base.
// Next 6 bits are reserved.
// Final 9 bits are original PCR extension.
func OPCR(packet packet.Packet) ([]byte, error) {
if badLen(packet) {
return emptyByteSlice, gots.ErrInvalidPacketLength
}
if !HasOPCR(packet) {
return emptyByteSlice, gots.ErrNoOPCR
func OPCR(pkt *packet.Packet) ([]byte, error) {
if !HasOPCR(pkt) {
return nil, gots.ErrNoOPCR
}
offset := 6
if HasPCR(packet) {
if HasPCR(pkt) {
offset += 6
}
return packet[offset : offset+6], nil
return pkt[offset : offset+6], nil
}

// SpliceCountdown returns a count of how many packets after this one until
// a splice point occurs or an error if none exist. This function calls
// HasSplicingPoint to check for the existence of a splice countdown.
func SpliceCountdown(packet packet.Packet) (uint8, error) {
if badLen(packet) {
return 0, gots.ErrInvalidPacketLength
}
if !HasSplicingPoint(packet) {
func SpliceCountdown(pkt *packet.Packet) (uint8, error) {
if !HasSplicingPoint(pkt) {
return 0, gots.ErrNoSplicePoint
}
offset := 6
if HasPCR(packet) {
if HasPCR(pkt) {
offset += 6
}
if HasOPCR(packet) {
if HasOPCR(pkt) {
offset += 6
}
return packet[offset], nil
return pkt[offset], nil
}

// TransportPrivateData returns the private data from this adaptation field
// or an empty array and an error if there is none. This function calls
// HasTransportPrivateData to check for the existence of private data.
func TransportPrivateData(packet packet.Packet) ([]byte, error) {
if badLen(packet) {
return emptyByteSlice, gots.ErrInvalidPacketLength
}
if !HasTransportPrivateData(packet) {
return emptyByteSlice, gots.ErrNoPrivateTransportData
func TransportPrivateData(pkt *packet.Packet) ([]byte, error) {
if !HasTransportPrivateData(pkt) {
return nil, gots.ErrNoPrivateTransportData
}
offset := 6
if HasPCR(packet) {
if HasPCR(pkt) {
offset += 6
}
if HasOPCR(packet) {
if HasOPCR(pkt) {
offset += 6
}
if HasSplicingPoint(packet) {
if HasSplicingPoint(pkt) {
offset++
}
dataLength := uint8(packet[offset])
dataLength := uint8(pkt[offset])
offset++
return packet[uint8(offset) : uint8(offset)+dataLength], nil
}

// badLen returns true if the packet has invalid length
func badLen(pkt packet.Packet) bool {
if len(pkt) != packet.PacketSize {
return true
}
return false
return pkt[uint8(offset) : uint8(offset)+dataLength], nil
}
13 changes: 6 additions & 7 deletions packet/adaptationfield/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@ import "github.com/Comcast/gots/packet"

func SetPrivateData(pkt *packet.Packet, af []byte) {
offset := 6
if HasPCR(*pkt) {
if HasPCR(pkt) {
offset += 6
}
if HasOPCR(*pkt) {
if HasOPCR(pkt) {
offset += 6
}
if HasSplicingPoint(*pkt) {
if HasSplicingPoint(pkt) {
offset++
}
(*pkt)[offset] = byte(0x04) // data length
pkt[offset] = byte(0x04) // data length
offset++
for i, b := range af {
(*pkt)[offset+i] = b
}
// FIXME(kortschak): Handle len(af) != 4.
copy(pkt[offset:offset+4], af)
}
Loading

0 comments on commit b075ace

Please sign in to comment.