[feat] rtp unpacker支持hevc ap格式

pull/211/head
q191201771 3 years ago
parent ace574dfb9
commit accb2092d5

@ -8,6 +8,8 @@
package rtprtcp
// h264的格式
//
// rfc3984 5.2. Common Structure of the RTP Payload Format
// Table 1. Summary of NAL unit types and their payload structures
//
@ -22,13 +24,19 @@ package rtprtcp
// 28 FU-A Fragmentation unit 5.8
// 29 FU-B Fragmentation unit 5.8
// 30-31 undefined -
//
// h265的格式
//
// rfc7798
// 4.4.2. Aggregation Packets (APs)
// 4.4.3. Fragmentation Units
const (
NaluTypeAvcSingleMax = 23
NaluTypeAvcStapa = 24 // one packet, multiple nals
NaluTypeAvcFua = 28
// NaluTypeHevcFua TODO(chef): hevc有stapa格式吗
NaluTypeHevcAp = 48
NaluTypeHevcFua = 49
)

@ -43,7 +43,8 @@ const (
PositionTypeFuaStart uint8 = 2
PositionTypeFuaMiddle uint8 = 3
PositionTypeFuaEnd uint8 = 4
PositionTypeStapa uint8 = 5
PositionTypeStapa uint8 = 5 // 1个rtp包包含多个帧目前供h264的stapa使用
PositionTypeAp uint8 = 6 // 1个rtp包包含多个帧目前供h265的ap使用
)
type RtpHeader struct {

@ -9,10 +9,12 @@
package rtprtcp
import (
"encoding/hex"
"github.com/q191201771/lal/pkg/avc"
"github.com/q191201771/lal/pkg/base"
"github.com/q191201771/lal/pkg/hevc"
"github.com/q191201771/naza/pkg/bele"
"github.com/q191201771/naza/pkg/nazabytes"
)
type RtpUnpackerAvcHevc struct {
@ -59,19 +61,26 @@ func (unpacker *RtpUnpackerAvcHevc) TryUnpackOne(list *RtpPacketList) (unpackedF
unpacker.onAvPacket(pkt)
return true, first.Packet.Header.Seq
case PositionTypeStapa:
case PositionTypeStapa, PositionTypeAp:
skip := uint32(1)
if first.Packet.positionType == PositionTypeStapa {
skip = 1
} else if first.Packet.positionType == PositionTypeAp {
skip = 2
}
var pkt base.AvPacket
pkt.PayloadType = unpacker.payloadType
pkt.Timestamp = int64(first.Packet.Header.Timestamp / uint32(unpacker.clockRate/1000))
// 跳过首字节并且将多nalu前的2字节长度替换成4字节长度
buf := first.Packet.Raw[first.Packet.Header.payloadOffset+1:]
// 跳过前面的字节并且将多nalu前的2字节长度替换成4字节长度
buf := first.Packet.Raw[first.Packet.Header.payloadOffset+skip:]
// 使用两次遍历,第一次遍历找出总大小,第二次逐个拷贝,目的是使得内存块一次就申请好,不用动态扩容造成额外性能开销
totalSize := 0
for i := 0; i != len(buf); {
if len(buf)-i < 2 {
Log.Errorf("invalid STAP-A packet.")
Log.Errorf("invalid STAP-A packet. len(buf)=%d, i=%d", len(buf), i)
return false, 0
}
naluSize := int(bele.BeUint16(buf[i:]))
@ -261,7 +270,8 @@ func calcPositionIfNeededAvc(pkt *RtpPacket) {
} else if outerNaluType == NaluTypeAvcStapa {
pkt.positionType = PositionTypeStapa
} else {
Log.Errorf("unknown nalu type. outerNaluType=%d", outerNaluType)
Log.Errorf("unknown nalu type. outerNaluType=%d(%d), header=%+v, len=%d, raw=%s",
b[0], outerNaluType, pkt.Header, len(pkt.Raw), hex.Dump(nazabytes.Prefix(pkt.Raw, 128)))
}
return
@ -323,9 +333,11 @@ func calcPositionIfNeededHevc(pkt *RtpPacket) {
pkt.positionType = PositionTypeFuaMiddle
return
} else if outerNaluType == NaluTypeHevcAp {
pkt.positionType = PositionTypeAp
return
}
// TODO chef: 没有实现 AP 48
Log.Errorf("unknown nalu type. outerNaluType=%d(%d), header=%+v, len=%d",
b[0], outerNaluType, pkt.Header, len(pkt.Raw))
Log.Errorf("unknown nalu type. outerNaluType=%d(%d), header=%+v, len=%d, raw=%s",
b[0], outerNaluType, pkt.Header, len(pkt.Raw), hex.Dump(nazabytes.Prefix(pkt.Raw, 128)))
}

@ -83,6 +83,25 @@ func TestHevcCase1(t *testing.T) {
})
}
func TestHevcCase2(t *testing.T) {
// vps40,sps42,pps44,sei4e
// 85 = 2 + 24 + 2 + 35 + 2 + 8 + 2 + 10
ss := []string{
"80601191bd9ee38884bc42f46001001840010c01ffff016000000300b0000003000003007bac09000023420101016000000300b0000003000003007ba003c08010e58dae4932f4dc040404020000084401c0f2f03c9000000a4e01e5040c7500008000",
}
out, _ := hex.DecodeString("0000001840010c01ffff016000000300b0000003000003007bac090000000023420101016000000300b0000003000003007ba003c08010e58dae4932f4dc0404040200000000084401c0f2f03c90000000000a4e01e5040c7500008000")
testHelperTemplete(t, base.AvPacketPtHevc, 90000, 128, ss, func(rtpPackets []RtpPacket) []base.AvPacket {
return []base.AvPacket{
{
Timestamp: 35347852,
PayloadType: base.AvPacketPtHevc,
Payload: out,
},
}
})
}
func TestAacCase1(t *testing.T) {
ss := []string{
"80e10e9a56843e4cf0bdf2fe00102d10214e6c425f74815f92415f94415f924100000114008a004027f313d564a770026fd01203c9cbac420e1aecaa41efb4619391309daa7938b4b905989c5c293c024819e4234eb324934327e3f083c98c2220137bc9b5b2bae5809351710e4bfec0dec11fffe0ab6e568f8357fb74c3461e892fc3a4e22ac512fa73bdc13004b9d73e21c5221387922692939994e38ab1516ea2cfb64df8cffb5468a81e4704f255a5139f7f21d622b944e0b08221916d4ba6e10a31b2a148c38642d1c8b2b12a15681c0f0b589160feb32b43c7ebade413590916a934148ca7915d6250904e5172a3ecc612ab23fd4431b0eef591be52155e4a0ac8564108012689c4df89221892e50d8fca64a747bb2313908211004222ea6a848132e87935978e03845905ccc057c743c7424e64e2338bfe52090d4a5a961f35ec5e14befbc2b3d41f89bdfe949fc2dd40e141b13e397f84f7e1ef43f303df77407bdacc01c2832c3d3df65fe3bfde0001f37f85f4a021f27baf11e4f388fd5ce464337648fc89e6043a0c8268a44f0e024e112910c8b9bc282ee2e5587762b2752c08a422ac99558f904273f858d9de9938ef2502493ae3217c247410eb39395f084a117f6486161103c5cab0881d7c24ffd7123cdcac226bc292c2dc213d04f0b26dd864e6e149c3a4468a48d86124209e172166c5b331e434c8cae4276e191acc2682d692a51210c1ce2254102e048435919442449f2c57bb271364fbb67f1d79364ee004a28c88e75dd53210eef613186531f22908a5253a87e66423fe1bffef7dd95fed588acf815908808fefff2ffef581fe23b2b8e9fdfbd7e3f7071c05d40ec89401efbdf87beee9a9c1eff2d054c0f7ff5febc514514514514514514517d7fe0faf145145111fc0dd8218d9f9d064ee8895cb84ee848064e7593530495f87ffa276e76549a4e6c0e381270c24ea288e0e1d8ad270f0dc243210e413a84b160e085b10a416be12011022b31354b202020771fe376bf6afe387e67fe0fee8087bee102bf415fa0afd0400000e3e3e3fe001f8f8ff53eff60fafab04fe0877121cebad11c16048271174dc251cbdd3da84e0c9ba23dd312b26500020154a269d9c4520270444131665313103f0f7412d40de5c59cfff0f6383440fc588e986f10b35ddbfdb6be780f30eb25f49fd7e479062097adbc044ba3e0c956ef043c31d188a23d453e83ca71ca44df64805f4514916e71c7e760674293094980642012d104ba2cacd260456e2e93a8c1f492739f9dd445aba9241088de157cb3d976e20888a41b34808f3a4ca181528c989641e0a187dc5443494c896e4421711580a84276a12a229662108289464d105b1513f80841836f009c987f86969641eea943c86c475685fb09043ae947ac5d22ff6ff7c1d380a48885c2a7d03905668ec9fd1fcdf7fc700450094d16f034c90003df9240b851764658e101efb8ea83855071d6871c5126a8385556aa0db094e571d9dc7271352b846810c4e24000000000000038e60384c4f09800000021e17eb447ca381218ff036078221ec1e7843a466acc013c0130585c7518330993235855b71158610843210aa9ba05c22ea5984de5e1227e3e4d2dd942a1659f5320232b45bb6c6418df87b313c727fc3f1d170a6ecb0b74e4449209804a3bf270c98518182b79dd74412c24f7e4f45131a889442502df3928282006d0f165c6e4d39059e7404eb1092044c67267817686dc7dbe82281f1d2f65ddaf70e67250c77adbe39d09be32b8f0007d2f905140d3c34fb6784075ce77075dfb069da091017344c80b6b9a36ff1d93c22889d5a7ccaa2073ccf278e1f8e9c38e1c9a8f502b8e9c84938542ae3a7e1313c26240000000000000384c4f1cc4f09890000021f49fc3847d1b76e8613938122e759d2494b9e4634fc812ab747e3132beb075bf23fed67a0943a245082648a4d06e11166a25f110a24c0c993964042ff0a8d24e4108c489514499641221f84c013c06008e0301c2e0038e6009e0327c7326000001c",
@ -156,6 +175,13 @@ func TestAacCase2(t *testing.T) {
})
}
// testHelperTemplete
//
// @param hexRtpPackets: rtp包的二进制数组
// @param expectedFn:
// []RtpPacket: `hexRtpPackets`解析成的rtp包数组
// []base.AvPacket: rtp包数组解析成的AvPacket数组
//
func testHelperTemplete(t *testing.T, payloadType base.AvPacketPt, clockRate int, maxSize int, hexRtpPackets []string, expectedFn func([]RtpPacket) []base.AvPacket) {
rtpPackets, err := testHelperHexstream2rtppackets(hexRtpPackets)
assert.Equal(t, nil, err)
@ -171,6 +197,8 @@ func testHelperAddPrefixLength(in []byte) (out []byte) {
return
}
// ---------------------------------------------------------------------------------------------------------------------
func testHelperUnpack(payloadType base.AvPacketPt, clockRate int, maxSize int, rtpPackets []RtpPacket) []base.AvPacket {
var outPkts []base.AvPacket
unpacker := DefaultRtpUnpackerFactory(payloadType, clockRate, maxSize, func(pkt base.AvPacket) {

Loading…
Cancel
Save