av/packets/RtpToTsConverter.go

146 lines
4.2 KiB
Go
Raw Normal View History

2017-12-13 09:52:18 +03:00
/*
NAME
RtpToTsConverter.go - provides utilities for the conversion of Rtp packets
to equivalent MpegTs packets.
DESCRIPTION
See Readme.md
AUTHOR
Saxon Nelson-Milton <saxon.milton@gmail.com>
LICENSE
RtpToTsConverter.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 packets
2017-12-19 11:30:47 +03:00
import "fmt"
2017-12-14 05:13:51 +03:00
2017-12-13 09:52:18 +03:00
type RtpToTsConverter interface {
Convert()
}
type rtpToTsConverter struct {
TsChan <-chan *MpegTsPacket
tsChan chan<- *MpegTsPacket
currentTsPacket *MpegTsPacket
payloadByteChan chan byte
currentCC byte
}
func NewRtpToTsConverter() (c *rtpToTsConverter) {
c = new(rtpToTsConverter)
tsChan := make(chan *MpegTsPacket,100)
c.TsChan = tsChan
c.tsChan = tsChan
c.payloadByteChan = make(chan byte, 10000)
c.currentCC = 0
return
}
func (c* rtpToTsConverter) Convert(rtpSession *Session) {
2017-12-20 09:47:28 +03:00
nalUnitChan := make(chan *NALUnit, 1000)
// Get nal units from incoming rtp
go func(){
for {
rtpPacket := <-rtpSession.RtpChan
if GetNalType( rtpPacket.Payload ) == 28 {
nalUnitChan<-ParseNALUnit(rtpPacket.Payload)
2017-12-13 09:52:18 +03:00
}
2017-12-20 09:47:28 +03:00
}
}()
// Create PES packets from NAl units
pesPktChan := make(chan []byte, 100)
go func(){
pesDataChan := make(chan []byte, 100)
for {
nalUnit:=<-nalUnitChan
if nalUnit.Start {
pesDataChanLen = len(pesDataChan)
if pesDataChanLen > 0 {
pesPkt := new(PESPacket)
pesPkt.StreamID = 0xE0
pesPkt.Length = 24 + pesDataChanLen
pesPkt.ScramblingControl = 0
pesPkt.Priority = true
pesPkt.DAI = false
pesPkt.Copyright = false
pesPkt.Original = true
pesPkt.PDI = false
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[i] = <-pesDataChan
}
pesPktChan<-pesPkt.ToByteSlice()
2017-12-13 09:52:18 +03:00
}
2017-12-20 09:47:28 +03:00
pesDataChan<-nalUnit.ToByteSlice()
}
}
}()
// Create mpegts using pes packets
for {
pesPkt := <-pesPktChan
for ii:=range pesPkt {
c.payloadByteChan<-pesPkt[ii]
}
firstPacket:=true
for len(c.payloadByteChan) > 0 {
lengthOfByteChan := len(c.payloadByteChan)
c.currentTsPacket = new(MpegTsPacket)
c.currentTsPacket.SyncByte = 0x47
c.currentTsPacket.TEI = false
c.currentTsPacket.PUSI = false
if firstPacket { // if it's the start of the payload
c.currentTsPacket.PUSI = true
firstPacket = false
}
c.currentTsPacket.Priority = false
c.currentTsPacket.PID = 256
c.currentTsPacket.TSC = 0
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)
c.currentTsPacket.AF[1] = 0
if c.currentTsPacket.PUSI {
c.currentTsPacket.AF[1] = 0x40
}
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] = <-c.payloadByteChan
2017-12-13 09:52:18 +03:00
}
2017-12-20 09:47:28 +03:00
c.tsChan<-c.currentTsPacket
2017-12-13 09:52:18 +03:00
}
}
}