feat: Added RTSP receiver reports
This commit is contained in:
parent
4db17be740
commit
1a6f9470d6
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/honuworx/vdk/codec/h264parser"
|
"github.com/honuworx/vdk/codec/h264parser"
|
||||||
"github.com/honuworx/vdk/codec/h265parser"
|
"github.com/honuworx/vdk/codec/h265parser"
|
||||||
"github.com/honuworx/vdk/format/rtsp/sdp"
|
"github.com/honuworx/vdk/format/rtsp/sdp"
|
||||||
|
"github.com/pion/rtcp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -260,6 +261,8 @@ func (client *RTSPClient) startStream() {
|
|||||||
header := make([]byte, 4)
|
header := make([]byte, 4)
|
||||||
first := make([]byte, 2)
|
first := make([]byte, 2)
|
||||||
failed := 0
|
failed := 0
|
||||||
|
var ssrc uint32
|
||||||
|
ssrc = 0
|
||||||
for {
|
for {
|
||||||
err := client.conn.SetDeadline(time.Now().Add(client.options.ReadWriteTimeout))
|
err := client.conn.SetDeadline(time.Now().Add(client.options.ReadWriteTimeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -272,6 +275,10 @@ func (client *RTSPClient) startStream() {
|
|||||||
client.Println("RTSP Client RTP keep-alive", err)
|
client.Println("RTSP Client RTP keep-alive", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ssrc != 0 {
|
||||||
|
client.sendRR(ssrc)
|
||||||
|
}
|
||||||
timer = time.Now()
|
timer = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +290,6 @@ func (client *RTSPClient) startStream() {
|
|||||||
client.Println("RTSP Client RTP Read Header", err)
|
client.Println("RTSP Client RTP Read Header", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
client.Println("Searching for 0x24 or 0x52 headers: ", first)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header[0] = first[0]
|
header[0] = first[0]
|
||||||
@ -295,9 +301,6 @@ func (client *RTSPClient) startStream() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
length := int32(binary.BigEndian.Uint16(header[2:]))
|
|
||||||
client.Println("Got frame header: ", header, length)
|
|
||||||
|
|
||||||
switch header[0] {
|
switch header[0] {
|
||||||
case 0x24:
|
case 0x24:
|
||||||
failed = 0
|
failed = 0
|
||||||
@ -326,7 +329,8 @@ func (client *RTSPClient) startStream() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pkt, got := client.RTPDemuxer(&content)
|
pkt, got, _ssrc := client.RTPDemuxer(&content)
|
||||||
|
ssrc = _ssrc
|
||||||
if !got {
|
if !got {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -369,6 +373,8 @@ func (client *RTSPClient) startStream() {
|
|||||||
failed = failed + 1
|
failed = failed + 1
|
||||||
client.Println("RTSP Client RTP Read DeSync: Failed frames", failed)
|
client.Println("RTSP Client RTP Read DeSync: Failed frames", failed)
|
||||||
|
|
||||||
|
ssrc = 0
|
||||||
|
|
||||||
if failed > 500 {
|
if failed > 500 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -376,6 +382,44 @@ func (client *RTSPClient) startStream() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *RTSPClient) sendRR(ssrc uint32) (err error) {
|
||||||
|
client.Println("Sending ReceiverReport", ssrc)
|
||||||
|
err = client.conn.SetDeadline(time.Now().Add(client.options.ReadWriteTimeout))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
client.seq++
|
||||||
|
|
||||||
|
rr := rtcp.ReceiverReport{}
|
||||||
|
recepReport := rtcp.ReceptionReport{}
|
||||||
|
|
||||||
|
rr.SSRC = ssrc
|
||||||
|
|
||||||
|
recepReport.SSRC = ssrc
|
||||||
|
recepReport.FractionLost = 0
|
||||||
|
recepReport.TotalLost = 0
|
||||||
|
recepReport.LastSequenceNumber = 0
|
||||||
|
recepReport.Jitter = 0
|
||||||
|
recepReport.LastSenderReport = 0
|
||||||
|
recepReport.Delay = 0
|
||||||
|
|
||||||
|
rr.Reports = append(rr.Reports, recepReport)
|
||||||
|
|
||||||
|
data, err := rr.Marshal()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
nb, err := client.connRW.Write(data)
|
||||||
|
|
||||||
|
if err != nil || nb == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (client *RTSPClient) request(method string, customHeaders map[string]string, uri string, one bool, nores bool) (err error) {
|
func (client *RTSPClient) request(method string, customHeaders map[string]string, uri string, one bool, nores bool) (err error) {
|
||||||
err = client.conn.SetDeadline(time.Now().Add(client.options.ReadWriteTimeout))
|
err = client.conn.SetDeadline(time.Now().Add(client.options.ReadWriteTimeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -574,19 +618,28 @@ func stringInBetween(str string, start string, end string) (result string) {
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) {
|
func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool, uint32) {
|
||||||
|
|
||||||
content := *payloadRAW
|
content := *payloadRAW
|
||||||
firstByte := content[4]
|
firstByte := content[4]
|
||||||
padding := (firstByte>>5)&1 == 1
|
padding := (firstByte>>5)&1 == 1
|
||||||
extension := (firstByte>>4)&1 == 1
|
extension := (firstByte>>4)&1 == 1
|
||||||
CSRCCnt := int(firstByte & 0x0f)
|
CSRCCnt := int(firstByte & 0x0f)
|
||||||
SequenceNumber := int(binary.BigEndian.Uint16(content[6:8]))
|
SequenceNumber := int(binary.BigEndian.Uint16(content[6:8]))
|
||||||
timestamp := int64(binary.BigEndian.Uint32(content[8:16]))
|
timestamp := int64(binary.BigEndian.Uint32(content[8:12]))
|
||||||
|
ssrc := uint32(binary.BigEndian.Uint32(content[12:16]))
|
||||||
|
|
||||||
if isRTCPPacket(content) {
|
if isRTCPPacket(content) {
|
||||||
client.Println("skipping RTCP packet")
|
client.Println("Processing RTCP packet")
|
||||||
return nil, false
|
rtcpPacketType := content[5]
|
||||||
|
if rtcpPacketType == RTCPSenderReport {
|
||||||
|
srr := rtcp.SenderReport{}
|
||||||
|
srr.Unmarshal(content)
|
||||||
|
|
||||||
|
client.Println(srr)
|
||||||
|
} else {
|
||||||
|
client.Println("skipping RTCP packet")
|
||||||
|
}
|
||||||
|
return nil, false, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
offset := RTPHeaderSize
|
offset := RTPHeaderSize
|
||||||
@ -596,7 +649,7 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) {
|
|||||||
offset += 4 * CSRCCnt
|
offset += 4 * CSRCCnt
|
||||||
}
|
}
|
||||||
if extension && len(content) < 4+offset+2+2 {
|
if extension && len(content) < 4+offset+2+2 {
|
||||||
return nil, false
|
return nil, false, 0
|
||||||
}
|
}
|
||||||
if extension && end-offset >= 4 {
|
if extension && end-offset >= 4 {
|
||||||
extLen := 4 * int(binary.BigEndian.Uint16(content[4+offset+2:]))
|
extLen := 4 * int(binary.BigEndian.Uint16(content[4+offset+2:]))
|
||||||
@ -636,7 +689,7 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) {
|
|||||||
}
|
}
|
||||||
nalRaw, _ := h264parser.SplitNALUs(content[offset:end])
|
nalRaw, _ := h264parser.SplitNALUs(content[offset:end])
|
||||||
if len(nalRaw) == 0 || len(nalRaw[0]) == 0 {
|
if len(nalRaw) == 0 || len(nalRaw[0]) == 0 {
|
||||||
return nil, false
|
return nil, false, 0
|
||||||
}
|
}
|
||||||
var retmap []*av.Packet
|
var retmap []*av.Packet
|
||||||
for _, nal := range nalRaw {
|
for _, nal := range nalRaw {
|
||||||
@ -776,7 +829,7 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) {
|
|||||||
}
|
}
|
||||||
if len(retmap) > 0 {
|
if len(retmap) > 0 {
|
||||||
client.PreVideoTS = timestamp
|
client.PreVideoTS = timestamp
|
||||||
return retmap, true
|
return retmap, true, ssrc
|
||||||
}
|
}
|
||||||
case client.audioID:
|
case client.audioID:
|
||||||
if client.PreAudioTS == 0 {
|
if client.PreAudioTS == 0 {
|
||||||
@ -850,12 +903,12 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) {
|
|||||||
}
|
}
|
||||||
if len(retmap) > 0 {
|
if len(retmap) > 0 {
|
||||||
client.PreAudioTS = timestamp
|
client.PreAudioTS = timestamp
|
||||||
return retmap, true
|
return retmap, true, ssrc
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
//client.Println("Unsuported Intervaled data packet", int(content[1]), content[offset:end])
|
//client.Println("Unsuported Intervaled data packet", int(content[1]), content[offset:end])
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false, ssrc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *RTSPClient) CodecUpdateSPS(val []byte) {
|
func (client *RTSPClient) CodecUpdateSPS(val []byte) {
|
||||||
|
2
go.mod
2
go.mod
@ -21,7 +21,7 @@ require (
|
|||||||
github.com/pion/mdns v0.0.5 // indirect
|
github.com/pion/mdns v0.0.5 // indirect
|
||||||
github.com/pion/quic v0.1.1 // indirect
|
github.com/pion/quic v0.1.1 // indirect
|
||||||
github.com/pion/randutil v0.1.0 // indirect
|
github.com/pion/randutil v0.1.0 // indirect
|
||||||
github.com/pion/rtcp v1.2.9 // indirect
|
github.com/pion/rtcp v1.2.10 // indirect
|
||||||
github.com/pion/rtp v1.7.13 // indirect
|
github.com/pion/rtp v1.7.13 // indirect
|
||||||
github.com/pion/sctp v1.8.2 // indirect
|
github.com/pion/sctp v1.8.2 // indirect
|
||||||
github.com/pion/sdp/v2 v2.4.0 // indirect
|
github.com/pion/sdp/v2 v2.4.0 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -74,6 +74,8 @@ github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TB
|
|||||||
github.com/pion/rtcp v1.2.3/go.mod h1:zGhIv0RPRF0Z1Wiij22pUt5W/c9fevqSzT4jje/oK7I=
|
github.com/pion/rtcp v1.2.3/go.mod h1:zGhIv0RPRF0Z1Wiij22pUt5W/c9fevqSzT4jje/oK7I=
|
||||||
github.com/pion/rtcp v1.2.9 h1:1ujStwg++IOLIEoOiIQ2s+qBuJ1VN81KW+9pMPsif+U=
|
github.com/pion/rtcp v1.2.9 h1:1ujStwg++IOLIEoOiIQ2s+qBuJ1VN81KW+9pMPsif+U=
|
||||||
github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo=
|
github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo=
|
||||||
|
github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc=
|
||||||
|
github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I=
|
||||||
github.com/pion/rtp v1.6.0/go.mod h1:QgfogHsMBVE/RFNno467U/KBqfUywEH+HK+0rtnwsdI=
|
github.com/pion/rtp v1.6.0/go.mod h1:QgfogHsMBVE/RFNno467U/KBqfUywEH+HK+0rtnwsdI=
|
||||||
github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA=
|
github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA=
|
||||||
github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||||
|
Loading…
Reference in New Issue
Block a user