2018-01-04 10:04:33 +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).
|
|
|
|
*/
|
|
|
|
|
2018-01-30 05:19:39 +03:00
|
|
|
package parser
|
2018-01-04 10:04:33 +03:00
|
|
|
|
|
|
|
import (
|
|
|
|
_"fmt"
|
|
|
|
"os"
|
2018-01-10 06:57:56 +03:00
|
|
|
|
2018-01-30 05:19:39 +03:00
|
|
|
//"bitbucket.org/ausocean/av/mpegts"
|
|
|
|
//"bitbucket.org/ausocean/av/rtp"
|
|
|
|
//"bitbucket.org/ausocean/av/tools"
|
|
|
|
//"bitbucket.org/ausocean/av/itut"
|
|
|
|
"../mpegts"
|
|
|
|
"../rtp"
|
|
|
|
"../tools"
|
|
|
|
"../itut"
|
2018-01-04 10:04:33 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
type RtpToH264Converter interface {
|
|
|
|
Convert()
|
|
|
|
}
|
|
|
|
|
|
|
|
type rtpToH264Converter struct {
|
2018-01-10 06:57:56 +03:00
|
|
|
TsChan <-chan *mpegts.MpegTsPacket
|
|
|
|
tsChan chan<- *mpegts.MpegTsPacket
|
|
|
|
InputChan chan<- rtp.RtpPacket
|
|
|
|
inputChan <-chan rtp.RtpPacket
|
|
|
|
currentTsPacket *mpegts.MpegTsPacket
|
2018-01-04 10:04:33 +03:00
|
|
|
payloadByteChan chan byte
|
|
|
|
currentCC byte
|
|
|
|
}
|
|
|
|
|
|
|
|
//func parseH264File()
|
|
|
|
func NewRtpToH264Converter() (c *rtpToH264Converter) {
|
|
|
|
c = new(rtpToH264Converter)
|
2018-01-10 06:57:56 +03:00
|
|
|
tsChan := make(chan *mpegts.MpegTsPacket,100)
|
2018-01-04 10:04:33 +03:00
|
|
|
c.TsChan = tsChan
|
|
|
|
c.tsChan = tsChan
|
2018-01-10 06:57:56 +03:00
|
|
|
inputChan := make(chan rtp.RtpPacket,100)
|
2018-01-04 10:04:33 +03:00
|
|
|
c.InputChan = inputChan
|
|
|
|
c.inputChan = inputChan
|
|
|
|
c.currentCC = 0
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c* rtpToH264Converter) Convert() {
|
|
|
|
file,_ := os.Create("video")
|
2018-01-10 06:57:56 +03:00
|
|
|
var rtpBuffer [](*rtp.RtpPacket)
|
2018-01-04 10:04:33 +03:00
|
|
|
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
|
2018-01-10 06:57:56 +03:00
|
|
|
for tools.GetOctectType(rtpBuffer[0]) != 7 {
|
2018-01-04 10:04:33 +03:00
|
|
|
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
|
2018-01-10 06:57:56 +03:00
|
|
|
for tools.GetOctectType(rtpBuffer[0]) != 7 {
|
|
|
|
switch(tools.GetOctectType(rtpBuffer[0])){
|
2018-01-04 10:04:33 +03:00
|
|
|
case 28:
|
2018-01-10 06:57:56 +03:00
|
|
|
if tools.GetStartBit(rtpBuffer[0]) == 1{
|
2018-01-04 10:04:33 +03:00
|
|
|
var buffer []byte
|
2018-01-10 06:57:56 +03:00
|
|
|
buffer = append(buffer, append(itut.StartCode1(),itut.AUD()...)...)
|
|
|
|
buffer = append(buffer, append(itut.StartCode1(),sps...)...)
|
|
|
|
buffer = append(buffer, append(itut.StartCode1(),pps...)...)
|
|
|
|
buffer = append(buffer, append(itut.StartCode1(),sei...)...)
|
|
|
|
buffer = append(buffer, itut.StartCode1()...)
|
2018-01-04 10:04:33 +03:00
|
|
|
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:]...)
|
2018-01-10 06:57:56 +03:00
|
|
|
if tools.GetEndBit(rtpBuffer[0]) == 1 {
|
2018-01-04 10:04:33 +03:00
|
|
|
rtpBuffer = rtpBuffer[1:]
|
|
|
|
file.Write(buffer)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
rtpBuffer = rtpBuffer[1:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case 1:
|
|
|
|
var buffer []byte
|
2018-01-10 06:57:56 +03:00
|
|
|
buffer = append(buffer, append(itut.StartCode1(), itut.AUD()...)...)
|
|
|
|
buffer = append(buffer, append(itut.StartCode1(), sps...)...)
|
|
|
|
buffer = append(buffer, append(itut.StartCode1(),pps...)...)
|
|
|
|
buffer = append(buffer, append(itut.StartCode1(),sei...)...)
|
|
|
|
buffer = append(buffer, itut.StartCode1()...)
|
2018-01-04 10:04:33 +03:00
|
|
|
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:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|