mirror of
https://github.com/jech/galene.git
synced 2024-11-22 16:45:58 +01:00
Rewrite AV1 keyframe detection.
Metadata OBUs can appear between the sequence header and the first frame header.
This commit is contained in:
parent
4435a30a53
commit
d94e5583cd
1 changed files with 44 additions and 44 deletions
|
@ -47,71 +47,72 @@ func isKeyframe(codec string, packet *rtp.Packet) (bool, bool) {
|
||||||
if len(packet.Payload) < 2 {
|
if len(packet.Payload) < 2 {
|
||||||
return false, true
|
return false, true
|
||||||
}
|
}
|
||||||
|
// Z=0, N=1
|
||||||
if (packet.Payload[0] & 0x88) != 0x08 {
|
if (packet.Payload[0] & 0x88) != 0x08 {
|
||||||
return false, true
|
return false, true
|
||||||
}
|
}
|
||||||
w := (packet.Payload[0] & 0x30) >> 4
|
w := (packet.Payload[0] & 0x30) >> 4
|
||||||
|
|
||||||
getObu := func(data []byte) ([]byte, int) {
|
getObu := func(data []byte, last bool) ([]byte, int, bool) {
|
||||||
|
if last {
|
||||||
|
return data, len(data), false
|
||||||
|
}
|
||||||
offset := 0
|
offset := 0
|
||||||
length := 0
|
length := 0
|
||||||
for {
|
for {
|
||||||
if len(data) <= offset {
|
if len(data) <= offset {
|
||||||
return nil, 0
|
return nil, offset, offset > 0
|
||||||
}
|
}
|
||||||
l := data[offset]
|
l := data[offset]
|
||||||
length = length*128 + int(l&0x7f)
|
length |= int(l & 0x7f) << (offset * 7)
|
||||||
offset++
|
offset++
|
||||||
if (l & 0x80) == 0 {
|
if (l & 0x80) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(data) < offset+length {
|
if len(data) < offset+length {
|
||||||
return nil, 0
|
return data[offset:], len(data), true
|
||||||
}
|
}
|
||||||
return data[offset : offset+length], offset + length
|
return data[offset : offset+length],
|
||||||
|
offset + length, false
|
||||||
}
|
}
|
||||||
var obu1, obu2 []byte
|
offset := 1
|
||||||
if w == 1 {
|
i := 0
|
||||||
obu1 = packet.Payload[1:]
|
for {
|
||||||
} else {
|
obu, length, truncated :=
|
||||||
var o int
|
getObu(packet.Payload[offset:], int(w) == i+1)
|
||||||
obu1, o = getObu(packet.Payload[1:])
|
if len(obu) < 1 {
|
||||||
if len(obu1) == 0 {
|
|
||||||
return false, false
|
return false, false
|
||||||
}
|
}
|
||||||
if w == 2 {
|
tpe := (obu[0] & 0x38) >> 3
|
||||||
obu2 = packet.Payload[1+o:]
|
switch i {
|
||||||
} else {
|
case 0:
|
||||||
obu2, _ = getObu(packet.Payload[1+o:])
|
// OBU_SEQUENCE_HEADER
|
||||||
|
if tpe != 1 {
|
||||||
|
return false, true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// OBU_FRAME_HEADER or OBU_FRAME
|
||||||
|
if tpe == 3 || tpe == 6 {
|
||||||
|
if len(obu) < 2 {
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
// show_existing_frame == 0
|
||||||
|
if (obu[1] & 0x80) != 0 {
|
||||||
|
return false, true
|
||||||
|
}
|
||||||
|
// frame_type == KEY_FRAME
|
||||||
|
return (obu[1] & 0x60) == 0, true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if truncated || i >= int(w) {
|
||||||
|
// the first frame header is in a second
|
||||||
|
// packet, give up.
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
offset += length
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
if len(obu1) < 1 {
|
|
||||||
return false, false
|
|
||||||
}
|
|
||||||
header := obu1[0]
|
|
||||||
tpe := (header & 0x38) >> 3
|
|
||||||
if tpe != 1 {
|
|
||||||
return false, true
|
|
||||||
}
|
|
||||||
if w == 1 {
|
|
||||||
return false, false
|
|
||||||
}
|
|
||||||
if len(obu2) < 1 {
|
|
||||||
return false, false
|
|
||||||
}
|
|
||||||
header2 := obu2[0]
|
|
||||||
tpe2 := (header2 & 0x38) >> 3
|
|
||||||
if tpe2 != 6 {
|
|
||||||
return false, false
|
|
||||||
}
|
|
||||||
if len(obu2) < 2 {
|
|
||||||
return false, false
|
|
||||||
}
|
|
||||||
if (obu2[1] & 0x80) != 0 {
|
|
||||||
return false, true
|
|
||||||
}
|
|
||||||
return (obu2[1] & 0x60) == 0, false
|
|
||||||
} else if strings.EqualFold(codec, "video/h264") {
|
} else if strings.EqualFold(codec, "video/h264") {
|
||||||
if len(packet.Payload) < 1 {
|
if len(packet.Payload) < 1 {
|
||||||
return false, false
|
return false, false
|
||||||
|
@ -174,9 +175,8 @@ func isKeyframe(codec string, packet *rtp.Packet) (bool, bool) {
|
||||||
return (packet.Payload[1]&0x1F == 7), true
|
return (packet.Payload[1]&0x1F == 7), true
|
||||||
}
|
}
|
||||||
return false, false
|
return false, false
|
||||||
} else {
|
|
||||||
return false, false
|
|
||||||
}
|
}
|
||||||
|
return false, false
|
||||||
}
|
}
|
||||||
|
|
||||||
var errTruncated = errors.New("truncated packet")
|
var errTruncated = errors.New("truncated packet")
|
||||||
|
|
Loading…
Reference in a new issue