Commit c8de6620 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Send non-trivial bitmaps during NACK forwarding.

parent 9f6e23aa
......@@ -515,25 +515,51 @@ func sendFIR(pc *webrtc.PeerConnection, ssrc uint32, seqno uint8) error {
func (up *rtpUpConnection) sendNACK(track *rtpUpTrack, first uint16, bitmap uint16) error {
if !track.hasRtcpFb("nack", "") {
return nil
return ErrUnsupportedFeedback
}
err := sendNACK(up.pc, track.track.SSRC(), first, bitmap)
err := sendNACKs(up.pc, track.track.SSRC(),
[]rtcp.NackPair{{first, rtcp.PacketBitmap(bitmap)}},
)
if err == nil {
track.cache.Expect(1 + bits.OnesCount16(bitmap))
}
return err
}
func sendNACK(pc *webrtc.PeerConnection, ssrc uint32, first uint16, bitmap uint16) error {
func (up *rtpUpConnection) sendNACKs(track *rtpUpTrack, seqnos []uint16) error {
count := len(seqnos)
if count == 0 {
return nil
}
if !track.hasRtcpFb("nack", "") {
return ErrUnsupportedFeedback
}
var nacks []rtcp.NackPair
for len(seqnos) > 0 {
if len(nacks) >= 240 {
log.Printf("NACK: packet overflow")
break
}
var f, b uint16
f, b, seqnos = packetcache.ToBitmap(seqnos)
nacks = append(nacks, rtcp.NackPair{f, rtcp.PacketBitmap(b)})
}
err := sendNACKs(up.pc, track.track.SSRC(), nacks)
if err == nil {
track.cache.Expect(count)
}
return err
}
func sendNACKs(pc *webrtc.PeerConnection, ssrc uint32, nacks []rtcp.NackPair) error {
packet := rtcp.Packet(
&rtcp.TransportLayerNack{
MediaSSRC: ssrc,
Nacks: []rtcp.NackPair{
{
first,
rtcp.PacketBitmap(bitmap),
},
},
Nacks: nacks,
},
)
return pc.WriteRTCP([]rtcp.Packet{packet})
......
......@@ -32,6 +32,7 @@ func readLoop(conn *rtpUpConnection, track *rtpUpTrack) {
isvideo := track.track.Kind() == webrtc.RTPCodecTypeVideo
codec := track.track.Codec().Name
sendNACK := track.hasRtcpFb("nack", "")
buf := make([]byte, packetcache.BufSize)
var packet rtp.Packet
for {
......@@ -87,7 +88,7 @@ func readLoop(conn *rtpUpConnection, track *rtpUpTrack) {
found, first, bitmap := track.cache.BitmapGet(
packet.SequenceNumber - unnacked,
)
if found {
if found && sendNACK {
err := conn.sendNACK(track, first, bitmap)
if err != nil {
log.Printf("%v", err)
......
......@@ -374,6 +374,10 @@ func nackWriter(conn *rtpUpConnection, track *rtpUpTrack) {
track.bufferedNACKs = nil
track.mu.Unlock()
if !track.hasRtcpFb("nack", "") {
return
}
// drop any nacks before the last keyframe
var cutoff uint16
found, seqno, _ := track.cache.KeyframeSeqno()
......@@ -409,7 +413,7 @@ func nackWriter(conn *rtpUpConnection, track *rtpUpTrack) {
return nacks[i]-cutoff < nacks[j]-cutoff
})
for _, nack := range nacks {
conn.sendNACK(track, nack, 0)
if len(nacks) > 0 {
conn.sendNACKs(track, nacks)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment