diff --git a/README b/README index 757f61b..dd6a6eb 100644 --- a/README +++ b/README @@ -232,8 +232,9 @@ following fields are allowed: Supported video codecs include: - `"vp8"` (compatible with all supported browsers); - - `"vp9"` (better video quality than `"vp8"`, but incompatible with - older versions of Mac OS); + - `"vp9"` (better video quality, but incompatible with Safari); + - `"av1"` (even better video quality, only supported by some browsers, + recording is not supported); - `"h264"` (incompatible with Debian, Ubuntu, and some Android devices, recording is not supported). diff --git a/group/group.go b/group/group.go index fb9d15f..fac1d07 100644 --- a/group/group.go +++ b/group/group.go @@ -145,6 +145,12 @@ func codecFromName(name string) (webrtc.RTPCodecCapability, error) { "profile-id=0", nil, }, nil + case "av1": + return webrtc.RTPCodecCapability{ + "video/AV1X", 90000, 0, + "", + nil, + }, nil case "h264": return webrtc.RTPCodecCapability{ "video/H264", 90000, 0, @@ -186,6 +192,8 @@ func payloadType(codec webrtc.RTPCodecCapability) (webrtc.PayloadType, error) { return 96, nil case "video/vp9": return 98, nil + case "video/av1x": + return 104, nil case "video/h264": return 102, nil case "audio/opus": diff --git a/rtpconn/codec.go b/rtpconn/codec.go index cd3c857..011424c 100644 --- a/rtpconn/codec.go +++ b/rtpconn/codec.go @@ -43,6 +43,75 @@ func isKeyframe(codec string, packet *rtp.Packet) (bool, bool) { return (vp9.Payload[0] & 0xC) == 0, true } return (vp9.Payload[0] & 0x6) == 0, true + } else if strings.EqualFold(codec, "video/av1x") { + if len(packet.Payload) < 2 { + return false, true + } + if (packet.Payload[0] & 0x88) != 0x08 { + return false, true + } + w := (packet.Payload[0] & 0x30) >> 4 + + getObu := func(data []byte) ([]byte, int) { + offset := 0 + length := 0 + for { + if len(data) <= offset { + return nil, 0 + } + l := data[offset] + length = length*128 + int(l&0x7f) + offset++ + if (l & 0x80) == 0 { + break + } + } + if len(data) < offset+length { + return nil, 0 + } + return data[offset : offset+length], offset + length + } + var obu1, obu2 []byte + if w == 1 { + obu1 = packet.Payload[1:] + } else { + var o int + obu1, o = getObu(packet.Payload[1:]) + if len(obu1) == 0 { + return false, false + } + if w == 2 { + obu2 = packet.Payload[1+o:] + } else { + obu2, _ = getObu(packet.Payload[1+o:]) + } + } + 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") { if len(packet.Payload) < 1 { return false, false