Got mpegts working!

This commit is contained in:
Unknown 2018-01-08 11:42:26 +10:30
parent da11e2888f
commit 18019992f7
6 changed files with 99 additions and 92 deletions

View File

@ -31,6 +31,7 @@ package mpegts
import (
"../tools"
"errors"
_"fmt"
)
/*
@ -106,7 +107,6 @@ type MpegTsPacket struct {
TSC byte // Transport Scrambling Control
AFC byte // Adaption Field Control
CC byte // Continuity Counter
AFL byte // Adaptation field length
DI bool // Discontinouty indicator
RAI bool // random access indicator
ESPI bool // Elementary stream priority indicator
@ -121,23 +121,40 @@ type MpegTsPacket struct {
TPDL byte // Tranposrt private data length
TPD []byte // Private data
Ext []byte // Adaptation field extension
Stuff []byte // Stuffing bytes
Payload []byte // Mpeg ts payload
}
func (p *MpegTsPacket) FillPayload(channel chan byte){
p.Payload = []byte{}
currentPktLength := 6 + int(tools.BoolToByte(p.PCRF))*6+int(tools.BoolToByte(p.OPCRF))*6+
int(tools.BoolToByte(p.SPF))*1+int(tools.BoolToByte(p.TPDF))*1+len(p.TPD)
for len(channel) > 0 && (currentPktLength+len(p.Payload)) < 188 {
nextByte := <-channel
p.Payload = append(p.Payload,nextByte)
}
}
func (p *MpegTsPacket) ToByteSlice() (output []byte, err error) {
stuffingLength := 182-len(p.Payload)-len(p.TPD)-int(tools.BoolToByte(p.PCRF))*6-
int(tools.BoolToByte(p.OPCRF))*6 - int(tools.BoolToByte(p.SPF))
stuffing := make([]byte,stuffingLength)
for i := range stuffing {
stuffing[i] = 0xFF
}
afl := 1+int(tools.BoolToByte(p.PCRF))*6+int(tools.BoolToByte(p.OPCRF))*
6+int(tools.BoolToByte(p.SPF))*1+int(tools.BoolToByte(p.TPDF))*1+len(p.TPD)+len(stuffing)
output = append(output, []byte{
0x47,
(tools.BoolToByte(p.TEI)<<7 | tools.BoolToByte(p.PUSI)<<6 | tools.BoolToByte(p.Priority)<<5 |
byte((p.PID&0xFF00)>>8)),
byte(p.PID & 0x00FF),
(p.TSC<<6 | p.AFC<<4 | p.CC),
p.AFL,
byte(afl),
(tools.BoolToByte(p.DI)<<7 | tools.BoolToByte(p.RAI)<<6 | tools.BoolToByte(p.ESPI)<<5 | tools.BoolToByte(p.PCRF)<<4 |
tools.BoolToByte(p.OPCRF)<<3 | tools.BoolToByte(p.SPF)<<2 | tools.BoolToByte(p.TPDF)<<1 | tools.BoolToByte(p.AFEF)),
}...)
for i := 40; p.PCRF && i >= 0; i-=8 {
output = append(output, byte(p.PCR>>uint(i)))
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)))
@ -148,7 +165,8 @@ func (p *MpegTsPacket) ToByteSlice() (output []byte, err error) {
if p.TPDF {
output = append(output, append([]byte{p.TPDL}, p.TPD...)...)
}
output = append(output, append(p.Ext, append(p.Stuff, p.Payload...)...)...)
output = append(output, append(p.Ext, append(stuffing, p.Payload...)...)...)
if len(output) != 188 {
err = errors.New("Length of MPEG-TS packet is not 188! Something is wrong!")
}

View File

@ -41,7 +41,7 @@ func TestPesToByteSlice(t *testing.T) {
StreamID: 0xE0, // StreamID
PDI: byte(2),
PTS: 100000,
HeaderLength: byte(11),
HeaderLength: byte(10),
Stuff: []byte{0xFF,0xFF,},
Data: []byte{ 0xEA, 0x4B, 0x12, },
}
@ -54,7 +54,7 @@ func TestPesToByteSlice(t *testing.T) {
0x00, // PES packet length byte 2
0x80, // Marker bits,ScramblingControl, Priority, DAI, Copyright, Original
0x80, // PDI, ESCR, ESRate, DSMTrickMode, ACI, CRC, Ext
byte(11), // header length
byte(10), // header length
0x21, // PCR byte 1
0x00, // pcr byte 2
0x07, // pcr byte 3

View File

@ -47,7 +47,8 @@ import (
"time"
"os"
"../packets"
"../tscreator"
"../tools"
"bitbucket.org/ausocean/av/ringbuffer"
@ -80,6 +81,7 @@ const (
rtspUrl = "rtsp://192.168.0.50:8554/CH002.sdp"
rtpUrl = "rtsp://192.168.0.50:8554/CH002.sdp/track1"
inputFileName = "testInput.h264"
framesPerSec = 25
)
// flag values
@ -219,7 +221,7 @@ func input(input string, output string) {
return
}
}
converter := packets.NewRtpToTsConverter()
converter := tscreator.NewTsCreator(framesPerSec)
// Open the h264 file
file, err := os.Open(inputFileName)
if err != nil {
@ -237,7 +239,7 @@ func input(input string, output string) {
}
// Start parsing the h264 file and send nal access units to the converter
go packets.ParseH264Buffer(buffer,converter.NalInputChan)
go tools.ParseH264Buffer(buffer,converter.NalInputChan)
go converter.Convert()
clipSize := 0
packetCount := 0
@ -250,7 +252,7 @@ func input(input string, output string) {
{71,64,0,16,0,0,176,13,0,1,193,0,0,0,1,240,0,42,177,4,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255},
/*PMT*/{71,80,0,16,
/*Start of payload*/
0,2,176,18,0,1,193,0,0,255,255,240,0,27,225,0,240,0,193,91,65,224,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255},
0,2,176,18,0,1,193,0,0,0xE1,0x00,0xF0,0,0x1B,0xE1,0,0xF0,0,0x15,0xBD,0x4D,0x56,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255},
}
donePSI := false
@ -271,7 +273,10 @@ func input(input string, output string) {
} else {
donePSI = true
packet := <-converter.TsChan
packetByteSlice := packet.ToByteSlice()
packetByteSlice,err := packet.ToByteSlice()
if err != nil {
fmt.Println(err)
}
copy(clip[clipSize:upperBound],packetByteSlice)
}
//fmt.Println(clip[clipSize:upperBound])

Binary file not shown.

View File

@ -50,7 +50,7 @@ func GetStartBit(p *rtp.RtpPacket) byte {
return (p.Payload[1] & 0x80) >> 7
}
func getEndBit(p *rtp.RtpPacket) byte {
func GetEndBit(p *rtp.RtpPacket) byte {
return (p.Payload[1] & 0x40) >> 6
}

View File

@ -26,50 +26,70 @@ LICENSE
along with revid in gpl.txt. If not, see [GNU licenses](http://www.gnu.org/licenses).
*/
package packets
package tscreator
import (
_ "fmt"
"os"
_"os"
"../mpegts"
"../pes"
"../tools"
"../rtp"
)
type RtpToTsConverter interface {
type TsConverter interface {
Convert()
}
type rtpToTsConverter struct {
TsChan <-chan *MpegTsPacket
tsChan chan<- *MpegTsPacket
InputChan chan<- RtpPacket
inputChan <-chan RtpPacket
type tsCreator struct {
TsChan <-chan *mpegts.MpegTsPacket
tsChan chan<- *mpegts.MpegTsPacket
InputChan chan<- rtp.RtpPacket
inputChan <-chan rtp.RtpPacket
NalInputChan chan<- []byte
nalInputChan <-chan []byte
currentTsPacket *MpegTsPacket
currentTsPacket *mpegts.MpegTsPacket
payloadByteChan chan byte
currentCC byte
currentPtsTime float64
currentPcrTime float64
fps uint
}
func NewRtpToTsConverter() (c *rtpToTsConverter) {
c = new(rtpToTsConverter)
tsChan := make(chan *MpegTsPacket, 100)
func NewTsCreator(fps uint) (c *tsCreator) {
c = new(tsCreator)
tsChan := make(chan *mpegts.MpegTsPacket, 100)
c.TsChan = tsChan
c.tsChan = tsChan
inputChan := make(chan RtpPacket, 100)
inputChan := make(chan rtp.RtpPacket, 100)
c.InputChan = inputChan
c.inputChan = inputChan
nalInputChan := make(chan []byte, 10000)
c.NalInputChan = nalInputChan
c.nalInputChan = nalInputChan
c.currentCC = 0
c.fps = fps
c.currentPcrTime = .0
c.currentPtsTime = .7
return
}
func (c *rtpToTsConverter) Convert() {
file, _ := os.Create("video")
func (c* tsCreator) genPts()(pts uint64){
pts = uint64(c.currentPtsTime * float64(90000))
c.currentPtsTime += 1.0/float64(c.fps)
return
}
func (c* tsCreator) genPcr()(pcr uint64){
pcr = uint64(c.currentPcrTime * float64(90000))
c.currentPcrTime += 1.0/float64(c.fps)
return
}
func (c *tsCreator) Convert() {
pesPktChan := make(chan []byte, 1000)
pesDataChan := make(chan byte, 50000)
payloadByteChan := make(chan byte, 100000)
var rtpBuffer [](*RtpPacket)
var rtpBuffer [](*rtp.RtpPacket)
for {
select {
default:
@ -88,28 +108,24 @@ func (c *rtpToTsConverter) Convert() {
}
}
}
if len(rtpBuffer) > 200 {
// Discard everything before a type 7
for GetOctectType(rtpBuffer[0]) != 7 {
for tools.GetOctectType(rtpBuffer[0]) != 7 {
rtpBuffer = rtpBuffer[1:]
}
// get sps
sps := make([]byte, len(rtpBuffer[0].Payload))
copy(sps[:], rtpBuffer[0].Payload[:])
rtpBuffer = rtpBuffer[1:]
// get pps
pps := make([]byte, len(rtpBuffer[0].Payload))
copy(pps[:], rtpBuffer[0].Payload[:])
rtpBuffer = rtpBuffer[1:]
// get sei
sei := make([]byte, len(rtpBuffer[0].Payload))
copy(sei[:], rtpBuffer[0].Payload[:])
rtpBuffer = rtpBuffer[1:]
// while we haven't reached the next sps in the buffer
for GetOctectType(rtpBuffer[0]) != 7 {
switch GetOctectType(rtpBuffer[0]) {
for tools.GetOctectType(rtpBuffer[0]) != 7 {
switch tools.GetOctectType(rtpBuffer[0]) {
case 28:
if GetStartBit(rtpBuffer[0]) == 1 {
if tools.GetStartBit(rtpBuffer[0]) == 1 {
var buffer []byte
buffer = append(buffer, []byte{0x00, 0x00, 0x01}...)
buffer = append(buffer, []byte{0x09, 0x10}...)
@ -125,10 +141,9 @@ func (c *rtpToTsConverter) Convert() {
rtpBuffer = rtpBuffer[1:]
for {
buffer = append(buffer, rtpBuffer[0].Payload[2:]...)
if getEndBit(rtpBuffer[0]) == 1 {
if tools.GetEndBit(rtpBuffer[0]) == 1 {
rtpBuffer = rtpBuffer[1:]
c.NalInputChan <- buffer
file.Write(buffer)
break
}
rtpBuffer = rtpBuffer[1:]
@ -149,73 +164,42 @@ func (c *rtpToTsConverter) Convert() {
buffer = append(buffer, rtpBuffer[0].Payload[2:]...)
rtpBuffer = rtpBuffer[1:]
c.NalInputChan <- buffer
file.Write(buffer)
default:
}
}
}
case nalUnit := <-c.nalInputChan:
for ii := range nalUnit {
pesDataChan <- nalUnit[ii]
}
pesDataChanLen := len(nalUnit)
pesPkt := new(PESPacket)
pesPkt.StreamID = 0xE0
pesPkt.Length = uint16(3 + pesDataChanLen)
pesPkt.ScramblingControl = 0
pesPkt.Priority = true
pesPkt.DAI = false
pesPkt.Copyright = false
pesPkt.Original = true
pesPkt.PDI = 0
pesPkt.ESCR = false
pesPkt.ESRate = false
pesPkt.DSMTrickMode = false
pesPkt.ACI = false
pesPkt.CRC = false
pesPkt.Ext = false
pesPkt.HeaderLength = 0
pesPkt.Data = make([]byte, pesDataChanLen)
for ii := 0; ii < pesDataChanLen; ii++ {
pesPkt.Data[ii] = <-pesDataChan
pesPkt := pes.PESPacket{
StreamID: 0xE0,
PDI: byte(2),
PTS: c.genPts(),
Data: nalUnit,
HeaderLength: 5,
}
pesPktChan <- pesPkt.ToByteSlice()
case pesPkt := <-pesPktChan:
for ii := range pesPkt {
payloadByteChan <- pesPkt[ii]
}
firstPacket := true
pusi := true
for len(payloadByteChan) > 0 {
lengthOfByteChan := len(payloadByteChan)
c.currentTsPacket = new(MpegTsPacket)
c.currentTsPacket.SyncByte = 0x47
c.currentTsPacket.PUSI = false
if firstPacket { // if it's the start of the payload
c.currentTsPacket.PUSI = true
firstPacket = false
pkt := mpegts.MpegTsPacket{
PUSI: pusi,
PID: 256,
RAI: pusi,
CC: c.currentCC,
AFC: byte(3),
PCRF: pusi,
}
pkt.FillPayload(payloadByteChan)
if pusi {
pkt.PCR = c.genPcr()
pusi = false
}
c.currentTsPacket.PID = 256
c.currentTsPacket.CC = c.currentCC
if c.currentCC++; c.currentCC > 15 {
c.currentCC = 0
}
payloadLength := 182
if lengthOfByteChan < 182 {
payloadLength = lengthOfByteChan
}
c.currentTsPacket.AFC = 3
stuffingLength := 182 - payloadLength
c.currentTsPacket.AF = make([]byte, 2+stuffingLength) // adaptationfield flag length = 16
c.currentTsPacket.AF[0] = byte(1 + stuffingLength)
for ii := 0; ii < stuffingLength; ii++ {
c.currentTsPacket.AF[2+ii] = 0xFF
}
c.currentTsPacket.Payload = make([]byte, payloadLength)
for ii := 0; ii < payloadLength; ii++ {
c.currentTsPacket.Payload[ii] = <-payloadByteChan
}
c.tsChan <- c.currentTsPacket
c.tsChan <- &pkt
}
}
}