Move keyframe handling to the sender side.

This is simpler and gets rid of ErrKeyframeNeeded.
This commit is contained in:
Juliusz Chroboczek
2021-05-11 22:36:56 +02:00
parent b2ea8e8533
commit c52e1f4ce0
5 changed files with 59 additions and 108 deletions
+4 -52
View File
@@ -4,7 +4,6 @@ import (
"errors"
"log"
"sort"
"strings"
"time"
"github.com/pion/rtp"
@@ -223,33 +222,22 @@ func sendKeyframe(kf []uint16, track conn.DownTrack, cache *packetcache.Cache) {
return
}
err = track.WriteRTP(&packet)
if err != nil && err != conn.ErrKeyframeNeeded {
if err != nil {
return
}
track.Accumulate(uint32(bytes))
}
}
const (
kfUnneeded = iota
kfNeededPLI
kfNeededFIR
kfNeededNewFIR
)
// rtpWriterLoop is the main loop of an rtpWriter.
func rtpWriterLoop(writer *rtpWriter, up *rtpUpConnection, track *rtpUpTrack) {
defer close(writer.done)
codec := track.track.Codec()
buf := make([]byte, packetcache.BufSize)
var packet rtp.Packet
local := make([]conn.DownTrack, 0)
kfNeeded := kfUnneeded
for {
select {
case action := <-writer.action:
@@ -277,8 +265,7 @@ func rtpWriterLoop(writer *rtpWriter, up *rtpUpConnection, track *rtpUpTrack) {
found, _, lts := track.cache.Last()
kts, _, kf := track.cache.Keyframe()
if strings.ToLower(codec.MimeType) == "video/vp8" &&
found && len(kf) > 0 {
if found && len(kf) > 0 {
if ((lts-kts)&0x80000000) != 0 ||
lts-kts < 2*90000 {
// we got a recent keyframe
@@ -288,8 +275,7 @@ func rtpWriterLoop(writer *rtpWriter, up *rtpUpConnection, track *rtpUpTrack) {
track.cache,
)
} else {
// Request a new keyframe
kfNeeded = kfNeededNewFIR
track.RequestKeyframe()
}
} else {
// no keyframe yet, one should
@@ -333,44 +319,10 @@ func rtpWriterLoop(writer *rtpWriter, up *rtpUpConnection, track *rtpUpTrack) {
for _, l := range local {
err := l.WriteRTP(&packet)
if err != nil {
if err == conn.ErrKeyframeNeeded {
kfNeeded = kfNeededPLI
} else {
continue
}
continue
}
l.Accumulate(uint32(bytes))
}
if kfNeeded > kfUnneeded {
kf, kfKnown :=
isKeyframe(codec.MimeType, &packet)
if kf {
kfNeeded = kfUnneeded
}
if kfNeeded >= kfNeededFIR {
err := up.sendFIR(
track,
kfNeeded >= kfNeededNewFIR,
)
if err == ErrUnsupportedFeedback {
kfNeeded = kfNeededPLI
} else {
kfNeeded = kfNeededFIR
}
}
if kfNeeded == kfNeededPLI {
up.sendPLI(track)
}
if !kfKnown {
// we cannot detect keyframes for
// this codec, reset our state
kfNeeded = kfUnneeded
}
}
}
}
}