actioncam/libipcamera/RTPRelay.go
2025-11-24 20:56:27 +02:00

104 lines
1.6 KiB
Go

package libipcamera
import (
"bytes"
"context"
"encoding/binary"
"io"
"log"
"net"
"time"
)
type Frame struct {
Data []byte
}
type RTPRelay struct {
close bool
listener net.PacketConn
Context context.Context
Frames chan Frame
}
var closeFlag bool
func CreateRTPRelay(ctx context.Context) *RTPRelay {
conn, err := net.ListenPacket("udp", ":6669")
if err != nil {
log.Printf("ERROR: %s\n", err)
}
closeFlag = false
relay := &RTPRelay{
close: false,
listener: conn,
Context: ctx,
Frames: make(chan Frame, 30),
}
go relay.readLoop()
return relay
}
func (r *RTPRelay) readLoop() {
buf := make([]byte, 2048)
packetReader := bytes.NewReader(buf)
header := streamHeader{}
var payload []byte
frameBuffer := bytes.Buffer{}
for {
r.listener.SetReadDeadline(time.Now().Add(10 * time.Second))
select {
case <-r.Context.Done():
close(r.Frames)
return
default:
}
_, _, err := r.listener.ReadFrom(buf)
if err != nil {
continue
}
packetReader.Reset(buf)
binary.Read(packetReader, binary.BigEndian, &header)
if header.Magic != 0xBCDE {
continue
}
if header.Length > 0 {
payload = make([]byte, header.Length)
_, err := io.ReadFull(packetReader, payload)
if err != nil {
continue
}
} else {
payload = []byte{}
}
switch header.MessageType {
case 0x0001:
frameBuffer.Write(payload)
case 0x0002:
// Emit a full H264 frame
if frameBuffer.Len() > 0 {
cp := append([]byte{}, frameBuffer.Bytes()...)
r.Frames <- Frame{Data: cp}
frameBuffer.Reset()
}
}
}
}
func (r *RTPRelay) Stop() {
closeFlag = true
r.close = true
r.listener.Close()
close(r.Frames)
}