mirror of https://bitbucket.org/ausocean/av.git
198 lines
8.8 KiB
Go
198 lines
8.8 KiB
Go
/*
|
|
NAME
|
|
MpegTs.go - provides a data structure intended to encapsulate the properties
|
|
of an MpegTs packet and also functions to allow manipulation of these packets.
|
|
|
|
DESCRIPTION
|
|
See Readme.md
|
|
|
|
AUTHOR
|
|
Saxon A. Nelson-Milton <saxon.milton@gmail.com>
|
|
|
|
LICENSE
|
|
MpegTs.go is Copyright (C) 2017 the Australian Ocean Lab (AusOcean)
|
|
|
|
It is free software: you can redistribute it and/or modify them
|
|
under the terms of the GNU General Public License as published by the
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
|
option) any later version.
|
|
|
|
It is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with revid in gpl.txt. If not, see [GNU licenses](http://www.gnu.org/licenses).
|
|
*/
|
|
|
|
package mpegts
|
|
|
|
import (
|
|
"bitbucket.org/ausocean/av/tools"
|
|
|
|
//"../tools"
|
|
|
|
_"errors"
|
|
//"fmt"
|
|
)
|
|
|
|
const (
|
|
mpegTsSize = 188
|
|
mpegtsPayloadSize = 176
|
|
)
|
|
|
|
/*
|
|
The below data struct encapsulates the fields of an MPEG-TS packet. Below is
|
|
the formatting of an MPEG-TS packet for reference!
|
|
|
|
MPEG-TS Packet Formatting
|
|
============================================================================
|
|
| octet no | bit 0 | bit 1 | bit 2 | bit 3 | bit 4 | bit 5 | bit 6 | bit 7 |
|
|
============================================================================
|
|
| octet 0 | sync byte (0x47) |
|
|
----------------------------------------------------------------------------
|
|
| octet 1 | TEI | PUSI | Prior | PID |
|
|
----------------------------------------------------------------------------
|
|
| octet 2 | PID cont. |
|
|
----------------------------------------------------------------------------
|
|
| octet 3 | TSC | AFC | CC |
|
|
----------------------------------------------------------------------------
|
|
| octet 4 | AFL |
|
|
----------------------------------------------------------------------------
|
|
| octet 5 | DI | RAI | ESPI | PCRF | OPCRF | SPF | TPDF | AFEF |
|
|
----------------------------------------------------------------------------
|
|
| optional | PCR (48 bits => 6 bytes) |
|
|
----------------------------------------------------------------------------
|
|
| - | PCR cont. |
|
|
----------------------------------------------------------------------------
|
|
| - | PCR cont. |
|
|
----------------------------------------------------------------------------
|
|
| - | PCR cont. |
|
|
----------------------------------------------------------------------------
|
|
| - | PCR cont. |
|
|
----------------------------------------------------------------------------
|
|
| - | PCR cont. |
|
|
----------------------------------------------------------------------------
|
|
| optional | OPCR (48 bits => 6 bytes) |
|
|
----------------------------------------------------------------------------
|
|
| - | OPCR cont. |
|
|
----------------------------------------------------------------------------
|
|
| - | OPCR cont. |
|
|
----------------------------------------------------------------------------
|
|
| - | OPCR cont. |
|
|
----------------------------------------------------------------------------
|
|
| - | OPCR cont. |
|
|
----------------------------------------------------------------------------
|
|
| - | OPCR cont. |
|
|
----------------------------------------------------------------------------
|
|
| optional | SC |
|
|
----------------------------------------------------------------------------
|
|
| optional | TPDL |
|
|
----------------------------------------------------------------------------
|
|
| optional | TPD (variable length) |
|
|
----------------------------------------------------------------------------
|
|
| - | ... |
|
|
----------------------------------------------------------------------------
|
|
| optional | Extension (variable length) |
|
|
----------------------------------------------------------------------------
|
|
| - | ... |
|
|
----------------------------------------------------------------------------
|
|
| optional | Stuffing (variable length) |
|
|
----------------------------------------------------------------------------
|
|
| - | ... |
|
|
----------------------------------------------------------------------------
|
|
| optional | Payload (variable length) |
|
|
----------------------------------------------------------------------------
|
|
| - | ... |
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
type MpegTsPacket struct {
|
|
TEI bool // Transport Error Indicator
|
|
PUSI bool // Payload Unit Start Indicator
|
|
Priority bool // Tranposrt priority indicator
|
|
PID uint16 // Packet identifier
|
|
TSC byte // Transport Scrambling Control
|
|
AFC byte // Adaption Field Control
|
|
CC byte // Continuity Counter
|
|
DI bool // Discontinouty indicator
|
|
RAI bool // random access indicator
|
|
ESPI bool // Elementary stream priority indicator
|
|
PCRF bool // PCR flag
|
|
OPCRF bool // OPCR flag
|
|
SPF bool // Splicing point flag
|
|
TPDF bool // Transport private data flag
|
|
AFEF bool // Adaptation field extension flag
|
|
PCR uint64 // Program clock reference
|
|
OPCR uint64 // Original program clock reference
|
|
SC byte // Splice countdown
|
|
TPDL byte // Tranposrt private data length
|
|
TPD []byte // Private data
|
|
Ext []byte // Adaptation field extension
|
|
Payload []byte // Mpeg ts Payload
|
|
}
|
|
|
|
// FillPayload takes a channel and fills the packets Payload field until the
|
|
// channel is empty or we've the packet reaches capacity
|
|
func (p *MpegTsPacket) FillPayload(channel chan byte){
|
|
p.Payload = make([]byte,0,mpegtsPayloadSize)
|
|
currentPktLength := 6 + int(btb(p.PCRF))*6+int(btb(p.OPCRF))*6+
|
|
int(btb(p.SPF))*1+int(btb(p.TPDF))*1+len(p.TPD)
|
|
// While we're within the mpegts packet size and we still have data we can use
|
|
for (currentPktLength+len(p.Payload)) < mpegTsSize && len(channel) > 0 {
|
|
p.Payload = append(p.Payload,<-channel)
|
|
}
|
|
}
|
|
|
|
// btb is a simple wrapper function for tools.BoolToByte which takes a bool
|
|
// and returns an equivalent byte
|
|
func btb(b bool) byte {
|
|
return tools.BoolToByte(b)
|
|
}
|
|
|
|
// ToByteSlice interprets the fields of the ts packet instance and outputs a
|
|
// corresponding byte slice
|
|
func (p *MpegTsPacket) ToByteSlice() (output []byte) {
|
|
stuffingLength := 182-len(p.Payload)-len(p.TPD)-int(btb(p.PCRF))*6-
|
|
int(btb(p.OPCRF))*6 - int(btb(p.SPF))
|
|
var stuffing []byte
|
|
if stuffingLength > 0 {
|
|
stuffing = make([]byte,stuffingLength)
|
|
}
|
|
for i := range stuffing {
|
|
stuffing[i] = 0xFF
|
|
}
|
|
afl := 1+int(btb(p.PCRF))*6+int(btb(p.OPCRF))*6+int(btb(p.SPF))+int(btb(p.TPDF))+len(p.TPD)+len(stuffing)
|
|
output = make([]byte,0,mpegTsSize)
|
|
output = append(output, []byte{
|
|
0x47,
|
|
(btb(p.TEI)<<7 | btb(p.PUSI)<<6 | btb(p.Priority)<<5 | byte((p.PID&0xFF00)>>8)),
|
|
byte(p.PID & 0x00FF),
|
|
(p.TSC<<6 | p.AFC<<4 | p.CC),
|
|
}...)
|
|
|
|
if p.AFC == 3 || p.AFC == 2 {
|
|
output = append(output, []byte{
|
|
byte(afl), (btb(p.DI)<<7 | btb(p.RAI)<<6 | btb(p.ESPI)<<5 |
|
|
btb(p.PCRF)<<4 | btb(p.OPCRF)<<3 | btb(p.SPF)<<2 |
|
|
btb(p.TPDF)<<1 | btb(p.AFEF)),
|
|
}...)
|
|
for i := 40; p.PCRF && i >= 0; i-=8 {
|
|
output = append(output, byte((p.PCR<<15)>>uint(i)))
|
|
}
|
|
for i := 40; p.OPCRF && i >= 0; i-=8 {
|
|
output = append(output, byte(p.OPCR>>uint(i)))
|
|
}
|
|
if p.SPF {
|
|
output = append(output, p.SC)
|
|
}
|
|
if p.TPDF {
|
|
output = append(output, append([]byte{p.TPDL}, p.TPD...)...)
|
|
}
|
|
output = append(output, p.Ext...)
|
|
output = append(output, stuffing...)
|
|
}
|
|
output = append(output, p.Payload...)
|
|
return
|
|
}
|