mirror of
https://github.com/Monibuca/plugin-gb28181.git
synced 2025-12-24 13:27:57 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ecd97c8439 | ||
|
|
bfd71a72d8 | ||
|
|
c6bef8ccd8 | ||
|
|
20c0ac52cb | ||
|
|
34f5b7da79 |
14
README.md
14
README.md
@@ -22,7 +22,7 @@ gb28181:
|
||||
prefetchrecord: false
|
||||
udpcachesize: 0
|
||||
sipnetwork: udp
|
||||
sipip:
|
||||
sipip: ""
|
||||
sipport: 5060
|
||||
serial: "34020000002000000001"
|
||||
realm: "3402000000"
|
||||
@@ -35,14 +35,15 @@ gb28181:
|
||||
heartbeatinterval: 60
|
||||
heartbeatretry: 3
|
||||
|
||||
mediaip:
|
||||
mediaip: ""
|
||||
mediaport: 58200
|
||||
mediaidletimeout: 30
|
||||
medianetwork: udp
|
||||
|
||||
mediaportmin: 0
|
||||
meidaportmax: 0
|
||||
|
||||
removebaninterval: 600
|
||||
loglevel: info
|
||||
audioenable: true
|
||||
```
|
||||
|
||||
- `AutoInvite` bool 表示自动发起invite,当Server(SIP)接收到设备信息时,立即向设备发送invite命令获取流
|
||||
@@ -68,12 +69,15 @@ gb28181:
|
||||
- `MediaPort` uint16 媒体服务器端口
|
||||
- `MediaNetwork` string 媒体传输协议,默认UDP,可选TCP
|
||||
- `MediaIdleTimeout` uint16 推流超时时间,超过则断开链接,让设备重连
|
||||
|
||||
- `MediaPortMin` uint16 媒体服务器端口范围最小值
|
||||
- `MediaPortMax` uint16 媒体服务器端口范围最大值
|
||||
- `AudioEnable` bool 是否开启音频
|
||||
- `LogLevel` string 日志级别,默认 info(trace,debug,info,warn,error,fatal, panic)
|
||||
- `RemoveBanInterval` int 定时移除注册失败的设备黑名单,单位秒,默认10分钟(600秒)
|
||||
- `UdpCacheSize` int 表示UDP缓存大小,默认为0,不开启。仅当TCP关闭,切缓存大于0时才开启,会最多缓存最多N个包,并排序,修复乱序造成的无法播放问题,注意开启后,会有一定的性能损耗,并丢失部分包。
|
||||
|
||||
**如果配置了端口范围,将采用范围端口机制,每一个流对应一个端口
|
||||
|
||||
**注意某些摄像机没有设置用户名的地方,摄像机会以自身的国标id作为用户名,这个时候m7s会忽略使用摄像机的用户名,忽略配置的用户名**
|
||||
如果设备配置了错误的用户名和密码,连续三次上报错误后,m7s会记录设备id,并在10分钟内禁止设备注册
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
. "m7s.live/engine/v4"
|
||||
"github.com/ghettovoice/gosip/sip"
|
||||
"go.uber.org/zap"
|
||||
"m7s.live/plugin/gb28181/v4/utils"
|
||||
@@ -393,6 +394,11 @@ func (channel *Channel) Invite(opt InviteOptions) (code int, err error) {
|
||||
}
|
||||
|
||||
func (channel *Channel) Bye(live bool) int {
|
||||
d := channel.device
|
||||
streamPath := fmt.Sprintf("%s/%s", d.ID, channel.DeviceID)
|
||||
if s := Streams.Get(streamPath); s != nil {
|
||||
s.Close()
|
||||
}
|
||||
if live && channel.LivePublisher != nil {
|
||||
return channel.LivePublisher.Bye()
|
||||
}
|
||||
|
||||
28
publisher.go
28
publisher.go
@@ -116,9 +116,9 @@ func (p *GBPublisher) PushVideo(pts uint32, dts uint32, payload []byte) {
|
||||
default:
|
||||
//推测编码类型
|
||||
var maybe264 H264NALUType
|
||||
maybe264 = maybe264.Parse(payload[5])
|
||||
maybe264 = maybe264.Parse(payload[4])
|
||||
switch maybe264 {
|
||||
case NALU_Non_IDR_Picture, NALU_IDR_Picture, NALU_SEI, NALU_SPS, NALU_PPS:
|
||||
case NALU_Non_IDR_Picture, NALU_IDR_Picture, NALU_SEI, NALU_SPS, NALU_PPS, NALU_Access_Unit_Delimiter:
|
||||
p.VideoTrack = NewH264(p.Publisher.Stream)
|
||||
default:
|
||||
p.VideoTrack = NewH265(p.Publisher.Stream)
|
||||
@@ -161,21 +161,20 @@ func (p *GBPublisher) PushAudio(ts uint32, payload []byte) {
|
||||
|
||||
// 解析rtp封装 https://www.ietf.org/rfc/rfc2250.txt
|
||||
func (p *GBPublisher) PushPS(rtp *rtp.Packet) {
|
||||
if !conf.IsMediaNetworkTCP() {
|
||||
rtp = p.reorder.Push(rtp.SequenceNumber, rtp)
|
||||
} else {
|
||||
p.lastSeq = rtp.SequenceNumber
|
||||
}
|
||||
if p.parser == nil {
|
||||
p.parser = utils.NewDecPSPackage(p)
|
||||
}
|
||||
for rtp != nil {
|
||||
if rtp.SequenceNumber != p.lastSeq+1 {
|
||||
p.parser.Drop()
|
||||
}
|
||||
if conf.IsMediaNetworkTCP() {
|
||||
p.parser.Feed(rtp.Payload)
|
||||
p.lastSeq = rtp.SequenceNumber
|
||||
rtp = p.reorder.Pop()
|
||||
} else {
|
||||
for rtp = p.reorder.Push(rtp.SequenceNumber, rtp); rtp != nil; rtp = p.reorder.Pop() {
|
||||
if rtp.SequenceNumber != p.lastSeq+1 {
|
||||
p.parser.Drop()
|
||||
}
|
||||
p.parser.Feed(rtp.Payload)
|
||||
p.lastSeq = rtp.SequenceNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,16 +221,19 @@ func (p *GBPublisher) ListenUDP() (port uint16, err error) {
|
||||
mediaAddr, _ := net.ResolveUDPAddr("udp", addr)
|
||||
conn, err := net.ListenUDP("udp", mediaAddr)
|
||||
if err != nil {
|
||||
conf.udpPorts.Recycle(port)
|
||||
plugin.Error("listen media server udp err", zap.String("addr", addr), zap.Error(err))
|
||||
return 0, err
|
||||
}
|
||||
p.SetIO(conn)
|
||||
go func() {
|
||||
defer conn.Close()
|
||||
bufUDP := make([]byte, networkBuffer)
|
||||
plugin.Info("Media udp server start.", zap.Uint16("port", port))
|
||||
defer plugin.Info("Media udp server stop", zap.Uint16("port", port))
|
||||
defer conf.udpPorts.Recycle(port)
|
||||
dumpLen := make([]byte, 6)
|
||||
conn.SetReadDeadline(time.Now().Add(time.Second * 10))
|
||||
for n, _, err := conn.ReadFromUDP(bufUDP); err == nil; n, _, err = conn.ReadFromUDP(bufUDP) {
|
||||
ps := bufUDP[:n]
|
||||
if err := rtpPacket.Unmarshal(ps); err != nil {
|
||||
@@ -249,6 +251,7 @@ func (p *GBPublisher) ListenUDP() (port uint16, err error) {
|
||||
p.dumpFile.Write(ps)
|
||||
}
|
||||
p.PushPS(&rtpPacket)
|
||||
conn.SetReadDeadline(time.Now().Add(time.Second * 10))
|
||||
}
|
||||
}()
|
||||
return
|
||||
@@ -263,6 +266,7 @@ func (p *GBPublisher) ListenTCP() (port uint16, err error) {
|
||||
mediaAddr, _ := net.ResolveTCPAddr("tcp", addr)
|
||||
listen, err := net.ListenTCP("tcp", mediaAddr)
|
||||
if err != nil {
|
||||
defer conf.tcpPorts.Recycle(port)
|
||||
plugin.Error("listen media server tcp err", zap.String("addr", addr), zap.Error(err))
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -164,6 +164,8 @@ func (dec *DecPSPackage) Feed(ps []byte) (err error) {
|
||||
if dec.Len() >= 4 {
|
||||
//说明需要处理PS包,处理完后,清空缓存
|
||||
defer dec.Reset()
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 说明是中间数据,直接写入缓存,否则数据不合法需要丢弃
|
||||
|
||||
Reference in New Issue
Block a user