diff --git a/h264/h264Parser.go b/h264/h264Parser.go index e7ef2a61..ab80a1ce 100644 --- a/h264/h264Parser.go +++ b/h264/h264Parser.go @@ -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{} + } + } + } + } + } + } + } + */ } diff --git a/itut/standards.go b/itut/standards.go index b68d612e..96f66b2a 100644 --- a/itut/standards.go +++ b/itut/standards.go @@ -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} } diff --git a/revid/RevidInstance.go b/revid/RevidInstance.go index 03aaf4c4..14744fbb 100644 --- a/revid/RevidInstance.go +++ b/revid/RevidInstance.go @@ -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()) } diff --git a/revid/revid_test.go b/revid/revid_test.go index 16d1dbde..aa54dadf 100644 --- a/revid/revid_test.go +++ b/revid/revid_test.go @@ -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() } +* */ + + +