mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-08-07 06:15:15 +03:00
90 lines
2.3 KiB
Go
90 lines
2.3 KiB
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/pion/rtp"
|
|
"github.com/pion/rtp/codecs"
|
|
"github.com/pion/webrtc/v4"
|
|
"github.com/sagernet/sing/common/logger"
|
|
)
|
|
|
|
func AddTunnelTracks(pc *webrtc.PeerConnection, logger logger.ContextLogger, prefix string) *webrtc.TrackLocalStaticSample {
|
|
sampleTrack, _ := webrtc.NewTrackLocalStaticSample(
|
|
webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8},
|
|
"video", "tunnel-video",
|
|
)
|
|
audioTrack, _ := webrtc.NewTrackLocalStaticRTP(
|
|
webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus},
|
|
"audio", "tunnel-audio",
|
|
)
|
|
audioSender, audioErr := pc.AddTrack(audioTrack)
|
|
videoSender, videoErr := pc.AddTrack(sampleTrack)
|
|
logger.Debug(fmt.Sprintf("%s: AddTrack audio: sender=%v err=%v", prefix, audioSender != nil, audioErr))
|
|
logger.Debug(fmt.Sprintf("%s: AddTrack video: sender=%v err=%v", prefix, videoSender != nil, videoErr))
|
|
logger.Debug(fmt.Sprintf("%s: senders count: %d", prefix, len(pc.GetSenders())))
|
|
return sampleTrack
|
|
}
|
|
|
|
func ReadTrack(track *webrtc.TrackRemote, handler func([]byte), logger logger.ContextLogger, prefix string) {
|
|
if track.Codec().MimeType != webrtc.MimeTypeVP8 {
|
|
buf := make([]byte, UDPBufSize)
|
|
for {
|
|
if _, _, err := track.Read(buf); err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
var vp8Pkt codecs.VP8Packet
|
|
var pkt rtp.Packet
|
|
var frameBuf []byte
|
|
var lastSeq uint16
|
|
var haveLastSeq bool
|
|
frameValid := false
|
|
recvCount := 0
|
|
buf := make([]byte, RTPBufSize)
|
|
for {
|
|
n, _, err := track.Read(buf)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if pkt.Unmarshal(buf[:n]) != nil {
|
|
continue
|
|
}
|
|
if haveLastSeq && pkt.SequenceNumber != lastSeq+1 {
|
|
frameValid = false
|
|
frameBuf = frameBuf[:0]
|
|
}
|
|
lastSeq = pkt.SequenceNumber
|
|
haveLastSeq = true
|
|
vp8Payload, err := vp8Pkt.Unmarshal(pkt.Payload)
|
|
if err != nil {
|
|
frameValid = false
|
|
frameBuf = frameBuf[:0]
|
|
continue
|
|
}
|
|
if vp8Pkt.S == 1 {
|
|
frameBuf = frameBuf[:0]
|
|
frameValid = true
|
|
}
|
|
if !frameValid {
|
|
continue
|
|
}
|
|
frameBuf = append(frameBuf, vp8Payload...)
|
|
if !pkt.Marker {
|
|
continue
|
|
}
|
|
recvCount++
|
|
if recvCount <= 3 || recvCount%200 == 0 {
|
|
logger.Debug(fmt.Sprintf("%s: recv vp8 frame #%d %d bytes", prefix, recvCount, len(frameBuf)))
|
|
}
|
|
if handler != nil {
|
|
frame := make([]byte, len(frameBuf))
|
|
copy(frame, frameBuf)
|
|
handler(frame)
|
|
}
|
|
frameBuf = frameBuf[:0]
|
|
frameValid = false
|
|
}
|
|
}
|