1
Fork 0

Make isKeyframe codec-agnostic.

This commit is contained in:
Juliusz Chroboczek 2020-12-25 16:39:12 +01:00
parent ed9377e38f
commit cc35931ad1
3 changed files with 71 additions and 20 deletions

48
rtpconn/rtp_test.go Normal file
View File

@ -0,0 +1,48 @@
package rtpconn
import (
"testing"
"github.com/pion/rtp"
)
func TestVP8Keyframe(t *testing.T) {
ps := [][]byte{
{
0x80, 0xe0, 0x71, 0x3e, 0x5d, 0x6f, 0x3c, 0xc5,
0x75, 0xc, 0x80, 0x96, 0x90, 0x80, 0xb0, 0x4c,
0x90, 0x2, 0x0, 0x9d, 0x1, 0x2a, 0x10, 0x0, 0x10,
0x0, 0x39, 0x3, 0x0, 0x0, 0x1c, 0x22, 0x16, 0x16,
0x22, 0x66, 0x12, 0x20, 0x4, 0x90, 0x40, 0x4e,
0x9e, 0x8d, 0xe9, 0x40, 0xfe, 0xff, 0xab, 0x59,
0x72, 0x30, 0xd1, 0xaf, 0xe4, 0x6a, 0x11, 0x3,
0xfd, 0x15, 0xe9, 0x2, 0x2e, 0xdf, 0xd9, 0xd1,
0xb8, 0x0, 0x0,
},
{
0x80, 0x6f, 0x61, 0x8f, 0xd5, 0x36, 0xdc, 0x15,
0x1b, 0x4a, 0xb5, 0x29, 0x78, 0x9, 0xa1, 0x93,
0xa0, 0x5b, 0xd8, 0xf1, 0xde, 0x87, 0x23, 0x5a,
0xb9, 0x19, 0x97, 0xb7, 0xbd, 0xbf, 0xf7, 0x6e,
0xad, 0x82, 0xc4, 0x70, 0x1c, 0xc9, 0x3a, 0xb4,
0x1f, 0x13, 0x45, 0xb5, 0xf1, 0x0, 0xa5, 0xa5,
0xa9, 0xd0, 0xa5, 0xdf, 0x67, 0x88, 0x26, 0x30,
0x32,
},
}
var packet rtp.Packet
for i, p := range ps {
err := packet.Unmarshal(p)
if err != nil {
t.Errorf("Unmarshal(p%v): %v", i, err)
}
kf, kfKnown := isKeyframe("video/vp8", &packet)
if kf != (i == 0) || !kfKnown {
t.Errorf("isKeyframe(p%v): %v %v", i, kf, kfKnown)
}
}
}

View File

@ -13,15 +13,26 @@ import (
"github.com/jech/galene/rtptime"
)
func isVP8Keyframe(packet *rtp.Packet) bool {
var vp8 codecs.VP8Packet
_, err := vp8.Unmarshal(packet.Payload)
if err != nil {
return false
}
// isKeyframe determines if packet is the start of a keyframe.
// It returns (true, true) if that is the case, (false, true) if that is
// definitely not the case, and (false, false) if the information cannot
// be determined.
func isKeyframe(codec string, packet *rtp.Packet) (bool, bool) {
switch strings.ToLower(codec) {
case "video/vp8":
var vp8 codecs.VP8Packet
_, err := vp8.Unmarshal(packet.Payload)
if err != nil || len(vp8.Payload) < 1 {
return false, false
}
return vp8.S != 0 && vp8.PID == 0 &&
len(vp8.Payload) > 0 && (vp8.Payload[0]&0x1) == 0
if vp8.S != 0 && vp8.PID == 0 && (vp8.Payload[0]&0x1) == 0 {
return true, true
}
return false, true
default:
return false, false
}
}
func readLoop(conn *rtpUpConnection, track *rtpUpTrack) {
@ -54,10 +65,7 @@ func readLoop(conn *rtpUpConnection, track *rtpUpTrack) {
track.jitter.Accumulate(packet.Timestamp)
kf := false
if isvideo && strings.ToLower(codec.MimeType) == "video/vp8" {
kf = isVP8Keyframe(&packet)
}
kf, _ := isKeyframe(codec.MimeType, &packet)
first, index := track.cache.Store(
packet.SequenceNumber, packet.Timestamp,

View File

@ -343,13 +343,8 @@ func rtpWriterLoop(writer *rtpWriter, up *rtpUpConnection, track *rtpUpTrack) {
}
if kfNeeded > kfUnneeded {
kf := false
kfValid := false
switch strings.ToLower(codec.MimeType) {
case "video/vp8":
kf = isVP8Keyframe(&packet)
kfValid = true
}
kf, kfKnown :=
isKeyframe(codec.MimeType, &packet)
if kf {
kfNeeded = kfUnneeded
}
@ -370,7 +365,7 @@ func rtpWriterLoop(writer *rtpWriter, up *rtpUpConnection, track *rtpUpTrack) {
up.sendPLI(track)
}
if !kfValid {
if !kfKnown {
// we cannot detect keyframes for
// this codec, reset our state
kfNeeded = kfUnneeded