/* 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 import ( _"fmt" "os" ) type RtpToH264Converter interface { Convert() } type rtpToH264Converter struct { TsChan <-chan *MpegTsPacket tsChan chan<- *MpegTsPacket InputChan chan<- RtpPacket inputChan <-chan RtpPacket currentTsPacket *MpegTsPacket payloadByteChan chan byte currentCC byte } //func parseH264File() func NewRtpToH264Converter() (c *rtpToH264Converter) { c = new(rtpToH264Converter) 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* rtpToH264Converter) Convert() { file,_ := os.Create("video") var rtpBuffer [](*RtpPacket) for { select { default: case rtpPacket := <-c.inputChan: rtpBuffer = append(rtpBuffer,&rtpPacket) if len(rtpBuffer) > 2 { // if there's something weird going on with sequence numbers then sort if rtpPacket.SequenceNumber < rtpBuffer[len(rtpBuffer)-2].SequenceNumber { for i := 1; i < len(rtpBuffer); i++ { for j := i; j > 0 && rtpBuffer[j].SequenceNumber < rtpBuffer[j - 1].SequenceNumber; j-- { temp := rtpBuffer[j] rtpBuffer[j] = rtpBuffer[j-1] rtpBuffer[j-1] = temp } } } } if len(rtpBuffer) > 200 { // Discard everything before a type 7 for 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])){ case 28: if GetStartBit(rtpBuffer[0]) == 1{ var buffer []byte buffer = append(buffer, []byte{0x00,0x00,0x01}...) buffer = append(buffer, []byte{0x09,0x10}...) buffer = append(buffer, []byte{0x00,0x00,0x01}...) buffer = append(buffer, sps...) buffer = append(buffer, []byte{0x00,0x00,0x01}...) buffer = append(buffer, pps...) buffer = append(buffer, []byte{0x00,0x00,0x01}...) buffer = append(buffer, sei...) buffer = append(buffer, []byte{0x00,0x00,0x01}...) buffer = append(buffer, rtpBuffer[0].Payload[0] & 0xE0 | rtpBuffer[0].Payload[1] & 0x1F ) buffer = append(buffer, rtpBuffer[0].Payload[2:]...) rtpBuffer = rtpBuffer[1:] for { buffer = append(buffer, rtpBuffer[0].Payload[2:]...) if getEndBit(rtpBuffer[0]) == 1 { rtpBuffer = rtpBuffer[1:] file.Write(buffer) break } rtpBuffer = rtpBuffer[1:] } } case 1: var buffer []byte buffer = append(buffer, []byte{0x00,0x00,0x01}...) buffer = append(buffer, []byte{0x09,0x10}...) buffer = append(buffer, []byte{0x00,0x00,0x01}...) buffer = append(buffer, sps...) buffer = append(buffer, []byte{0x00,0x00,0x01}...) buffer = append(buffer, pps...) buffer = append(buffer, []byte{0x00,0x00,0x01}...) buffer = append(buffer, sei...) buffer = append(buffer, []byte{0x00,0x00,0x01}...) buffer = append(buffer, rtpBuffer[0].Payload[0] & 0xE0 | rtpBuffer[0].Payload[1] & 0x1F ) buffer = append(buffer, rtpBuffer[0].Payload[2:]...) rtpBuffer = rtpBuffer[1:] file.Write(buffer) default: } } } } } }