From d8eb94f9a067bb35f0ffa2d8637a2835efc7fd82 Mon Sep 17 00:00:00 2001 From: macbookpro Date: Sat, 15 Dec 2018 17:40:32 +0800 Subject: [PATCH] =?UTF-8?q?1=20fix=20keyframes=20may=20be=20incorrect=20bu?= =?UTF-8?q?g=20=E4=BF=AE=E6=94=B9=E4=BA=86=E5=85=B3=E9=94=AE=E5=B8=A7?= =?UTF-8?q?=E5=88=A4=E5=AE=9A=E5=8F=AF=E8=83=BD=E4=B8=8D=E6=AD=A3=E7=A1=AE?= =?UTF-8?q?=E7=9A=84bug=202=20fix=20H265=20keyframe=20not=20correct=20bug?= =?UTF-8?q?=20=E4=BF=AE=E6=94=B9=E4=BA=86265=E6=B5=81=E5=85=B3=E9=94=AE?= =?UTF-8?q?=E6=AD=A3=E4=B8=8D=E5=AF=B9=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rtsp/rtp-parser.go | 80 ++++++++++++++++++++++++++++++++++++++++++---- rtsp/sdp-parser.go | 2 ++ 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/rtsp/rtp-parser.go b/rtsp/rtp-parser.go index 2e5ab6eb..9e95b966 100644 --- a/rtsp/rtp-parser.go +++ b/rtsp/rtp-parser.go @@ -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 diff --git a/rtsp/sdp-parser.go b/rtsp/sdp-parser.go index f37527d0..d3cc1bdb 100644 --- a/rtsp/sdp-parser.go +++ b/rtsp/sdp-parser.go @@ -64,6 +64,8 @@ func ParseSDP(sdpRaw string) map[string]*SDPInfo { info.Codec = "aac" case "H264": info.Codec = "h264" + case "H265": + info.Codec = "h265" } if i, err := strconv.Atoi(keyval[1]); err == nil { info.TimeScale = i