mirror of
https://github.com/bluenviron/mediamtx.git
synced 2025-12-20 02:00:05 -08:00
Some checks failed
code_lint / go (push) Has been cancelled
code_lint / go_mod (push) Has been cancelled
code_lint / docs (push) Has been cancelled
code_lint / api_docs (push) Has been cancelled
code_test / test_64 (push) Has been cancelled
code_test / test_32 (push) Has been cancelled
code_test / test_e2e (push) Has been cancelled
105 lines
2 KiB
Go
105 lines
2 KiB
Go
package webrtc
|
|
|
|
import (
|
|
"strings"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/bluenviron/gortsplib/v5/pkg/rtpsender"
|
|
"github.com/pion/rtcp"
|
|
"github.com/pion/rtp"
|
|
"github.com/pion/webrtc/v4"
|
|
)
|
|
|
|
// OutgoingTrack is a WebRTC outgoing track
|
|
type OutgoingTrack struct {
|
|
Caps webrtc.RTPCodecCapability
|
|
|
|
track *webrtc.TrackLocalStaticRTP
|
|
ssrc uint32
|
|
rtcpSender *rtpsender.Sender
|
|
rtpPacketsSent *uint64
|
|
}
|
|
|
|
func (t *OutgoingTrack) isVideo() bool {
|
|
return strings.Split(t.Caps.MimeType, "/")[0] == "video"
|
|
}
|
|
|
|
func (t *OutgoingTrack) setup(p *PeerConnection) error {
|
|
var trackID string
|
|
if t.isVideo() {
|
|
trackID = "video"
|
|
} else {
|
|
trackID = "audio"
|
|
}
|
|
|
|
var err error
|
|
t.track, err = webrtc.NewTrackLocalStaticRTP(
|
|
t.Caps,
|
|
trackID,
|
|
webrtcStreamID,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
sender, err := p.wr.AddTrack(t.track)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
t.ssrc = uint32(sender.GetParameters().Encodings[0].SSRC)
|
|
|
|
t.rtcpSender = &rtpsender.Sender{
|
|
ClockRate: int(t.track.Codec().ClockRate),
|
|
Period: 1 * time.Second,
|
|
TimeNow: time.Now,
|
|
WritePacketRTCP: func(pkt rtcp.Packet) {
|
|
p.wr.WriteRTCP([]rtcp.Packet{pkt}) //nolint:errcheck
|
|
},
|
|
}
|
|
t.rtcpSender.Initialize()
|
|
|
|
t.rtpPacketsSent = p.rtpPacketsSent
|
|
|
|
// incoming RTCP packets must always be read to make interceptors work
|
|
go func() {
|
|
buf := make([]byte, 1500)
|
|
for {
|
|
n, _, err2 := sender.Read(buf)
|
|
if err2 != nil {
|
|
return
|
|
}
|
|
|
|
_, err2 = rtcp.Unmarshal(buf[:n])
|
|
if err2 != nil {
|
|
panic(err2)
|
|
}
|
|
}
|
|
}()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *OutgoingTrack) close() {
|
|
if t.rtcpSender != nil {
|
|
t.rtcpSender.Close()
|
|
}
|
|
}
|
|
|
|
// WriteRTP writes a RTP packet.
|
|
func (t *OutgoingTrack) WriteRTP(pkt *rtp.Packet) error {
|
|
return t.WriteRTPWithNTP(pkt, time.Now())
|
|
}
|
|
|
|
// WriteRTPWithNTP writes a RTP packet.
|
|
func (t *OutgoingTrack) WriteRTPWithNTP(pkt *rtp.Packet, ntp time.Time) error {
|
|
// use right SSRC in packet to make rtcpSender work
|
|
pkt.SSRC = t.ssrc
|
|
|
|
t.rtcpSender.ProcessPacket(pkt, ntp, true)
|
|
|
|
atomic.AddUint64(t.rtpPacketsSent, 1)
|
|
|
|
return t.track.WriteRTP(pkt)
|
|
}
|