av/packets/RtpToH264Converter.go

151 lines
5.0 KiB
Go

/*
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
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:
}
}
}
}
}
}