mirror of https://bitbucket.org/ausocean/av.git
Updating remote
This commit is contained in:
parent
00a6bd8212
commit
dd05c13110
|
@ -30,17 +30,24 @@ package h264
|
|||
|
||||
import (
|
||||
"bitbucket.org/ausocean/av/itut"
|
||||
"reflect"
|
||||
"log"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
acceptedLength = 1000
|
||||
)
|
||||
|
||||
var (
|
||||
Info *log.Logger
|
||||
mutex *sync.Mutex
|
||||
)
|
||||
|
||||
type H264Parser struct {
|
||||
inputBuffer []byte
|
||||
isParsing bool
|
||||
OutputChan chan<- []byte
|
||||
}
|
||||
|
||||
func (p* H264Parser)SendInputData(someData []byte){
|
||||
p.inputBuffer = append(p.inputBuffer, someData...)
|
||||
InputByteChan chan byte
|
||||
}
|
||||
|
||||
func (p* H264Parser)Stop(){
|
||||
|
@ -48,31 +55,59 @@ func (p* H264Parser)Stop(){
|
|||
}
|
||||
|
||||
func (p* H264Parser)Parse() {
|
||||
p.isParsing = true
|
||||
buffer := p.inputBuffer
|
||||
for p.isParsing {
|
||||
for i := 0; len(buffer) > 10; i++{
|
||||
var start bool
|
||||
i, start = func() (int,bool) {
|
||||
switch{
|
||||
case reflect.DeepEqual(buffer[i:i+3],itut.StartCode1()):
|
||||
return i+3, true
|
||||
case reflect.DeepEqual(buffer[i:i+4],itut.StartCode2()):
|
||||
return i+4, true
|
||||
}
|
||||
return i, false
|
||||
}()
|
||||
if nalType := buffer[i] & 0x1F; start && ( nalType == 1 || nalType == 5) {
|
||||
for ; i < len(buffer) && !(i+3 < len(buffer) && ( reflect.DeepEqual(buffer[i:i+3],itut.StartCode1()) ||
|
||||
reflect.DeepEqual(buffer[i:i+4],itut.StartCode2()))); i++ {}
|
||||
p.OutputChan<-append(append(itut.StartCode1(),itut.AUD()...),buffer[:i]...)
|
||||
buffer = buffer[i:]
|
||||
i=0
|
||||
}
|
||||
if i >= len(buffer) {
|
||||
buffer = []byte{}
|
||||
break
|
||||
p.isParsing = true
|
||||
outputBuffer := []byte{}
|
||||
searchingForEnd := false
|
||||
p.InputByteChan = make(chan byte, 10000)
|
||||
for p.isParsing {
|
||||
aByte := <-p.InputByteChan
|
||||
|
||||
outputBuffer = append(outputBuffer, aByte)
|
||||
for i:=1; aByte == 0x00 && i != 4; i++ {
|
||||
aByte = <-p.InputByteChan
|
||||
outputBuffer = append(outputBuffer, aByte)
|
||||
if ( aByte == 0x01 && i == 2 ) || ( aByte == 0x01 && i == 3 ) {
|
||||
if searchingForEnd {
|
||||
outputBuffer = outputBuffer[:len(outputBuffer)-(i+1)]
|
||||
p.OutputChan<-append(append(itut.StartCode1(),itut.AUD()...),outputBuffer...)
|
||||
outputBuffer = []byte{}
|
||||
searchingForEnd = false
|
||||
}
|
||||
aByte = <-p.InputByteChan
|
||||
outputBuffer = append(outputBuffer, aByte)
|
||||
if nalType := aByte & 0x1F; nalType == 1 || nalType == 5 {
|
||||
searchingForEnd = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
for p.isParsing {
|
||||
aByte := <-p.InputByteChan
|
||||
outputBuffer = append(outputBuffer, aByte)
|
||||
for i:=1; aByte == 0x00 && i != 4; i++ {
|
||||
aByte = <-p.InputByteChan
|
||||
outputbuffer = append(outputBuffer, aByte)
|
||||
if ( aByte == 0x01 && i == 2 ) || ( aByte == 0x01 && i == 3 ) {
|
||||
aByte = <-p.InputByteChan
|
||||
outputBuffer = append(outputBuffer, aByte)
|
||||
if nalType := aByte & 0x1F; nalType == 1 || nalType == 5 {
|
||||
for {
|
||||
aByte = <-p.InputByteChan
|
||||
outputBuffer = append(outputBuffer,aByte)
|
||||
for i := 1; aByte == 0x00; i++ {
|
||||
aByte = <-p.InputByteChan
|
||||
outputbuffer = append(outputBuffer, aByte)
|
||||
if ( aByte == 0x01 && i == 2 ) || ( aByte == 0x01 && i == 3 ) {
|
||||
outputBuffer = outputBuffer[:len(outputBuffer)-(i+1)]
|
||||
outputChan<-append(append(itut.StartCode1(),itut.AUD()...),outputBuffer...)
|
||||
outputBuffer = []byte{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -30,4 +30,4 @@ package itut
|
|||
|
||||
func StartCode1() []byte { return []byte{0x00, 0x00, 0x01} }
|
||||
func StartCode2() []byte { return []byte{0x00, 0x00, 0x00, 0x01} }
|
||||
func AUD() []byte { return []byte{0x09, 0x10} }
|
||||
func AUD() []byte { return []byte{0x09, 0xF0} }
|
||||
|
|
|
@ -43,6 +43,7 @@ import (
|
|||
"os/exec"
|
||||
"strconv"
|
||||
"time"
|
||||
"io"
|
||||
|
||||
"bitbucket.org/ausocean/av/h264"
|
||||
"bitbucket.org/ausocean/av/tsgenerator"
|
||||
|
@ -66,26 +67,27 @@ const (
|
|||
motionThreshold = "0.0025"
|
||||
qscale = "3"
|
||||
defaultRaspividCmd = "raspivid -o -"
|
||||
framesPerSec = 25
|
||||
packetsPerFrame = 7
|
||||
framesPerSec = 25
|
||||
packetsPerFrame = 7
|
||||
h264BufferSize = 500000
|
||||
)
|
||||
|
||||
const (
|
||||
raspivid = 0
|
||||
rtp = 1
|
||||
raspivid = 0
|
||||
rtp = 1
|
||||
h264Codec = 2
|
||||
file = 4
|
||||
httpOut = 5
|
||||
file = 4
|
||||
httpOut = 5
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Input uint8
|
||||
InputCmd string
|
||||
Output uint8
|
||||
Input uint8
|
||||
InputCmd string
|
||||
Output uint8
|
||||
OutputFileName string
|
||||
InputFileName string
|
||||
}
|
||||
|
||||
|
||||
type RevidInst interface {
|
||||
Start()
|
||||
Stop()
|
||||
|
@ -104,7 +106,7 @@ type revidInst struct {
|
|||
isRunning bool
|
||||
Error *log.Logger
|
||||
outputFile *os.File
|
||||
inputFile *os.File
|
||||
inputFile *os.File
|
||||
}
|
||||
|
||||
func NewRevidInstance(config Config) (r *revidInst, err error) {
|
||||
|
@ -122,6 +124,13 @@ func NewRevidInstance(config Config) (r *revidInst, err error) {
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
switch r.config.Input {
|
||||
case file:
|
||||
r.inputFile, err = os.Open(r.config.InputFileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -145,11 +154,13 @@ func (r *revidInst) input() {
|
|||
generator := tsgenerator.NewTsGenerator(framesPerSec)
|
||||
go generator.Generate()
|
||||
h264Parser := h264.H264Parser{OutputChan: generator.NalInputChan}
|
||||
// TODO: Need to create constructor for parser otherwise I'm going to break
|
||||
// something eventuallyl
|
||||
go h264Parser.Parse()
|
||||
var inputReader *bufio.Reader
|
||||
switch r.config.Input {
|
||||
case raspivid:
|
||||
cmd := exec.Command("raspivid", "-o -")
|
||||
cmd := exec.Command("raspivid", "-o", "-", "-n", "-t", "0")
|
||||
stdout, _ := cmd.StdoutPipe()
|
||||
err := cmd.Start()
|
||||
inputReader = bufio.NewReader(stdout)
|
||||
|
@ -157,6 +168,9 @@ func (r *revidInst) input() {
|
|||
r.Error.Println(err.Error())
|
||||
return
|
||||
}
|
||||
case file:
|
||||
|
||||
|
||||
default:
|
||||
r.Error.Println("Input not valid!")
|
||||
}
|
||||
|
@ -166,21 +180,46 @@ func (r *revidInst) input() {
|
|||
prevTime := now
|
||||
|
||||
startPackets := [][]byte{
|
||||
{71,64,17,16,0,66,240,65,0,1,193,0,0,255,1,255,0,1,252,128,48,72,46,1,6,70,70,109,112,101,103,37,115,116,114,101,97,109,101,100,32,98,121,32,116,104,101,32,71,101,111,86,105,115,105,111,110,32,82,116,115,112,32,83,101,114,118,101,114,99,176,214,195,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255},
|
||||
{71,64,0,16,0,0,176,13,0,1,193,0,0,0,1,240,0,42,177,4,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255},
|
||||
/*PMT*/{71,80,0,16,
|
||||
/*Start of payload*/
|
||||
0,2,176,18,0,1,193,0,0,0xE1,0x00,0xF0,0,0x1B,0xE1,0,0xF0,0,0x15,0xBD,0x4D,0x56,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255},
|
||||
{71, 64, 17, 16, 0, 66, 240, 65, 0, 1, 193, 0, 0, 255, 1, 255, 0, 1, 252, 128, 48, 72, 46, 1, 6, 70, 70, 109, 112, 101, 103, 37, 115, 116, 114, 101, 97, 109, 101, 100, 32, 98, 121, 32, 116, 104, 101, 32, 71, 101, 111, 86, 105, 115, 105, 111, 110, 32, 82, 116, 115, 112, 32, 83, 101, 114, 118, 101, 114, 99, 176, 214, 195, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{71, 64, 0, 16, 0, 0, 176, 13, 0, 1, 193, 0, 0, 0, 1, 240, 0, 42, 177, 4, 178, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
/*PMT*/ {71, 80, 0, 16,
|
||||
/*Start of payload*/
|
||||
0, 2, 176, 18, 0, 1, 193, 0, 0, 0xE1, 0x00, 0xF0, 0, 0x1B, 0xE1, 0, 0xF0, 0, 0x15, 0xBD, 0x4D, 0x56, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
}
|
||||
|
||||
donePSI := false
|
||||
ii:=0
|
||||
ii := 0
|
||||
for r.isRunning {
|
||||
h264Data, err := ioutil.ReadAll(inputReader)
|
||||
if err != nil {
|
||||
r.Error.Println(err.Error())
|
||||
fmt.Println("reading")
|
||||
var h264Data []byte
|
||||
switch(r.config.Input){
|
||||
case raspivid:
|
||||
go func(){
|
||||
for {
|
||||
h264Data = make([]byte, 1)
|
||||
io.ReadFull(inputReader, h264Data)
|
||||
h264Parser.InputByteChan<-h264Data[0]
|
||||
}
|
||||
}()
|
||||
case file:
|
||||
stats, err := r.inputFile.Stat()
|
||||
if err != nil {
|
||||
panic("Could not get file stats!")
|
||||
}
|
||||
h264Data = make([]byte, stats.Size())
|
||||
_, err = r.inputFile.Read(h264Data)
|
||||
if err != nil {
|
||||
r.Error.Println(err.Error())
|
||||
}
|
||||
fmt.Println("about to start sending data")
|
||||
for i := range h264Data {
|
||||
fmt.Printf("i: %v\n", i)
|
||||
h264Parser.InputByteChan<-h264Data[i]
|
||||
}
|
||||
fmt.Println("all data sent")
|
||||
}
|
||||
h264Parser.SendInputData(h264Data)
|
||||
|
||||
|
||||
if clip, err := r.ringBuffer.Get(); err != nil {
|
||||
r.Error.Println(err.Error())
|
||||
return
|
||||
|
@ -189,14 +228,16 @@ func (r *revidInst) input() {
|
|||
upperBound := clipSize + mp2tPacketSize
|
||||
if ii < 3 && !donePSI {
|
||||
packetByteSlice := startPackets[ii]
|
||||
copy(clip[clipSize:upperBound],packetByteSlice)
|
||||
copy(clip[clipSize:upperBound], packetByteSlice)
|
||||
ii++
|
||||
} else {
|
||||
donePSI = true
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
byteSlice,err := (<-generator.TsChan).ToByteSlice()
|
||||
fmt.Println("getting ts packet")
|
||||
tsPacket := <-generator.TsChan
|
||||
byteSlice, err := tsPacket.ToByteSlice()
|
||||
if err != nil {
|
||||
r.Error.Println(err.Error())
|
||||
}
|
||||
|
|
|
@ -33,13 +33,34 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
* Testing with file input
|
||||
*
|
||||
*/
|
||||
func TestFileInput(t *testing.T){
|
||||
config := Config{
|
||||
Input: file,
|
||||
InputFileName: "testInput.h264",
|
||||
Output: file,
|
||||
OutputFileName: "output/TestFileAsInput.ts",
|
||||
}
|
||||
revidInst, err := NewRevidInstance(config)
|
||||
if err != nil {
|
||||
t.Errorf("Should not have got error!")
|
||||
}
|
||||
revidInst.Start()
|
||||
time.Sleep(100*time.Second)
|
||||
revidInst.Stop()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Testing use with raspivid
|
||||
*/
|
||||
/*
|
||||
func TestRaspividInput(t *testing.T){
|
||||
config := Config{
|
||||
Input: raspivid,
|
||||
InputCmd: "raspivid",
|
||||
Output: file,
|
||||
OutputFileName: "output/TestRaspividOutput.ts",
|
||||
}
|
||||
|
@ -48,6 +69,10 @@ func TestRaspividInput(t *testing.T){
|
|||
t.Errorf("Should not have got an error!")
|
||||
}
|
||||
revidInst.Start()
|
||||
time.Sleep(5*time.Second)
|
||||
time.Sleep(100*time.Second)
|
||||
revidInst.Stop()
|
||||
}
|
||||
* */
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue