Browse Source

rtsp: parse all incoming RTP/RTCP packets

pull/858/head
aler9 5 years ago committed by Alessandro Ros
parent
commit
5504ff44b6
  1. 8
      go.mod
  2. 16
      go.sum
  3. 27
      internal/core/hls_muxer.go
  4. 7
      internal/core/hls_source.go
  5. 5
      internal/core/hls_source_test.go
  6. 9
      internal/core/reader.go
  7. 59
      internal/core/rtmp_conn.go
  8. 33
      internal/core/rtmp_source.go
  9. 33
      internal/core/rtsp_server_test.go
  10. 10
      internal/core/rtsp_session.go
  11. 25
      internal/core/rtsp_source.go
  12. 41
      internal/core/rtsp_source_test.go
  13. 22
      internal/core/stream.go
  14. 47
      internal/hls/client.go
  15. 5
      internal/hls/client_test.go
  16. 10
      internal/rtcpsenderset/rtcpsenderset.go

8
go.mod

@ -4,7 +4,7 @@ go 1.17
require ( require (
code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5 code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5
github.com/aler9/gortsplib v0.0.0-20220213160013-a235613fd674 github.com/aler9/gortsplib v0.0.0-20220217230339-d44f1eb03a9f
github.com/asticode/go-astits v1.10.0 github.com/asticode/go-astits v1.10.0
github.com/fsnotify/fsnotify v1.4.9 github.com/fsnotify/fsnotify v1.4.9
github.com/gin-gonic/gin v1.7.2 github.com/gin-gonic/gin v1.7.2
@ -12,8 +12,9 @@ require (
github.com/grafov/m3u8 v0.11.1 github.com/grafov/m3u8 v0.11.1
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/notedit/rtmp v0.0.2 github.com/notedit/rtmp v0.0.2
github.com/pion/rtp v1.6.2 github.com/pion/rtcp v1.2.9
github.com/stretchr/testify v1.6.1 github.com/pion/rtp v1.7.4
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
@ -36,7 +37,6 @@ require (
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
github.com/pion/randutil v0.1.0 // indirect github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.4 // indirect
github.com/pion/sdp/v3 v3.0.2 // indirect github.com/pion/sdp/v3 v3.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect github.com/ugorji/go/codec v1.1.7 // indirect

16
go.sum

@ -4,8 +4,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafo
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/aler9/gortsplib v0.0.0-20220213160013-a235613fd674 h1:06MThBlbTAfeJXy/49/SfYgdjF6XA5YSkg3nEWLn5ko= github.com/aler9/gortsplib v0.0.0-20220217230339-d44f1eb03a9f h1:NIH+yILuAy6RP6mjzt/c+dIBB23FDFK3hk29VfRByxk=
github.com/aler9/gortsplib v0.0.0-20220213160013-a235613fd674/go.mod h1:fyQrQyHo8QvdR/h357tkv1g36VesZlzEPsdAu2VrHHc= github.com/aler9/gortsplib v0.0.0-20220217230339-d44f1eb03a9f/go.mod h1:mst8cTkmxLn8Osiug8HBjMsNFRt0u7QHt5phJQ1tFVw=
github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927 h1:95mXJ5fUCYpBRdSOnLAQAdJHHKxxxJrVCiaqDi965YQ= github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927 h1:95mXJ5fUCYpBRdSOnLAQAdJHHKxxxJrVCiaqDi965YQ=
github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927/go.mod h1:vzuE21rowz+lT1NGsWbreIvYulgBpCGnQyeTyFblUHc= github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927/go.mod h1:vzuE21rowz+lT1NGsWbreIvYulgBpCGnQyeTyFblUHc=
github.com/asticode/go-astikit v0.20.0 h1:+7N+J4E4lWx2QOkRdOf6DafWJMv6O4RRfgClwQokrH8= github.com/asticode/go-astikit v0.20.0 h1:+7N+J4E4lWx2QOkRdOf6DafWJMv6O4RRfgClwQokrH8=
@ -82,11 +82,10 @@ github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtcp v1.2.4 h1:NT3H5LkUGgaEapvp0HGik+a+CpflRF7KTD7H+o7OWIM= github.com/pion/rtcp v1.2.9 h1:1ujStwg++IOLIEoOiIQ2s+qBuJ1VN81KW+9pMPsif+U=
github.com/pion/rtcp v1.2.4/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0= github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo=
github.com/pion/rtp v1.6.1/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= github.com/pion/rtp v1.7.4 h1:4dMbjb1SuynU5OpA3kz1zHK+u+eOCQjW3MAeVHf1ODA=
github.com/pion/rtp v1.6.2 h1:iGBerLX6JiDjB9NXuaPzHyxHFG9JsIEdgwTC0lp5n/U= github.com/pion/rtp v1.7.4/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
github.com/pion/sdp/v3 v3.0.2 h1:UNnSPVaMM+Pdu/mR9UvAyyo6zkdYbKeuOooCwZvTl/g= github.com/pion/sdp/v3 v3.0.2 h1:UNnSPVaMM+Pdu/mR9UvAyyo6zkdYbKeuOooCwZvTl/g=
github.com/pion/sdp/v3 v3.0.2/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk= github.com/pion/sdp/v3 v3.0.2/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk=
github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE= github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
@ -96,8 +95,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=

27
internal/core/hls_muxer.go

@ -17,6 +17,7 @@ import (
"github.com/aler9/gortsplib/pkg/ringbuffer" "github.com/aler9/gortsplib/pkg/ringbuffer"
"github.com/aler9/gortsplib/pkg/rtpaac" "github.com/aler9/gortsplib/pkg/rtpaac"
"github.com/aler9/gortsplib/pkg/rtph264" "github.com/aler9/gortsplib/pkg/rtph264"
"github.com/pion/rtcp"
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/aler9/rtsp-simple-server/internal/conf" "github.com/aler9/rtsp-simple-server/internal/conf"
@ -109,7 +110,7 @@ type hlsMuxerRequest struct {
type hlsMuxerTrackIDPayloadPair struct { type hlsMuxerTrackIDPayloadPair struct {
trackID int trackID int
buf []byte packet *rtp.Packet
} }
type hlsMuxerPathManager interface { type hlsMuxerPathManager interface {
@ -342,14 +343,7 @@ func (m *hlsMuxer) runInner(innerCtx context.Context, innerReady chan struct{})
pair := data.(hlsMuxerTrackIDPayloadPair) pair := data.(hlsMuxerTrackIDPayloadPair)
if videoTrack != nil && pair.trackID == videoTrackID { if videoTrack != nil && pair.trackID == videoTrackID {
var pkt rtp.Packet nalus, pts, err := h264Decoder.DecodeUntilMarker(pair.packet)
err := pkt.Unmarshal(pair.buf)
if err != nil {
m.log(logger.Warn, "unable to decode RTP packet: %v", err)
continue
}
nalus, pts, err := h264Decoder.DecodeUntilMarker(&pkt)
if err != nil { if err != nil {
if err != rtph264.ErrMorePacketsNeeded && if err != rtph264.ErrMorePacketsNeeded &&
err != rtph264.ErrNonStartingPacketAndNoPrevious { err != rtph264.ErrNonStartingPacketAndNoPrevious {
@ -364,14 +358,7 @@ func (m *hlsMuxer) runInner(innerCtx context.Context, innerReady chan struct{})
continue continue
} }
} else if audioTrack != nil && pair.trackID == audioTrackID { } else if audioTrack != nil && pair.trackID == audioTrackID {
var pkt rtp.Packet aus, pts, err := aacDecoder.Decode(pair.packet)
err := pkt.Unmarshal(pair.buf)
if err != nil {
m.log(logger.Warn, "unable to decode RTP packet: %v", err)
continue
}
aus, pts, err := aacDecoder.Decode(&pkt)
if err != nil { if err != nil {
if err != rtpaac.ErrMorePacketsNeeded { if err != rtpaac.ErrMorePacketsNeeded {
m.log(logger.Warn, "unable to decode audio track: %v", err) m.log(logger.Warn, "unable to decode audio track: %v", err)
@ -548,12 +535,12 @@ func (m *hlsMuxer) onReaderAccepted() {
} }
// onReaderPacketRTP implements reader. // onReaderPacketRTP implements reader.
func (m *hlsMuxer) onReaderPacketRTP(trackID int, payload []byte) { func (m *hlsMuxer) onReaderPacketRTP(trackID int, pkt *rtp.Packet) {
m.ringBuffer.Push(hlsMuxerTrackIDPayloadPair{trackID, payload}) m.ringBuffer.Push(hlsMuxerTrackIDPayloadPair{trackID, pkt})
} }
// onReaderPacketRTCP implements reader. // onReaderPacketRTCP implements reader.
func (m *hlsMuxer) onReaderPacketRTCP(trackID int, payload []byte) { func (m *hlsMuxer) onReaderPacketRTCP(trackID int, pkt rtcp.Packet) {
} }
// onReaderAPIDescribe implements reader. // onReaderAPIDescribe implements reader.

7
internal/core/hls_source.go

@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/pion/rtp"
"github.com/aler9/rtsp-simple-server/internal/hls" "github.com/aler9/rtsp-simple-server/internal/hls"
"github.com/aler9/rtsp-simple-server/internal/logger" "github.com/aler9/rtsp-simple-server/internal/logger"
@ -128,7 +129,7 @@ func (s *hlsSource) runInner() bool {
return nil return nil
} }
onPacket := func(isVideo bool, payload []byte) { onPacket := func(isVideo bool, pkt *rtp.Packet) {
var trackID int var trackID int
if isVideo { if isVideo {
trackID = videoTrackID trackID = videoTrackID
@ -137,8 +138,8 @@ func (s *hlsSource) runInner() bool {
} }
if stream != nil { if stream != nil {
rtcpSenders.OnPacketRTP(trackID, payload) rtcpSenders.OnPacketRTP(trackID, pkt)
stream.onPacketRTP(trackID, payload) stream.onPacketRTP(trackID, pkt)
} }
} }

5
internal/core/hls_source_test.go

@ -134,10 +134,7 @@ func TestHLSSource(t *testing.T) {
frameRecv := make(chan struct{}) frameRecv := make(chan struct{})
c := gortsplib.Client{ c := gortsplib.Client{
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
var pkt rtp.Packet
err := pkt.Unmarshal(payload)
require.NoError(t, err)
require.Equal(t, []byte{0x05}, pkt.Payload) require.Equal(t, []byte{0x05}, pkt.Payload)
close(frameRecv) close(frameRecv)
}, },

9
internal/core/reader.go

@ -1,10 +1,15 @@
package core package core
import (
"github.com/pion/rtcp"
"github.com/pion/rtp"
)
// reader is an entity that can read a stream. // reader is an entity that can read a stream.
type reader interface { type reader interface {
close() close()
onReaderAccepted() onReaderAccepted()
onReaderPacketRTP(int, []byte) onReaderPacketRTP(int, *rtp.Packet)
onReaderPacketRTCP(int, []byte) onReaderPacketRTCP(int, rtcp.Packet)
onReaderAPIDescribe() interface{} onReaderAPIDescribe() interface{}
} }

59
internal/core/rtmp_conn.go

@ -16,6 +16,7 @@ import (
"github.com/aler9/gortsplib/pkg/rtpaac" "github.com/aler9/gortsplib/pkg/rtpaac"
"github.com/aler9/gortsplib/pkg/rtph264" "github.com/aler9/gortsplib/pkg/rtph264"
"github.com/notedit/rtmp/av" "github.com/notedit/rtmp/av"
"github.com/pion/rtcp"
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/aler9/rtsp-simple-server/internal/conf" "github.com/aler9/rtsp-simple-server/internal/conf"
@ -39,7 +40,7 @@ func pathNameAndQuery(inURL *url.URL) (string, url.Values, string) {
type rtmpConnTrackIDPayloadPair struct { type rtmpConnTrackIDPayloadPair struct {
trackID int trackID int
buf []byte packet *rtp.Packet
} }
type rtmpConnPathManager interface { type rtmpConnPathManager interface {
@ -330,14 +331,7 @@ func (c *rtmpConn) runRead(ctx context.Context) error {
pair := data.(rtmpConnTrackIDPayloadPair) pair := data.(rtmpConnTrackIDPayloadPair)
if videoTrack != nil && pair.trackID == videoTrackID { if videoTrack != nil && pair.trackID == videoTrackID {
var pkt rtp.Packet nalus, pts, err := h264Decoder.DecodeUntilMarker(pair.packet)
err := pkt.Unmarshal(pair.buf)
if err != nil {
c.log(logger.Warn, "unable to decode RTP packet: %v", err)
continue
}
nalus, pts, err := h264Decoder.DecodeUntilMarker(&pkt)
if err != nil { if err != nil {
if err != rtph264.ErrMorePacketsNeeded && err != rtph264.ErrNonStartingPacketAndNoPrevious { if err != rtph264.ErrMorePacketsNeeded && err != rtph264.ErrNonStartingPacketAndNoPrevious {
c.log(logger.Warn, "unable to decode video track: %v", err) c.log(logger.Warn, "unable to decode video track: %v", err)
@ -398,14 +392,7 @@ func (c *rtmpConn) runRead(ctx context.Context) error {
return err return err
} }
} else if audioTrack != nil && pair.trackID == audioTrackID { } else if audioTrack != nil && pair.trackID == audioTrackID {
var pkt rtp.Packet aus, pts, err := aacDecoder.Decode(pair.packet)
err := pkt.Unmarshal(pair.buf)
if err != nil {
c.log(logger.Warn, "unable to decode RTP packet: %v", err)
continue
}
aus, pts, err := aacDecoder.Decode(&pkt)
if err != nil { if err != nil {
if err != rtpaac.ErrMorePacketsNeeded { if err != rtpaac.ErrMorePacketsNeeded {
c.log(logger.Warn, "unable to decode audio track: %v", err) c.log(logger.Warn, "unable to decode audio track: %v", err)
@ -510,9 +497,9 @@ func (c *rtmpConn) runPublish(ctx context.Context) error {
rtcpSenders := rtcpsenderset.New(tracks, rres.stream.onPacketRTCP) rtcpSenders := rtcpsenderset.New(tracks, rres.stream.onPacketRTCP)
defer rtcpSenders.Close() defer rtcpSenders.Close()
onPacketRTP := func(trackID int, payload []byte) { onPacketRTP := func(trackID int, pkt *rtp.Packet) {
rtcpSenders.OnPacketRTP(trackID, payload) rtcpSenders.OnPacketRTP(trackID, pkt)
rres.stream.onPacketRTP(trackID, payload) rres.stream.onPacketRTP(trackID, pkt)
} }
for { for {
@ -555,17 +542,8 @@ func (c *rtmpConn) runPublish(ctx context.Context) error {
return fmt.Errorf("error while encoding H264: %v", err) return fmt.Errorf("error while encoding H264: %v", err)
} }
bytss := make([][]byte, len(pkts)) for _, pkt := range pkts {
for i, pkt := range pkts { onPacketRTP(videoTrackID, pkt)
byts, err := pkt.Marshal()
if err != nil {
return fmt.Errorf("error while encoding H264: %v", err)
}
bytss[i] = byts
}
for _, byts := range bytss {
onPacketRTP(videoTrackID, byts)
} }
case av.AAC: case av.AAC:
@ -578,17 +556,8 @@ func (c *rtmpConn) runPublish(ctx context.Context) error {
return fmt.Errorf("error while encoding AAC: %v", err) return fmt.Errorf("error while encoding AAC: %v", err)
} }
bytss := make([][]byte, len(pkts)) for _, pkt := range pkts {
for i, pkt := range pkts { onPacketRTP(audioTrackID, pkt)
byts, err := pkt.Marshal()
if err != nil {
return fmt.Errorf("error while encoding AAC: %v", err)
}
bytss[i] = byts
}
for _, byts := range bytss {
onPacketRTP(audioTrackID, byts)
} }
} }
} }
@ -646,12 +615,12 @@ func (c *rtmpConn) onReaderAccepted() {
} }
// onReaderPacketRTP implements reader. // onReaderPacketRTP implements reader.
func (c *rtmpConn) onReaderPacketRTP(trackID int, payload []byte) { func (c *rtmpConn) onReaderPacketRTP(trackID int, pkt *rtp.Packet) {
c.ringBuffer.Push(rtmpConnTrackIDPayloadPair{trackID, payload}) c.ringBuffer.Push(rtmpConnTrackIDPayloadPair{trackID, pkt})
} }
// onReaderPacketRTCP implements reader. // onReaderPacketRTCP implements reader.
func (c *rtmpConn) onReaderPacketRTCP(trackID int, payload []byte) { func (c *rtmpConn) onReaderPacketRTCP(trackID int, pkt rtcp.Packet) {
} }
// onReaderAPIDescribe implements reader. // onReaderAPIDescribe implements reader.

33
internal/core/rtmp_source.go

@ -11,6 +11,7 @@ import (
"github.com/aler9/gortsplib/pkg/rtpaac" "github.com/aler9/gortsplib/pkg/rtpaac"
"github.com/aler9/gortsplib/pkg/rtph264" "github.com/aler9/gortsplib/pkg/rtph264"
"github.com/notedit/rtmp/av" "github.com/notedit/rtmp/av"
"github.com/pion/rtp"
"github.com/aler9/rtsp-simple-server/internal/conf" "github.com/aler9/rtsp-simple-server/internal/conf"
"github.com/aler9/rtsp-simple-server/internal/logger" "github.com/aler9/rtsp-simple-server/internal/logger"
@ -164,9 +165,9 @@ func (s *rtmpSource) runInner() bool {
rtcpSenders := rtcpsenderset.New(tracks, res.stream.onPacketRTCP) rtcpSenders := rtcpsenderset.New(tracks, res.stream.onPacketRTCP)
defer rtcpSenders.Close() defer rtcpSenders.Close()
onPacketRTP := func(trackID int, payload []byte) { onPacketRTP := func(trackID int, pkt *rtp.Packet) {
rtcpSenders.OnPacketRTP(trackID, payload) rtcpSenders.OnPacketRTP(trackID, pkt)
res.stream.onPacketRTP(trackID, payload) res.stream.onPacketRTP(trackID, pkt)
} }
for { for {
@ -204,17 +205,8 @@ func (s *rtmpSource) runInner() bool {
return fmt.Errorf("error while encoding H264: %v", err) return fmt.Errorf("error while encoding H264: %v", err)
} }
bytss := make([][]byte, len(pkts)) for _, pkt := range pkts {
for i, pkt := range pkts { onPacketRTP(videoTrackID, pkt)
byts, err := pkt.Marshal()
if err != nil {
return fmt.Errorf("error while encoding H264: %v", err)
}
bytss[i] = byts
}
for _, byts := range bytss {
onPacketRTP(videoTrackID, byts)
} }
case av.AAC: case av.AAC:
@ -227,17 +219,8 @@ func (s *rtmpSource) runInner() bool {
return fmt.Errorf("error while encoding AAC: %v", err) return fmt.Errorf("error while encoding AAC: %v", err)
} }
bytss := make([][]byte, len(pkts)) for _, pkt := range pkts {
for i, pkt := range pkts { onPacketRTP(audioTrackID, pkt)
byts, err := pkt.Marshal()
if err != nil {
return fmt.Errorf("error while encoding AAC: %v", err)
}
bytss[i] = byts
}
for _, byts := range bytss {
onPacketRTP(audioTrackID, byts)
} }
} }
} }

33
internal/core/rtsp_server_test.go

@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/pion/rtp"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -458,11 +459,11 @@ func TestRTSPServerPublisherOverride(t *testing.T) {
frameRecv := make(chan struct{}) frameRecv := make(chan struct{})
c := gortsplib.Client{ c := gortsplib.Client{
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
if ca == "enabled" { if ca == "enabled" {
require.Equal(t, []byte{0x05, 0x06, 0x07, 0x08}, payload) require.Equal(t, []byte{0x05, 0x06, 0x07, 0x08}, pkt.Payload)
} else { } else {
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, payload) require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, pkt.Payload)
} }
close(frameRecv) close(frameRecv)
}, },
@ -472,8 +473,17 @@ func TestRTSPServerPublisherOverride(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer c.Close() defer c.Close()
err = s1.WritePacketRTP(0, err = s1.WritePacketRTP(0, &rtp.Packet{
[]byte{0x01, 0x02, 0x03, 0x04}) Header: rtp.Header{
Version: 0x02,
PayloadType: 97,
SequenceNumber: 57899,
Timestamp: 345234345,
SSRC: 978651231,
Marker: true,
},
Payload: []byte{0x01, 0x02, 0x03, 0x04},
})
if ca == "enabled" { if ca == "enabled" {
require.Error(t, err) require.Error(t, err)
} else { } else {
@ -481,8 +491,17 @@ func TestRTSPServerPublisherOverride(t *testing.T) {
} }
if ca == "enabled" { if ca == "enabled" {
err = s2.WritePacketRTP(0, err = s2.WritePacketRTP(0, &rtp.Packet{
[]byte{0x05, 0x06, 0x07, 0x08}) Header: rtp.Header{
Version: 0x02,
PayloadType: 97,
SequenceNumber: 57899,
Timestamp: 345234345,
SSRC: 978651231,
Marker: true,
},
Payload: []byte{0x05, 0x06, 0x07, 0x08},
})
require.NoError(t, err) require.NoError(t, err)
} }

10
internal/core/rtsp_session.go

@ -9,6 +9,8 @@ import (
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/base" "github.com/aler9/gortsplib/pkg/base"
"github.com/pion/rtcp"
"github.com/pion/rtp"
"github.com/aler9/rtsp-simple-server/internal/conf" "github.com/aler9/rtsp-simple-server/internal/conf"
"github.com/aler9/rtsp-simple-server/internal/externalcmd" "github.com/aler9/rtsp-simple-server/internal/externalcmd"
@ -345,12 +347,12 @@ func (s *rtspSession) onReaderAccepted() {
} }
// onReaderPacketRTP implements reader. // onReaderPacketRTP implements reader.
func (s *rtspSession) onReaderPacketRTP(trackID int, payload []byte) { func (s *rtspSession) onReaderPacketRTP(trackID int, pkt *rtp.Packet) {
// packets are routed to the session by gortsplib.ServerStream. // packets are routed to the session by gortsplib.ServerStream.
} }
// onReaderPacketRTCP implements reader. // onReaderPacketRTCP implements reader.
func (s *rtspSession) onReaderPacketRTCP(trackID int, payload []byte) { func (s *rtspSession) onReaderPacketRTCP(trackID int, pkt rtcp.Packet) {
// packets are routed to the session by gortsplib.ServerStream. // packets are routed to the session by gortsplib.ServerStream.
} }
@ -404,7 +406,7 @@ func (s *rtspSession) onPacketRTP(ctx *gortsplib.ServerHandlerOnPacketRTPCtx) {
return return
} }
s.stream.onPacketRTP(ctx.TrackID, ctx.Payload) s.stream.onPacketRTP(ctx.TrackID, ctx.Packet)
} }
// onPacketRTCP is called by rtspServer. // onPacketRTCP is called by rtspServer.
@ -413,5 +415,5 @@ func (s *rtspSession) onPacketRTCP(ctx *gortsplib.ServerHandlerOnPacketRTCPCtx)
return return
} }
s.stream.onPacketRTCP(ctx.TrackID, ctx.Payload) s.stream.onPacketRTCP(ctx.TrackID, ctx.Packet)
} }

25
internal/core/rtsp_source.go

@ -14,6 +14,7 @@ import (
"github.com/aler9/gortsplib/pkg/base" "github.com/aler9/gortsplib/pkg/base"
"github.com/aler9/gortsplib/pkg/h264" "github.com/aler9/gortsplib/pkg/h264"
"github.com/aler9/gortsplib/pkg/rtph264" "github.com/aler9/gortsplib/pkg/rtph264"
"github.com/pion/rtcp"
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/aler9/rtsp-simple-server/internal/conf" "github.com/aler9/rtsp-simple-server/internal/conf"
@ -209,12 +210,12 @@ func (s *rtspSource) runInner() bool {
s.parent.onSourceStaticSetNotReady(pathSourceStaticSetNotReadyReq{source: s}) s.parent.onSourceStaticSetNotReady(pathSourceStaticSetNotReadyReq{source: s})
}() }()
c.OnPacketRTP = func(trackID int, payload []byte) { c.OnPacketRTP = func(trackID int, pkt *rtp.Packet) {
res.stream.onPacketRTP(trackID, payload) res.stream.onPacketRTP(trackID, pkt)
} }
c.OnPacketRTCP = func(trackID int, payload []byte) { c.OnPacketRTCP = func(trackID int, pkt rtcp.Packet) {
res.stream.onPacketRTCP(trackID, payload) res.stream.onPacketRTCP(trackID, pkt)
} }
_, err = c.Play(nil) _, err = c.Play(nil)
@ -267,7 +268,7 @@ func (s *rtspSource) handleMissingH264Params(c *gortsplib.Client, tracks gortspl
var pps []byte var pps []byte
paramsReceived := make(chan struct{}) paramsReceived := make(chan struct{})
c.OnPacketRTP = func(trackID int, payload []byte) { c.OnPacketRTP = func(trackID int, pkt *rtp.Packet) {
streamMutex.RLock() streamMutex.RLock()
defer streamMutex.RUnlock() defer streamMutex.RUnlock()
@ -282,13 +283,7 @@ func (s *rtspSource) handleMissingH264Params(c *gortsplib.Client, tracks gortspl
default: default:
} }
var pkt rtp.Packet nalus, _, err := decoder.Decode(pkt)
err := pkt.Unmarshal(payload)
if err != nil {
return
}
nalus, _, err := decoder.Decode(&pkt)
if err != nil { if err != nil {
return return
} }
@ -310,16 +305,16 @@ func (s *rtspSource) handleMissingH264Params(c *gortsplib.Client, tracks gortspl
} }
} }
} else { } else {
stream.onPacketRTP(trackID, payload) stream.onPacketRTP(trackID, pkt)
} }
} }
c.OnPacketRTCP = func(trackID int, payload []byte) { c.OnPacketRTCP = func(trackID int, pkt rtcp.Packet) {
streamMutex.RLock() streamMutex.RLock()
defer streamMutex.RUnlock() defer streamMutex.RUnlock()
if stream != nil { if stream != nil {
stream.onPacketRTCP(trackID, payload) stream.onPacketRTCP(trackID, pkt)
} }
} }

41
internal/core/rtsp_source_test.go

@ -74,7 +74,17 @@ func TestRTSPSource(t *testing.T) {
onPlay: func(ctx *gortsplib.ServerHandlerOnPlayCtx) (*base.Response, error) { onPlay: func(ctx *gortsplib.ServerHandlerOnPlayCtx) (*base.Response, error) {
go func() { go func() {
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
stream.WritePacketRTP(0, []byte{0x01, 0x02, 0x03, 0x04}) stream.WritePacketRTP(0, &rtp.Packet{
Header: rtp.Header{
Version: 0x02,
PayloadType: 97,
SequenceNumber: 57899,
Timestamp: 345234345,
SSRC: 978651231,
Marker: true,
},
Payload: []byte{0x01, 0x02, 0x03, 0x04},
})
}() }()
return &base.Response{ return &base.Response{
@ -133,8 +143,8 @@ func TestRTSPSource(t *testing.T) {
received := make(chan struct{}) received := make(chan struct{})
c := gortsplib.Client{ c := gortsplib.Client{
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, payload) require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, pkt.Payload)
close(received) close(received)
}, },
} }
@ -232,30 +242,25 @@ func TestRTSPSourceMissingH264Params(t *testing.T) {
pkts, err := enc.Encode([][]byte{{5}}, 0) // IDR pkts, err := enc.Encode([][]byte{{5}}, 0) // IDR
require.NoError(t, err) require.NoError(t, err)
byts, _ := pkts[0].Marshal() stream.WritePacketRTP(0, pkts[0])
stream.WritePacketRTP(0, byts)
pkts, err = enc.Encode([][]byte{{7, 1, 2, 3}}, 0) // SPS pkts, err = enc.Encode([][]byte{{7, 1, 2, 3}}, 0) // SPS
require.NoError(t, err) require.NoError(t, err)
byts, _ = pkts[0].Marshal() stream.WritePacketRTP(0, pkts[0])
stream.WritePacketRTP(0, byts)
pkts, err = enc.Encode([][]byte{{8}}, 0) // PPS pkts, err = enc.Encode([][]byte{{8}}, 0) // PPS
require.NoError(t, err) require.NoError(t, err)
byts, _ = pkts[0].Marshal() stream.WritePacketRTP(0, pkts[0])
stream.WritePacketRTP(0, byts)
pkts, err = enc.Encode([][]byte{{5, 1}}, 0) // IDR pkts, err = enc.Encode([][]byte{{5, 1}}, 0) // IDR
require.NoError(t, err) require.NoError(t, err)
byts, _ = pkts[0].Marshal() stream.WritePacketRTP(0, pkts[0])
stream.WritePacketRTP(0, byts)
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
pkts, err = enc.Encode([][]byte{{5, 2}}, 0) // IDR pkts, err = enc.Encode([][]byte{{5, 2}}, 0) // IDR
require.NoError(t, err) require.NoError(t, err)
byts, _ = pkts[0].Marshal() stream.WritePacketRTP(0, pkts[0])
stream.WritePacketRTP(0, byts)
}() }()
return &base.Response{ return &base.Response{
@ -283,14 +288,8 @@ func TestRTSPSourceMissingH264Params(t *testing.T) {
decoder := rtph264.NewDecoder() decoder := rtph264.NewDecoder()
c := gortsplib.Client{ c := gortsplib.Client{
OnPacketRTP: func(trackID int, payload []byte) { OnPacketRTP: func(trackID int, pkt *rtp.Packet) {
var pkt rtp.Packet nalus, _, err := decoder.Decode(pkt)
err := pkt.Unmarshal(payload)
if err != nil {
return
}
nalus, _, err := decoder.Decode(&pkt)
if err != nil { if err != nil {
return return
} }

22
internal/core/stream.go

@ -4,6 +4,8 @@ import (
"sync" "sync"
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/pion/rtcp"
"github.com/pion/rtp"
) )
type streamNonRTSPReadersMap struct { type streamNonRTSPReadersMap struct {
@ -35,21 +37,21 @@ func (m *streamNonRTSPReadersMap) remove(r reader) {
delete(m.ma, r) delete(m.ma, r)
} }
func (m *streamNonRTSPReadersMap) forwardPacketRTP(trackID int, payload []byte) { func (m *streamNonRTSPReadersMap) forwardPacketRTP(trackID int, pkt *rtp.Packet) {
m.mutex.RLock() m.mutex.RLock()
defer m.mutex.RUnlock() defer m.mutex.RUnlock()
for c := range m.ma { for c := range m.ma {
c.onReaderPacketRTP(trackID, payload) c.onReaderPacketRTP(trackID, pkt)
} }
} }
func (m *streamNonRTSPReadersMap) forwardPacketRTCP(trackID int, payload []byte) { func (m *streamNonRTSPReadersMap) forwardPacketRTCP(trackID int, pkt rtcp.Packet) {
m.mutex.RLock() m.mutex.RLock()
defer m.mutex.RUnlock() defer m.mutex.RUnlock()
for c := range m.ma { for c := range m.ma {
c.onReaderPacketRTCP(trackID, payload) c.onReaderPacketRTCP(trackID, pkt)
} }
} }
@ -87,18 +89,18 @@ func (s *stream) readerRemove(r reader) {
} }
} }
func (s *stream) onPacketRTP(trackID int, payload []byte) { func (s *stream) onPacketRTP(trackID int, pkt *rtp.Packet) {
// forward to RTSP readers // forward to RTSP readers
s.rtspStream.WritePacketRTP(trackID, payload) s.rtspStream.WritePacketRTP(trackID, pkt)
// forward to non-RTSP readers // forward to non-RTSP readers
s.nonRTSPReaders.forwardPacketRTP(trackID, payload) s.nonRTSPReaders.forwardPacketRTP(trackID, pkt)
} }
func (s *stream) onPacketRTCP(trackID int, payload []byte) { func (s *stream) onPacketRTCP(trackID int, pkt rtcp.Packet) {
// forward to RTSP readers // forward to RTSP readers
s.rtspStream.WritePacketRTCP(trackID, payload) s.rtspStream.WritePacketRTCP(trackID, pkt)
// forward to non-RTSP readers // forward to non-RTSP readers
s.nonRTSPReaders.forwardPacketRTCP(trackID, payload) s.nonRTSPReaders.forwardPacketRTCP(trackID, pkt)
} }

47
internal/hls/client.go

@ -22,6 +22,7 @@ import (
"github.com/aler9/gortsplib/pkg/rtph264" "github.com/aler9/gortsplib/pkg/rtph264"
"github.com/asticode/go-astits" "github.com/asticode/go-astits"
"github.com/grafov/m3u8" "github.com/grafov/m3u8"
"github.com/pion/rtp"
"github.com/aler9/rtsp-simple-server/internal/logger" "github.com/aler9/rtsp-simple-server/internal/logger"
) )
@ -135,7 +136,7 @@ type clientVideoProcessorData struct {
type clientVideoProcessor struct { type clientVideoProcessor struct {
ctx context.Context ctx context.Context
onTrack func(gortsplib.Track) error onTrack func(gortsplib.Track) error
onPacket func([]byte) onPacket func(*rtp.Packet)
queue chan clientVideoProcessorData queue chan clientVideoProcessorData
sps []byte sps []byte
@ -147,7 +148,7 @@ type clientVideoProcessor struct {
func newClientVideoProcessor( func newClientVideoProcessor(
ctx context.Context, ctx context.Context,
onTrack func(gortsplib.Track) error, onTrack func(gortsplib.Track) error,
onPacket func([]byte), onPacket func(*rtp.Packet),
) *clientVideoProcessor { ) *clientVideoProcessor {
p := &clientVideoProcessor{ p := &clientVideoProcessor{
ctx: ctx, ctx: ctx,
@ -249,17 +250,8 @@ func (p *clientVideoProcessor) doProcess(
return fmt.Errorf("error while encoding H264: %v", err) return fmt.Errorf("error while encoding H264: %v", err)
} }
bytss := make([][]byte, len(pkts)) for _, pkt := range pkts {
for i, pkt := range pkts { p.onPacket(pkt)
byts, err := pkt.Marshal()
if err != nil {
return fmt.Errorf("error while encoding H264: %v", err)
}
bytss[i] = byts
}
for _, byts := range bytss {
p.onPacket(byts)
} }
return nil return nil
@ -291,7 +283,7 @@ type clientAudioProcessorData struct {
type clientAudioProcessor struct { type clientAudioProcessor struct {
ctx context.Context ctx context.Context
onTrack func(gortsplib.Track) error onTrack func(gortsplib.Track) error
onPacket func([]byte) onPacket func(*rtp.Packet)
queue chan clientAudioProcessorData queue chan clientAudioProcessorData
encoder *rtpaac.Encoder encoder *rtpaac.Encoder
@ -301,7 +293,7 @@ type clientAudioProcessor struct {
func newClientAudioProcessor( func newClientAudioProcessor(
ctx context.Context, ctx context.Context,
onTrack func(gortsplib.Track) error, onTrack func(gortsplib.Track) error,
onPacket func([]byte), onPacket func(*rtp.Packet),
) *clientAudioProcessor { ) *clientAudioProcessor {
p := &clientAudioProcessor{ p := &clientAudioProcessor{
ctx: ctx, ctx: ctx,
@ -376,17 +368,8 @@ func (p *clientAudioProcessor) doProcess(
return fmt.Errorf("error while encoding AAC: %v", err) return fmt.Errorf("error while encoding AAC: %v", err)
} }
bytss := make([][]byte, len(pkts)) for _, pkt := range pkts {
for i, pkt := range pkts { p.onPacket(pkt)
byts, err := pkt.Marshal()
if err != nil {
return fmt.Errorf("error while encoding AAC: %v", err)
}
bytss[i] = byts
}
for _, byts := range bytss {
p.onPacket(byts)
} }
return nil return nil
@ -409,7 +392,7 @@ type ClientParent interface {
// Client is a HLS client. // Client is a HLS client.
type Client struct { type Client struct {
onTracks func(gortsplib.Track, gortsplib.Track) error onTracks func(gortsplib.Track, gortsplib.Track) error
onPacket func(bool, []byte) onPacket func(bool, *rtp.Packet)
parent ClientParent parent ClientParent
ctx context.Context ctx context.Context
@ -445,7 +428,7 @@ func NewClient(
primaryPlaylistURLStr string, primaryPlaylistURLStr string,
fingerprint string, fingerprint string,
onTracks func(gortsplib.Track, gortsplib.Track) error, onTracks func(gortsplib.Track, gortsplib.Track) error,
onPacket func(bool, []byte), onPacket func(bool, *rtp.Packet),
parent ClientParent, parent ClientParent,
) (*Client, error) { ) (*Client, error) {
primaryPlaylistURL, err := url.Parse(primaryPlaylistURLStr) primaryPlaylistURL, err := url.Parse(primaryPlaylistURLStr)
@ -909,16 +892,16 @@ func (c *Client) initializeEncoders() error {
return c.onTracks(c.videoTrack, c.audioTrack) return c.onTracks(c.videoTrack, c.audioTrack)
} }
func (c *Client) onVideoPacket(payload []byte) { func (c *Client) onVideoPacket(pkt *rtp.Packet) {
c.tracksMutex.RLock() c.tracksMutex.RLock()
defer c.tracksMutex.RUnlock() defer c.tracksMutex.RUnlock()
c.onPacket(true, payload) c.onPacket(true, pkt)
} }
func (c *Client) onAudioPacket(payload []byte) { func (c *Client) onAudioPacket(pkt *rtp.Packet) {
c.tracksMutex.RLock() c.tracksMutex.RLock()
defer c.tracksMutex.RUnlock() defer c.tracksMutex.RUnlock()
c.onPacket(false, payload) c.onPacket(false, pkt)
} }

5
internal/hls/client_test.go

@ -15,6 +15,7 @@ import (
"github.com/aler9/gortsplib/pkg/h264" "github.com/aler9/gortsplib/pkg/h264"
"github.com/asticode/go-astits" "github.com/asticode/go-astits"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/pion/rtp"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/aler9/rtsp-simple-server/internal/logger" "github.com/aler9/rtsp-simple-server/internal/logger"
@ -206,9 +207,9 @@ func TestClient(t *testing.T) {
func(gortsplib.Track, gortsplib.Track) error { func(gortsplib.Track, gortsplib.Track) error {
return nil return nil
}, },
func(isVideo bool, byts []byte) { func(isVideo bool, pkt *rtp.Packet) {
require.Equal(t, true, isVideo) require.Equal(t, true, isVideo)
require.Equal(t, byte(0x05), byts[12]) require.Equal(t, []byte{0x05}, pkt.Payload)
close(packetRecv) close(packetRecv)
}, },
testLogger{}, testLogger{},

10
internal/rtcpsenderset/rtcpsenderset.go

@ -5,11 +5,13 @@ import (
"github.com/aler9/gortsplib" "github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/rtcpsender" "github.com/aler9/gortsplib/pkg/rtcpsender"
"github.com/pion/rtcp"
"github.com/pion/rtp"
) )
// RTCPSenderSet is a set of RTCP senders. // RTCPSenderSet is a set of RTCP senders.
type RTCPSenderSet struct { type RTCPSenderSet struct {
onPacketRTCP func(int, []byte) onPacketRTCP func(int, rtcp.Packet)
senders []*rtcpsender.RTCPSender senders []*rtcpsender.RTCPSender
// in // in
@ -22,7 +24,7 @@ type RTCPSenderSet struct {
// New allocates a RTCPSenderSet. // New allocates a RTCPSenderSet.
func New( func New(
tracks gortsplib.Tracks, tracks gortsplib.Tracks,
onPacketRTCP func(int, []byte), onPacketRTCP func(int, rtcp.Packet),
) *RTCPSenderSet { ) *RTCPSenderSet {
s := &RTCPSenderSet{ s := &RTCPSenderSet{
onPacketRTCP: onPacketRTCP, onPacketRTCP: onPacketRTCP,
@ -71,6 +73,6 @@ func (s *RTCPSenderSet) run() {
} }
// OnPacketRTP sends a RTP packet to the senders. // OnPacketRTP sends a RTP packet to the senders.
func (s *RTCPSenderSet) OnPacketRTP(trackID int, payload []byte) { func (s *RTCPSenderSet) OnPacketRTP(trackID int, pkt *rtp.Packet) {
s.senders[trackID].ProcessPacketRTP(time.Now(), payload) s.senders[trackID].ProcessPacketRTP(time.Now(), pkt)
} }

Loading…
Cancel
Save