/* 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 InputChan chan<- *RtpPacket inputChan <-chan *RtpPacket 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 inputChan := make(chan *RtpPacket,100) c.InputChan = inputChan c.inputChan = inputChan c.currentCC = 0 return } func (c* rtpToTsConverter) Convert() { nalUnitChan := make(chan NALUnit, 1000) pesPktChan := make(chan []byte, 1000) pesDataChan := make(chan byte, 1000) payloadByteChan := make(chan byte, 10000) // Get nal units from incoming rtp for { select { default: case rtpPacket := <-c.inputChan: if GetNalType( rtpPacket.Payload ) == 28 { nalUnitChan<-ParseNALFragment(rtpPacket.Payload) } else { nalUnitChan<-ParseNALSpsPps(rtpPacket.Payload) } case nalUnit := <-nalUnitChan: nalUnitByteSlice := nalUnit.ToByteSlice() for ii := range nalUnitByteSlice { pesDataChan<-nalUnitByteSlice[ii] } if nalFragment, isNALFragment := nalUnit.(*NALFragment); (isNALFragment && nalFragment.End) || !isNALFragment { pesDataChanLen := len(pesDataChan) 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(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] = 0x00 } 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 } } } }