mirror of
https://github.com/livekit/livekit.git
synced 2026-08-29 09:49:24 +00:00
Send PLI when target client doesn't have keyframes
This commit is contained in:
@@ -89,6 +89,9 @@ func (f *SimpleForwarder) ChannelType() ChannelType {
|
||||
|
||||
func (f *SimpleForwarder) Start() {
|
||||
f.once.Do(func() {
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
go f.rtcpWorker()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -469,6 +469,9 @@ func (p *Participant) downTracksRTCPWorker() {
|
||||
func (p *Participant) rtcpSendWorker() {
|
||||
// read from rtcpChan
|
||||
for pkts := range p.rtcpCh {
|
||||
for _, pkt := range pkts {
|
||||
logger.GetLogger().Debugw("writing RTCP", "packet", pkt)
|
||||
}
|
||||
if err := p.peerConn.WriteRTCP(pkts); err != nil {
|
||||
logger.GetLogger().Errorw("could not write RTCP to participant",
|
||||
"participant", p.id,
|
||||
|
||||
@@ -82,6 +82,8 @@ func (r *Room) Join(participant *Participant) error {
|
||||
"srcParticipant", p.ID())
|
||||
}
|
||||
}
|
||||
// start the workers once connectivity is established
|
||||
participant.Start()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-5
@@ -17,8 +17,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
creationDelay = 500 * time.Millisecond
|
||||
feedbackTypes = []webrtc.RTCPFeedback{{"goog-remb", ""}, {"nack", ""}, {"nack", "pli"}}
|
||||
creationDelay = 500 * time.Millisecond
|
||||
maxPLIFrequency = 1 * time.Second
|
||||
feedbackTypes = []webrtc.RTCPFeedback{{"goog-remb", ""}, {"nack", ""}, {"nack", "pli"}}
|
||||
)
|
||||
|
||||
// Track represents a remoteTrack that needs to be forwarded
|
||||
@@ -35,6 +36,7 @@ type Track struct {
|
||||
forwarders map[string]Forwarder
|
||||
receiver *Receiver
|
||||
lastNack int64
|
||||
lastPLI time.Time
|
||||
}
|
||||
|
||||
func NewTrack(pId string, rtcpCh chan []rtcp.Packet, track *webrtc.TrackRemote, receiver *Receiver) *Track {
|
||||
@@ -203,13 +205,19 @@ func (t *Track) forwardRTPWorker() {
|
||||
}
|
||||
|
||||
if err == sfu.ErrRequiresKeyFrame {
|
||||
delta := time.Now().Sub(t.lastPLI)
|
||||
if delta < maxPLIFrequency {
|
||||
continue
|
||||
}
|
||||
logger.GetLogger().Infow("keyframe required, sending PLI")
|
||||
rtcpPkts := []rtcp.Packet{
|
||||
&rtcp.PictureLossIndication{SenderSSRC: uint32(t.remoteTrack.SSRC()), MediaSSRC: pkt.SSRC},
|
||||
}
|
||||
// queue up a PLI, but don't block channel
|
||||
go func() {
|
||||
t.rtcpCh <- []rtcp.Packet{
|
||||
&rtcp.PictureLossIndication{SenderSSRC: forwarder.Track().SSRC(), MediaSSRC: pkt.SSRC},
|
||||
}
|
||||
t.rtcpCh <- rtcpPkts
|
||||
}()
|
||||
t.lastPLI = time.Now()
|
||||
} else if err != nil {
|
||||
logger.GetLogger().Warnw("could not forward packet to participant",
|
||||
"src", t.participantId,
|
||||
|
||||
@@ -229,8 +229,9 @@ func (d *DownTrack) writeSimpleRTP(pkt rtp.Packet) error {
|
||||
}
|
||||
}
|
||||
if !relay {
|
||||
// TODO: how do we sent PLI to the source?
|
||||
//return ErrRequiresKeyFrame
|
||||
// when we are writing to a new client and there isn't a keyframe, it makes it impossible
|
||||
// for clients to render a frame. we'll send an error for the track writer.
|
||||
return ErrRequiresKeyFrame
|
||||
}
|
||||
}
|
||||
d.snOffset = pkt.SequenceNumber - d.lastSN - 1
|
||||
|
||||
Reference in New Issue
Block a user