mirror of https://github.com/EasyDarwin/EasyDarwin
fix some HK camera stream blurred issue
parent
05ba4e9837
commit
b7580fafe3
130
rtsp/pusher.go
130
rtsp/pusher.go
|
@ -19,8 +19,9 @@ type Pusher struct {
|
||||||
gopCacheLock sync.RWMutex
|
gopCacheLock sync.RWMutex
|
||||||
UDPServer *UDPServer
|
UDPServer *UDPServer
|
||||||
|
|
||||||
cond *sync.Cond
|
spsppsInSTAPaPack bool
|
||||||
queue []*RTPPack
|
cond *sync.Cond
|
||||||
|
queue []*RTPPack
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pusher *Pusher) String() string {
|
func (pusher *Pusher) String() string {
|
||||||
|
@ -231,20 +232,12 @@ func (pusher *Pusher) Start() {
|
||||||
|
|
||||||
if pusher.gopCacheEnable && pack.Type == RTP_TYPE_VIDEO {
|
if pusher.gopCacheEnable && pack.Type == RTP_TYPE_VIDEO {
|
||||||
pusher.gopCacheLock.Lock()
|
pusher.gopCacheLock.Lock()
|
||||||
if strings.EqualFold(pusher.VCodec(), "h264") {
|
if rtp := ParseRTP(pack.Buffer.Bytes()); rtp != nil && pusher.shouldSequeceStart(rtp) {
|
||||||
if rtp := ParseRTP(pack.Buffer.Bytes()); rtp != nil && rtp.IsKeyframeStart() {
|
pusher.gopCache = make([]*RTPPack, 0)
|
||||||
pusher.gopCache = make([]*RTPPack, 0)
|
|
||||||
}
|
|
||||||
pusher.gopCache = append(pusher.gopCache, pack)
|
|
||||||
} else if strings.EqualFold(pusher.VCodec(), "h265") {
|
|
||||||
if rtp := ParseRTP(pack.Buffer.Bytes()); rtp != nil && rtp.IsKeyframeStartH265() {
|
|
||||||
pusher.gopCache = make([]*RTPPack, 0)
|
|
||||||
}
|
|
||||||
pusher.gopCache = append(pusher.gopCache, pack)
|
|
||||||
}
|
}
|
||||||
|
pusher.gopCache = append(pusher.gopCache, pack)
|
||||||
pusher.gopCacheLock.Unlock()
|
pusher.gopCacheLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
pusher.BroadcastRTP(pack)
|
pusher.BroadcastRTP(pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,3 +317,114 @@ func (pusher *Pusher) ClearPlayer() {
|
||||||
v.Stop()
|
v.Stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pusher *Pusher) shouldSequeceStart(rtp *RTPInfo) bool {
|
||||||
|
if strings.EqualFold(pusher.VCodec(), "h264") {
|
||||||
|
var realNALU uint8
|
||||||
|
payloadHeader := rtp.Payload[0] //https://tools.ietf.org/html/rfc6184#section-5.2
|
||||||
|
NaluType := uint8(payloadHeader & 0x1F)
|
||||||
|
// log.Printf("RTP Type:%d", NaluType)
|
||||||
|
switch {
|
||||||
|
case NaluType <= 23:
|
||||||
|
realNALU = rtp.Payload[0]
|
||||||
|
log.Printf("Single NAL:%d", NaluType)
|
||||||
|
case NaluType == 28 || NaluType == 29:
|
||||||
|
realNALU = rtp.Payload[1]
|
||||||
|
if realNALU&0x40 != 0 {
|
||||||
|
log.Printf("FU NAL End :%02X", realNALU)
|
||||||
|
}
|
||||||
|
if realNALU&0x80 != 0 {
|
||||||
|
log.Printf("FU NAL Begin :%02X", realNALU)
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case NaluType == 24:
|
||||||
|
log.Printf("STAP-A")
|
||||||
|
off := 1
|
||||||
|
singleSPSPPS := 0
|
||||||
|
for {
|
||||||
|
nalSize := ((uint16(rtp.Payload[off])) << 8) | uint16(rtp.Payload[off+1])
|
||||||
|
if nalSize < 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
off += 2
|
||||||
|
nalUnit := rtp.Payload[off : off+int(nalSize)]
|
||||||
|
off += int(nalSize)
|
||||||
|
realNALU = nalUnit[0]
|
||||||
|
singleSPSPPS += int(realNALU & 0x1F)
|
||||||
|
if off >= len(rtp.Payload) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if singleSPSPPS == 0x0F {
|
||||||
|
pusher.spsppsInSTAPaPack = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if realNALU&0x1F == 0x05 {
|
||||||
|
if pusher.spsppsInSTAPaPack {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if realNALU&0x1F == 0x07 { // maybe sps pps header + key frame?
|
||||||
|
if len(rtp.Payload) < 200 { // consider sps pps header only.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
} else if strings.EqualFold(pusher.VCodec(), "h265") {
|
||||||
|
if len(rtp.Payload) >= 3 {
|
||||||
|
firstByte := rtp.Payload[0]
|
||||||
|
headerType := (firstByte >> 1) & 0x3f
|
||||||
|
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
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ type RTPInfo struct {
|
||||||
Timestamp int
|
Timestamp int
|
||||||
SSRC int
|
SSRC int
|
||||||
Payload []byte
|
Payload []byte
|
||||||
|
PayloadOffset int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseRTP(rtpBytes []byte) *RTPInfo {
|
func ParseRTP(rtpBytes []byte) *RTPInfo {
|
||||||
|
@ -58,94 +59,10 @@ func ParseRTP(rtpBytes []byte) *RTPInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info.Payload = rtpBytes[offset:end]
|
info.Payload = rtpBytes[offset:end]
|
||||||
|
info.PayloadOffset = offset
|
||||||
if end-offset < 1 {
|
if end-offset < 1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rtp *RTPInfo) IsKeyframeStart() bool {
|
|
||||||
var realNALU uint8
|
|
||||||
payloadHeader := rtp.Payload[0] //https://tools.ietf.org/html/rfc6184#section-5.2
|
|
||||||
NaluType := uint8(payloadHeader & 0x1F)
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case NaluType <= 23:
|
|
||||||
realNALU = rtp.Payload[0]
|
|
||||||
//log.Printf("Single NAL:%d", rtp.NaluType)
|
|
||||||
case NaluType == 28 || 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
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rtp *RTPInfo) IsKeyframeStartH265() bool {
|
|
||||||
if len(rtp.Payload) >= 3 {
|
|
||||||
firstByte := rtp.Payload[0]
|
|
||||||
headerType := (firstByte >> 1) & 0x3f
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue