Send PLI when target client doesn't have keyframes

This commit is contained in:
David Zhao
2020-12-17 22:28:03 -08:00
parent 2111513fde
commit 050da05000
5 changed files with 24 additions and 7 deletions
+3
View File
@@ -89,6 +89,9 @@ func (f *SimpleForwarder) ChannelType() ChannelType {
func (f *SimpleForwarder) Start() {
f.once.Do(func() {
defer func() {
recover()
}()
go f.rtcpWorker()
})
}
+3
View File
@@ -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,
+2
View File
@@ -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
View File
@@ -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,
+3 -2
View File
@@ -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