mirror of
https://github.com/comma-hacks/webrtc.git
synced 2025-10-06 00:26:52 +08:00
mysterious
This commit is contained in:
4
TODO
4
TODO
@@ -3,7 +3,9 @@
|
|||||||
- [x] camera switcher: discovered that it is broken https://github.com/aiortc/aiortc/issues/304 meanwhile Pion has been supporting it for 3 years https://github.com/pion/webrtc/pull/1527
|
- [x] camera switcher: discovered that it is broken https://github.com/aiortc/aiortc/issues/304 meanwhile Pion has been supporting it for 3 years https://github.com/pion/webrtc/pull/1527
|
||||||
beginning of port from python/aiortc to go/pion ... maybe other issues around performance will be resolved too by doing so.
|
beginning of port from python/aiortc to go/pion ... maybe other issues around performance will be resolved too by doing so.
|
||||||
- [x] write a go version of the compressed_vipc decoder demo
|
- [x] write a go version of the compressed_vipc decoder demo
|
||||||
- [ ] write a Pion-compatible vision IPC track by looking at https://github.com/pion/webrtc/blob/master/examples/rtp-to-webrtc/main.go and https://github.com/asticode/go-astiav/blob/master/examples/transcoding/main.go
|
- [x] write a Pion-compatible vision IPC track by looking at https://github.com/pion/webrtc/blob/master/examples/rtp-to-webrtc/main.go and https://github.com/asticode/go-astiav/blob/master/examples/transcoding/main.go
|
||||||
|
- [ ] debug why we dont see anything on the iOS side even though it appears RTP packets are flowing out
|
||||||
|
- [ ] integrate bandwidth estimation https://github.com/pion/webrtc/blob/master/examples/bandwidth-estimation-from-disk/main.go
|
||||||
- battery view
|
- battery view
|
||||||
- lowcam view
|
- lowcam view
|
||||||
- multicam
|
- multicam
|
||||||
|
@@ -53,11 +53,14 @@ func NewEncoder(params EncoderParams) (ts *Encoder, err error) {
|
|||||||
|
|
||||||
s.encCodecContext.SetHeight(params.Height)
|
s.encCodecContext.SetHeight(params.Height)
|
||||||
s.encCodecContext.SetPixelFormat(params.PixelFormat)
|
s.encCodecContext.SetPixelFormat(params.PixelFormat)
|
||||||
s.encCodecContext.SetBitRate(1000)
|
s.encCodecContext.SetBitRate(200_000)
|
||||||
s.encCodecContext.SetSampleAspectRatio(params.AspectRatio)
|
s.encCodecContext.SetSampleAspectRatio(params.AspectRatio)
|
||||||
s.encCodecContext.SetTimeBase(params.TimeBase)
|
s.encCodecContext.SetTimeBase(params.TimeBase)
|
||||||
s.encCodecContext.SetWidth(params.Width)
|
s.encCodecContext.SetWidth(params.Width)
|
||||||
|
|
||||||
|
// Update flags
|
||||||
|
s.encCodecContext.SetFlags(s.encCodecContext.Flags().Add(astiav.CodecContextFlagGlobalHeader))
|
||||||
|
|
||||||
// Open codec context
|
// Open codec context
|
||||||
if err = s.encCodecContext.Open(s.encCodec, nil); err != nil {
|
if err = s.encCodecContext.Open(s.encCodec, nil); err != nil {
|
||||||
err = fmt.Errorf("encoder: opening codec context failed: %w", err)
|
err = fmt.Errorf("encoder: opening codec context failed: %w", err)
|
||||||
|
10
main.go
10
main.go
@@ -21,12 +21,12 @@ func main() {
|
|||||||
<-signal.PairWaitChannel
|
<-signal.PairWaitChannel
|
||||||
}
|
}
|
||||||
signal.OnPeerConnectionCreated = func(pc *webrtc.PeerConnection) {
|
signal.OnPeerConnectionCreated = func(pc *webrtc.PeerConnection) {
|
||||||
// ReplaceTrack("road", pc)
|
ReplaceTrack("road", pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
visionTrack, _ = NewVisionIpcTrack("roadEncodeData")
|
// visionTrack, _ = NewVisionIpcTrack("roadEncodeData")
|
||||||
videoTrack, _ := visionTrack.NewTrackRTP()
|
// _, _ = visionTrack.NewTrackRTP()
|
||||||
visionTrack.StartRTP(videoTrack)
|
// visionTrack.StartRTP()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {}
|
select {}
|
||||||
@@ -78,7 +78,7 @@ func ReplaceTrack(prefix string, peerConnection *webrtc.PeerConnection) {
|
|||||||
log.Println(fmt.Errorf("main: peer connection closed due to error: %w", err))
|
log.Println(fmt.Errorf("main: peer connection closed due to error: %w", err))
|
||||||
}
|
}
|
||||||
} else if connectionState.String() == "connected" {
|
} else if connectionState.String() == "connected" {
|
||||||
go visionTrack.StartRTP(videoTrack)
|
go visionTrack.StartRTP()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -5,13 +5,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/asticode/go-astiav"
|
"github.com/asticode/go-astiav"
|
||||||
"github.com/commaai/cereal"
|
"github.com/commaai/cereal"
|
||||||
zmq "github.com/pebbe/zmq4"
|
zmq "github.com/pebbe/zmq4"
|
||||||
"github.com/pion/rtp/v2"
|
"github.com/pion/rtp"
|
||||||
"github.com/pion/rtp/v2/codecs"
|
"github.com/pion/rtp/v2/codecs"
|
||||||
"github.com/pion/webrtc/v3"
|
"github.com/pion/webrtc/v3"
|
||||||
)
|
)
|
||||||
@@ -33,14 +32,15 @@ type VisionIpcTrack struct {
|
|||||||
seenIframe bool
|
seenIframe bool
|
||||||
pkt *astiav.Packet
|
pkt *astiav.Packet
|
||||||
f *astiav.Frame
|
f *astiav.Frame
|
||||||
|
encoder *Encoder
|
||||||
|
packetizer rtp.Packetizer
|
||||||
|
videoTrack *webrtc.TrackLocalStaticRTP
|
||||||
|
|
||||||
networkLatency float64
|
networkLatency float64
|
||||||
frameLatency float64
|
frameLatency float64
|
||||||
processLatency float64
|
processLatency float64
|
||||||
pcLatency float64
|
pcLatency float64
|
||||||
timeQ []int64
|
timeQ []int64
|
||||||
|
|
||||||
Frame chan *Frame
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Frame struct {
|
type Frame struct {
|
||||||
@@ -112,8 +112,6 @@ func NewVisionIpcTrack(name string) (track *VisionIpcTrack, err error) {
|
|||||||
processLatency: 0.0,
|
processLatency: 0.0,
|
||||||
pcLatency: 0.0,
|
pcLatency: 0.0,
|
||||||
timeQ: []int64{},
|
timeQ: []int64{},
|
||||||
|
|
||||||
Frame: make(chan *Frame),
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,17 +144,14 @@ func (v *VisionIpcTrack) Stop() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
Open = false
|
Open = false
|
||||||
defer func() {
|
|
||||||
v.f.Free()
|
v.f.Free()
|
||||||
v.pkt.Free()
|
v.pkt.Free()
|
||||||
v.stream.decCodecContext.Free()
|
v.stream.decCodecContext.Free()
|
||||||
v.subscriber.Close()
|
v.subscriber.Close()
|
||||||
v.context.Term()
|
v.context.Term()
|
||||||
}()
|
|
||||||
<-v.Frame
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VisionIpcTrack) Start() {
|
func (v *VisionIpcTrack) Start(OnFrame func(outFrame *Frame)) {
|
||||||
if Open {
|
if Open {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -166,6 +161,9 @@ func (v *VisionIpcTrack) Start() {
|
|||||||
if len(msgs) > 0 {
|
if len(msgs) > 0 {
|
||||||
for _, msg := range msgs {
|
for _, msg := range msgs {
|
||||||
|
|
||||||
|
v.pkt.Unref()
|
||||||
|
v.f.Unref()
|
||||||
|
|
||||||
evt, err := cereal.ReadRootEvent(msg)
|
evt, err := cereal.ReadRootEvent(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(fmt.Errorf("cereal read root event failed: %w", err))
|
log.Fatal(fmt.Errorf("cereal read root event failed: %w", err))
|
||||||
@@ -272,33 +270,11 @@ func (v *VisionIpcTrack) Start() {
|
|||||||
len(data),
|
len(data),
|
||||||
v.name,
|
v.name,
|
||||||
)
|
)
|
||||||
v.Frame <- &Frame{Frame: v.f, Roll: roll}
|
outFrame := &Frame{Frame: v.f, Roll: roll}
|
||||||
|
OnFrame(outFrame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(v.Frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVisionIPCTrack(name string) {
|
|
||||||
track, err := NewVisionIpcTrack(name)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(fmt.Errorf("main: creating track failed: %w", err))
|
|
||||||
}
|
|
||||||
defer track.Stop()
|
|
||||||
|
|
||||||
// Handle ffmpeg logs
|
|
||||||
astiav.SetLogLevel(astiav.LogLevelError)
|
|
||||||
astiav.SetLogCallback(func(l astiav.LogLevel, fmt, msg, parent string) {
|
|
||||||
log.Printf("ffmpeg log: %s (level: %d)\n", strings.TrimSpace(msg), l)
|
|
||||||
})
|
|
||||||
|
|
||||||
go track.Start()
|
|
||||||
|
|
||||||
for frame := range track.Frame {
|
|
||||||
// Do something with decoded frame
|
|
||||||
fmt.Println(frame.Roll)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VisionIpcTrack) NewTrackRTP() (videoTrack *webrtc.TrackLocalStaticRTP, err error) {
|
func (v *VisionIpcTrack) NewTrackRTP() (videoTrack *webrtc.TrackLocalStaticRTP, err error) {
|
||||||
@@ -307,10 +283,11 @@ func (v *VisionIpcTrack) NewTrackRTP() (videoTrack *webrtc.TrackLocalStaticRTP,
|
|||||||
MimeType: webrtc.MimeTypeH264,
|
MimeType: webrtc.MimeTypeH264,
|
||||||
ClockRate: 90000,
|
ClockRate: 90000,
|
||||||
}, "video", "pion")
|
}, "video", "pion")
|
||||||
|
v.videoTrack = videoTrack
|
||||||
return videoTrack, err
|
return videoTrack, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (visionTrack *VisionIpcTrack) StartRTP(videoTrack *webrtc.TrackLocalStaticRTP) {
|
func (visionTrack *VisionIpcTrack) StartRTP() {
|
||||||
encoderParams := EncoderParams{
|
encoderParams := EncoderParams{
|
||||||
Width: visionTrack.Width(),
|
Width: visionTrack.Width(),
|
||||||
Height: visionTrack.Height(),
|
Height: visionTrack.Height(),
|
||||||
@@ -327,23 +304,25 @@ func (visionTrack *VisionIpcTrack) StartRTP(videoTrack *webrtc.TrackLocalStaticR
|
|||||||
}
|
}
|
||||||
defer encoder.Close()
|
defer encoder.Close()
|
||||||
|
|
||||||
go visionTrack.Start()
|
visionTrack.encoder = encoder
|
||||||
defer visionTrack.Stop()
|
|
||||||
|
|
||||||
// Create a H.264 payloader
|
// Create a H.264 payloader
|
||||||
payloader := &codecs.H264Payloader{}
|
payloader := &codecs.H264Payloader{}
|
||||||
|
|
||||||
// Create a RTP packetizer with some parameters
|
// Create a RTP packetizer with some parameters
|
||||||
packetizer := rtp.NewPacketizer(
|
visionTrack.packetizer = rtp.NewPacketizer(
|
||||||
1600,
|
1200,
|
||||||
96,
|
0, // Value is handled when writing
|
||||||
1,
|
0, // Value is handled when writing
|
||||||
payloader,
|
payloader,
|
||||||
rtp.NewRandomSequencer(),
|
rtp.NewRandomSequencer(),
|
||||||
|
visionTrack.videoTrack.Codec().ClockRate,
|
||||||
)
|
)
|
||||||
|
|
||||||
for visionTrack != nil {
|
visionTrack.Start(visionTrack.HandleFrameRTP)
|
||||||
for frame := range visionTrack.Frame {
|
}
|
||||||
|
|
||||||
|
func (v *VisionIpcTrack) HandleFrameRTP(frame *Frame) {
|
||||||
fmt.Println(frame.Roll)
|
fmt.Println(frame.Roll)
|
||||||
|
|
||||||
// so right now frame is a raw decoded AVFrame
|
// so right now frame is a raw decoded AVFrame
|
||||||
@@ -352,29 +331,22 @@ func (visionTrack *VisionIpcTrack) StartRTP(videoTrack *webrtc.TrackLocalStaticR
|
|||||||
|
|
||||||
// we need to:
|
// we need to:
|
||||||
// 1. transcode to h264 with adaptive bitrate using astiav
|
// 1. transcode to h264 with adaptive bitrate using astiav
|
||||||
outFrame, err := encoder.Encode(avframe)
|
outFrame, err := v.encoder.Encode(avframe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(fmt.Errorf("encode error: %w", err))
|
log.Println(fmt.Errorf("encode error: %w", err))
|
||||||
|
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. create an RTP packet with h264 data inside using pion's rtp packetizer
|
// 2. create an RTP packet with h264 data inside using pion's rtp packetizer
|
||||||
log.Println(outFrame.Duration())
|
samples := uint32((1.0 / v.encoder.Stream.encCodecContext.TimeBase().ToDouble()) * float64(visionTrack.videoTrack.Codec().ClockRate))
|
||||||
rtpPackets := packetizer.Packetize(outFrame.Data(), uint32(outFrame.Duration()))
|
rtpPackets := v.packetizer.Packetize(outFrame.Data(), samples)
|
||||||
|
|
||||||
// 3. write the RTP packet to the videoTrack
|
// 3. write the RTP packet to the videoTrack
|
||||||
// Loop over the RTP packets and send them to an output stream
|
// Loop over the RTP packets and send them to an output stream
|
||||||
for rtpPacketNo, rtpPacket := range rtpPackets {
|
for _, rtpPacket := range rtpPackets {
|
||||||
// Write the RTP packet to output
|
|
||||||
data, err := rtpPacket.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
log.Println(fmt.Errorf("rtp marshall error: %w", err))
|
|
||||||
|
|
||||||
continue
|
err = v.videoTrack.WriteRTP(rtpPacket)
|
||||||
}
|
|
||||||
|
|
||||||
bytesWritten, err := videoTrack.Write(data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, io.ErrClosedPipe) {
|
if errors.Is(err, io.ErrClosedPipe) {
|
||||||
// The peerConnection has been closed.
|
// The peerConnection has been closed.
|
||||||
@@ -384,10 +356,7 @@ func (visionTrack *VisionIpcTrack) StartRTP(videoTrack *webrtc.TrackLocalStaticR
|
|||||||
log.Println(fmt.Errorf("rtp write error: %w", err))
|
log.Println(fmt.Errorf("rtp write error: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("RTP(%d:%d)", rtpPacketNo, bytesWritten)
|
// log.Printf("RTP(%d)", rtpPacketNo)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user