mirror of
https://github.com/Monibuca/plugin-rtsp.git
synced 2025-10-04 15:22:51 +08:00
Compare commits
16 Commits
v4.2.6
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
![]() |
985f2d013b | ||
![]() |
5e722bf849 | ||
![]() |
6c1207ae43 | ||
![]() |
c794c0514f | ||
![]() |
e65f970097 | ||
![]() |
855038c132 | ||
![]() |
2a62472b1d | ||
![]() |
3e4dcdf649 | ||
![]() |
9ac21a130e | ||
![]() |
c13d8c659d | ||
![]() |
c4700713a8 | ||
![]() |
62409f14b5 | ||
![]() |
df9c5a69cc | ||
![]() |
4a5ba9b834 | ||
![]() |
5df8f237de | ||
![]() |
9936b2ca20 |
@@ -52,7 +52,6 @@ rtsp:
|
||||
rtcpaddr: :8001
|
||||
readbuffercount: 2048
|
||||
writebuffercount: 2048
|
||||
pullprotocol: tcp # auto, tcp, udp
|
||||
```
|
||||
:::tip Configuration override
|
||||
publish and subscribe, any section not configured will use global configuration.
|
||||
|
@@ -49,7 +49,6 @@ rtsp:
|
||||
rtcpaddr: :8001
|
||||
readbuffercount: 2048 # 读取缓存队列大小
|
||||
writebuffercount: 2048 # 写出缓存队列大小
|
||||
pullprotocol: tcp # auto, tcp, udp
|
||||
```
|
||||
:::tip 配置覆盖
|
||||
publish
|
||||
|
86
client.go
86
client.go
@@ -4,8 +4,9 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v3"
|
||||
"github.com/bluenviron/gortsplib/v3/pkg/url"
|
||||
"github.com/bluenviron/gortsplib/v4"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/base"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/url"
|
||||
"go.uber.org/zap"
|
||||
"m7s.live/engine/v4"
|
||||
)
|
||||
@@ -21,6 +22,13 @@ type RTSPPuller struct {
|
||||
RTSPClient
|
||||
}
|
||||
|
||||
func (p *RTSPClient) Close() error {
|
||||
if p.Client != nil {
|
||||
p.Client.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *RTSPClient) Disconnect() {
|
||||
if p.Client != nil {
|
||||
p.Client.Close()
|
||||
@@ -28,60 +36,60 @@ func (p *RTSPClient) Disconnect() {
|
||||
}
|
||||
|
||||
func (p *RTSPPuller) Connect() error {
|
||||
p.Client = &gortsplib.Client{
|
||||
DialContext: p.DialContext,
|
||||
ReadBufferCount: rtspConfig.ReadBufferCount,
|
||||
AnyPortEnable: true,
|
||||
}
|
||||
client := &gortsplib.Client{
|
||||
DialContext: p.DialContext,
|
||||
|
||||
switch rtspConfig.PullProtocol {
|
||||
case "tcp", "TCP":
|
||||
p.Transport = gortsplib.TransportTCP
|
||||
p.Client.Transport = &p.Transport
|
||||
case "udp", "UDP":
|
||||
p.Transport = gortsplib.TransportUDP
|
||||
p.Client.Transport = &p.Transport
|
||||
AnyPortEnable: true,
|
||||
}
|
||||
p.Transport = gortsplib.TransportTCP
|
||||
client.Transport = &p.Transport
|
||||
// parse URL
|
||||
u, err := url.Parse(p.RemoteURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// connect to the server
|
||||
if err = p.Client.Start(u.Scheme, u.Host); err != nil {
|
||||
if err = client.Start(u.Scheme, u.Host); err != nil {
|
||||
return err
|
||||
}
|
||||
p.SetIO(p.Client)
|
||||
p.Client = client
|
||||
p.SetIO(p)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *RTSPPuller) Pull() (err error) {
|
||||
u, _ := url.Parse(p.RemoteURL)
|
||||
if _, err = p.Options(u); err != nil {
|
||||
p.Error("Options", zap.Error(err))
|
||||
return
|
||||
var res *base.Response
|
||||
if rtspConfig.SendOptions {
|
||||
if res, err = p.Options(u); err != nil {
|
||||
p.Error("Options", zap.Error(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
p.Debug("Options", zap.Any("res", res))
|
||||
// find published tracks
|
||||
tracks, baseURL, _, err := p.Describe(u)
|
||||
session, res, err := p.Describe(u)
|
||||
if err != nil {
|
||||
p.Error("Describe", zap.Error(err))
|
||||
return
|
||||
return err
|
||||
}
|
||||
p.tracks = tracks
|
||||
p.Debug("Describe", zap.Any("res", res))
|
||||
p.session = session
|
||||
err = p.SetTracks()
|
||||
if err != nil {
|
||||
p.Error("SetTracks", zap.Error(err))
|
||||
return
|
||||
return err
|
||||
}
|
||||
if err = p.SetupAll(tracks, baseURL); err != nil {
|
||||
if err = p.SetupAll(session.BaseURL, session.Medias); err != nil {
|
||||
p.Error("SetupAndPlay", zap.Error(err))
|
||||
return
|
||||
return err
|
||||
}
|
||||
p.OnPacketRTPAny(p.OnPacket)
|
||||
_, err = p.Play(nil)
|
||||
res, err = p.Play(nil)
|
||||
p.Debug("Play", zap.Any("res", res))
|
||||
if err != nil {
|
||||
p.Error("Play", zap.Error(err))
|
||||
return
|
||||
return err
|
||||
}
|
||||
return p.Wait()
|
||||
}
|
||||
@@ -105,9 +113,11 @@ func (p *RTSPPusher) OnEvent(event any) {
|
||||
|
||||
func (p *RTSPPusher) Connect() error {
|
||||
p.Client = &gortsplib.Client{
|
||||
DialContext: p.DialContext,
|
||||
WriteBufferCount: rtspConfig.WriteBufferCount,
|
||||
DialContext: p.DialContext,
|
||||
WriteQueueSize: rtspConfig.WriteBufferCount,
|
||||
}
|
||||
p.Transport = gortsplib.TransportTCP
|
||||
p.Client.Transport = &p.Transport
|
||||
// parse URL
|
||||
u, err := url.Parse(p.RemoteURL)
|
||||
if err != nil {
|
||||
@@ -119,10 +129,13 @@ func (p *RTSPPusher) Connect() error {
|
||||
p.Error("Client.Start", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
p.SetIO(p.Client)
|
||||
_, err = p.Client.Options(u)
|
||||
p.SetIO(p)
|
||||
if rtspConfig.SendOptions {
|
||||
_, err = p.Client.Options(u)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *RTSPPusher) Push() (err error) {
|
||||
var u *url.URL
|
||||
u, err = url.Parse(p.RemoteURL)
|
||||
@@ -132,19 +145,24 @@ func (p *RTSPPusher) Push() (err error) {
|
||||
// return fmt.Errorf("timeout")
|
||||
// }
|
||||
// }
|
||||
if _, err = p.Announce(u, p.tracks); err != nil {
|
||||
var res *base.Response
|
||||
if res, err = p.Announce(u, p.session); err != nil {
|
||||
p.Error("Announce", zap.Error(err))
|
||||
return
|
||||
} else {
|
||||
p.Debug("Announce", zap.Any("res", res))
|
||||
}
|
||||
err = p.SetupAll(p.tracks, u)
|
||||
err = p.SetupAll(u, p.session.Medias)
|
||||
if err != nil {
|
||||
p.Error("Setup", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = p.Record(); err != nil {
|
||||
if res, err = p.Record(); err != nil {
|
||||
p.Error("Record", zap.Error(err))
|
||||
return
|
||||
} else {
|
||||
p.Debug("Record", zap.Any("res", res))
|
||||
}
|
||||
p.PlayRTP()
|
||||
return
|
||||
|
32
go.mod
32
go.mod
@@ -3,11 +3,11 @@ module m7s.live/plugin/rtsp/v4
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/bluenviron/gortsplib/v3 v3.9.0
|
||||
github.com/bluenviron/mediacommon v0.7.0
|
||||
github.com/pion/rtp v1.8.0
|
||||
github.com/bluenviron/gortsplib/v4 v4.3.0
|
||||
github.com/bluenviron/mediacommon v1.5.0
|
||||
github.com/pion/rtp v1.8.2
|
||||
go.uber.org/zap v1.24.0
|
||||
m7s.live/engine/v4 v4.13.9
|
||||
m7s.live/engine/v4 v4.14.3
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -17,32 +17,34 @@ require (
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/logrusorgru/aurora/v4 v4.0.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect
|
||||
github.com/mcuadros/go-defaults v1.2.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/pion/randutil v0.1.0 // indirect
|
||||
github.com/pion/rtcp v1.2.10 // indirect
|
||||
github.com/pion/sdp/v3 v3.0.6 // indirect
|
||||
github.com/pion/webrtc/v3 v3.2.14 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect
|
||||
github.com/q191201771/naza v0.30.8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||
github.com/q191201771/naza v0.30.11 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.1 // indirect
|
||||
github.com/quic-go/quic-go v0.37.4 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.22.11 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.23.7 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||
github.com/yapingcat/gomedia v0.0.0-20230727105416-c491e66c9d2a // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.8.0 // indirect
|
||||
golang.org/x/crypto v0.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/net v0.12.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sync v0.2.0 // indirect
|
||||
golang.org/x/sys v0.10.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/tools v0.9.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
68
go.sum
68
go.sum
@@ -1,9 +1,9 @@
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/bluenviron/gortsplib/v3 v3.9.0 h1:aAHV6MhsDtgBF6yKaNBBCdvtSpLB8ne4kyUfLQlN7nM=
|
||||
github.com/bluenviron/gortsplib/v3 v3.9.0/go.mod h1:5h3Zu7jkzwDknYrf+89q2saab//oioKgM9mgvBEX3pg=
|
||||
github.com/bluenviron/mediacommon v0.7.0 h1:dJWLLL9oDbAqfK8KuNfnDUQwNbeMAtGeRjZc9Vo95js=
|
||||
github.com/bluenviron/mediacommon v0.7.0/go.mod h1:wuLJdxcITiSPgY1MvQqrX+qPlKmNfeV9wNvXth5M98I=
|
||||
github.com/bluenviron/gortsplib/v4 v4.3.0 h1:wYtXickYP9zkCxbBIt2WEseQPX0wROB+K0DAew4Ls7g=
|
||||
github.com/bluenviron/gortsplib/v4 v4.3.0/go.mod h1:4XBcXsbK4MDFqnraexSDeKj++ZzrSd81CVplSpSNqKk=
|
||||
github.com/bluenviron/mediacommon v1.5.0 h1:lS0YKNo22ZOyCsYcLh3jn3TgUALqYw0f7RVwalC09vI=
|
||||
github.com/bluenviron/mediacommon v1.5.0/go.mod h1:Ij/kE1LEucSjryNBVTyPL/gBI0d6/Css3f5PyrM957w=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
@@ -50,8 +50,9 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@@ -62,11 +63,11 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/logrusorgru/aurora/v4 v4.0.0 h1:sRjfPpun/63iADiSvGGjgA1cAYegEWMPCJdUpJYn9JA=
|
||||
github.com/logrusorgru/aurora/v4 v4.0.0/go.mod h1:lP0iIa2nrnT/qoFXcOZSrZQpJ1o6n2CUf/hyHi2Q4ZQ=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY=
|
||||
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
|
||||
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik=
|
||||
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
|
||||
github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc=
|
||||
github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
@@ -97,8 +98,9 @@ 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.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||
github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||
github.com/pion/rtp v1.8.0 h1:SYD7040IR+NqrGBOc2GDU5iDjAR+0m5rnX/EWCUMNhw=
|
||||
github.com/pion/rtp v1.8.0/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
|
||||
github.com/pion/rtp v1.8.2 h1:oKMM0K1/QYQ5b5qH+ikqDSZRipP5mIxPJcgcvw5sH0w=
|
||||
github.com/pion/rtp v1.8.2/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
|
||||
github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0=
|
||||
github.com/pion/sctp v1.8.7/go.mod h1:g1Ul+ARqZq5JEmoFy87Q/4CePtKnTJ1QCL9dBBdN6AU=
|
||||
github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw=
|
||||
@@ -115,28 +117,31 @@ github.com/pion/webrtc/v3 v3.2.14 h1:GlqnBnnLlcYYA/LOwqLLU1plZYwx0Y/e/57bZ2tzQcU
|
||||
github.com/pion/webrtc/v3 v3.2.14/go.mod h1:r1mtixc2MH847mmQTPwlEvGge7D18C2T5qp8jI9Lm44=
|
||||
github.com/pixelbender/go-sdp v1.1.0/go.mod h1:6IBlz9+BrUHoFTea7gcp4S54khtOhjCW/nVDLhmZBAs=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI=
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/q191201771/naza v0.30.8 h1:Lhh29o65C4PmTDj2l+eKfsw9dddpgWZk4bFICtcnSaA=
|
||||
github.com/q191201771/naza v0.30.8/go.mod h1:n+dpJjQSh90PxBwxBNuifOwQttywvSIN5TkWSSYCeBk=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/q191201771/naza v0.30.11 h1:az4PkAAFMA2szF6eoVJXrnProgLHV41n3IRuQSaO6mQ=
|
||||
github.com/q191201771/naza v0.30.11/go.mod h1:n+dpJjQSh90PxBwxBNuifOwQttywvSIN5TkWSSYCeBk=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.1 h1:O4BLOM3hwfVF3AcktIylQXyl7Yi2iBNVy5QsV+ySxbg=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/quic-go v0.37.4 h1:ke8B73yMCWGq9MfrCCAw0Uzdm7GaViC3i39dsIdDlH4=
|
||||
github.com/quic-go/quic-go v0.37.4/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/shirou/gopsutil/v3 v3.22.11 h1:kxsPKS+Eeo+VnEQ2XCaGJepeP6KY53QoRTETx3+1ndM=
|
||||
github.com/shirou/gopsutil/v3 v3.22.11/go.mod h1:xl0EeL4vXJ+hQMAGN8B9VFpxukEMA0XdevQOe5MZ1oY=
|
||||
github.com/shirou/gopsutil/v3 v3.23.7 h1:C+fHO8hfIppoJ1WdsVm1RoI0RwXoNdfTK7yWXV0wVj4=
|
||||
github.com/shirou/gopsutil/v3 v3.23.7/go.mod h1:c4gnmoRC0hQuaLqvxnx1//VXQ0Ms/X9UnJF8pddY5z4=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmGV240rTHfO0hfE83S6/a3/Q1siZJ/vXf7A=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
@@ -153,14 +158,13 @@ github.com/yapingcat/gomedia v0.0.0-20230727105416-c491e66c9d2a/go.mod h1:WSZ59b
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
|
||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
|
||||
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@@ -170,8 +174,9 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@@ -196,8 +201,9 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -234,8 +240,9 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -257,8 +264,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
@@ -279,7 +286,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
@@ -293,8 +300,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
m7s.live/engine/v4 v4.13.9 h1:XttLwLQQQSDDZ/oPiAs1jR6pUrd7ERpPk1CyBbjYCOk=
|
||||
m7s.live/engine/v4 v4.13.9/go.mod h1:k/6iFSuJxmhJL8VO45NAga8BbgZHLLfRXOwCcCzk2s8=
|
||||
m7s.live/engine/v4 v4.14.3 h1:yTUm40lQ+wI7/IkO2UvPZAbKAS5ovmbdm2DPe+twhl4=
|
||||
m7s.live/engine/v4 v4.14.3/go.mod h1:cRR/WOZbPSAQfYxIHuCkj1YMg+C54CYlFpOJ88q+OG4=
|
||||
|
33
main.go
33
main.go
@@ -5,7 +5,7 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v3"
|
||||
"github.com/bluenviron/gortsplib/v4"
|
||||
"go.uber.org/zap"
|
||||
. "m7s.live/engine/v4"
|
||||
"m7s.live/engine/v4/config"
|
||||
@@ -17,19 +17,19 @@ type RTSPConfig struct {
|
||||
config.Subscribe
|
||||
config.Pull
|
||||
config.Push
|
||||
ListenAddr string `default:":554"`
|
||||
UDPAddr string `default:":8000"`
|
||||
RTCPAddr string `default:":8001"`
|
||||
ReadBufferCount int `default:"2048"`
|
||||
WriteBufferCount int `default:"2048"`
|
||||
PullProtocol string `default:"tcp"` //tcp、udp、auto
|
||||
ListenAddr string `default:":554" desc:"rtsp监听地址"`
|
||||
UDPAddr string `default:":8000" desc:"udp rtp监听地址"`
|
||||
RTCPAddr string `default:":8001" desc:"udp rtcp监听地址"`
|
||||
WriteBufferCount int `default:"2048" desc:"rtsp写缓冲区大小"`
|
||||
SendOptions bool `default:"true" desc:"是否发送options请求"`
|
||||
sync.Map
|
||||
server *gortsplib.Server
|
||||
}
|
||||
|
||||
func (conf *RTSPConfig) OnEvent(event any) {
|
||||
switch v := event.(type) {
|
||||
case FirstConfig:
|
||||
s := &gortsplib.Server{
|
||||
conf.server = &gortsplib.Server{
|
||||
Handler: conf,
|
||||
RTSPAddress: conf.ListenAddr,
|
||||
UDPRTPAddress: conf.UDPAddr,
|
||||
@@ -37,10 +37,9 @@ func (conf *RTSPConfig) OnEvent(event any) {
|
||||
MulticastIPRange: "224.1.0.0/16",
|
||||
MulticastRTPPort: 8002,
|
||||
MulticastRTCPPort: 8003,
|
||||
ReadBufferCount: conf.ReadBufferCount,
|
||||
WriteBufferCount: conf.WriteBufferCount,
|
||||
WriteQueueSize: conf.WriteBufferCount,
|
||||
}
|
||||
if err := s.Start(); err != nil {
|
||||
if err := conf.server.Start(); err != nil {
|
||||
RTSPPlugin.Error("server start", zap.Error(err))
|
||||
RTSPPlugin.Disabled = true
|
||||
}
|
||||
@@ -50,15 +49,15 @@ func (conf *RTSPConfig) OnEvent(event any) {
|
||||
}
|
||||
}
|
||||
case SEpublish:
|
||||
if url, ok := conf.PushList[v.Target.Path]; ok {
|
||||
if err := RTSPPlugin.Push(v.Target.Path, url, new(RTSPPusher), false); err != nil {
|
||||
RTSPPlugin.Error("push", zap.String("streamPath", v.Target.Path), zap.String("url", url), zap.Error(err))
|
||||
if remoteURL := conf.CheckPush(v.Target.Path); remoteURL != "" {
|
||||
if err := RTSPPlugin.Push(v.Target.Path, remoteURL, new(RTSPPusher), false); err != nil {
|
||||
RTSPPlugin.Error("push", zap.String("streamPath", v.Target.Path), zap.String("url", remoteURL), zap.Error(err))
|
||||
}
|
||||
}
|
||||
case InvitePublish: //按需拉流
|
||||
if url, ok := conf.PullOnSub[v.Target]; ok {
|
||||
if err := RTSPPlugin.Pull(v.Target, url, new(RTSPPuller), 0); err != nil {
|
||||
RTSPPlugin.Error("pull", zap.String("streamPath", v.Target), zap.String("url", url), zap.Error(err))
|
||||
if remoteURL := conf.CheckPullOnSub(v.Target); remoteURL != "" {
|
||||
if err := RTSPPlugin.Pull(v.Target, remoteURL, new(RTSPPuller), 0); err != nil {
|
||||
RTSPPlugin.Error("pull", zap.String("streamPath", v.Target), zap.String("url", remoteURL), zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
35
publisher.go
35
publisher.go
@@ -3,8 +3,8 @@ package rtsp
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v3/pkg/formats"
|
||||
"github.com/bluenviron/gortsplib/v3/pkg/media"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/description"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
||||
"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
|
||||
"github.com/pion/rtp"
|
||||
"go.uber.org/zap"
|
||||
@@ -15,21 +15,21 @@ import (
|
||||
|
||||
type RTSPPublisher struct {
|
||||
Publisher
|
||||
Tracks map[*media.Media]common.AVTrack `json:"-" yaml:"-"`
|
||||
Tracks map[*description.Media]common.AVTrack `json:"-" yaml:"-"`
|
||||
RTSPIO
|
||||
}
|
||||
|
||||
func (p *RTSPPublisher) SetTracks() error {
|
||||
p.Tracks = make(map[*media.Media]common.AVTrack, len(p.tracks))
|
||||
p.Tracks = make(map[*description.Media]common.AVTrack, len(p.session.Medias))
|
||||
defer func() {
|
||||
for _, track := range p.Tracks {
|
||||
p.Info("set track", zap.String("name", track.GetName()))
|
||||
}
|
||||
}()
|
||||
for _, track := range p.tracks {
|
||||
for _, track := range p.session.Medias {
|
||||
for _, forma := range track.Formats {
|
||||
switch f := forma.(type) {
|
||||
case *formats.H264:
|
||||
case *format.H264:
|
||||
vt := p.VideoTrack
|
||||
if vt == nil {
|
||||
vt = NewH264(p.Stream, f.PayloadType())
|
||||
@@ -42,7 +42,7 @@ func (p *RTSPPublisher) SetTracks() error {
|
||||
if len(f.PPS) > 0 {
|
||||
vt.WriteSliceBytes(f.PPS)
|
||||
}
|
||||
case *formats.H265:
|
||||
case *format.H265:
|
||||
vt := p.VideoTrack
|
||||
if vt == nil {
|
||||
vt = NewH265(p.Stream, f.PayloadType())
|
||||
@@ -57,8 +57,15 @@ func (p *RTSPPublisher) SetTracks() error {
|
||||
}
|
||||
if len(f.PPS) > 0 {
|
||||
vt.WriteSliceBytes(f.PPS)
|
||||
}
|
||||
case *format.AV1:
|
||||
vt := p.VideoTrack
|
||||
if vt == nil {
|
||||
vt = NewAV1(p.Stream, f.PayloadType())
|
||||
p.VideoTrack = vt
|
||||
}
|
||||
case *formats.MPEG4Audio:
|
||||
p.Tracks[track] = p.VideoTrack
|
||||
case *format.MPEG4Audio:
|
||||
at := p.AudioTrack
|
||||
if at == nil {
|
||||
at := NewAAC(p.Stream, f.PayloadType(), uint32(f.Config.SampleRate))
|
||||
@@ -75,13 +82,19 @@ func (p *RTSPPublisher) SetTracks() error {
|
||||
p.AudioTrack = at
|
||||
}
|
||||
p.Tracks[track] = p.AudioTrack
|
||||
case *formats.G711:
|
||||
case *format.G711:
|
||||
at := p.AudioTrack
|
||||
if at == nil {
|
||||
at := NewG711(p.Stream, !f.MULaw, f.PayloadType(), uint32(f.ClockRate()))
|
||||
p.AudioTrack = at
|
||||
}
|
||||
p.Tracks[track] = p.AudioTrack
|
||||
case *format.Opus:
|
||||
at := p.AudioTrack
|
||||
if at == nil {
|
||||
at := NewOpus(p.Stream, f.PayloadType(), uint32(f.ClockRate()))
|
||||
p.AudioTrack = at
|
||||
}
|
||||
default:
|
||||
rtpMap := strings.ToLower(forma.RTPMap())
|
||||
if strings.Contains(rtpMap, "pcm") {
|
||||
@@ -96,7 +109,7 @@ func (p *RTSPPublisher) SetTracks() error {
|
||||
}
|
||||
p.Tracks[track] = p.AudioTrack
|
||||
} else {
|
||||
p.Warn("unknown format", zap.Any("format", f.Codec()))
|
||||
p.Warn("unknown format", zap.Any("format", f.FMTP()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,7 +125,7 @@ func (p *RTSPPublisher) SetTracks() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *RTSPPublisher) OnPacket(m *media.Media, f formats.Format, pack *rtp.Packet) {
|
||||
func (p *RTSPPublisher) OnPacket(m *description.Media, f format.Format, pack *rtp.Packet) {
|
||||
if t, ok := p.Tracks[m]; ok {
|
||||
t.WriteRTPPack(pack)
|
||||
}
|
||||
|
26
server.go
26
server.go
@@ -1,18 +1,20 @@
|
||||
package rtsp
|
||||
|
||||
import (
|
||||
"github.com/bluenviron/gortsplib/v3"
|
||||
"github.com/bluenviron/gortsplib/v3/pkg/base"
|
||||
"github.com/bluenviron/gortsplib/v3/pkg/media"
|
||||
"github.com/bluenviron/gortsplib/v4"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/base"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/description"
|
||||
"go.uber.org/zap"
|
||||
. "m7s.live/engine/v4"
|
||||
)
|
||||
|
||||
type RTSPIO struct {
|
||||
tracks media.Medias
|
||||
server *gortsplib.Server
|
||||
session *description.Session
|
||||
tracks []*description.Media
|
||||
stream *gortsplib.ServerStream
|
||||
audioTrack *media.Media
|
||||
videoTrack *media.Media
|
||||
audioTrack *description.Media
|
||||
videoTrack *description.Media
|
||||
}
|
||||
|
||||
func (conf *RTSPConfig) OnConnOpen(ctx *gortsplib.ServerHandlerOnConnOpenCtx) {
|
||||
@@ -32,15 +34,14 @@ func (conf *RTSPConfig) OnSessionOpen(ctx *gortsplib.ServerHandlerOnSessionOpenC
|
||||
|
||||
func (conf *RTSPConfig) OnSessionClose(ctx *gortsplib.ServerHandlerOnSessionCloseCtx) {
|
||||
RTSPPlugin.Debug("session closed")
|
||||
// if p, ok := conf.LoadAndDelete(ctx.Session); ok {
|
||||
// p.(IIO).Stop()
|
||||
// }
|
||||
conf.Delete(ctx.Session)
|
||||
}
|
||||
|
||||
// called after receiving a DESCRIBE request.
|
||||
func (conf *RTSPConfig) OnDescribe(ctx *gortsplib.ServerHandlerOnDescribeCtx) (*base.Response, *gortsplib.ServerStream, error) {
|
||||
RTSPPlugin.Debug("describe request")
|
||||
RTSPPlugin.Debug("describe request", zap.String("sdp", string(ctx.Request.Body)))
|
||||
var suber RTSPSubscriber
|
||||
suber.server = conf.server
|
||||
suber.RemoteAddr = ctx.Conn.NetConn().RemoteAddr().String()
|
||||
suber.SetIO(ctx.Conn.NetConn())
|
||||
streamPath := ctx.Path
|
||||
@@ -99,11 +100,12 @@ func (conf *RTSPConfig) OnRecord(ctx *gortsplib.ServerHandlerOnRecordCtx) (*base
|
||||
}, nil
|
||||
}
|
||||
func (conf *RTSPConfig) OnAnnounce(ctx *gortsplib.ServerHandlerOnAnnounceCtx) (*base.Response, error) {
|
||||
RTSPPlugin.Debug("annouce request", zap.String("sdp", string(ctx.Request.Body)))
|
||||
p := &RTSPPublisher{}
|
||||
p.SetIO(ctx.Conn.NetConn())
|
||||
if err := RTSPPlugin.Publish(ctx.Path, p); err == nil {
|
||||
p.tracks = ctx.Medias
|
||||
p.stream = gortsplib.NewServerStream(ctx.Medias)
|
||||
p.session = ctx.Description
|
||||
p.stream = gortsplib.NewServerStream(conf.server, ctx.Description)
|
||||
if err = p.SetTracks(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -1,10 +1,12 @@
|
||||
package rtsp
|
||||
|
||||
import (
|
||||
"github.com/bluenviron/gortsplib/v3"
|
||||
"fmt"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v4"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/description"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
||||
"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
|
||||
"github.com/bluenviron/gortsplib/v3/pkg/formats"
|
||||
"github.com/bluenviron/gortsplib/v3/pkg/media"
|
||||
. "m7s.live/engine/v4"
|
||||
"m7s.live/engine/v4/codec"
|
||||
"m7s.live/engine/v4/track"
|
||||
@@ -23,40 +25,53 @@ func (s *RTSPSubscriber) OnEvent(event any) {
|
||||
}
|
||||
switch v.CodecID {
|
||||
case codec.CodecID_H264:
|
||||
video := &media.Media{
|
||||
Type: media.TypeVideo,
|
||||
Formats: []formats.Format{&formats.H264{
|
||||
s.videoTrack = &description.Media{
|
||||
Type: description.MediaTypeVideo,
|
||||
Formats: []format.Format{&format.H264{
|
||||
PacketizationMode: 1,
|
||||
PayloadTyp: v.PayloadType,
|
||||
SPS: v.ParamaterSets[0],
|
||||
PPS: v.ParamaterSets[1],
|
||||
}},
|
||||
}
|
||||
s.videoTrack = video
|
||||
s.tracks = append(s.tracks, video)
|
||||
case codec.CodecID_H265:
|
||||
video := &media.Media{
|
||||
Type: media.TypeVideo,
|
||||
Formats: []formats.Format{&formats.H265{
|
||||
s.videoTrack = &description.Media{
|
||||
Type: description.MediaTypeVideo,
|
||||
Formats: []format.Format{&format.H265{
|
||||
PayloadTyp: v.PayloadType,
|
||||
VPS: v.ParamaterSets[0],
|
||||
SPS: v.ParamaterSets[1],
|
||||
PPS: v.ParamaterSets[2],
|
||||
}},
|
||||
}
|
||||
s.videoTrack = video
|
||||
s.tracks = append(s.tracks, video)
|
||||
case codec.CodecID_AV1:
|
||||
var idx, profile, tail int
|
||||
idx = int(v.ParamaterSets[1][0])
|
||||
profile = int(v.ParamaterSets[1][1])
|
||||
tail = int(v.ParamaterSets[1][2])
|
||||
s.videoTrack = &description.Media{
|
||||
Type: description.MediaTypeVideo,
|
||||
Formats: []format.Format{&format.AV1{
|
||||
PayloadTyp: v.PayloadType,
|
||||
LevelIdx: &idx,
|
||||
Profile: &profile,
|
||||
Tier: &tail,
|
||||
}},
|
||||
}
|
||||
}
|
||||
if s.videoTrack != nil {
|
||||
s.tracks = append(s.tracks, s.videoTrack)
|
||||
s.AddTrack(v)
|
||||
}
|
||||
s.AddTrack(v)
|
||||
case *track.Audio:
|
||||
if s.Audio != nil {
|
||||
return
|
||||
}
|
||||
switch v.CodecID {
|
||||
case codec.CodecID_AAC:
|
||||
audio := &media.Media{
|
||||
Type: media.TypeAudio,
|
||||
Formats: []formats.Format{&formats.MPEG4Audio{
|
||||
s.audioTrack = &description.Media{
|
||||
Type: description.MediaTypeAudio,
|
||||
Formats: []format.Format{&format.MPEG4Audio{
|
||||
PayloadTyp: v.PayloadType,
|
||||
Config: &mpeg4audio.Config{
|
||||
Type: mpeg4audio.ObjectTypeAACLC,
|
||||
@@ -68,28 +83,43 @@ func (s *RTSPSubscriber) OnEvent(event any) {
|
||||
IndexDeltaLength: v.IndexDeltaLength,
|
||||
}},
|
||||
}
|
||||
s.audioTrack = audio
|
||||
s.tracks = append(s.tracks, audio)
|
||||
case codec.CodecID_PCMA:
|
||||
audio := &media.Media{
|
||||
Type: media.TypeAudio,
|
||||
Formats: []formats.Format{&formats.G711{}},
|
||||
}
|
||||
s.audioTrack = audio
|
||||
s.tracks = append(s.tracks, audio)
|
||||
case codec.CodecID_PCMU:
|
||||
audio := &media.Media{
|
||||
Type: media.TypeAudio,
|
||||
Formats: []formats.Format{&formats.G711{
|
||||
MULaw: true,
|
||||
s.audioTrack = &description.Media{
|
||||
Type: description.MediaTypeAudio,
|
||||
Formats: []format.Format{&format.Generic{
|
||||
PayloadTyp: v.PayloadType,
|
||||
ClockRat: int(v.SampleRate),
|
||||
RTPMa: fmt.Sprintf("PCMA/%d", v.SampleRate),
|
||||
}},
|
||||
}
|
||||
case codec.CodecID_PCMU:
|
||||
s.audioTrack = &description.Media{
|
||||
Type: description.MediaTypeAudio,
|
||||
Formats: []format.Format{&format.Generic{
|
||||
PayloadTyp: v.PayloadType,
|
||||
ClockRat: int(v.SampleRate),
|
||||
RTPMa: fmt.Sprintf("PCMU/%d", v.SampleRate),
|
||||
}},
|
||||
}
|
||||
case codec.CodecID_OPUS:
|
||||
s.audioTrack = &description.Media{
|
||||
Type: description.MediaTypeAudio,
|
||||
Formats: []format.Format{&format.Opus{
|
||||
PayloadTyp: v.PayloadType,
|
||||
}},
|
||||
}
|
||||
s.audioTrack = audio
|
||||
s.tracks = append(s.tracks, audio)
|
||||
}
|
||||
s.AddTrack(v)
|
||||
if s.audioTrack != nil {
|
||||
s.tracks = append(s.tracks, s.audioTrack)
|
||||
s.AddTrack(v)
|
||||
}
|
||||
case ISubscriber:
|
||||
s.stream = gortsplib.NewServerStream(s.tracks)
|
||||
s.session = &description.Session{
|
||||
Medias: s.tracks,
|
||||
}
|
||||
if s.server != nil {
|
||||
s.stream = gortsplib.NewServerStream(s.server, s.session)
|
||||
}
|
||||
case VideoRTP:
|
||||
s.stream.WritePacketRTP(s.videoTrack, v.Packet)
|
||||
case AudioRTP:
|
||||
|
Reference in New Issue
Block a user