/* NAME RtpToTsConverter.go - provides utilities for the conversion of Rtp packets to equivalent MpegTs packets. DESCRIPTION See Readme.md AUTHOR Saxon Nelson-Milton 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 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) { nalUnitChan := make(chan NALUnit, 1000) // Get nal units from incoming rtp go func(){ for { rtpPacket := <-rtpSession.RtpChan if GetNalType( rtpPacket.Payload ) == 28 { nalUnitChan<-ParseNALFragment(rtpPacket.Payload) } else { // nalUnitChan<-ParseSPSPPS(rtpPacket.Payload) } } }() // Create PES packets from NAl units pesPktChan := make(chan []byte, 100) go func(){ pesDataChan := make(chan byte, 100) for { nalUnit:=<-nalUnitChan if nalFragment, isNALFragment := nalUnit.(*NALFragment); (isNALFragment && nalFragment.Start) || !isNALFragment { pesDataChanLen := len(pesDataChan) if pesDataChanLen > 0 { 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 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 } c.tsChan<-c.currentTsPacket } } }