Compare commits

...

23 Commits

Author SHA1 Message Date
dexter
9a3ad6a51c 音频加入时钟频率 2023-02-15 19:32:37 +08:00
dexter
e0c6fbefcd 适配引擎 2023-02-14 21:22:54 +08:00
dexter
b924977085 Merge pull request #80 from yangchao2015/v4
基于新版本修改时间判断,调整AutosubPosition 默认为false
2023-02-03 16:14:47 +08:00
yangchao
521ee36769 基于新版本修改时间判断,调整AutosubPosition 默认为false 2023-02-03 16:02:09 +08:00
dexter
583754ea82 对时间配置统一改成time.Duration类型 2023-02-02 12:03:44 +08:00
charlestamz
58b6a818bd Merge pull request #79 from yangchao2015/v4
调整和更新GB轨迹订阅和获取
2023-02-01 16:59:20 +08:00
yangchao
8b1b176f51 调整和更新GB轨迹订阅和获取 2023-02-01 16:07:45 +08:00
dexter
68d6cbaab9 g711初始化代码收于引擎中 2023-01-18 21:03:08 +08:00
dexter
f88d4d264e tcp使用范围端口时不再判断ssrc 2023-01-10 09:24:27 +08:00
dexter
55aa20e868 fix: 时间戳设置错误 2022-12-31 21:30:28 +08:00
dexter
9f4ad83da7 增加对aac的预测 2022-12-18 14:28:21 +08:00
charlestamz
68ff4dba5b Merge remote-tracking branch 'origin/v4' into v4 2022-11-29 12:38:00 +08:00
charlestamz
e9f576e3f4 解决GB设备兼容的问题。
修复发送invite指令中非同域To的地址问题
2022-11-29 12:37:46 +08:00
charlestamz
b271cb8e50 merge remote changes 2022-11-29 12:32:09 +08:00
dexter
2b82a0ffc4 📦 NEW: 设置丢帧标志 2022-11-22 11:18:21 +08:00
dexter
940d7c5e59 🐛 FIX: 优化PS解析 2022-11-17 23:47:20 +08:00
dexter
2142a474a3 🐛 FIX: 大PES分包机制 2022-11-17 11:53:36 +08:00
dexter
86e9bccb85 🐛 FIX: 增加对AAC的支持以及多slice合并发送 2022-11-13 23:30:45 +08:00
dexter
bb3a679a60 音频时间戳转换 2022-10-25 21:38:06 +08:00
dexter
ecd97c8439 🐛 FIX: tcp解析 2022-10-25 15:35:00 +08:00
dexter
bfd71a72d8 Merge pull request #74 from hongri8488/v4
添加28181 bye接口调用时将流关闭
2022-10-25 14:44:39 +08:00
dexter
c6bef8ccd8 🐛 FIX: udp范围端口增加超时功能 2022-10-25 14:44:03 +08:00
hongri8488
20c0ac52cb 添加28181 bye接口调用时将流关闭 2022-10-25 13:51:31 +08:00
12 changed files with 385 additions and 227 deletions

View File

@@ -19,6 +19,10 @@ _ "m7s.live/plugin/gb28181/v4"
```yaml
gb28181:
autoinvite: true
position:
autosubposition: false #是否自动订阅定位
expires: 3600s #订阅周期(单位:秒)默认3600
interval: 6s #订阅间隔单位默认6
prefetchrecord: false
udpcachesize: 0
sipnetwork: udp
@@ -29,11 +33,7 @@ gb28181:
username: ""
password: ""
acktimeout: 10
registervalidity: 60
registerinterval: 60
heartbeatinterval: 60
heartbeatretry: 3
registervalidity: 60s
mediaip: ""
mediaport: 58200
@@ -42,7 +42,7 @@ gb28181:
mediaportmin: 0
meidaportmax: 0
removebaninterval: 600
removebaninterval: 10m
loglevel: info
```
@@ -58,11 +58,7 @@ gb28181:
- `Username` string sip 服务器账号
- `Password` string sip 服务器密码
- `AckTimeout` uint16 sip 服务应答超时,单位秒
- `RegisterValidity` int 注册有效期,单位秒,默认 3600
- `RegisterInterval` int 注册间隔,单位秒,默认 60
- `HeartbeatInterval` int 心跳间隔,单位秒,默认 60
- `HeartbeatRetry` int 心跳超时次数,默认 3
- `RegisterValidity` time.Duration 注册有效期,单位秒,默认 60
* 媒体服务器配置
- `MediaIP` string 媒体服务器地址 默认 自动适配设备网段
@@ -71,9 +67,8 @@ gb28181:
- `MediaIdleTimeout` uint16 推流超时时间,超过则断开链接,让设备重连
- `MediaPortMin` uint16 媒体服务器端口范围最小值
- `MediaPortMax` uint16 媒体服务器端口范围最大值
- `AudioEnable` bool 是否开启音频
- `LogLevel` string 日志级别,默认 infotracedebuginfowarnerrorfatal, panic
- `RemoveBanInterval` int 定时移除注册失败的设备黑名单单位秒默认10分钟600秒
- `LogLevel` string 日志级别,默认 infotracedebuginfowarnerrorfatal, panic
- `RemoveBanInterval` time.Duration 定时移除注册失败的设备黑名单单位秒默认10分钟600秒
- `UdpCacheSize` int 表示UDP缓存大小默认为0不开启。仅当TCP关闭切缓存大于0时才开启会最多缓存最多N个包并排序修复乱序造成的无法播放问题注意开启后会有一定的性能损耗并丢失部分包。
**如果配置了端口范围,将采用范围端口机制,每一个流对应一个端口
@@ -130,12 +125,12 @@ type Device struct {
`/gb28181/api/invite`
参数名 | 必传 | 含义
|----|---|---
id|是 | 设备ID
channel|是|通道编号
startTime|否|开始时间纯数字Unix时间戳
endTime|否|结束时间纯数字Unix时间戳
| 参数名 | 必传 | 含义 |
| --------- | ---- | ---------------------------- |
| id | 是 | 设备ID |
| channel | 是 | 通道编号 |
| startTime | 否 | 开始时间纯数字Unix时间戳 |
| endTime | 否 | 结束时间纯数字Unix时间戳 |
返回200代表成功
@@ -143,38 +138,38 @@ endTime|否|结束时间纯数字Unix时间戳
`/gb28181/api/bye`
参数名 | 必传 | 含义
|----|---|---
id|是 | 设备ID
channel|是|通道编号
| 参数名 | 必传 | 含义 |
| ------- | ---- | -------- |
| id | 是 | 设备ID |
| channel | 是 | 通道编号 |
### 发送控制命令
`/gb28181/api/control`
参数名 | 必传 | 含义
|----|---|---
id|是 | 设备ID
channel|是|通道编号
ptzcmd|是|PTZ控制指令
| 参数名 | 必传 | 含义 |
| ------- | ---- | ----------- |
| id | 是 | 设备ID |
| channel | 是 | 通道编号 |
| ptzcmd | 是 | PTZ控制指令 |
### 查询录像
`/gb28181/api/records`
参数名 | 必传 | 含义
|----|---|---
id|是 | 设备ID
channel|是|通道编号
startTime|否|开始时间字符串格式2021-7-23T12:00:00
endTime|否|结束时间(字符串格式同上)
| 参数名 | 必传 | 含义 |
| --------- | ---- | -------------------------------------------- |
| id | 是 | 设备ID |
| channel | 是 | 通道编号 |
| startTime | 否 | 开始时间字符串格式2021-7-23T12:00:00 |
| endTime | 否 | 结束时间(字符串格式同上) |
### 移动位置订阅
`/gb28181/api/position`
参数名 | 必传 | 含义
|----|---|---
id|是 | 设备ID
expires|是|订阅周期(秒)
interval|是|订阅间隔(秒)
| 参数名 | 必传 | 含义 |
| -------- | ---- | -------------- |
| id | 是 | 设备ID |
| expires | 是 | 订阅周期(秒) |
| interval | 是 | 订阅间隔(秒) |

View File

@@ -12,6 +12,7 @@ import (
"github.com/ghettovoice/gosip/sip"
"go.uber.org/zap"
. "m7s.live/engine/v4"
"m7s.live/plugin/gb28181/v4/utils"
)
@@ -42,6 +43,7 @@ type Channel struct {
Owner string
CivilCode string
Address string
Port int
Parental int
SafetyWay int
RegisterWay int
@@ -79,6 +81,7 @@ func (c *Channel) CreateRequst(Method sip.RequestMethod) (req sip.Request) {
callId := sip.CallID(utils.RandNumString(10))
userAgent := sip.UserAgentHeader("Monibuca")
maxForwards := sip.MaxForwards(70) //增加max-forwards为默认值 70
cseq := sip.CSeq{
SeqNo: uint32(d.sn),
MethodName: Method,
@@ -93,9 +96,17 @@ func (c *Channel) CreateRequst(Method sip.RequestMethod) (req sip.Request) {
},
Params: sip.NewParams().Add("tag", sip.String{Str: utils.RandNumString(9)}),
}
//非同一域的目标地址需要使用@host
host := conf.Realm
if c.DeviceID[0:9] != host {
deviceIp := d.NetAddr
deviceIp = deviceIp[0:strings.LastIndex(deviceIp, ":")]
host = fmt.Sprintf("%s:%d", deviceIp, c.Port)
}
channelAddr := sip.Address{
//DisplayName: sip.String{Str: d.serverConfig.Serial},
Uri: &sip.SipUri{FUser: sip.String{Str: c.DeviceID}, FHost: conf.Realm},
Uri: &sip.SipUri{FUser: sip.String{Str: c.DeviceID}, FHost: host},
}
req = sip.NewRequest(
"",
@@ -108,6 +119,7 @@ func (c *Channel) CreateRequst(Method sip.RequestMethod) (req sip.Request) {
&callId,
&userAgent,
&cseq,
&maxForwards,
serverAddr.AsContactHeader(),
},
"",
@@ -393,6 +405,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()
}

View File

@@ -67,6 +67,9 @@ type Device struct {
CallID string
Timeout time.Time
}
GpsTime time.Time //gps时间
Longitude string //经度
Latitude string //纬度
}
func (config *GB28181Config) RecoverDevice(d *Device, req sip.Request) {
@@ -161,7 +164,7 @@ func ReadDevices() {
var items []*Device
if err = json.NewDecoder(f).Decode(&items); err == nil {
for _, item := range items {
if time.Since(item.UpdateTime) < time.Duration(conf.RegisterValidity)*time.Second {
if time.Since(item.UpdateTime) < conf.RegisterValidity {
item.Status = "RECOVER"
Devices.Store(item.ID, item)
}
@@ -264,6 +267,7 @@ func (d *Device) CreateRequest(Method sip.RequestMethod) (req sip.Request) {
callId := sip.CallID(utils.RandNumString(10))
userAgent := sip.UserAgentHeader("Monibuca")
maxForwards := sip.MaxForwards(70) //增加max-forwards为默认值 70
cseq := sip.CSeq{
SeqNo: uint32(d.sn),
MethodName: Method,
@@ -289,6 +293,7 @@ func (d *Device) CreateRequest(Method sip.RequestMethod) (req sip.Request) {
&callId,
&userAgent,
&cseq,
&maxForwards,
serverAddr.AsContactHeader(),
},
"",
@@ -401,19 +406,19 @@ func (d *Device) SipRequestForResponse(request sip.Request) (sip.Response, error
}
// MobilePositionSubscribe 移动位置订阅
func (d *Device) MobilePositionSubscribe(id string, expires int, interval int) (code int) {
func (d *Device) MobilePositionSubscribe(id string, expires time.Duration, interval time.Duration) (code int) {
mobilePosition := d.CreateRequest(sip.SUBSCRIBE)
if d.subscriber.CallID != "" {
callId := sip.CallID(utils.RandNumString(10))
mobilePosition.ReplaceHeaders(callId.Name(), []sip.Header{&callId})
}
expiresHeader := sip.Expires(expires)
d.subscriber.Timeout = time.Now().Add(time.Second * time.Duration(expires))
expiresHeader := sip.Expires(expires / time.Second)
d.subscriber.Timeout = time.Now().Add(expires)
contentType := sip.ContentType("Application/MANSCDP+xml")
mobilePosition.AppendHeader(&contentType)
mobilePosition.AppendHeader(&expiresHeader)
mobilePosition.SetBody(BuildDevicePositionXML(d.sn, id, interval), true)
mobilePosition.SetBody(BuildDevicePositionXML(d.sn, id, int(interval/time.Second)), true)
response, err := d.SipRequestForResponse(mobilePosition)
if err == nil && response != nil {
@@ -431,12 +436,16 @@ func (d *Device) MobilePositionSubscribe(id string, expires int, interval int) (
// UpdateChannelPosition 更新通道GPS坐标
func (d *Device) UpdateChannelPosition(channelId string, gpsTime string, lng string, lat string) {
if c, ok := d.channelMap[channelId]; ok {
c.ChannelEx.GpsTime, _ = time.ParseInLocation("2006-01-02 15:04:05", gpsTime, time.Local)
c.ChannelEx.GpsTime = time.Now() //时间取系统收到的时间,避免设备时间和格式问题
c.ChannelEx.Longitude = lng
c.ChannelEx.Latitude = lat
plugin.Sugar().Debugf("更新通道[%s]坐标成功\n", c.Name)
} else {
plugin.Sugar().Debugf("更新失败,未找到通道[%s]\n", channelId)
//如果未找到通道,则更新到设备上
d.GpsTime = time.Now() //时间取系统收到的时间,避免设备时间和格式问题
d.Longitude = lng
d.Latitude = lat
plugin.Sugar().Debugf("未找到通道[%s],更新设备[%s]坐标成功\n", channelId, d.ID)
}
}
@@ -467,6 +476,7 @@ func (d *Device) UpdateChannelStatus(deviceList []*notifyMessage) {
Owner: v.Owner,
CivilCode: v.CivilCode,
Address: v.Address,
Port: v.Port,
Parental: v.Parental,
SafetyWay: v.SafetyWay,
RegisterWay: v.RegisterWay,
@@ -491,6 +501,7 @@ func (d *Device) UpdateChannelStatus(deviceList []*notifyMessage) {
Owner: v.Owner,
CivilCode: v.CivilCode,
Address: v.Address,
Port: v.Port,
Parental: v.Parental,
SafetyWay: v.SafetyWay,
RegisterWay: v.RegisterWay,

53
go.mod
View File

@@ -3,50 +3,59 @@ module m7s.live/plugin/gb28181/v4
go 1.18
require (
github.com/ghettovoice/gosip v0.0.0-20220420085539-cf932c28a8fe
github.com/husanpao/ip v0.0.0-20220711072141-f1e1174bc11b
github.com/ghettovoice/gosip v0.0.0-20221121090201-9a2ed2233b6d
github.com/husanpao/ip v0.0.0-20220711082147-73160bb611a8
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/pion/rtp/v2 v2.0.0-20220302185659-b3d10fc096b0
go.uber.org/zap v1.21.0
golang.org/x/net v0.0.0-20220607020251-c690dde0001d
golang.org/x/text v0.3.7
m7s.live/engine/v4 v4.5.0
go.uber.org/zap v1.23.0
golang.org/x/net v0.2.0
golang.org/x/text v0.4.0
m7s.live/engine/v4 v4.8.5
)
require (
github.com/cnotch/ipchub v1.1.0 // indirect
github.com/discoviking/fsm v0.0.0-20150126104936-f4a273feecca // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.1.0 // 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/kr/text v0.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20220517141722-cf486979b281 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/lucas-clemente/quic-go v0.31.0 // indirect
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.19.0 // indirect
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtp v1.7.13 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect
github.com/q191201771/naza v0.30.2 // indirect
github.com/q191201771/naza v0.30.8 // indirect
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b // indirect
github.com/shirou/gopsutil/v3 v3.22.5 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/shirou/gopsutil/v3 v3.22.10 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/tevino/abool v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.5.0 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect
golang.org/x/crypto v0.3.0 // indirect
golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/term v0.2.0 // indirect
golang.org/x/tools v0.3.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

115
go.sum
View File

@@ -1,6 +1,5 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/cnotch/apirouter v0.0.0-20200731232942-89e243a791f3/go.mod h1:5deJPLON/x/s2dLOQfuKS0lenhOIT4xX0pvtN/OEIuY=
github.com/cnotch/ipchub v1.1.0 h1:hH0lh2mU3AZXPiqMwA0pdtqrwo7PFIMRGush9OobMUs=
github.com/cnotch/ipchub v1.1.0/go.mod h1:2PbeBs2q2VxxTVCn1eYCDwpAWuVXbq1+N0FU7GimOH4=
@@ -18,11 +17,12 @@ github.com/discoviking/fsm v0.0.0-20150126104936-f4a273feecca/go.mod h1:W+3LQaEk
github.com/emitter-io/address v1.0.0/go.mod h1:GfZb5+S/o8694B1GMGK2imUYQyn2skszMvGNA5D84Ug=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/ghettovoice/gosip v0.0.0-20220420085539-cf932c28a8fe h1:turrF/P/KarJUx9aUnRNZMQtUu2hsNFNa+iNog+e/fc=
github.com/ghettovoice/gosip v0.0.0-20220420085539-cf932c28a8fe/go.mod h1:yTr3BEYSFe9As6XM7ldyrVgqsPwlnw8Ahc4N28VFM2g=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/ghettovoice/gosip v0.0.0-20221121090201-9a2ed2233b6d h1:f1JRfm0MwkluwtUsbYxuVReDMajlc9Wn6zc2orX4sRE=
github.com/ghettovoice/gosip v0.0.0-20221121090201-9a2ed2233b6d/go.mod h1:yTr3BEYSFe9As6XM7ldyrVgqsPwlnw8Ahc4N28VFM2g=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
@@ -31,6 +31,8 @@ github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm
github.com/gobwas/ws v1.1.0-rc.1/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@@ -38,36 +40,45 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
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/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.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/husanpao/ip v0.0.0-20220711082147-73160bb611a8 h1:4Jk58quTZmzJcTrLlbB5L1Q6qXu49EIjCReWxcBFWKo=
github.com/husanpao/ip v0.0.0-20220711082147-73160bb611a8/go.mod h1:medl9/CfYoQlqAXtAARmMW5dAX2UOdwwkhaszYPk0AM=
github.com/kelindar/process v0.0.0-20170730150328-69a29e249ec3/go.mod h1:+lTCLnZFXOkqwD8sLPl6u4erAc0cP8wFegQHfipz7KE=
github.com/kelindar/rate v1.0.0/go.mod h1:AjT4G+hTItNwt30lucEGZIz8y7Uk5zPho6vurIZ+1Es=
github.com/kelindar/tcp v1.0.0/go.mod h1:JB5hj1cshLU60XrLij2BBxW3JQ4hOye8vqbyvuKb52k=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
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/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
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/lucas-clemente/quic-go v0.31.0 h1:MfNp3fk0wjWRajw6quMFA3ap1AVtlU+2mtwmbVogB2M=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20220517141722-cf486979b281 h1:aczX6NMOtt6L4YT0fQvKkDK6LZEtdOso9sUH89V1+P0=
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/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.5/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
@@ -78,44 +89,60 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ=
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
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/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
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/v2 v2.0.0-20220302185659-b3d10fc096b0 h1:zyOGxHutZ6IhksQSMtwf3OFXB29W5R18yFQWOQJYWjU=
github.com/pion/rtp/v2 v2.0.0-20220302185659-b3d10fc096b0/go.mod h1:Vj+rrFbJCT3yxqE/VSwaOo9DQ2pMKGPxuE7hplGOlOs=
github.com/pixelbender/go-sdp v1.1.0/go.mod h1:6IBlz9+BrUHoFTea7gcp4S54khtOhjCW/nVDLhmZBAs=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/q191201771/naza v0.30.2 h1:9ZC4T5AdSgGlW9cuFGp6H0mOOXQ156HxOzkYPqrvc14=
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/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM=
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/shirou/gopsutil/v3 v3.22.5 h1:atX36I/IXgFiB81687vSiBI5zrMsxcIBkP9cQMJQoJA=
github.com/shirou/gopsutil/v3 v3.22.10 h1:4KMHdfBRYXGF9skjDWiL4RA2N+E8dRdodU/bOZpPoVg=
github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
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.1.1/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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
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 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
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 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5/go.mod h1:f1SCnEOt6sc3fOJfPQDRDzHOtSXuTtnz0ImG9kPRDV0=
github.com/tevino/abool v1.2.0 h1:heAkClL8H6w+mK5md9dzsuohKeXHUpY7Vw0ZCKW+huA=
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
github.com/tklauser/numcpus v0.5.0 h1:ooe7gN0fg6myJ0EKoTAf5hebTZrH52px3New/D9iJ+A=
github.com/tevino/abool v1.2.0/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -123,35 +150,37 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
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=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
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/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 h1:yZNXmy+j/JpX19vZkVktWqAo7Gny4PBWYYK3zskGpx4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8=
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
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=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -172,20 +201,25 @@ golang.org/x/sys v0.0.0-20201214095126-aec9a390925b/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM=
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
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=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -196,8 +230,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
@@ -206,11 +240,10 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/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 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
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=
m7s.live/engine/v4 v4.5.0 h1:8UP1Yg0ryiwvKlYtwf4g+RX6EZPDEnpNWzrWcnsxU3U=
m7s.live/engine/v4 v4.5.0/go.mod h1:uzpGiVnIcuoXehpvqOj9iTVxnyf7RZQZ/Ikiwyjs01E=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
m7s.live/engine/v4 v4.8.5 h1:bUH71X7Ravj4gxINy/UrA67Nxycz26saiLeL3hBzuMU=
m7s.live/engine/v4 v4.8.5/go.mod h1:Knz1H4ZhJDooORkHOuHGNquSyA4txJFgVCng5rTEAm8=

View File

@@ -177,6 +177,11 @@ func (config *GB28181Config) OnMessage(req sip.Request, tx sip.ServerTransaction
}
d.CheckSubStream()
//在KeepLive 进行位置订阅的处理,如果开启了自动订阅位置,则去订阅位置
if config.Position.AutosubPosition && time.Since(d.GpsTime) > config.Position.Interval*2 {
d.MobilePositionSubscribe(d.ID, config.Position.Expires, config.Position.Interval)
plugin.Sugar().Debugf("位置自动订阅,设备[%s]成功\n", d.ID)
}
case "Catalog":
d.UpdateChannels(temp.DeviceList)
case "RecordInfo":
@@ -261,6 +266,7 @@ type notifyMessage struct {
Owner string
CivilCode string
Address string
Port int
Parental int
SafetyWay int
RegisterWay int

56
main.go
View File

@@ -3,12 +3,19 @@ package gb28181
import (
"fmt"
"strings"
"time"
myip "github.com/husanpao/ip"
. "m7s.live/engine/v4"
"m7s.live/engine/v4/config"
)
type GB28181PositionConfig struct {
AutosubPosition bool //是否自动订阅定位
Expires time.Duration //订阅周期(单位:秒)
Interval time.Duration //订阅间隔(单位:秒)
}
type GB28181Config struct {
AutoInvite bool
PreFetchRecord bool
@@ -22,29 +29,31 @@ type GB28181Config struct {
Username string //sip 服务器账号
Password string //sip 服务器密码
AckTimeout uint16 //sip 服务应答超时,单位秒
RegisterValidity int //注册有效期,单位秒,默认 3600
RegisterInterval int //注册间隔,单位秒,默认 60
HeartbeatInterval int //心跳间隔,单位秒,默认 60
HeartbeatRetry int //心跳超时次数,默认 3
// AckTimeout uint16 //sip 服务应答超时,单位秒
RegisterValidity time.Duration //注册有效期,单位秒,默认 3600
// RegisterInterval int //注册间隔,单位秒,默认 60
// HeartbeatInterval int //心跳间隔,单位秒,默认 60
// HeartbeatRetry int //心跳超时次数,默认 3
//媒体服务器配置
MediaIP string //媒体服务器地址
MediaPort uint16 //媒体服务器端口
MediaNetwork string //媒体传输协议默认UDP可选TCP
MediaPortMin uint16
MediaPortMax uint16
MediaIdleTimeout uint16 //推流超时时间,超过则断开链接,让设备重连
MediaIP string //媒体服务器地址
MediaPort uint16 //媒体服务器端口
MediaNetwork string //媒体传输协议默认UDP可选TCP
MediaPortMin uint16
MediaPortMax uint16
// MediaIdleTimeout uint16 //推流超时时间,超过则断开链接,让设备重连
// WaitKeyFrame bool //是否等待关键帧,如果等待,则在收到第一个关键帧之前,忽略所有媒体流
RemoveBanInterval int //移除禁止设备间隔
UdpCacheSize int //udp缓存大小
RemoveBanInterval time.Duration //移除禁止设备间隔
UdpCacheSize int //udp缓存大小
config.Publish
Server
LogLevel string //trace, debug, info, warn, error, fatal, panic
routes map[string]string
DumpPath string //dump PS流本地文件路径
Position GB28181PositionConfig //关于定位的配置参数
}
func (c *GB28181Config) initRoutes() {
@@ -83,20 +92,21 @@ var conf = &GB28181Config{
Username: "",
Password: "",
AckTimeout: 10,
RegisterValidity: 60,
RegisterInterval: 60,
HeartbeatInterval: 60,
HeartbeatRetry: 3,
// AckTimeout: 10,
RegisterValidity: 60 * time.Second,
// RegisterInterval: 60,
// HeartbeatInterval: 60,
// HeartbeatRetry: 3,
MediaIP: "",
MediaPort: 58200,
MediaIdleTimeout: 30,
MediaNetwork: "udp",
MediaIP: "",
MediaPort: 58200,
// MediaIdleTimeout: 30,
MediaNetwork: "udp",
RemoveBanInterval: 600,
RemoveBanInterval: 600 * time.Second,
LogLevel: "info",
// WaitKeyFrame: true,
Position: GB28181PositionConfig{AutosubPosition: false, Expires: 3600 * time.Second, Interval: 6 * time.Second},
}
var plugin = InstallPlugin(conf)

View File

@@ -1,6 +1,7 @@
package gb28181
import (
"encoding/binary"
"fmt"
"io"
"net"
@@ -12,6 +13,7 @@ import (
"go.uber.org/zap"
. "m7s.live/engine/v4"
. "m7s.live/engine/v4/codec"
"m7s.live/engine/v4/codec/mpegts"
. "m7s.live/engine/v4/track"
"m7s.live/engine/v4/util"
"m7s.live/plugin/gb28181/v4/utils"
@@ -109,18 +111,24 @@ func (p *GBPublisher) Bye() int {
func (p *GBPublisher) PushVideo(pts uint32, dts uint32, payload []byte) {
if p.VideoTrack == nil {
switch p.parser.VideoStreamType {
case utils.StreamTypeH264:
case mpegts.STREAM_TYPE_H264:
p.VideoTrack = NewH264(p.Publisher.Stream)
case utils.StreamTypeH265:
case mpegts.STREAM_TYPE_H265:
p.VideoTrack = NewH265(p.Publisher.Stream)
default:
//推测编码类型
var maybe264 H264NALUType
maybe264 = maybe264.Parse(payload[4])
switch maybe264 {
case NALU_Non_IDR_Picture, NALU_IDR_Picture, NALU_SEI, NALU_SPS, NALU_PPS, NALU_Access_Unit_Delimiter:
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.Info("maybe h265", zap.Uint8("type", maybe264.Byte()))
p.VideoTrack = NewH265(p.Publisher.Stream)
}
}
@@ -133,49 +141,56 @@ func (p *GBPublisher) PushVideo(pts uint32, dts uint32, payload []byte) {
if dts == 0 {
dts = pts
}
p.VideoTrack.WriteAnnexB(pts, dts, payload)
// if binary.BigEndian.Uint32(payload) != 1 {
// panic("not annexb")
// }
p.WriteAnnexB(pts, dts, payload)
}
func (p *GBPublisher) PushAudio(ts uint32, payload []byte) {
if p.AudioTrack == nil {
switch p.parser.AudioStreamType {
case utils.G711A:
at := NewG711(p.Publisher.Stream, true)
at.Audio.SampleRate = 8000
at.Audio.SampleSize = 16
at.Channels = 1
at.AVCCHead = []byte{(byte(at.CodecID) << 4) | (1 << 1)}
p.AudioTrack = at
case utils.G711A + 1:
at := NewG711(p.Publisher.Stream, false)
at.Audio.SampleRate = 8000
at.Audio.SampleSize = 16
at.Channels = 1
at.AVCCHead = []byte{(byte(at.CodecID) << 4) | (1 << 1)}
p.AudioTrack = at
case mpegts.STREAM_TYPE_G711A:
p.AudioTrack = NewG711(p.Publisher.Stream, true, uint32(90000))
case mpegts.STREAM_TYPE_G711U:
p.AudioTrack = NewG711(p.Publisher.Stream, false, uint32(90000))
case mpegts.STREAM_TYPE_AAC:
p.AudioTrack = NewAAC(p.Publisher.Stream, uint32(90000))
p.WriteADTS(ts, payload)
case 0: //推测编码类型
if payload[0] == 0xff && payload[1]>>4 == 0xf {
p.AudioTrack = NewAAC(p.Publisher.Stream, uint32(90000))
p.WriteADTS(ts, payload)
}
default:
return
p.Error("audio type not supported yet", zap.Uint32("type", p.parser.AudioStreamType))
}
} else if p.parser.AudioStreamType == mpegts.STREAM_TYPE_AAC {
p.WriteADTS(ts, payload)
} else {
p.WriteRaw(ts, payload)
}
p.AudioTrack.WriteAVCC(ts, payload)
}
// 解析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()
}
p.parser.Feed(rtp.Payload)
if conf.IsMediaNetworkTCP() {
p.parser.Feed(rtp)
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 {
fmt.Println("drop", rtp.SequenceNumber, p.lastSeq)
p.parser.Drop()
if p.VideoTrack != nil {
p.SetLostFlag()
}
}
p.parser.Feed(rtp)
p.lastSeq = rtp.SequenceNumber
}
}
}
@@ -222,16 +237,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 +267,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 +282,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
}
@@ -277,7 +297,23 @@ func (p *GBPublisher) ListenTCP() (port uint16, err error) {
plugin.Error("Accept err=", zap.Error(err))
return
}
processTcpMediaConn(conf, conn)
var rtpPacket rtp.Packet
lenBuf := make([]byte, 2)
defer conn.Close()
for err == nil {
if _, err = io.ReadFull(conn, lenBuf); err != nil {
return
}
ps := make([]byte, binary.BigEndian.Uint16(lenBuf))
if _, err = io.ReadFull(conn, ps); err != nil {
return
}
if err := rtpPacket.Unmarshal(ps); err != nil {
plugin.Error("gb28181 decode rtp error:", zap.Error(err))
} else if !p.IsClosed() {
p.PushPS(&rtpPacket)
}
}
}()
return
}

View File

@@ -14,7 +14,7 @@ func (conf *GB28181Config) API_list(w http.ResponseWriter, r *http.Request) {
util.ReturnJson(func() (list []*Device) {
Devices.Range(func(key, value interface{}) bool {
device := value.(*Device)
if time.Since(device.UpdateTime) > time.Duration(conf.RegisterValidity)*time.Second {
if time.Since(device.UpdateTime) > conf.RegisterValidity {
Devices.Delete(key)
} else {
list = append(list, device)
@@ -124,8 +124,14 @@ func (conf *GB28181Config) API_position(w http.ResponseWriter, r *http.Request)
//订阅间隔(单位:秒)
interval := query.Get("interval")
expiresInt, _ := strconv.Atoi(expires)
intervalInt, _ := strconv.Atoi(interval)
expiresInt, err := time.ParseDuration(expires)
if expires == "" || err != nil {
expiresInt = conf.Position.Expires
}
intervalInt, err := time.ParseDuration(interval)
if interval == "" || err != nil {
intervalInt = conf.Position.Interval
}
if v, ok := Devices.Load(id); ok {
d := v.(*Device)
@@ -134,3 +140,32 @@ func (conf *GB28181Config) API_position(w http.ResponseWriter, r *http.Request)
http.NotFound(w, r)
}
}
type DevicePosition struct {
ID string
GpsTime time.Time //gps时间
Longitude string //经度
Latitude string //纬度
}
func (conf *GB28181Config) API_get_position(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
//设备id
id := query.Get("id")
util.ReturnJson(func() (list []*DevicePosition) {
if id == "" {
Devices.Range(func(key, value interface{}) bool {
d := value.(*Device)
if time.Since(d.GpsTime) <= conf.Position.Interval {
list = append(list, &DevicePosition{ID: d.ID, GpsTime: d.GpsTime, Longitude: d.Longitude, Latitude: d.Latitude})
}
return true
})
} else if v, ok := Devices.Load(id); ok {
d := v.(*Device)
list = append(list, &DevicePosition{ID: d.ID, GpsTime: d.GpsTime, Longitude: d.Longitude, Latitude: d.Latitude})
}
return
}, conf.Position.Interval, w, r)
}

View File

@@ -238,7 +238,7 @@ func (config *GB28181Config) listenMediaUDP() {
// }
func removeBanDevice(config *GB28181Config) {
t := time.NewTicker(time.Duration(config.RemoveBanInterval) * time.Second)
t := time.NewTicker(config.RemoveBanInterval)
for range t.C {
DeviceRegisterCount.Range(func(key, value interface{}) bool {
if value.(int) > MaxRegisterCount {

View File

@@ -47,6 +47,13 @@ func (b *IOBuffer) ReadN(length int) ([]byte, error) {
return nil, io.EOF
}
func (b *IOBuffer) Read(buf []byte) (n int, err error) {
var ret []byte
ret, err = b.ReadN(len(buf))
copy(buf, ret)
return len(ret), err
}
// empty reports whether the unread portion of the buffer is empty.
func (b *IOBuffer) empty() bool { return b.Len() <= b.off }

View File

@@ -5,6 +5,8 @@ import (
"errors"
"fmt"
"io"
"github.com/pion/rtp/v2"
)
const (
@@ -13,16 +15,6 @@ const (
TCPTransferPassive int = 2
LocalCache int = 3
StreamTypeH264 = 0x1b
StreamTypeH265 = 0x24
G711A = 0x90 //PCMA
G7221AUDIOTYPE = 0x92
G7231AUDIOTYPE = 0x93
G729AUDIOTYPE = 0x99
StreamIDVideo = 0xe0
StreamIDAudio = 0xc0
StartCodePS = 0x000001ba
StartCodeSYS = 0x000001bb
StartCodeMAP = 0x000001bc
@@ -112,9 +104,9 @@ type Pusher interface {
https://github.com/videolan/vlc/blob/master/modules/demux/mpeg
*/
type DecPSPackage struct {
systemClockReferenceBase uint64
systemClockReferenceExtension uint64
programMuxRate uint32
// systemClockReferenceBase uint64
// systemClockReferenceExtension uint64
// programMuxRate uint32
VideoStreamType uint32
AudioStreamType uint32
@@ -122,8 +114,10 @@ type DecPSPackage struct {
Payload []byte
videoBuffer []byte
audioBuffer []byte
PTS uint32
DTS uint32
aPTS uint32
aDTS uint32
vPTS uint32
vDTS uint32
Pusher
}
@@ -133,21 +127,25 @@ func NewDecPSPackage(p Pusher) *DecPSPackage {
Pusher: p,
}
}
func (dec *DecPSPackage) clean() {
dec.systemClockReferenceBase = 0
dec.systemClockReferenceExtension = 0
dec.programMuxRate = 0
dec.Payload = nil
dec.PTS = 0
dec.DTS = 0
}
// func (dec *DecPSPackage) clean() {
// dec.systemClockReferenceBase = 0
// dec.systemClockReferenceExtension = 0
// dec.programMuxRate = 0
// dec.Payload = nil
// dec.PTS = 0
// dec.DTS = 0
// }
func (dec *DecPSPackage) ReadPayload() (payload []byte, err error) {
payloadlen, err := dec.Uint16()
if err != nil {
return
}
return dec.ReadN(int(payloadlen))
if l := int(payloadlen); dec.Len() >= l {
return dec.Next(l), nil
}
return dec.Next(dec.Len()), io.EOF
}
// Drop 由于丢包引起的必须丢弃的数据
@@ -158,8 +156,14 @@ func (dec *DecPSPackage) Drop() {
dec.Payload = nil
}
func (dec *DecPSPackage) Feed(ps []byte) (err error) {
if ps[0] == 0 && ps[1] == 0 && ps[2] == 1 {
func (dec *DecPSPackage) Feed(rtp *rtp.Packet) (err error) {
ps := rtp.Payload
if len(ps) < 4 {
return nil
}
// println(binary.BigEndian.Uint32(ps))
switch binary.BigEndian.Uint32(ps) {
case StartCodePS, StartCodeSYS, StartCodeMAP, StartCodeVideo, StartCodeAudio, PrivateStreamCode, MEPGProgramEndCode:
defer dec.Write(ps)
if dec.Len() >= 4 {
//说明需要处理PS包处理完后清空缓存
@@ -167,7 +171,7 @@ func (dec *DecPSPackage) Feed(ps []byte) (err error) {
} else {
return
}
} else {
default:
// 说明是中间数据,直接写入缓存,否则数据不合法需要丢弃
if dec.Len() > 0 {
dec.Write(ps)
@@ -181,7 +185,7 @@ func (dec *DecPSPackage) Feed(ps []byte) (err error) {
case StartCodePS:
dec.PrintDump("</td></tr><tr><td>")
if len(dec.audioBuffer) > 0 {
dec.PushAudio(dec.PTS, dec.audioBuffer)
dec.PushAudio(dec.aPTS, dec.audioBuffer)
dec.audioBuffer = nil
}
if err := dec.Skip(9); err != nil {
@@ -195,6 +199,10 @@ func (dec *DecPSPackage) Feed(ps []byte) (err error) {
if err = dec.Skip(int(psl)); err != nil {
return err
}
if len(dec.videoBuffer) > 0 {
dec.PushVideo(dec.vPTS, dec.vDTS, dec.videoBuffer)
dec.videoBuffer = nil
}
case StartCodeSYS:
dec.PrintDump("</td><td>[sys]")
dec.ReadPayload()
@@ -205,23 +213,19 @@ func (dec *DecPSPackage) Feed(ps []byte) (err error) {
if dec.videoBuffer == nil {
dec.PrintDump("</td><td>")
}
if err = dec.decPESPacket(); err == nil {
if dec.Payload[0] == 0 && dec.Payload[1] == 0 && dec.Payload[2] == 0 && dec.Payload[3] == 1 {
if len(dec.videoBuffer) > 0 {
dec.PushVideo(dec.PTS, dec.DTS, dec.videoBuffer)
dec.videoBuffer = nil
}
}
dec.videoBuffer = append(dec.videoBuffer, dec.Payload...)
} else {
fmt.Println("video", err)
}
dec.decPESPacket(&dec.vPTS, &dec.vDTS)
dec.videoBuffer = append(dec.videoBuffer, dec.Payload...)
// if err != nil {
//说明还有后续数据,需要继续处理
// println(rtp.SequenceNumber)
// }
dec.PrintDump("[video]")
case StartCodeAudio:
if dec.audioBuffer == nil {
dec.PrintDump("</td><td>")
}
if err = dec.decPESPacket(); err == nil {
if err = dec.decPESPacket(&dec.aPTS, &dec.aDTS); err == nil {
dec.audioBuffer = append(dec.audioBuffer, dec.Payload...)
dec.PrintDump("[audio]")
} else {
@@ -307,11 +311,9 @@ func (dec *DecPSPackage) decProgramStreamMap() error {
return nil
}
func (dec *DecPSPackage) decPESPacket() error {
func (dec *DecPSPackage) decPESPacket(pts *uint32, dts *uint32) error {
payload, err := dec.ReadPayload()
if err != nil {
return err
}
if len(payload) < 4 {
return errors.New("not enough data")
}
@@ -319,24 +321,21 @@ func (dec *DecPSPackage) decPESPacket() error {
flag := payload[1]
ptsFlag := flag>>7 == 1
dtsFlag := (flag&0b0100_0000)>>6 == 1
var pts, dts uint32
pesHeaderDataLen := payload[2]
payload = payload[3:]
extraData := payload[:pesHeaderDataLen]
if ptsFlag && len(extraData) > 4 {
pts = uint32(extraData[0]&0b0000_1110) << 29
pts += uint32(extraData[1]) << 22
pts += uint32(extraData[2]&0b1111_1110) << 14
pts += uint32(extraData[3]) << 7
pts += uint32(extraData[4]) >> 1
dec.PTS = pts
*pts = uint32(extraData[0]&0b0000_1110) << 29
*pts += uint32(extraData[1]) << 22
*pts += uint32(extraData[2]&0b1111_1110) << 14
*pts += uint32(extraData[3]) << 7
*pts += uint32(extraData[4]) >> 1
if dtsFlag && len(extraData) > 9 {
dts = uint32(extraData[5]&0b0000_1110) << 29
dts += uint32(extraData[6]) << 22
dts += uint32(extraData[7]&0b1111_1110) << 14
dts += uint32(extraData[8]) << 7
dts += uint32(extraData[9]) >> 1
dec.DTS = dts
*dts = uint32(extraData[5]&0b0000_1110) << 29
*dts += uint32(extraData[6]) << 22
*dts += uint32(extraData[7]&0b1111_1110) << 14
*dts += uint32(extraData[8]) << 7
*dts += uint32(extraData[9]) >> 1
}
}
dec.Payload = payload[pesHeaderDataLen:]