|
|
|
@ -19,6 +19,7 @@ type RTPInfo struct {
|
|
|
|
|
Timestamp int |
|
|
|
|
SSRC int |
|
|
|
|
Payload []byte |
|
|
|
|
NaluType uint8 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func ParseRTP(rtpBytes []byte) *RTPInfo { |
|
|
|
@ -58,11 +59,39 @@ func ParseRTP(rtpBytes []byte) *RTPInfo {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
info.Payload = rtpBytes[offset:end] |
|
|
|
|
if end-offset < 1 { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
payloadHeader := rtpBytes[offset] //https://tools.ietf.org/html/rfc6184#section-5.2
|
|
|
|
|
info.NaluType = uint8(payloadHeader & 0x1F) |
|
|
|
|
return info |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (rtp *RTPInfo) IsKeyframeStart() bool { |
|
|
|
|
if len(rtp.Payload) >= 2 && rtp.Payload[0] == 0x7c && (rtp.Payload[1] == 0x87 || rtp.Payload[1] == 0x85) { |
|
|
|
|
var realNALU uint8 |
|
|
|
|
|
|
|
|
|
switch { |
|
|
|
|
case rtp.NaluType <= 23: |
|
|
|
|
realNALU = rtp.Payload[0] |
|
|
|
|
//log.Printf("Single NAL:%d", rtp.NaluType)
|
|
|
|
|
case rtp.NaluType == 28 || rtp.NaluType == 29: |
|
|
|
|
realNALU = rtp.Payload[1] |
|
|
|
|
if realNALU&0x80 != 0 { |
|
|
|
|
//log.Printf("FU NAL Begin :%d", rtp.NaluType)
|
|
|
|
|
} else { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
if realNALU&0x40 != 0 { |
|
|
|
|
//log.Printf("FU NAL End :%d", rtp.NaluType)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if realNALU&0x1F == 0x05 { |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
if realNALU&0x1F == 0x07 { // maybe sps pps header + key frame?
|
|
|
|
|
if len(rtp.Payload) < 200 { // consider sps pps header only.
|
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
return false |
|
|
|
@ -72,13 +101,50 @@ func (rtp *RTPInfo) IsKeyframeStartH265() bool {
|
|
|
|
|
if len(rtp.Payload) >= 3 { |
|
|
|
|
firstByte := rtp.Payload[0] |
|
|
|
|
headerType := (firstByte >> 1) & 0x3f |
|
|
|
|
if headerType == 49 { |
|
|
|
|
frametByte := rtp.Payload[2] |
|
|
|
|
frameType := frametByte & 0x3f |
|
|
|
|
rtpStart := (frametByte & 0x80) >> 7 |
|
|
|
|
if rtpStart == 1 && (frameType == 19 || frameType == 20 || frameType == 21 || frameType == 32 || frameType == 33 || frameType == 34) { |
|
|
|
|
return true |
|
|
|
|
var frameType uint8 |
|
|
|
|
if headerType == 49 { //Fragmentation Units
|
|
|
|
|
|
|
|
|
|
FUHeader := rtp.Payload[2] |
|
|
|
|
/* |
|
|
|
|
+---------------+ |
|
|
|
|
|0|1|2|3|4|5|6|7| |
|
|
|
|
+-+-+-+-+-+-+-+-+ |
|
|
|
|
|S|E| FuType | |
|
|
|
|
+---------------+ |
|
|
|
|
*/ |
|
|
|
|
rtpStart := (FUHeader & 0x80) != 0 |
|
|
|
|
if !rtpStart { |
|
|
|
|
if (FUHeader & 0x40) != 0 { |
|
|
|
|
//log.Printf("FU frame end")
|
|
|
|
|
} |
|
|
|
|
return false |
|
|
|
|
} else { |
|
|
|
|
//log.Printf("FU frame start")
|
|
|
|
|
} |
|
|
|
|
frameType = FUHeader & 0x3f |
|
|
|
|
} else if headerType == 48 { //Aggregation Packets
|
|
|
|
|
|
|
|
|
|
} else if headerType == 50 { //PACI Packets
|
|
|
|
|
|
|
|
|
|
} else { // Single NALU
|
|
|
|
|
/* |
|
|
|
|
+---------------+---------------+ |
|
|
|
|
|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| |
|
|
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|
|
|
|
|F| Type | LayerId | TID | |
|
|
|
|
+-------------+-----------------+ |
|
|
|
|
*/ |
|
|
|
|
frameType = firstByte & 0x7e |
|
|
|
|
} |
|
|
|
|
if frameType >= 16 && frameType <= 21 { |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
if frameType == 32 { |
|
|
|
|
// vps sps pps...
|
|
|
|
|
if len(rtp.Payload) < 200 { // consider sps pps header only.
|
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false |
|
|
|
|