Files
webrtc/main.go
2023-02-19 17:19:00 -08:00

158 lines
4.0 KiB
Go

package main
import (
"fmt"
"os"
"unsafe"
"github.com/giorgisio/goav/avcodec"
"github.com/giorgisio/goav/avutil"
"github.com/commaai/cereal"
zmq "github.com/pebbe/zmq4"
)
func main() {
// Create a new context
context, _ := zmq.NewContext()
defer context.Term()
// Connect to the socket
subscriber, _ := context.NewSocket(zmq.SUB)
defer subscriber.Close()
out := GetServiceURI("roadEncodeData")
fmt.Println(out)
subscriber.SetSubscribe("")
subscriber.Connect(out)
avcodec.AvcodecRegisterAll()
// Find the HEVC decoder
codec := avcodec.AvcodecFindDecoderByName("hevc")
if codec == nil {
fmt.Println("HEVC decoder not found")
return
}
codecContext := codec.AvcodecAllocContext3()
if codecContext == nil {
fmt.Println("Failed to allocate codec context")
os.Exit(1)
}
// Open codec
if codecContext.AvcodecOpen2(codec, nil) < 0 {
fmt.Println("Could not open codec")
os.Exit(1)
}
var lastIdx = -1
var seenIframe = false
var V4L2_BUF_FLAG_KEYFRAME = uint32(8)
for {
// Allocate video frame
pFrame := avutil.AvFrameAlloc()
var frame []byte
for frame == nil {
msgs := DrainSock(subscriber, true)
if len(msgs) > 0 {
for _, msg := range msgs {
evt, err := cereal.ReadRootEncodeData(msg)
if err != nil {
panic(err)
}
ts := evt.UnixTimestampNanos()
idx, err := evt.Idx()
if err != nil {
panic(err)
}
encodeId := idx.EncodeId()
idxFlags := idx.Flags()
frameId := idx.FrameId()
idxType := idx.Type().String()
segmentNum := idx.SegmentNum()
segmentId := idx.SegmentId()
fmt.Printf("ts: %d,frameId: %d,type:%s,encodeId: %d,segmentNum: %d,segmentId: %d,idxFlags: %d\n",
ts, frameId, idxType, encodeId, segmentNum, segmentId, idxFlags,
)
continue
if encodeId != 0 && encodeId != uint32(lastIdx+1) {
fmt.Println("DROP PACKET!")
}
lastIdx = int(encodeId)
if !seenIframe && (idxFlags&V4L2_BUF_FLAG_KEYFRAME) == 0 {
fmt.Println("waiting for iframe")
continue
}
if !seenIframe {
// Decode video frame
pkt := avcodec.AvPacketAlloc()
if pkt == nil {
panic("cannot allocate packet")
}
// AvPacketFromData
header, err := evt.Header()
if err != nil {
panic(err)
}
headerPtr := unsafe.Pointer(&header[0])
pkt.AvPacketFromData((*uint8)(headerPtr), len(header))
// pkt.AvInitPacket()
pkt.SetFlags(pkt.Flags() | avcodec.AV_CODEC_FLAG_TRUNCATED)
response := codecContext.AvcodecSendPacket(pkt)
if response < 0 {
fmt.Printf("Error while sending a packet to the decoder: %s\n", avutil.ErrorFromCode(response))
// panic("decoding error")
}
if response >= 0 {
response = codecContext.AvcodecReceiveFrame((*avcodec.Frame)(unsafe.Pointer(pFrame)))
if response == avutil.AvErrorEAGAIN || response == avutil.AvErrorEOF {
fmt.Println("decode error")
break
} else if response < 0 {
fmt.Printf("Error while receiving a frame from the decoder: %s\n", avutil.ErrorFromCode(response))
fmt.Println("DROP SURFACE")
continue
}
fmt.Println("??")
seenIframe = true
}
fmt.Println("sss")
// frames, err := codec.Decode(av.Packet{Data: evt.Data()})
// if err != nil {
// fmt.Println("DROP SURFACE")
// continue
// }
// if len(frames) == 0 {
// fmt.Println("DROP SURFACE")
// continue
// }
// assert(len(frames) == 1)
// frame = frames[0].Data
// framePts := frames[0].Pts
// frameTimebase := frames[0].Timebase
// frame = append(append(make([]byte, 0, len(frame)+FrameHeaderLen), encodeUint32(uint32(len(frame)))...), frame...)
// binary.LittleEndian.PutUint32(frame[4:], encodeUint64(framePts))
// binary.LittleEndian.PutUint32(frame[12:], encodeUint64(frameTimebase))
}
}
}
}
fmt.Println("Received frame with size:", len(frame), "bytes")
}
}