Commit 30ae9e929fad80f624ab632c53081db3d2dc9aec
合并主线
Showing
128 changed files
with
5910 additions
and
2400 deletions
.github/ISSUE_TEMPLATE/--bug---.md renamed to .github/ISSUE_TEMPLATE/bug.md
| 1 | --- | 1 | --- |
| 2 | name: "[ BUG ] " | 2 | name: "[ BUG ] " |
| 3 | -about: Create a report to help us improve | ||
| 4 | -title: '' | ||
| 5 | -labels: '' | 3 | +about: 关于wvp的bug,与zlm有关的建议直接在zlm的issue中提问 |
| 4 | +title: 'BUG' | ||
| 5 | +labels: 'wvp的bug' | ||
| 6 | assignees: '' | 6 | assignees: '' |
| 7 | 7 | ||
| 8 | --- | 8 | --- |
| 9 | 9 | ||
| 10 | +**环境信息:** | ||
| 11 | + | ||
| 12 | + - 1. 部署方式 wvp-pro docker / zlm(docker) + 编译wvp-pro/ wvp-prp + zlm都是编译部署/ | ||
| 13 | + - 2. 部署环境 windows / ubuntu/ centos ... | ||
| 14 | + - 3. 端口开放情况 | ||
| 15 | + - 4. 是否是公网部署 | ||
| 16 | + - 5. 是否使用https | ||
| 17 | + - 6. 方便的话提供下使用的设备品牌或平台 | ||
| 18 | + - 7. 你做过哪些尝试 | ||
| 19 | + - 8. 代码更新时间 | ||
| 20 | + | ||
| 10 | **描述错误** | 21 | **描述错误** |
| 11 | 描述下您遇到的问题 | 22 | 描述下您遇到的问题 |
| 12 | 23 | ||
| 13 | **如何复现** | 24 | **如何复现** |
| 14 | 有明确复现步骤的问题会很容易被解决 | 25 | 有明确复现步骤的问题会很容易被解决 |
| 15 | 26 | ||
| 16 | -**预期行为** | ||
| 17 | -清晰简洁的描述您期望发生的事情 | 27 | +**截图** |
| 18 | 28 | ||
| 19 | -**截图** | 29 | +**抓包文件** |
| 30 | + | ||
| 31 | +**日志** | ||
| 32 | +``` | ||
| 33 | +日志内容放这里, 文件的话请直接上传 | ||
| 34 | +``` | ||
| 20 | 35 | ||
| 21 | 36 | ||
| 22 | -**环境信息:** | ||
| 23 | - - 1. 部署方式 wvp-pro docker / zlm(docker) + 编译wvp-pro/ wvp-prp + zlm都是编译部署/ | ||
| 24 | - - 2. 部署环境 windows / ubuntu/ centos ... | ||
| 25 | - - 3. 端口开放情况 | ||
| 26 | - - 4. 是否是公网部署 | ||
| 27 | - - 5. 是否使用https | ||
| 28 | - - 6. 方便的话提供下使用的设备品牌或平台 | ||
| 29 | - - 7. 你做过哪些尝试 |
.github/ISSUE_TEMPLATE/-------.md renamed to .github/ISSUE_TEMPLATE/new.md
.github/ISSUE_TEMPLATE/solve.md
0 → 100644
| 1 | +--- | ||
| 2 | +name: "[ 技术咨询 ] " | ||
| 3 | +about: 对于使用中遇到问题 | ||
| 4 | +title: '技术咨询' | ||
| 5 | +labels: '技术咨询' | ||
| 6 | +assignees: '' | ||
| 7 | + | ||
| 8 | +--- | ||
| 9 | + | ||
| 10 | +**环境信息:** | ||
| 11 | + | ||
| 12 | + - 1. 部署方式 wvp-pro docker / zlm(docker) + 编译wvp-pro/ wvp-prp + zlm都是编译部署/ | ||
| 13 | + - 2. 部署环境 windows / ubuntu/ centos ... | ||
| 14 | + - 3. 端口开放情况 | ||
| 15 | + - 4. 是否是公网部署 | ||
| 16 | + - 5. 是否使用https | ||
| 17 | + - 6. 方便的话提供下使用的设备品牌或平台 | ||
| 18 | + - 7. 你做过哪些尝试 | ||
| 19 | + - 8. 代码更新时间 | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +**内容描述:** | ||
| 23 | + | ||
| 24 | +**截图** | ||
| 25 | + | ||
| 26 | +**抓包文件** | ||
| 27 | + | ||
| 28 | +**日志** | ||
| 29 | +``` | ||
| 30 | +日志内容放这里, 文件的话请直接上传 | ||
| 31 | +``` |
README.md
| @@ -15,17 +15,21 @@ WEB VIDEO PLATFORM銝銝芸鈭B28181-2016蝞勗 | @@ -15,17 +15,21 @@ WEB VIDEO PLATFORM銝銝芸鈭B28181-2016蝞勗 | ||
| 15 | 垢憿菟鈭Kyle MediaServerUI [https://gitee.com/kkkkk5G/MediaServerUI](https://gitee.com/kkkkk5G/MediaServerUI) 餈耨. | 15 | 垢憿菟鈭Kyle MediaServerUI [https://gitee.com/kkkkk5G/MediaServerUI](https://gitee.com/kkkkk5G/MediaServerUI) 餈耨. |
| 16 | 16 | ||
| 17 | # 摨嚗 | 17 | # 摨嚗 |
| 18 | -辣仍閫 | ||
| 19 | -像VR蝑挽憭 | 18 | +辣仍閫 |
| 19 | +挽憭(像VR蝑)霈曉 | ||
| 20 | +(onvif, rtsp, rtmp嚗霈曉)霈曉嚗 | ||
| 20 | 漣像蝥扯楊蝵 | 21 | 漣像蝥扯楊蝵 |
| 21 | -tsp/rtmp蝑蓮像 | ||
| 22 | -tsp/rtmp蝑瘚蓮像 | 22 | +楊蝵撟喳鈭 |
| 23 | 23 | ||
| 24 | -# 憿寧 | ||
| 25 | -銝芣蔭,蝙,靘蹂輕28181縑隞斤頂蝏, 靘皞獢ZLMediaKit, 摰銝銝芸GB28181撟喳. | ||
| 26 | 24 | ||
| 27 | -# 蝵脫﹝ | ||
| 28 | -[doc.wvp-pro.cn](https://doc.wvp-pro.cn) | 25 | +# ﹝ |
| 26 | +wvp雿輻﹝ [https://doc.wvp-pro.cn](https://doc.wvp-pro.cn) | ||
| 27 | +ZLM雿輻﹝ [https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit) | ||
| 28 | +> wvp﹝gitee嚗霂瑕活 | ||
| 29 | + | ||
| 30 | +# 蝷曄黎 | ||
| 31 | +[](https://t.zsxq.com/0d8VAD3Dm) | ||
| 32 | +> 韐寞銝箔憟賜嚗撖嫣憭抒銝予隞亦縑凝靽∪嚗之摰嗅蝢扎銝予說隞亦甈橘之摰嗡閬▽憳予銋銝隞乓 | ||
| 29 | 33 | ||
| 30 | # gitee郊隞 | 34 | # gitee郊隞 |
| 31 | https://gitee.com/pan648540858/wvp-GB28181-pro.git | 35 | https://gitee.com/pan648540858/wvp-GB28181-pro.git |
| @@ -100,23 +104,17 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git | @@ -100,23 +104,17 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git | ||
| 100 | - [X] 鈭垢敶瘚/隞/隞亙鈭垢嚗蝸 | 104 | - [X] 鈭垢敶瘚/隞/隞亙鈭垢嚗蝸 |
| 101 | - [X] 銵arar | 105 | - [X] 銵arar |
| 102 | - [X] 楊窈瘙垢氖蝵 | 106 | - [X] 楊窈瘙垢氖蝵 |
| 103 | - | ||
| 104 | - | ||
| 105 | -# 憸圾 | ||
| 106 | -暻餌鈭挽憭摰寞改隞仿閬之挽憭瘚挽憭偌撟單隞仿憸 | ||
| 107 | -1. ﹝蝵粉隞亙葬雿憸 | ||
| 108 | -2. 揣issues嚗之 | ||
| 109 | -3. Q蝢歹901799015嚗之敹撈嚗撣歇蝏粉鈭iki揣鈭ssues | ||
| 110 | -4. 雿隞亥窈雿蛹雿圾蝑晶 | ||
| 111 | -5. 雿隞交憸挽憭隞交摰寞摰寡挽憭圾憸 | ||
| 112 | - | ||
| 113 | -# 雿輻撣桀 | ||
| 114 | -QQ蝢: 901799015, ZLM雿輻﹝[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit) | ||
| 115 | -QQ蝘縑銝銝, 蝎曉.甈Z之摰嗅蝢日悄霈.閫★撖嫣葬嚗洽餈tar漱pr | ||
| 116 | 107 | ||
| 117 | # 悅 | 108 | # 悅 |
| 118 | 憿寧誨蝙摰賣IT悅嚗靽縑銝隞亥摨鈭★ 雿憿寧銋蝣蝙鈭鈭隞皞誨銝窈銵隞嚗 鈭蝙憿寧漣熒噩蛹銝璁憿寧嚗窈銵 雿輻憿寧隞嚗砲悅銝剖銵冽憿寧靘洵銝摨悅 | 109 | 憿寧誨蝙摰賣IT悅嚗靽縑銝隞亥摨鈭★ 雿憿寧銋蝣蝙鈭鈭隞皞誨銝窈銵隞嚗 鈭蝙憿寧漣熒噩蛹銝璁憿寧嚗窈銵 雿輻憿寧隞嚗砲悅銝剖銵冽憿寧靘洵銝摨悅 |
| 119 | 110 | ||
| 111 | +# | ||
| 112 | + | ||
| 113 | +[霂(https://t.zsxq.com/0d8VAD3Dm)銝”嚗 | ||
| 114 | +- [雿輻蝟餃嚗VP-PRO銋(https://t.zsxq.com/0dLguVoSp) | ||
| 115 | + | ||
| 116 | +窈隞嗅648540858@qq.com | ||
| 117 | + | ||
| 120 | # 靚 | 118 | # 靚 |
| 121 | 陝雿憭(https://github.com/xia-chu) 皞獢,撟嗅撘葉蝏葬 | 119 | 陝雿憭(https://github.com/xia-chu) 皞獢,撟嗅撘葉蝏葬 |
| 122 | 陝雿dexter langhuihui](https://github.com/langhuihui) 撘皞末EB | 120 | 陝雿dexter langhuihui](https://github.com/langhuihui) 撘皞末EB |
| @@ -128,7 +126,6 @@ QQ蝘縑銝銝, 蝎曉.甈Z之摰嗅蝢日悄霈.閫★撖嫣 | @@ -128,7 +126,6 @@ QQ蝘縑銝銝, 蝎曉.甈Z之摰嗅蝢日悄霈.閫★撖嫣 | ||
| 128 | [ydpd](https://github.com/ydpd) [szy833](https://github.com/szy833) [ydwxb](https://github.com/ydwxb) [Albertzhu666](https://github.com/Albertzhu666) | 126 | [ydpd](https://github.com/ydpd) [szy833](https://github.com/szy833) [ydwxb](https://github.com/ydwxb) [Albertzhu666](https://github.com/Albertzhu666) |
| 129 | [mk1990](https://github.com/mk1990) [SaltFish001](https://github.com/SaltFish001) | 127 | [mk1990](https://github.com/mk1990) [SaltFish001](https://github.com/SaltFish001) |
| 130 | 128 | ||
| 131 | -ps: 葵摰鈭之雿穿洽餈之雿祈頂溶 | ||
| 132 | 129 | ||
| 133 | ffmpeg -re -i 123.mp3 -acodec pcm_alaw -ar 8000 -ac 1 -f rtsp rtsp://192.168.1.3:30554/broadcast/34020000001320000101_34020000001310000001 | 130 | ffmpeg -re -i 123.mp3 -acodec pcm_alaw -ar 8000 -ac 1 -f rtsp rtsp://192.168.1.3:30554/broadcast/34020000001320000101_34020000001310000001 |
| 134 | 131 |
doc/README.md
| @@ -14,6 +14,10 @@ | @@ -14,6 +14,10 @@ | ||
| 14 | - 完全开源,且使用MIT许可协议。保留版权的情况下可以用于商业项目。 | 14 | - 完全开源,且使用MIT许可协议。保留版权的情况下可以用于商业项目。 |
| 15 | - 支持多流媒体节点负载均衡。 | 15 | - 支持多流媒体节点负载均衡。 |
| 16 | 16 | ||
| 17 | +# 社群 | ||
| 18 | +[](https://t.zsxq.com/0d8VAD3Dm) | ||
| 19 | +> 收费是为了提供更好的服务,也是对作者更大的激励。加入星球的用户三天后可以私信我留下微信号,我会拉大家入群。加入三天内不满意可以直接退款,大家不需要有顾虑,来白嫖三天也不是不可以。 | ||
| 20 | + | ||
| 17 | # 我们实现了哪些国标功能 | 21 | # 我们实现了哪些国标功能 |
| 18 | **作为上级平台** | 22 | **作为上级平台** |
| 19 | - [X] 注册 | 23 | - [X] 注册 |
doc/_content/ability/_media/img_16.png
doc/_content/qa/bug.md
| @@ -2,18 +2,11 @@ | @@ -2,18 +2,11 @@ | ||
| 2 | # 反馈bug | 2 | # 反馈bug |
| 3 | 代码是在不断的完善的,不断修改会修复旧的问题也有可能引入新的问题,所以遇到BUG是很正常的一件事。所以遇到问题不要烦燥,咱们就事论事就好了。 | 3 | 代码是在不断的完善的,不断修改会修复旧的问题也有可能引入新的问题,所以遇到BUG是很正常的一件事。所以遇到问题不要烦燥,咱们就事论事就好了。 |
| 4 | ## 如何反馈 | 4 | ## 如何反馈 |
| 5 | -1. 更新代码,很可能你遇到问题别人已经更早的遇到了,或者是作者自己发现了,已经解决了,所以你可以更新代码再次进行测试; | ||
| 6 | -2. 可以在github提ISSUE,我几乎每天都会去看issue,你的问题我会尽快给予答复; | ||
| 7 | -3. 你可以来我的QQ群里,询问群友看看是否遇到了同样的问题; | ||
| 8 | -4. 你可以私聊我的QQ,如果我有时间我会给你答复,但是除非你有明确的复现步骤或者修复方案,否则你可能等不到我的答复。 | ||
| 9 | - | ||
| 10 | -## 如何快速解决BUG | ||
| 11 | -目前解决BUG有三种方式: | ||
| 12 | -1. 作者验证以及修复; | ||
| 13 | -2. 热心开发者提来的PR; | ||
| 14 | -3. 使用运维手段屏蔽BUG的影响。 | ||
| 15 | - | ||
| 16 | -- 对于第一种:详细的复现步骤,完整的抓包文件,有条理的错误分析都可以帮助作者复现问题,进而解决问题。解决问题往往不是最难的,复现才是。 | ||
| 17 | -- 对于第二种:如果你是开发者,你已经发现了造成BUG的原因以及知道如何正确的修复,那么我很希望你PR,SRS的大佬经常说的,开源不是一个人的事。所以你的参与就是最大的鼓励。 | ||
| 18 | -- 对于第三种:如果你有一个有经验的运维伙伴,那么部分问题是可以通过运维的手段暂时屏蔽的,在等待修复的这段时间了以保证项目的运行。 | 5 | +1. 在知识星球提问。 |
| 6 | +2. 更新代码,很可能你遇到问题别人已经更早的遇到了,或者是作者自己发现了,已经解决了,所以你可以更新代码再次进行测试; | ||
| 7 | +3. 可以在github提ISSUE,我几乎每天都会去看issue,你的问题我会尽快给予答复; | ||
| 8 | +> 有偿支持可以给我发邮件, 648540858@qq.com | ||
| 19 | 9 | ||
| 10 | +## 社群 | ||
| 11 | +[](https://t.zsxq.com/0d8VAD3Dm) | ||
| 12 | +> 收费是为了提供更好的服务,也是对作者更大的激励。加入星球的用户三天后可以私信我留下微信号,我会拉大家入群。加入三天内不满意可以直接退款,大家不需要有顾虑,来白嫖三天也不是不可以。 | ||
| 20 | \ No newline at end of file | 13 | \ No newline at end of file |
doc/_media/shequ.png
0 → 100644
35.3 KB
src/main/java/com/genersoft/iot/vmp/common/CommonCallback.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/common/InviteInfo.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.common; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.service.bean.SSRCInfo; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 记录每次发送invite消息的状态 | ||
| 7 | + */ | ||
| 8 | +public class InviteInfo { | ||
| 9 | + | ||
| 10 | + private String deviceId; | ||
| 11 | + | ||
| 12 | + private String channelId; | ||
| 13 | + | ||
| 14 | + private String stream; | ||
| 15 | + | ||
| 16 | + private SSRCInfo ssrcInfo; | ||
| 17 | + | ||
| 18 | + private String receiveIp; | ||
| 19 | + | ||
| 20 | + private Integer receivePort; | ||
| 21 | + | ||
| 22 | + private String streamMode; | ||
| 23 | + | ||
| 24 | + private InviteSessionType type; | ||
| 25 | + | ||
| 26 | + private InviteSessionStatus status; | ||
| 27 | + | ||
| 28 | + private StreamInfo streamInfo; | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + public static InviteInfo getinviteInfo(String deviceId, String channelId, String stream, SSRCInfo ssrcInfo, | ||
| 32 | + String receiveIp, Integer receivePort, String streamMode, | ||
| 33 | + InviteSessionType type, InviteSessionStatus status) { | ||
| 34 | + InviteInfo inviteInfo = new InviteInfo(); | ||
| 35 | + inviteInfo.setDeviceId(deviceId); | ||
| 36 | + inviteInfo.setChannelId(channelId); | ||
| 37 | + inviteInfo.setStream(stream); | ||
| 38 | + inviteInfo.setSsrcInfo(ssrcInfo); | ||
| 39 | + inviteInfo.setReceiveIp(receiveIp); | ||
| 40 | + inviteInfo.setReceivePort(receivePort); | ||
| 41 | + inviteInfo.setStreamMode(streamMode); | ||
| 42 | + inviteInfo.setType(type); | ||
| 43 | + inviteInfo.setStatus(status); | ||
| 44 | + return inviteInfo; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + public String getDeviceId() { | ||
| 48 | + return deviceId; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + public void setDeviceId(String deviceId) { | ||
| 52 | + this.deviceId = deviceId; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + public String getChannelId() { | ||
| 56 | + return channelId; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + public void setChannelId(String channelId) { | ||
| 60 | + this.channelId = channelId; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + public InviteSessionType getType() { | ||
| 64 | + return type; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + public void setType(InviteSessionType type) { | ||
| 68 | + this.type = type; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + public InviteSessionStatus getStatus() { | ||
| 72 | + return status; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + public void setStatus(InviteSessionStatus status) { | ||
| 76 | + this.status = status; | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + public StreamInfo getStreamInfo() { | ||
| 80 | + return streamInfo; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + public void setStreamInfo(StreamInfo streamInfo) { | ||
| 84 | + this.streamInfo = streamInfo; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + public String getStream() { | ||
| 88 | + return stream; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + public void setStream(String stream) { | ||
| 92 | + this.stream = stream; | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + public SSRCInfo getSsrcInfo() { | ||
| 96 | + return ssrcInfo; | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + public void setSsrcInfo(SSRCInfo ssrcInfo) { | ||
| 100 | + this.ssrcInfo = ssrcInfo; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + public String getReceiveIp() { | ||
| 104 | + return receiveIp; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + public void setReceiveIp(String receiveIp) { | ||
| 108 | + this.receiveIp = receiveIp; | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + public Integer getReceivePort() { | ||
| 112 | + return receivePort; | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + public void setReceivePort(Integer receivePort) { | ||
| 116 | + this.receivePort = receivePort; | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + public String getStreamMode() { | ||
| 120 | + return streamMode; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + public void setStreamMode(String streamMode) { | ||
| 124 | + this.streamMode = streamMode; | ||
| 125 | + } | ||
| 126 | +} |
src/main/java/com/genersoft/iot/vmp/common/InviteSessionStatus.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
| @@ -16,8 +16,6 @@ public class VideoManagerConstants { | @@ -16,8 +16,6 @@ public class VideoManagerConstants { | ||
| 16 | 16 | ||
| 17 | public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_"; | 17 | public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_"; |
| 18 | 18 | ||
| 19 | - public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM"; | ||
| 20 | - | ||
| 21 | public static final String DEVICE_PREFIX = "VMP_DEVICE_"; | 19 | public static final String DEVICE_PREFIX = "VMP_DEVICE_"; |
| 22 | 20 | ||
| 23 | // 设备同步完成 | 21 | // 设备同步完成 |
| @@ -28,9 +26,10 @@ public class VideoManagerConstants { | @@ -28,9 +26,10 @@ public class VideoManagerConstants { | ||
| 28 | public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_"; | 26 | public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_"; |
| 29 | 27 | ||
| 30 | // TODO 此处多了一个_,暂不修改 | 28 | // TODO 此处多了一个_,暂不修改 |
| 31 | - public static final String PLAYER_PREFIX = "VMP_PLAYER_"; | ||
| 32 | - public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_"; | ||
| 33 | - public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_"; | 29 | + public static final String INVITE_PREFIX = "VMP_INVITE"; |
| 30 | + public static final String PLAYER_PREFIX = "VMP_INVITE_PLAY_"; | ||
| 31 | + public static final String PLAY_BLACK_PREFIX = "VMP_INVITE_PLAYBACK_"; | ||
| 32 | + public static final String DOWNLOAD_PREFIX = "VMP_INVITE_DOWNLOAD_"; | ||
| 34 | 33 | ||
| 35 | public static final String PLATFORM_KEEPALIVE_PREFIX = "VMP_PLATFORM_KEEPALIVE_"; | 34 | public static final String PLATFORM_KEEPALIVE_PREFIX = "VMP_PLATFORM_KEEPALIVE_"; |
| 36 | 35 | ||
| @@ -123,6 +122,7 @@ public class VideoManagerConstants { | @@ -123,6 +122,7 @@ public class VideoManagerConstants { | ||
| 123 | */ | 122 | */ |
| 124 | public static final String VM_MSG_SUBSCRIBE_ALARM = "alarm"; | 123 | public static final String VM_MSG_SUBSCRIBE_ALARM = "alarm"; |
| 125 | 124 | ||
| 125 | + | ||
| 126 | /** | 126 | /** |
| 127 | * 报警通知的发送 (收到redis发出的通知,转发给其他平台) | 127 | * 报警通知的发送 (收到redis发出的通知,转发给其他平台) |
| 128 | */ | 128 | */ |
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
| @@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.conf; | @@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.conf; | ||
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 3 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 4 | import com.genersoft.iot.vmp.service.IMediaServerService; | 4 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 5 | -import org.apache.catalina.connector.ClientAbortException; | ||
| 6 | import org.apache.http.HttpHost; | 5 | import org.apache.http.HttpHost; |
| 7 | import org.apache.http.HttpRequest; | 6 | import org.apache.http.HttpRequest; |
| 8 | import org.apache.http.HttpResponse; | 7 | import org.apache.http.HttpResponse; |
| @@ -194,11 +193,11 @@ public class ProxyServletConfig { | @@ -194,11 +193,11 @@ public class ProxyServletConfig { | ||
| 194 | } catch (IOException ioException) { | 193 | } catch (IOException ioException) { |
| 195 | if (ioException instanceof ConnectException) { | 194 | if (ioException instanceof ConnectException) { |
| 196 | logger.error("录像服务 连接失败"); | 195 | logger.error("录像服务 连接失败"); |
| 197 | - }else if (ioException instanceof ClientAbortException) { | ||
| 198 | - /** | ||
| 199 | - * TODO 使用这个代理库实现代理在遇到代理视频文件时,如果是206结果,会遇到报错蛋市目前功能正常, | ||
| 200 | - * TODO 暂时去除异常处理。后续使用其他代理框架修改测试 | ||
| 201 | - */ | 196 | +// }else if (ioException instanceof ClientAbortException) { |
| 197 | +// /** | ||
| 198 | +// * TODO 使用这个代理库实现代理在遇到代理视频文件时,如果是206结果,会遇到报错蛋市目前功能正常, | ||
| 199 | +// * TODO 暂时去除异常处理。后续使用其他代理框架修改测试 | ||
| 200 | +// */ | ||
| 202 | 201 | ||
| 203 | }else { | 202 | }else { |
| 204 | logger.error("录像服务 代理失败: ", e); | 203 | logger.error("录像服务 代理失败: ", e); |
src/main/java/com/genersoft/iot/vmp/conf/ScheduleConfig.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf; | ||
| 2 | + | ||
| 3 | +import org.apache.commons.lang3.concurrent.BasicThreadFactory; | ||
| 4 | +import org.springframework.context.annotation.Configuration; | ||
| 5 | +import org.springframework.scheduling.annotation.SchedulingConfigurer; | ||
| 6 | +import org.springframework.scheduling.config.ScheduledTaskRegistrar; | ||
| 7 | + | ||
| 8 | +import java.util.concurrent.ScheduledThreadPoolExecutor; | ||
| 9 | +import java.util.concurrent.ThreadPoolExecutor; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * "@Scheduled"是Spring框架提供的一种定时任务执行机制,默认情况下它是单线程的,在同时执行多个定时任务时可能会出现阻塞和性能问题。 | ||
| 13 | + * 为了解决这种单线程瓶颈问题,可以将定时任务的执行机制改为支持多线程 | ||
| 14 | + */ | ||
| 15 | +@Configuration | ||
| 16 | +public class ScheduleConfig implements SchedulingConfigurer { | ||
| 17 | + | ||
| 18 | + public static final int cpuNum = Runtime.getRuntime().availableProcessors(); | ||
| 19 | + | ||
| 20 | + private static final int corePoolSize = cpuNum; | ||
| 21 | + | ||
| 22 | + private static final String threadNamePrefix = "scheduled-task-pool-%d"; | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { | ||
| 26 | + taskRegistrar.setScheduler(new ScheduledThreadPoolExecutor(corePoolSize, | ||
| 27 | + new BasicThreadFactory.Builder().namingPattern(threadNamePrefix).daemon(true).build(), | ||
| 28 | + new ThreadPoolExecutor.CallerRunsPolicy())); | ||
| 29 | + } | ||
| 30 | +} |
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
| @@ -48,10 +48,13 @@ public class SipPlatformRunner implements CommandLineRunner { | @@ -48,10 +48,13 @@ public class SipPlatformRunner implements CommandLineRunner { | ||
| 48 | parentPlatformCatch.setParentPlatform(parentPlatform); | 48 | parentPlatformCatch.setParentPlatform(parentPlatform); |
| 49 | parentPlatformCatch.setId(parentPlatform.getServerGBId()); | 49 | parentPlatformCatch.setId(parentPlatform.getServerGBId()); |
| 50 | redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | 50 | redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); |
| 51 | - // 取消订阅 | ||
| 52 | - sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{ | ||
| 53 | - platformService.login(parentPlatform); | ||
| 54 | - }); | 51 | + if (parentPlatformCatchOld != null) { |
| 52 | + // 取消订阅 | ||
| 53 | + sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{ | ||
| 54 | + platformService.login(parentPlatform); | ||
| 55 | + }); | ||
| 56 | + } | ||
| 57 | + | ||
| 55 | // 设置所有平台离线 | 58 | // 设置所有平台离线 |
| 56 | platformService.offline(parentPlatform, true); | 59 | platformService.offline(parentPlatform, true); |
| 57 | } | 60 | } |
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
| @@ -54,6 +54,9 @@ public class UserSetting { | @@ -54,6 +54,9 @@ public class UserSetting { | ||
| 54 | 54 | ||
| 55 | private Boolean refuseChannelStatusChannelFormNotify = Boolean.FALSE; | 55 | private Boolean refuseChannelStatusChannelFormNotify = Boolean.FALSE; |
| 56 | 56 | ||
| 57 | + private Boolean deviceStatusNotify = Boolean.FALSE; | ||
| 58 | + private Boolean useCustomSsrcForParentInvite = Boolean.TRUE; | ||
| 59 | + | ||
| 57 | private String serverId = "000000"; | 60 | private String serverId = "000000"; |
| 58 | 61 | ||
| 59 | private String recordPath = null; | 62 | private String recordPath = null; |
| @@ -66,6 +69,8 @@ public class UserSetting { | @@ -66,6 +69,8 @@ public class UserSetting { | ||
| 66 | 69 | ||
| 67 | private List<String> allowedOrigins = new ArrayList<>(); | 70 | private List<String> allowedOrigins = new ArrayList<>(); |
| 68 | 71 | ||
| 72 | + private int maxNotifyCountQueue = 10000; | ||
| 73 | + | ||
| 69 | public Boolean getSavePositionHistory() { | 74 | public Boolean getSavePositionHistory() { |
| 70 | return savePositionHistory; | 75 | return savePositionHistory; |
| 71 | } | 76 | } |
| @@ -277,4 +282,28 @@ public class UserSetting { | @@ -277,4 +282,28 @@ public class UserSetting { | ||
| 277 | public void setRecordPath(String recordPath) { | 282 | public void setRecordPath(String recordPath) { |
| 278 | this.recordPath = recordPath; | 283 | this.recordPath = recordPath; |
| 279 | } | 284 | } |
| 285 | + | ||
| 286 | + public int getMaxNotifyCountQueue() { | ||
| 287 | + return maxNotifyCountQueue; | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + public void setMaxNotifyCountQueue(int maxNotifyCountQueue) { | ||
| 291 | + this.maxNotifyCountQueue = maxNotifyCountQueue; | ||
| 292 | + } | ||
| 293 | + | ||
| 294 | + public Boolean getDeviceStatusNotify() { | ||
| 295 | + return deviceStatusNotify; | ||
| 296 | + } | ||
| 297 | + | ||
| 298 | + public void setDeviceStatusNotify(Boolean deviceStatusNotify) { | ||
| 299 | + this.deviceStatusNotify = deviceStatusNotify; | ||
| 300 | + } | ||
| 301 | + | ||
| 302 | + public Boolean getUseCustomSsrcForParentInvite() { | ||
| 303 | + return useCustomSsrcForParentInvite; | ||
| 304 | + } | ||
| 305 | + | ||
| 306 | + public void setUseCustomSsrcForParentInvite(Boolean useCustomSsrcForParentInvite) { | ||
| 307 | + this.useCustomSsrcForParentInvite = useCustomSsrcForParentInvite; | ||
| 308 | + } | ||
| 280 | } | 309 | } |
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java
| 1 | -package com.genersoft.iot.vmp.conf.redis; | ||
| 2 | - | ||
| 3 | - | ||
| 4 | -import com.genersoft.iot.vmp.common.VideoManagerConstants; | ||
| 5 | -import com.genersoft.iot.vmp.service.redisMsg.*; | ||
| 6 | -import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer; | ||
| 7 | -import org.springframework.beans.factory.annotation.Autowired; | ||
| 8 | -import org.springframework.cache.annotation.CachingConfigurerSupport; | ||
| 9 | -import com.alibaba.fastjson2.support.spring.data.redis.GenericFastJsonRedisSerializer; | ||
| 10 | -import org.springframework.context.annotation.Bean; | ||
| 11 | -import org.springframework.context.annotation.Configuration; | ||
| 12 | -import org.springframework.core.annotation.Order; | ||
| 13 | -import org.springframework.data.redis.connection.RedisConnectionFactory; | ||
| 14 | -import org.springframework.data.redis.core.RedisTemplate; | ||
| 15 | -import org.springframework.data.redis.serializer.StringRedisSerializer; | ||
| 16 | - | ||
| 17 | - | ||
| 18 | -/** | ||
| 19 | - * Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置 | ||
| 20 | - * swwheihei | ||
| 21 | - * 2019年5月30日 上午10:58:25 | ||
| 22 | - * | ||
| 23 | - */ | ||
| 24 | -@Configuration | ||
| 25 | -@Order(value=1) | ||
| 26 | -public class RedisConfig { | ||
| 27 | - | ||
| 28 | - | ||
| 29 | - @Bean | ||
| 30 | - public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { | ||
| 31 | - | ||
| 32 | - RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); | ||
| 33 | - // 使用fastJson序列化 | ||
| 34 | - GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer(); | ||
| 35 | - // value值的序列化采用fastJsonRedisSerializer | ||
| 36 | - redisTemplate.setValueSerializer(fastJsonRedisSerializer); | ||
| 37 | - redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); | ||
| 38 | - | ||
| 39 | - // key的序列化采用StringRedisSerializer | ||
| 40 | - redisTemplate.setKeySerializer(new StringRedisSerializer()); | ||
| 41 | - redisTemplate.setHashKeySerializer(new StringRedisSerializer()); | ||
| 42 | - redisTemplate.setConnectionFactory(redisConnectionFactory); | ||
| 43 | - return redisTemplate; | ||
| 44 | - } | ||
| 45 | -} |
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisTemplateConfig.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.redis; | ||
| 2 | + | ||
| 3 | +import com.alibaba.fastjson2.support.spring.data.redis.GenericFastJsonRedisSerializer; | ||
| 4 | +import org.springframework.context.annotation.Bean; | ||
| 5 | +import org.springframework.context.annotation.Configuration; | ||
| 6 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | ||
| 7 | +import org.springframework.data.redis.core.RedisTemplate; | ||
| 8 | +import org.springframework.data.redis.serializer.StringRedisSerializer; | ||
| 9 | + | ||
| 10 | +@Configuration | ||
| 11 | +public class RedisTemplateConfig { | ||
| 12 | + | ||
| 13 | + @Bean | ||
| 14 | + public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { | ||
| 15 | + RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); | ||
| 16 | + // 使用fastJson序列化 | ||
| 17 | + GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer(); | ||
| 18 | + // value值的序列化采用fastJsonRedisSerializer | ||
| 19 | + redisTemplate.setValueSerializer(fastJsonRedisSerializer); | ||
| 20 | + redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); | ||
| 21 | + | ||
| 22 | + // key的序列化采用StringRedisSerializer | ||
| 23 | + redisTemplate.setKeySerializer(new StringRedisSerializer()); | ||
| 24 | + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); | ||
| 25 | + redisTemplate.setConnectionFactory(redisConnectionFactory); | ||
| 26 | + return redisTemplate; | ||
| 27 | + } | ||
| 28 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java
| @@ -2,6 +2,8 @@ package com.genersoft.iot.vmp.conf.security; | @@ -2,6 +2,8 @@ package com.genersoft.iot.vmp.conf.security; | ||
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.conf.UserSetting; | 3 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 4 | import com.genersoft.iot.vmp.conf.security.dto.JwtUser; | 4 | import com.genersoft.iot.vmp.conf.security.dto.JwtUser; |
| 5 | +import com.genersoft.iot.vmp.storager.dao.dto.Role; | ||
| 6 | +import com.genersoft.iot.vmp.storager.dao.dto.User; | ||
| 5 | import org.apache.commons.lang3.StringUtils; | 7 | import org.apache.commons.lang3.StringUtils; |
| 6 | import org.springframework.beans.factory.annotation.Autowired; | 8 | import org.springframework.beans.factory.annotation.Autowired; |
| 7 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | 9 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
| @@ -38,7 +40,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | @@ -38,7 +40,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||
| 38 | return; | 40 | return; |
| 39 | } | 41 | } |
| 40 | if (!userSetting.isInterfaceAuthentication()) { | 42 | if (!userSetting.isInterfaceAuthentication()) { |
| 41 | - // 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录 | ||
| 42 | UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() ); | 43 | UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() ); |
| 43 | SecurityContextHolder.getContext().setAuthentication(token); | 44 | SecurityContextHolder.getContext().setAuthentication(token); |
| 44 | chain.doFilter(request, response); | 45 | chain.doFilter(request, response); |
| @@ -76,7 +77,13 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | @@ -76,7 +77,13 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | // 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录 | 79 | // 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录 |
| 79 | - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword(), new ArrayList<>() ); | 80 | + User user = new User(); |
| 81 | + user.setUsername(jwtUser.getUserName()); | ||
| 82 | + user.setPassword(jwtUser.getPassword()); | ||
| 83 | + Role role = new Role(); | ||
| 84 | + role.setId(jwtUser.getRoleId()); | ||
| 85 | + user.setRole(role); | ||
| 86 | + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, jwtUser.getPassword(), new ArrayList<>() ); | ||
| 80 | SecurityContextHolder.getContext().setAuthentication(token); | 87 | SecurityContextHolder.getContext().setAuthentication(token); |
| 81 | chain.doFilter(request, response); | 88 | chain.doFilter(request, response); |
| 82 | } | 89 | } |
src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java
| @@ -37,7 +37,7 @@ public class JwtUtils { | @@ -37,7 +37,7 @@ public class JwtUtils { | ||
| 37 | */ | 37 | */ |
| 38 | public static final long expirationTime = 30; | 38 | public static final long expirationTime = 30; |
| 39 | 39 | ||
| 40 | - public static String createToken(String username, String password) { | 40 | + public static String createToken(String username, String password, Integer roleId) { |
| 41 | try { | 41 | try { |
| 42 | /** | 42 | /** |
| 43 | * “iss” (issuer) 发行人 | 43 | * “iss” (issuer) 发行人 |
| @@ -64,6 +64,7 @@ public class JwtUtils { | @@ -64,6 +64,7 @@ public class JwtUtils { | ||
| 64 | //添加自定义参数,必须是字符串类型 | 64 | //添加自定义参数,必须是字符串类型 |
| 65 | claims.setClaim("username", username); | 65 | claims.setClaim("username", username); |
| 66 | claims.setClaim("password", password); | 66 | claims.setClaim("password", password); |
| 67 | + claims.setClaim("roleId", roleId); | ||
| 67 | 68 | ||
| 68 | //jws | 69 | //jws |
| 69 | JsonWebSignature jws = new JsonWebSignature(); | 70 | JsonWebSignature jws = new JsonWebSignature(); |
| @@ -118,8 +119,10 @@ public class JwtUtils { | @@ -118,8 +119,10 @@ public class JwtUtils { | ||
| 118 | 119 | ||
| 119 | String username = (String) claims.getClaimValue("username"); | 120 | String username = (String) claims.getClaimValue("username"); |
| 120 | String password = (String) claims.getClaimValue("password"); | 121 | String password = (String) claims.getClaimValue("password"); |
| 122 | + Long roleId = (Long) claims.getClaimValue("roleId"); | ||
| 121 | jwtUser.setUserName(username); | 123 | jwtUser.setUserName(username); |
| 122 | jwtUser.setPassword(password); | 124 | jwtUser.setPassword(password); |
| 125 | + jwtUser.setRoleId(roleId.intValue()); | ||
| 123 | 126 | ||
| 124 | return jwtUser; | 127 | return jwtUser; |
| 125 | } catch (InvalidJwtException e) { | 128 | } catch (InvalidJwtException e) { |
src/main/java/com/genersoft/iot/vmp/conf/security/LoginFailureHandler.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.conf.security; | ||
| 2 | - | ||
| 3 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 4 | -import org.slf4j.Logger; | ||
| 5 | -import org.slf4j.LoggerFactory; | ||
| 6 | -import org.springframework.beans.factory.annotation.Autowired; | ||
| 7 | -import org.springframework.security.authentication.*; | ||
| 8 | -import org.springframework.security.core.AuthenticationException; | ||
| 9 | -import org.springframework.security.web.authentication.AuthenticationFailureHandler; | ||
| 10 | -import org.springframework.stereotype.Component; | ||
| 11 | - | ||
| 12 | -import javax.servlet.ServletException; | ||
| 13 | -import javax.servlet.http.HttpServletRequest; | ||
| 14 | -import javax.servlet.http.HttpServletResponse; | ||
| 15 | -import java.io.IOException; | ||
| 16 | -import java.util.HashMap; | ||
| 17 | -import java.util.Map; | ||
| 18 | - | ||
| 19 | -@Component | ||
| 20 | -public class LoginFailureHandler implements AuthenticationFailureHandler { | ||
| 21 | - | ||
| 22 | - private final static Logger logger = LoggerFactory.getLogger(LoginFailureHandler.class); | ||
| 23 | - | ||
| 24 | - @Autowired | ||
| 25 | - private ObjectMapper objectMapper; | ||
| 26 | - | ||
| 27 | - @Override | ||
| 28 | - public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { | ||
| 29 | - | ||
| 30 | - String username = request.getParameter("username"); | ||
| 31 | - if (e instanceof AccountExpiredException) { | ||
| 32 | - // 账号过期 | ||
| 33 | - logger.info("[登录失败] - 用户[{}]账号过期", username); | ||
| 34 | - | ||
| 35 | - } else if (e instanceof BadCredentialsException) { | ||
| 36 | - // 密码错误 | ||
| 37 | - logger.info("[登录失败] - 用户[{}]密码/SIP服务器ID 错误", username); | ||
| 38 | - | ||
| 39 | - } else if (e instanceof CredentialsExpiredException) { | ||
| 40 | - // 密码过期 | ||
| 41 | - logger.info("[登录失败] - 用户[{}]密码过期", username); | ||
| 42 | - | ||
| 43 | - } else if (e instanceof DisabledException) { | ||
| 44 | - // 用户被禁用 | ||
| 45 | - logger.info("[登录失败] - 用户[{}]被禁用", username); | ||
| 46 | - | ||
| 47 | - } else if (e instanceof LockedException) { | ||
| 48 | - // 用户被锁定 | ||
| 49 | - logger.info("[登录失败] - 用户[{}]被锁定", username); | ||
| 50 | - | ||
| 51 | - } else if (e instanceof InternalAuthenticationServiceException) { | ||
| 52 | - // 内部错误 | ||
| 53 | - logger.error(String.format("[登录失败] - [%s]内部错误", username), e); | ||
| 54 | - | ||
| 55 | - } else { | ||
| 56 | - // 其他错误 | ||
| 57 | - logger.error(String.format("[登录失败] - [%s]其他错误", username), e); | ||
| 58 | - } | ||
| 59 | - Map<String, Object> map = new HashMap<>(); | ||
| 60 | - map.put("code","0"); | ||
| 61 | - map.put("msg","登录失败"); | ||
| 62 | - response.setContentType("application/json;charset=UTF-8"); | ||
| 63 | - response.getWriter().write(objectMapper.writeValueAsString(map)); | ||
| 64 | - } | ||
| 65 | -} |
src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.conf.security; | ||
| 2 | - | ||
| 3 | -import org.slf4j.Logger; | ||
| 4 | -import org.slf4j.LoggerFactory; | ||
| 5 | -import org.springframework.security.core.Authentication; | ||
| 6 | -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | ||
| 7 | -import org.springframework.stereotype.Component; | ||
| 8 | - | ||
| 9 | -import javax.servlet.ServletException; | ||
| 10 | -import javax.servlet.http.HttpServletRequest; | ||
| 11 | -import javax.servlet.http.HttpServletResponse; | ||
| 12 | -import java.io.IOException; | ||
| 13 | - | ||
| 14 | -/** | ||
| 15 | - * @author lin | ||
| 16 | - */ | ||
| 17 | -@Component | ||
| 18 | -public class LoginSuccessHandler implements AuthenticationSuccessHandler { | ||
| 19 | - | ||
| 20 | - private final static Logger logger = LoggerFactory.getLogger(LoginSuccessHandler.class); | ||
| 21 | - | ||
| 22 | - @Override | ||
| 23 | - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { | ||
| 24 | -// String username = request.getParameter("username"); | ||
| 25 | -// httpServletResponse.setContentType("application/json;charset=UTF-8"); | ||
| 26 | -// // 生成JWT,并放置到请求头中 | ||
| 27 | -// String jwt = JwtUtils.createToken(authentication.getName(), ); | ||
| 28 | -// httpServletResponse.setHeader(JwtUtils.getHeader(), jwt); | ||
| 29 | -// ServletOutputStream outputStream = httpServletResponse.getOutputStream(); | ||
| 30 | -// outputStream.write(JSON.toJSONString(ErrorCode.SUCCESS).getBytes(StandardCharsets.UTF_8)); | ||
| 31 | -// outputStream.flush(); | ||
| 32 | -// outputStream.close(); | ||
| 33 | - | ||
| 34 | -// logger.info("[登录成功] - [{}]", username); | ||
| 35 | - } | ||
| 36 | -} |
src/main/java/com/genersoft/iot/vmp/conf/security/SecurityUtils.java
| @@ -53,14 +53,10 @@ public class SecurityUtils { | @@ -53,14 +53,10 @@ public class SecurityUtils { | ||
| 53 | Authentication authentication = getAuthentication(); | 53 | Authentication authentication = getAuthentication(); |
| 54 | if(authentication!=null){ | 54 | if(authentication!=null){ |
| 55 | Object principal = authentication.getPrincipal(); | 55 | Object principal = authentication.getPrincipal(); |
| 56 | - if(principal!=null && !"anonymousUser".equals(principal)){ | ||
| 57 | -// LoginUser user = (LoginUser) authentication.getPrincipal(); | 56 | + if(principal!=null && !"anonymousUser".equals(principal.toString())){ |
| 58 | 57 | ||
| 59 | - String username = (String) principal; | ||
| 60 | - User user = new User(); | ||
| 61 | - user.setUsername(username); | ||
| 62 | - LoginUser loginUser = new LoginUser(user, LocalDateTime.now()); | ||
| 63 | - return loginUser; | 58 | + User user = (User) principal; |
| 59 | + return new LoginUser(user, LocalDateTime.now()); | ||
| 64 | } | 60 | } |
| 65 | } | 61 | } |
| 66 | return null; | 62 | return null; |
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
| @@ -47,16 +47,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | @@ -47,16 +47,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | ||
| 47 | * 登出成功的处理 | 47 | * 登出成功的处理 |
| 48 | */ | 48 | */ |
| 49 | @Autowired | 49 | @Autowired |
| 50 | - private LoginFailureHandler loginFailureHandler; | ||
| 51 | - /** | ||
| 52 | - * 登录成功的处理 | ||
| 53 | - */ | ||
| 54 | - @Autowired | ||
| 55 | - private LoginSuccessHandler loginSuccessHandler; | ||
| 56 | - /** | ||
| 57 | - * 登出成功的处理 | ||
| 58 | - */ | ||
| 59 | - @Autowired | ||
| 60 | private LogoutHandler logoutHandler; | 50 | private LogoutHandler logoutHandler; |
| 61 | /** | 51 | /** |
| 62 | * 未登录的处理 | 52 | * 未登录的处理 |
src/main/java/com/genersoft/iot/vmp/conf/security/dto/JwtUser.java
| @@ -25,6 +25,8 @@ public class JwtUser { | @@ -25,6 +25,8 @@ public class JwtUser { | ||
| 25 | 25 | ||
| 26 | private String password; | 26 | private String password; |
| 27 | 27 | ||
| 28 | + private int roleId; | ||
| 29 | + | ||
| 28 | private TokenStatus status; | 30 | private TokenStatus status; |
| 29 | 31 | ||
| 30 | public String getUserName() { | 32 | public String getUserName() { |
| @@ -50,4 +52,12 @@ public class JwtUser { | @@ -50,4 +52,12 @@ public class JwtUser { | ||
| 50 | public void setPassword(String password) { | 52 | public void setPassword(String password) { |
| 51 | this.password = password; | 53 | this.password = password; |
| 52 | } | 54 | } |
| 55 | + | ||
| 56 | + public int getRoleId() { | ||
| 57 | + return roleId; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + public void setRoleId(int roleId) { | ||
| 61 | + this.roleId = roleId; | ||
| 62 | + } | ||
| 53 | } | 63 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
| @@ -36,8 +36,6 @@ public class SipLayer implements CommandLineRunner { | @@ -36,8 +36,6 @@ public class SipLayer implements CommandLineRunner { | ||
| 36 | private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>(); | 36 | private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>(); |
| 37 | private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>(); | 37 | private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>(); |
| 38 | 38 | ||
| 39 | - private SipFactory sipFactory; | ||
| 40 | - | ||
| 41 | @Override | 39 | @Override |
| 42 | public void run(String... args) { | 40 | public void run(String... args) { |
| 43 | List<String> monitorIps = new ArrayList<>(); | 41 | List<String> monitorIps = new ArrayList<>(); |
| @@ -50,8 +48,7 @@ public class SipLayer implements CommandLineRunner { | @@ -50,8 +48,7 @@ public class SipLayer implements CommandLineRunner { | ||
| 50 | monitorIps.add(sipConfig.getIp()); | 48 | monitorIps.add(sipConfig.getIp()); |
| 51 | } | 49 | } |
| 52 | 50 | ||
| 53 | - sipFactory = SipFactory.getInstance(); | ||
| 54 | - sipFactory.setPathName("gov.nist"); | 51 | + SipFactory.getInstance().setPathName("gov.nist"); |
| 55 | if (monitorIps.size() > 0) { | 52 | if (monitorIps.size() > 0) { |
| 56 | for (String monitorIp : monitorIps) { | 53 | for (String monitorIp : monitorIps) { |
| 57 | addListeningPoint(monitorIp, sipConfig.getPort()); | 54 | addListeningPoint(monitorIp, sipConfig.getPort()); |
| @@ -65,7 +62,7 @@ public class SipLayer implements CommandLineRunner { | @@ -65,7 +62,7 @@ public class SipLayer implements CommandLineRunner { | ||
| 65 | private void addListeningPoint(String monitorIp, int port){ | 62 | private void addListeningPoint(String monitorIp, int port){ |
| 66 | SipStackImpl sipStack; | 63 | SipStackImpl sipStack; |
| 67 | try { | 64 | try { |
| 68 | - sipStack = (SipStackImpl)sipFactory.createSipStack(DefaultProperties.getProperties(monitorIp, userSetting.getSipLog())); | 65 | + sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties(monitorIp, userSetting.getSipLog())); |
| 69 | } catch (PeerUnavailableException e) { | 66 | } catch (PeerUnavailableException e) { |
| 70 | logger.error("[Sip Server] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp); | 67 | logger.error("[Sip Server] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp); |
| 71 | return; | 68 | return; |
| @@ -106,10 +103,6 @@ public class SipLayer implements CommandLineRunner { | @@ -106,10 +103,6 @@ public class SipLayer implements CommandLineRunner { | ||
| 106 | } | 103 | } |
| 107 | } | 104 | } |
| 108 | 105 | ||
| 109 | - public SipFactory getSipFactory() { | ||
| 110 | - return sipFactory; | ||
| 111 | - } | ||
| 112 | - | ||
| 113 | public SipProviderImpl getUdpSipProvider(String ip) { | 106 | public SipProviderImpl getUdpSipProvider(String ip) { |
| 114 | if (ObjectUtils.isEmpty(ip)) { | 107 | if (ObjectUtils.isEmpty(ip)) { |
| 115 | return null; | 108 | return null; |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/CmdSendFailEvent.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.gb28181.bean; | ||
| 2 | - | ||
| 3 | -import javax.sip.Dialog; | ||
| 4 | -import java.util.EventObject; | ||
| 5 | - | ||
| 6 | -public class CmdSendFailEvent extends EventObject { | ||
| 7 | - | ||
| 8 | - private String callId; | ||
| 9 | - | ||
| 10 | - /** | ||
| 11 | - * Constructs a prototypical Event. | ||
| 12 | - * | ||
| 13 | - * @param dialog | ||
| 14 | - * @throws IllegalArgumentException if source is null. | ||
| 15 | - */ | ||
| 16 | - public CmdSendFailEvent(Dialog dialog) { | ||
| 17 | - super(dialog); | ||
| 18 | - } | ||
| 19 | - | ||
| 20 | - public String getCallId() { | ||
| 21 | - return callId; | ||
| 22 | - } | ||
| 23 | - | ||
| 24 | - public void setCallId(String callId) { | ||
| 25 | - this.callId = callId; | ||
| 26 | - } | ||
| 27 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
| @@ -247,6 +247,17 @@ public class Device { | @@ -247,6 +247,17 @@ public class Device { | ||
| 247 | return streamMode; | 247 | return streamMode; |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | + public Integer getStreamModeForParam() { | ||
| 251 | + if (streamMode.equalsIgnoreCase("UDP")) { | ||
| 252 | + return 0; | ||
| 253 | + }else if (streamMode.equalsIgnoreCase("TCP-PASSIVE")) { | ||
| 254 | + return 1; | ||
| 255 | + }else if (streamMode.equalsIgnoreCase("TCP-ACTIVE")) { | ||
| 256 | + return 2; | ||
| 257 | + } | ||
| 258 | + return 0; | ||
| 259 | + } | ||
| 260 | + | ||
| 250 | public void setStreamMode(String streamMode) { | 261 | public void setStreamMode(String streamMode) { |
| 251 | this.streamMode = streamMode; | 262 | this.streamMode = streamMode; |
| 252 | } | 263 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamType.java
| @@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.bean; | @@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.bean; | ||
| 2 | 2 | ||
| 3 | public enum InviteStreamType { | 3 | public enum InviteStreamType { |
| 4 | 4 | ||
| 5 | - PLAY,PLAYBACK,PUSH,PROXY,CLOUD_RECORD_PUSH,CLOUD_RECORD_PROXY,BROADCAST,TALK | 5 | + PLAY,PLAYBACK,DOWNLOAD,PUSH,PROXY,CLOUD_RECORD_PUSH,CLOUD_RECORD_PROXY,BROADCAST,TALK |
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | } | 8 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
| 1 | package com.genersoft.iot.vmp.gb28181.bean; | 1 | package com.genersoft.iot.vmp.gb28181.bean; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 3 | +import com.genersoft.iot.vmp.common.InviteSessionType; |
| 4 | 4 | ||
| 5 | public class SsrcTransaction { | 5 | public class SsrcTransaction { |
| 6 | 6 | ||
| @@ -13,7 +13,7 @@ public class SsrcTransaction { | @@ -13,7 +13,7 @@ public class SsrcTransaction { | ||
| 13 | 13 | ||
| 14 | private SipTransactionInfo sipTransactionInfo; | 14 | private SipTransactionInfo sipTransactionInfo; |
| 15 | 15 | ||
| 16 | - private VideoStreamSessionManager.SessionType type; | 16 | + private InviteSessionType type; |
| 17 | 17 | ||
| 18 | public String getDeviceId() { | 18 | public String getDeviceId() { |
| 19 | return deviceId; | 19 | return deviceId; |
| @@ -63,11 +63,11 @@ public class SsrcTransaction { | @@ -63,11 +63,11 @@ public class SsrcTransaction { | ||
| 63 | this.ssrc = ssrc; | 63 | this.ssrc = ssrc; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | - public VideoStreamSessionManager.SessionType getType() { | 66 | + public InviteSessionType getType() { |
| 67 | return type; | 67 | return type; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | - public void setType(VideoStreamSessionManager.SessionType type) { | 70 | + public void setType(InviteSessionType type) { |
| 71 | this.type = type; | 71 | this.type = type; |
| 72 | } | 72 | } |
| 73 | 73 |
src/main/java/com/genersoft/iot/vmp/gb28181/conf/ServerLoggerImpl.java
| @@ -27,7 +27,7 @@ public class ServerLoggerImpl implements ServerLogger { | @@ -27,7 +27,7 @@ public class ServerLoggerImpl implements ServerLogger { | ||
| 27 | return; | 27 | return; |
| 28 | } | 28 | } |
| 29 | StringBuilder stringBuilder = new StringBuilder(); | 29 | StringBuilder stringBuilder = new StringBuilder(); |
| 30 | - stringBuilder.append(!sender? "发送:目标--->" + from:"接收:来自--->" + to) | 30 | + stringBuilder.append(sender? "发送:目标--->" + from:"接收:来自--->" + to) |
| 31 | .append("\r\n") | 31 | .append("\r\n") |
| 32 | .append(message); | 32 | .append(message); |
| 33 | this.stackLogger.logInfo(stringBuilder.toString()); | 33 | this.stackLogger.logInfo(stringBuilder.toString()); |
| @@ -40,7 +40,7 @@ public class ServerLoggerImpl implements ServerLogger { | @@ -40,7 +40,7 @@ public class ServerLoggerImpl implements ServerLogger { | ||
| 40 | return; | 40 | return; |
| 41 | } | 41 | } |
| 42 | StringBuilder stringBuilder = new StringBuilder(); | 42 | StringBuilder stringBuilder = new StringBuilder(); |
| 43 | - stringBuilder.append(!sender? "发送: 目标->" + from :"接收:来自->" + to) | 43 | + stringBuilder.append(sender? "发送: 目标->" + from :"接收:来自->" + to) |
| 44 | .append("\r\n") | 44 | .append("\r\n") |
| 45 | .append(message); | 45 | .append(message); |
| 46 | this.stackLogger.logInfo(stringBuilder.toString()); | 46 | this.stackLogger.logInfo(stringBuilder.toString()); |
| @@ -52,7 +52,7 @@ public class ServerLoggerImpl implements ServerLogger { | @@ -52,7 +52,7 @@ public class ServerLoggerImpl implements ServerLogger { | ||
| 52 | return; | 52 | return; |
| 53 | } | 53 | } |
| 54 | StringBuilder stringBuilder = new StringBuilder(); | 54 | StringBuilder stringBuilder = new StringBuilder(); |
| 55 | - stringBuilder.append(!sender? "发送: 目标->" + from :"接收:来自->" + to) | 55 | + stringBuilder.append(sender? "发送: 目标->" + from :"接收:来自->" + to) |
| 56 | .append("\r\n") | 56 | .append("\r\n") |
| 57 | .append(message); | 57 | .append(message); |
| 58 | this.stackLogger.logInfo(stringBuilder.toString()); | 58 | this.stackLogger.logInfo(stringBuilder.toString()); |
| @@ -87,6 +87,4 @@ public class ServerLoggerImpl implements ServerLogger { | @@ -87,6 +87,4 @@ public class ServerLoggerImpl implements ServerLogger { | ||
| 87 | this.stackLogger = this.sipStack.getStackLogger(); | 87 | this.stackLogger = this.sipStack.getStackLogger(); |
| 88 | } | 88 | } |
| 89 | } | 89 | } |
| 90 | - | ||
| 91 | - | ||
| 92 | } | 90 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
| @@ -76,7 +76,11 @@ public class SipSubscribe { | @@ -76,7 +76,11 @@ public class SipSubscribe { | ||
| 76 | // 会话已结束 | 76 | // 会话已结束 |
| 77 | dialogTerminated, | 77 | dialogTerminated, |
| 78 | // 设备未找到 | 78 | // 设备未找到 |
| 79 | - deviceNotFoundEvent | 79 | + deviceNotFoundEvent, |
| 80 | + // 消息发送失败 | ||
| 81 | + cmdSendFailEvent, | ||
| 82 | + // 消息发送失败 | ||
| 83 | + failedToGetPort | ||
| 80 | } | 84 | } |
| 81 | 85 | ||
| 82 | public static class EventResult<EventObject>{ | 86 | public static class EventResult<EventObject>{ |
| @@ -86,9 +90,7 @@ public class SipSubscribe { | @@ -86,9 +90,7 @@ public class SipSubscribe { | ||
| 86 | public String callId; | 90 | public String callId; |
| 87 | public EventObject event; | 91 | public EventObject event; |
| 88 | 92 | ||
| 89 | - public EventResult(int statusCode, String msg) { | ||
| 90 | - this.statusCode = statusCode; | ||
| 91 | - this.msg = msg; | 93 | + public EventResult() { |
| 92 | } | 94 | } |
| 93 | 95 | ||
| 94 | public EventResult(EventObject event) { | 96 | public EventResult(EventObject event) { |
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
| 1 | package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog; | 1 | package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.common.VideoManagerConstants; | ||
| 4 | -import com.genersoft.iot.vmp.conf.SipConfig; | ||
| 5 | import com.genersoft.iot.vmp.conf.UserSetting; | 3 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 6 | import com.genersoft.iot.vmp.gb28181.bean.*; | 4 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 7 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| 8 | -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | ||
| 9 | import com.genersoft.iot.vmp.service.IGbStreamService; | 6 | import com.genersoft.iot.vmp.service.IGbStreamService; |
| 10 | -import com.genersoft.iot.vmp.service.IMediaServerService; | ||
| 11 | -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | ||
| 12 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 7 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 13 | import org.slf4j.Logger; | 8 | import org.slf4j.Logger; |
| 14 | import org.slf4j.LoggerFactory; | 9 | import org.slf4j.LoggerFactory; |
| @@ -16,12 +11,14 @@ import org.springframework.beans.factory.annotation.Autowired; | @@ -16,12 +11,14 @@ import org.springframework.beans.factory.annotation.Autowired; | ||
| 16 | import org.springframework.context.ApplicationListener; | 11 | import org.springframework.context.ApplicationListener; |
| 17 | import org.springframework.stereotype.Component; | 12 | import org.springframework.stereotype.Component; |
| 18 | import org.springframework.util.ObjectUtils; | 13 | import org.springframework.util.ObjectUtils; |
| 19 | -import org.springframework.util.StringUtils; | ||
| 20 | 14 | ||
| 21 | import javax.sip.InvalidArgumentException; | 15 | import javax.sip.InvalidArgumentException; |
| 22 | import javax.sip.SipException; | 16 | import javax.sip.SipException; |
| 23 | import java.text.ParseException; | 17 | import java.text.ParseException; |
| 24 | -import java.util.*; | 18 | +import java.util.ArrayList; |
| 19 | +import java.util.HashMap; | ||
| 20 | +import java.util.List; | ||
| 21 | +import java.util.Map; | ||
| 25 | 22 | ||
| 26 | /** | 23 | /** |
| 27 | * catalog事件 | 24 | * catalog事件 |
| @@ -43,6 +40,9 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { | @@ -43,6 +40,9 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { | ||
| 43 | @Autowired | 40 | @Autowired |
| 44 | private SubscribeHolder subscribeHolder; | 41 | private SubscribeHolder subscribeHolder; |
| 45 | 42 | ||
| 43 | + @Autowired | ||
| 44 | + private UserSetting userSetting; | ||
| 45 | + | ||
| 46 | @Override | 46 | @Override |
| 47 | public void onApplicationEvent(CatalogEvent event) { | 47 | public void onApplicationEvent(CatalogEvent event) { |
| 48 | SubscribeInfo subscribe = null; | 48 | SubscribeInfo subscribe = null; |
| @@ -93,6 +93,9 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { | @@ -93,6 +93,9 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { | ||
| 93 | } | 93 | } |
| 94 | if (event.getGbStreams() != null && event.getGbStreams().size() > 0){ | 94 | if (event.getGbStreams() != null && event.getGbStreams().size() > 0){ |
| 95 | for (GbStream gbStream : event.getGbStreams()) { | 95 | for (GbStream gbStream : event.getGbStreams()) { |
| 96 | + if (gbStream.getStreamType().equals("push") && !userSetting.isUsePushingAsStatus()) { | ||
| 97 | + continue; | ||
| 98 | + } | ||
| 96 | DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform); | 99 | DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform); |
| 97 | deviceChannelList.add(deviceChannelByStream); | 100 | deviceChannelList.add(deviceChannelByStream); |
| 98 | } | 101 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/session/SSRCFactory.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.session; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.conf.SipConfig; | ||
| 4 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 5 | +import org.springframework.data.redis.core.StringRedisTemplate; | ||
| 6 | +import org.springframework.stereotype.Component; | ||
| 7 | + | ||
| 8 | +import java.util.ArrayList; | ||
| 9 | +import java.util.List; | ||
| 10 | +import java.util.Set; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * ssrc使用 | ||
| 14 | + */ | ||
| 15 | +@Component | ||
| 16 | +public class SSRCFactory { | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * 播流最大并发个数 | ||
| 20 | + */ | ||
| 21 | + private static final Integer MAX_STREAM_COUNT = 10000; | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * 播流最大并发个数 | ||
| 25 | + */ | ||
| 26 | + private static final String SSRC_INFO_KEY = "VMP_SSRC_INFO_"; | ||
| 27 | + | ||
| 28 | + @Autowired | ||
| 29 | + private StringRedisTemplate redisTemplate; | ||
| 30 | + | ||
| 31 | + @Autowired | ||
| 32 | + private SipConfig sipConfig; | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) { | ||
| 36 | + String ssrcPrefix = sipConfig.getDomain().substring(3, 8); | ||
| 37 | + String redisKey = SSRC_INFO_KEY + mediaServerId; | ||
| 38 | + List<String> ssrcList = new ArrayList<>(); | ||
| 39 | + for (int i = 1; i < MAX_STREAM_COUNT; i++) { | ||
| 40 | + String ssrc = String.format("%s%04d", ssrcPrefix, i); | ||
| 41 | + | ||
| 42 | + if (null == usedSet || !usedSet.contains(ssrc)) { | ||
| 43 | + ssrcList.add(ssrc); | ||
| 44 | + | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + if (redisTemplate.opsForSet().size(redisKey) != null) { | ||
| 48 | + redisTemplate.delete(redisKey); | ||
| 49 | + } | ||
| 50 | + redisTemplate.opsForSet().add(redisKey, ssrcList.toArray(new String[0])); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * 获取视频预览的SSRC值,第一位固定为0 | ||
| 56 | + * | ||
| 57 | + * @return ssrc | ||
| 58 | + */ | ||
| 59 | + public String getPlaySsrc(String mediaServerId) { | ||
| 60 | + return "0" + getSN(mediaServerId); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * 获取录像回放的SSRC值,第一位固定为1 | ||
| 65 | + */ | ||
| 66 | + public String getPlayBackSsrc(String mediaServerId) { | ||
| 67 | + return "1" + getSN(mediaServerId); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽 | ||
| 72 | + * | ||
| 73 | + * @param ssrc 需要重置的ssrc | ||
| 74 | + */ | ||
| 75 | + public void releaseSsrc(String mediaServerId, String ssrc) { | ||
| 76 | + if (ssrc == null) { | ||
| 77 | + return; | ||
| 78 | + } | ||
| 79 | + String sn = ssrc.substring(1); | ||
| 80 | + String redisKey = SSRC_INFO_KEY + mediaServerId; | ||
| 81 | + redisTemplate.opsForSet().add(redisKey, sn); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + /** | ||
| 85 | + * 获取后四位数SN,随机数 | ||
| 86 | + */ | ||
| 87 | + private String getSN(String mediaServerId) { | ||
| 88 | + String sn = null; | ||
| 89 | + String redisKey = SSRC_INFO_KEY + mediaServerId; | ||
| 90 | + Long size = redisTemplate.opsForSet().size(redisKey); | ||
| 91 | + if (size == null || size == 0) { | ||
| 92 | + throw new RuntimeException("ssrc已经用完"); | ||
| 93 | + } else { | ||
| 94 | + // 在集合中移除并返回一个随机成员。 | ||
| 95 | + sn = (String) redisTemplate.opsForSet().pop(redisKey); | ||
| 96 | + redisTemplate.opsForSet().remove(redisKey, sn); | ||
| 97 | + } | ||
| 98 | + return sn; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * 重置一个流媒体服务的所有ssrc | ||
| 103 | + * | ||
| 104 | + * @param mediaServerId 流媒体服务ID | ||
| 105 | + */ | ||
| 106 | + public void reset(String mediaServerId) { | ||
| 107 | + this.initMediaServerSSRC(mediaServerId, null); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + /** | ||
| 111 | + * 是否已经存在了某个MediaServer的SSRC信息 | ||
| 112 | + * | ||
| 113 | + * @param mediaServerId 流媒体服务ID | ||
| 114 | + */ | ||
| 115 | + public boolean hasMediaServerSSRC(String mediaServerId) { | ||
| 116 | + String redisKey = SSRC_INFO_KEY + mediaServerId; | ||
| 117 | + return redisTemplate.opsForSet().members(redisKey) != null; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + /** | ||
| 121 | + * 查询ssrc是否可用 | ||
| 122 | + * | ||
| 123 | + * @param mediaServerId | ||
| 124 | + * @param ssrc | ||
| 125 | + * @return | ||
| 126 | + */ | ||
| 127 | + public boolean checkSsrc(String mediaServerId, String ssrc) { | ||
| 128 | + String sn = ssrc.substring(1); | ||
| 129 | + String redisKey = SSRC_INFO_KEY + mediaServerId; | ||
| 130 | + return redisTemplate.opsForSet().isMember(redisKey, sn) != null; | ||
| 131 | + } | ||
| 132 | +} |
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.gb28181.session; | ||
| 2 | - | ||
| 3 | -import com.genersoft.iot.vmp.utils.ConfigConst; | ||
| 4 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | - | ||
| 6 | -import java.util.ArrayList; | ||
| 7 | -import java.util.List; | ||
| 8 | -import java.util.Random; | ||
| 9 | -import java.util.Set; | ||
| 10 | - | ||
| 11 | -@Schema(description = "ssrc信息") | ||
| 12 | -public class SsrcConfig { | ||
| 13 | - | ||
| 14 | - /** | ||
| 15 | - * zlm流媒体服务器Id | ||
| 16 | - */ | ||
| 17 | - @Schema(description = "流媒体服务器Id") | ||
| 18 | - private String mediaServerId; | ||
| 19 | - | ||
| 20 | - @Schema(description = "SSRC前缀") | ||
| 21 | - private String ssrcPrefix; | ||
| 22 | - | ||
| 23 | - /** | ||
| 24 | - * zlm流媒体服务器已用会话句柄 | ||
| 25 | - */ | ||
| 26 | - @Schema(description = "zlm流媒体服务器已用会话句柄") | ||
| 27 | - private List<String> isUsed; | ||
| 28 | - | ||
| 29 | - /** | ||
| 30 | - * zlm流媒体服务器可用会话句柄 | ||
| 31 | - */ | ||
| 32 | - @Schema(description = "zlm流媒体服务器可用会话句柄") | ||
| 33 | - private List<String> notUsed; | ||
| 34 | - | ||
| 35 | - public SsrcConfig() { | ||
| 36 | - } | ||
| 37 | - | ||
| 38 | - public SsrcConfig(String mediaServerId, Set<String> usedSet, String sipDomain) { | ||
| 39 | - this.mediaServerId = mediaServerId; | ||
| 40 | - this.isUsed = new ArrayList<>(); | ||
| 41 | - this.ssrcPrefix = sipDomain.substring(3, 8); | ||
| 42 | - this.notUsed = new ArrayList<>(); | ||
| 43 | - for (int i = 1; i < ConfigConst.MAX_STRTEAM_COUNT; i++) { | ||
| 44 | - String ssrc; | ||
| 45 | - if (i < 10) { | ||
| 46 | - ssrc = "000" + i; | ||
| 47 | - } else if (i < 100) { | ||
| 48 | - ssrc = "00" + i; | ||
| 49 | - } else if (i < 1000) { | ||
| 50 | - ssrc = "0" + i; | ||
| 51 | - } else { | ||
| 52 | - ssrc = String.valueOf(i); | ||
| 53 | - } | ||
| 54 | - if (null == usedSet || !usedSet.contains(ssrc)) { | ||
| 55 | - this.notUsed.add(ssrc); | ||
| 56 | - } else { | ||
| 57 | - this.isUsed.add(ssrc); | ||
| 58 | - } | ||
| 59 | - } | ||
| 60 | - } | ||
| 61 | - | ||
| 62 | - | ||
| 63 | - /** | ||
| 64 | - * 获取视频预览的SSRC值,第一位固定为0 | ||
| 65 | - * @return ssrc | ||
| 66 | - */ | ||
| 67 | - public String getPlaySsrc() { | ||
| 68 | - return "0" + getSsrcPrefix() + getSN(); | ||
| 69 | - } | ||
| 70 | - | ||
| 71 | - /** | ||
| 72 | - * 获取录像回放的SSRC值,第一位固定为1 | ||
| 73 | - * | ||
| 74 | - */ | ||
| 75 | - public String getPlayBackSsrc() { | ||
| 76 | - return "1" + getSsrcPrefix() + getSN(); | ||
| 77 | - } | ||
| 78 | - | ||
| 79 | - /** | ||
| 80 | - * 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽 | ||
| 81 | - * @param ssrc 需要重置的ssrc | ||
| 82 | - */ | ||
| 83 | - public void releaseSsrc(String ssrc) { | ||
| 84 | - if (ssrc == null) { | ||
| 85 | - return; | ||
| 86 | - } | ||
| 87 | - String sn = ssrc.substring(6); | ||
| 88 | - try { | ||
| 89 | - isUsed.remove(sn); | ||
| 90 | - notUsed.add(sn); | ||
| 91 | - }catch (NullPointerException e){ | ||
| 92 | - } | ||
| 93 | - } | ||
| 94 | - | ||
| 95 | - /** | ||
| 96 | - * 获取后四位数SN,随机数 | ||
| 97 | - * | ||
| 98 | - */ | ||
| 99 | - private String getSN() { | ||
| 100 | - String sn = null; | ||
| 101 | - int index = 0; | ||
| 102 | - if (notUsed.size() == 0) { | ||
| 103 | - throw new RuntimeException("ssrc已经用完"); | ||
| 104 | - } else if (notUsed.size() == 1) { | ||
| 105 | - sn = notUsed.get(0); | ||
| 106 | - } else { | ||
| 107 | - index = new Random().nextInt(notUsed.size() - 1); | ||
| 108 | - sn = notUsed.get(index); | ||
| 109 | - } | ||
| 110 | - notUsed.remove(index); | ||
| 111 | - isUsed.add(sn); | ||
| 112 | - return sn; | ||
| 113 | - } | ||
| 114 | - | ||
| 115 | - public String getSsrcPrefix() { | ||
| 116 | - return ssrcPrefix; | ||
| 117 | - } | ||
| 118 | - | ||
| 119 | - public String getMediaServerId() { | ||
| 120 | - return mediaServerId; | ||
| 121 | - } | ||
| 122 | - | ||
| 123 | - public void setMediaServerId(String mediaServerId) { | ||
| 124 | - this.mediaServerId = mediaServerId; | ||
| 125 | - } | ||
| 126 | - | ||
| 127 | - public void setSsrcPrefix(String ssrcPrefix) { | ||
| 128 | - this.ssrcPrefix = ssrcPrefix; | ||
| 129 | - } | ||
| 130 | - | ||
| 131 | - public List<String> getIsUsed() { | ||
| 132 | - return isUsed; | ||
| 133 | - } | ||
| 134 | - | ||
| 135 | - public void setIsUsed(List<String> isUsed) { | ||
| 136 | - this.isUsed = isUsed; | ||
| 137 | - } | ||
| 138 | - | ||
| 139 | - public List<String> getNotUsed() { | ||
| 140 | - return notUsed; | ||
| 141 | - } | ||
| 142 | - | ||
| 143 | - public void setNotUsed(List<String> notUsed) { | ||
| 144 | - this.notUsed = notUsed; | ||
| 145 | - } | ||
| 146 | - | ||
| 147 | - public boolean checkSsrc(String ssrcInResponse) { | ||
| 148 | - return !isUsed.contains(ssrcInResponse); | ||
| 149 | - } | ||
| 150 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
| 1 | package com.genersoft.iot.vmp.gb28181.session; | 1 | package com.genersoft.iot.vmp.gb28181.session; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 3 | import com.genersoft.iot.vmp.common.VideoManagerConstants; | 4 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 4 | import com.genersoft.iot.vmp.conf.UserSetting; | 5 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 5 | import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; | 6 | import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; |
| @@ -27,14 +28,6 @@ public class VideoStreamSessionManager { | @@ -27,14 +28,6 @@ public class VideoStreamSessionManager { | ||
| 27 | @Autowired | 28 | @Autowired |
| 28 | private RedisTemplate<Object, Object> redisTemplate; | 29 | private RedisTemplate<Object, Object> redisTemplate; |
| 29 | 30 | ||
| 30 | - public enum SessionType { | ||
| 31 | - play, | ||
| 32 | - playback, | ||
| 33 | - download, | ||
| 34 | - broadcast, | ||
| 35 | - talk | ||
| 36 | - } | ||
| 37 | - | ||
| 38 | /** | 31 | /** |
| 39 | * 添加一个点播/回放的事务信息 | 32 | * 添加一个点播/回放的事务信息 |
| 40 | * 后续可以通过流Id/callID | 33 | * 后续可以通过流Id/callID |
| @@ -45,7 +38,7 @@ public class VideoStreamSessionManager { | @@ -45,7 +38,7 @@ public class VideoStreamSessionManager { | ||
| 45 | * @param mediaServerId 所使用的流媒体ID | 38 | * @param mediaServerId 所使用的流媒体ID |
| 46 | * @param response 回复 | 39 | * @param response 回复 |
| 47 | */ | 40 | */ |
| 48 | - public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, SessionType type){ | 41 | + public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, InviteSessionType type){ |
| 49 | SsrcTransaction ssrcTransaction = new SsrcTransaction(); | 42 | SsrcTransaction ssrcTransaction = new SsrcTransaction(); |
| 50 | ssrcTransaction.setDeviceId(deviceId); | 43 | ssrcTransaction.setDeviceId(deviceId); |
| 51 | ssrcTransaction.setChannelId(channelId); | 44 | ssrcTransaction.setChannelId(channelId); |
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
| @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; | @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 5 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 5 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 6 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | 6 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 7 | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | 7 | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
| 8 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | ||
| 8 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | 9 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 9 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | 10 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 10 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 11 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| @@ -38,6 +39,9 @@ public class SipRunner implements CommandLineRunner { | @@ -38,6 +39,9 @@ public class SipRunner implements CommandLineRunner { | ||
| 38 | private IRedisCatchStorage redisCatchStorage; | 39 | private IRedisCatchStorage redisCatchStorage; |
| 39 | 40 | ||
| 40 | @Autowired | 41 | @Autowired |
| 42 | + private SSRCFactory ssrcFactory; | ||
| 43 | + | ||
| 44 | + @Autowired | ||
| 41 | private UserSetting userSetting; | 45 | private UserSetting userSetting; |
| 42 | 46 | ||
| 43 | @Autowired | 47 | @Autowired |
| @@ -96,6 +100,7 @@ public class SipRunner implements CommandLineRunner { | @@ -96,6 +100,7 @@ public class SipRunner implements CommandLineRunner { | ||
| 96 | MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | 100 | MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 97 | redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStream()); | 101 | redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStream()); |
| 98 | if (mediaServerItem != null) { | 102 | if (mediaServerItem != null) { |
| 103 | + ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); | ||
| 99 | Map<String, Object> param = new HashMap<>(); | 104 | Map<String, Object> param = new HashMap<>(); |
| 100 | param.put("vhost","__defaultVhost__"); | 105 | param.put("vhost","__defaultVhost__"); |
| 101 | param.put("app",sendRtpItem.getApp()); | 106 | param.put("app",sendRtpItem.getApp()); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
| @@ -46,8 +46,7 @@ public class SIPSender { | @@ -46,8 +46,7 @@ public class SIPSender { | ||
| 46 | transmitRequest(ip, message, errorEvent, null); | 46 | transmitRequest(ip, message, errorEvent, null); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | - public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, ParseException { | ||
| 50 | - try { | 49 | + public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException { |
| 51 | ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME); | 50 | ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME); |
| 52 | String transport = "UDP"; | 51 | String transport = "UDP"; |
| 53 | if (viaHeader == null) { | 52 | if (viaHeader == null) { |
| @@ -57,7 +56,7 @@ public class SIPSender { | @@ -57,7 +56,7 @@ public class SIPSender { | ||
| 57 | } | 56 | } |
| 58 | if (message.getHeader(UserAgentHeader.NAME) == null) { | 57 | if (message.getHeader(UserAgentHeader.NAME) == null) { |
| 59 | try { | 58 | try { |
| 60 | - message.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 59 | + message.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 61 | } catch (ParseException e) { | 60 | } catch (ParseException e) { |
| 62 | logger.error("添加UserAgentHeader失败", e); | 61 | logger.error("添加UserAgentHeader失败", e); |
| 63 | } | 62 | } |
| @@ -104,9 +103,6 @@ public class SIPSender { | @@ -104,9 +103,6 @@ public class SIPSender { | ||
| 104 | sipProvider.sendResponse((Response)message); | 103 | sipProvider.sendResponse((Response)message); |
| 105 | } | 104 | } |
| 106 | } | 105 | } |
| 107 | - } finally { | ||
| 108 | -// logger.info("[SEND]:SUCCESS:{}", message); | ||
| 109 | - } | ||
| 110 | } | 106 | } |
| 111 | 107 | ||
| 112 | public CallIdHeader getNewCallIdHeader(String ip, String transport){ | 108 | public CallIdHeader getNewCallIdHeader(String ip, String transport){ |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
| @@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; | @@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; | ||
| 3 | import com.genersoft.iot.vmp.common.StreamInfo; | 3 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 4 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 5 | import com.genersoft.iot.vmp.gb28181.bean.*; | 5 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 7 | +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; | ||
| 6 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 8 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 7 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | 9 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| 8 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 10 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| @@ -107,7 +109,7 @@ public interface ISIPCommander { | @@ -107,7 +109,7 @@ public interface ISIPCommander { | ||
| 107 | * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss | 109 | * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss |
| 108 | * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss | 110 | * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss |
| 109 | */ | 111 | */ |
| 110 | - void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; | 112 | + void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; |
| 111 | 113 | ||
| 112 | /** | 114 | /** |
| 113 | * 请求历史媒体下载 | 115 | * 请求历史媒体下载 |
| @@ -119,7 +121,7 @@ public interface ISIPCommander { | @@ -119,7 +121,7 @@ public interface ISIPCommander { | ||
| 119 | * @param downloadSpeed 下载倍速参数 | 121 | * @param downloadSpeed 下载倍速参数 |
| 120 | */ | 122 | */ |
| 121 | void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | 123 | void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 122 | - String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, | 124 | + String startTime, String endTime, int downloadSpeed, ZlmHttpHookSubscribe.Event hookEvent, |
| 123 | SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; | 125 | SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; |
| 124 | 126 | ||
| 125 | 127 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
| @@ -17,6 +17,7 @@ import org.springframework.util.DigestUtils; | @@ -17,6 +17,7 @@ import org.springframework.util.DigestUtils; | ||
| 17 | 17 | ||
| 18 | import javax.sip.InvalidArgumentException; | 18 | import javax.sip.InvalidArgumentException; |
| 19 | import javax.sip.PeerUnavailableException; | 19 | import javax.sip.PeerUnavailableException; |
| 20 | +import javax.sip.SipFactory; | ||
| 20 | import javax.sip.address.Address; | 21 | import javax.sip.address.Address; |
| 21 | import javax.sip.address.SipURI; | 22 | import javax.sip.address.SipURI; |
| 22 | import javax.sip.header.*; | 23 | import javax.sip.header.*; |
| @@ -50,39 +51,39 @@ public class SIPRequestHeaderPlarformProvider { | @@ -50,39 +51,39 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 50 | Request request = null; | 51 | Request request = null; |
| 51 | String sipAddress = parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort(); | 52 | String sipAddress = parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort(); |
| 52 | //请求行 | 53 | //请求行 |
| 53 | - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), | 54 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), |
| 54 | parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); | 55 | parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); |
| 55 | //via | 56 | //via |
| 56 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 57 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 57 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(parentPlatform.getServerIP(), | 58 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getServerIP(), |
| 58 | parentPlatform.getServerPort(), parentPlatform.getTransport(), SipUtils.getNewViaTag()); | 59 | parentPlatform.getServerPort(), parentPlatform.getTransport(), SipUtils.getNewViaTag()); |
| 59 | viaHeader.setRPort(); | 60 | viaHeader.setRPort(); |
| 60 | viaHeaders.add(viaHeader); | 61 | viaHeaders.add(viaHeader); |
| 61 | //from | 62 | //from |
| 62 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain()); | ||
| 63 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 64 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag); | 63 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain()); |
| 64 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 65 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); | ||
| 65 | //to | 66 | //to |
| 66 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain()); | ||
| 67 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 68 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,toTag); | 67 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain()); |
| 68 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 69 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,toTag); | ||
| 69 | 70 | ||
| 70 | //Forwards | 71 | //Forwards |
| 71 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 72 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 72 | 73 | ||
| 73 | //ceq | 74 | //ceq |
| 74 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(CSeq, Request.REGISTER); | ||
| 75 | - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.REGISTER, callIdHeader, | 75 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(CSeq, Request.REGISTER); |
| 76 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.REGISTER, callIdHeader, | ||
| 76 | cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | 77 | cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); |
| 77 | 78 | ||
| 78 | - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory() | 79 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory() |
| 79 | .createSipURI(parentPlatform.getDeviceGBId(), sipAddress)); | 80 | .createSipURI(parentPlatform.getDeviceGBId(), sipAddress)); |
| 80 | - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress)); | 81 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); |
| 81 | 82 | ||
| 82 | - ExpiresHeader expiresHeader = sipLayer.getSipFactory().createHeaderFactory().createExpiresHeader(expires); | 83 | + ExpiresHeader expiresHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(expires); |
| 83 | request.addHeader(expiresHeader); | 84 | request.addHeader(expiresHeader); |
| 84 | 85 | ||
| 85 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 86 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 86 | 87 | ||
| 87 | return request; | 88 | return request; |
| 88 | } | 89 | } |
| @@ -92,9 +93,9 @@ public class SIPRequestHeaderPlarformProvider { | @@ -92,9 +93,9 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 92 | 93 | ||
| 93 | 94 | ||
| 94 | Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, toTag, callIdHeader, expires); | 95 | Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, toTag, callIdHeader, expires); |
| 95 | - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); | 96 | + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); |
| 96 | if (www == null) { | 97 | if (www == null) { |
| 97 | - AuthorizationHeader authorizationHeader = sipLayer.getSipFactory().createHeaderFactory().createAuthorizationHeader("Digest"); | 98 | + AuthorizationHeader authorizationHeader = SipFactory.getInstance().createHeaderFactory().createAuthorizationHeader("Digest"); |
| 98 | String username = parentPlatform.getUsername(); | 99 | String username = parentPlatform.getUsername(); |
| 99 | if ( username == null || username == "" ) | 100 | if ( username == null || username == "" ) |
| 100 | { | 101 | { |
| @@ -147,7 +148,7 @@ public class SIPRequestHeaderPlarformProvider { | @@ -147,7 +148,7 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 147 | 148 | ||
| 148 | String RESPONSE = DigestUtils.md5DigestAsHex(reStr.toString().getBytes()); | 149 | String RESPONSE = DigestUtils.md5DigestAsHex(reStr.toString().getBytes()); |
| 149 | 150 | ||
| 150 | - AuthorizationHeader authorizationHeader = sipLayer.getSipFactory().createHeaderFactory().createAuthorizationHeader(scheme); | 151 | + AuthorizationHeader authorizationHeader = SipFactory.getInstance().createHeaderFactory().createAuthorizationHeader(scheme); |
| 151 | authorizationHeader.setUsername(parentPlatform.getDeviceGBId()); | 152 | authorizationHeader.setUsername(parentPlatform.getDeviceGBId()); |
| 152 | authorizationHeader.setRealm(realm); | 153 | authorizationHeader.setRealm(realm); |
| 153 | authorizationHeader.setNonce(nonce); | 154 | authorizationHeader.setNonce(nonce); |
| @@ -165,7 +166,7 @@ public class SIPRequestHeaderPlarformProvider { | @@ -165,7 +166,7 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 165 | } | 166 | } |
| 166 | 167 | ||
| 167 | public Request createMessageRequest(ParentPlatform parentPlatform, String content, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException { | 168 | public Request createMessageRequest(ParentPlatform parentPlatform, String content, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException { |
| 168 | - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId()); | 169 | + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId()); |
| 169 | return createMessageRequest(parentPlatform, content, sendRtpItem.getToTag(), SipUtils.getNewViaTag(), sendRtpItem.getFromTag(), callIdHeader); | 170 | return createMessageRequest(parentPlatform, content, sendRtpItem.getToTag(), SipUtils.getNewViaTag(), sendRtpItem.getFromTag(), callIdHeader); |
| 170 | } | 171 | } |
| 171 | 172 | ||
| @@ -178,36 +179,36 @@ public class SIPRequestHeaderPlarformProvider { | @@ -178,36 +179,36 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 178 | Request request = null; | 179 | Request request = null; |
| 179 | String serverAddress = parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort(); | 180 | String serverAddress = parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort(); |
| 180 | // sipuri | 181 | // sipuri |
| 181 | - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress); | 182 | + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress); |
| 182 | // via | 183 | // via |
| 183 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 184 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 184 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(), | 185 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(), |
| 185 | parentPlatform.getTransport(), viaTag); | 186 | parentPlatform.getTransport(), viaTag); |
| 186 | viaHeader.setRPort(); | 187 | viaHeader.setRPort(); |
| 187 | viaHeaders.add(viaHeader); | 188 | viaHeaders.add(viaHeader); |
| 188 | // from | 189 | // from |
| 189 | - // SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), parentPlatform.getDeviceIp() + ":" + parentPlatform.getDeviceIp()); | ||
| 190 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain()); | ||
| 191 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 192 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag); | 190 | + // SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), parentPlatform.getDeviceIp() + ":" + parentPlatform.getDeviceIp()); |
| 191 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain()); | ||
| 192 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 193 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); | ||
| 193 | // to | 194 | // to |
| 194 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress); | ||
| 195 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 196 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, toTag); | 195 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress); |
| 196 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 197 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag); | ||
| 197 | 198 | ||
| 198 | // Forwards | 199 | // Forwards |
| 199 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 200 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 200 | // ceq | 201 | // ceq |
| 201 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE); | ||
| 202 | - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipLayer.getSipFactory().createMessageFactory(); | 202 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE); |
| 203 | + MessageFactoryImpl messageFactory = (MessageFactoryImpl) SipFactory.getInstance().createMessageFactory(); | ||
| 203 | // 设置编码, 防止中文乱码 | 204 | // 设置编码, 防止中文乱码 |
| 204 | messageFactory.setDefaultContentEncodingCharset(parentPlatform.getCharacterSet()); | 205 | messageFactory.setDefaultContentEncodingCharset(parentPlatform.getCharacterSet()); |
| 205 | request = messageFactory.createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, | 206 | request = messageFactory.createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, |
| 206 | toHeader, viaHeaders, maxForwards); | 207 | toHeader, viaHeaders, maxForwards); |
| 207 | 208 | ||
| 208 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 209 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 209 | 210 | ||
| 210 | - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | 211 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); |
| 211 | request.setContent(content, contentTypeHeader); | 212 | request.setContent(content, contentTypeHeader); |
| 212 | return request; | 213 | return request; |
| 213 | } | 214 | } |
| @@ -215,54 +216,54 @@ public class SIPRequestHeaderPlarformProvider { | @@ -215,54 +216,54 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 215 | public SIPRequest createNotifyRequest(ParentPlatform parentPlatform, String content, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException { | 216 | public SIPRequest createNotifyRequest(ParentPlatform parentPlatform, String content, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException { |
| 216 | SIPRequest request = null; | 217 | SIPRequest request = null; |
| 217 | // sipuri | 218 | // sipuri |
| 218 | - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort()); | 219 | + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort()); |
| 219 | // via | 220 | // via |
| 220 | ArrayList<ViaHeader> viaHeaders = new ArrayList<>(); | 221 | ArrayList<ViaHeader> viaHeaders = new ArrayList<>(); |
| 221 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(), | 222 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(), |
| 222 | parentPlatform.getTransport(), SipUtils.getNewViaTag()); | 223 | parentPlatform.getTransport(), SipUtils.getNewViaTag()); |
| 223 | viaHeader.setRPort(); | 224 | viaHeader.setRPort(); |
| 224 | viaHeaders.add(viaHeader); | 225 | viaHeaders.add(viaHeader); |
| 225 | // from | 226 | // from |
| 226 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), | 227 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), |
| 227 | parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort()); | 228 | parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort()); |
| 228 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 229 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse().getToTag()); | 229 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); |
| 230 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse().getToTag()); | ||
| 230 | // to | 231 | // to |
| 231 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain()); | ||
| 232 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 233 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag()); | 232 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain()); |
| 233 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 234 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag()); | ||
| 234 | 235 | ||
| 235 | // Forwards | 236 | // Forwards |
| 236 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 237 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 237 | // ceq | 238 | // ceq |
| 238 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.NOTIFY); | ||
| 239 | - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipLayer.getSipFactory().createMessageFactory(); | 239 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.NOTIFY); |
| 240 | + MessageFactoryImpl messageFactory = (MessageFactoryImpl) SipFactory.getInstance().createMessageFactory(); | ||
| 240 | // 设置编码, 防止中文乱码 | 241 | // 设置编码, 防止中文乱码 |
| 241 | messageFactory.setDefaultContentEncodingCharset("gb2312"); | 242 | messageFactory.setDefaultContentEncodingCharset("gb2312"); |
| 242 | 243 | ||
| 243 | - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId()); | 244 | + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId()); |
| 244 | 245 | ||
| 245 | request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader, | 246 | request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader, |
| 246 | toHeader, viaHeaders, maxForwards); | 247 | toHeader, viaHeaders, maxForwards); |
| 247 | 248 | ||
| 248 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 249 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 249 | 250 | ||
| 250 | - EventHeader event = sipLayer.getSipFactory().createHeaderFactory().createEventHeader(subscribeInfo.getEventType()); | 251 | + EventHeader event = SipFactory.getInstance().createHeaderFactory().createEventHeader(subscribeInfo.getEventType()); |
| 251 | if (subscribeInfo.getEventId() != null) { | 252 | if (subscribeInfo.getEventId() != null) { |
| 252 | event.setEventId(subscribeInfo.getEventId()); | 253 | event.setEventId(subscribeInfo.getEventId()); |
| 253 | } | 254 | } |
| 254 | 255 | ||
| 255 | request.addHeader(event); | 256 | request.addHeader(event); |
| 256 | 257 | ||
| 257 | - SubscriptionStateHeader active = sipLayer.getSipFactory().createHeaderFactory().createSubscriptionStateHeader("active"); | 258 | + SubscriptionStateHeader active = SipFactory.getInstance().createHeaderFactory().createSubscriptionStateHeader("active"); |
| 258 | request.setHeader(active); | 259 | request.setHeader(active); |
| 259 | 260 | ||
| 260 | String sipAddress = parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort(); | 261 | String sipAddress = parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort(); |
| 261 | - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory() | 262 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory() |
| 262 | .createSipURI(parentPlatform.getDeviceGBId(), sipAddress)); | 263 | .createSipURI(parentPlatform.getDeviceGBId(), sipAddress)); |
| 263 | - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress)); | 264 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); |
| 264 | 265 | ||
| 265 | - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | 266 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); |
| 266 | request.setContent(content, contentTypeHeader); | 267 | request.setContent(content, contentTypeHeader); |
| 267 | return request; | 268 | return request; |
| 268 | } | 269 | } |
| @@ -275,42 +276,42 @@ public class SIPRequestHeaderPlarformProvider { | @@ -275,42 +276,42 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 275 | 276 | ||
| 276 | SIPRequest request = null; | 277 | SIPRequest request = null; |
| 277 | // sipuri | 278 | // sipuri |
| 278 | - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+ ":" + platform.getServerPort()); | 279 | + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+ ":" + platform.getServerPort()); |
| 279 | // via | 280 | // via |
| 280 | ArrayList<ViaHeader> viaHeaders = new ArrayList<>(); | 281 | ArrayList<ViaHeader> viaHeaders = new ArrayList<>(); |
| 281 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(platform.getDeviceIp(), platform.getDevicePort(), | 282 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(platform.getDeviceIp(), platform.getDevicePort(), |
| 282 | platform.getTransport(), SipUtils.getNewViaTag()); | 283 | platform.getTransport(), SipUtils.getNewViaTag()); |
| 283 | viaHeader.setRPort(); | 284 | viaHeader.setRPort(); |
| 284 | viaHeaders.add(viaHeader); | 285 | viaHeaders.add(viaHeader); |
| 285 | // from | 286 | // from |
| 286 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(platform.getDeviceGBId(), | 287 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getDeviceGBId(), |
| 287 | platform.getDeviceIp() + ":" + platform.getDevicePort()); | 288 | platform.getDeviceIp() + ":" + platform.getDevicePort()); |
| 288 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 289 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, sendRtpItem.getToTag()); | 289 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); |
| 290 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, sendRtpItem.getToTag()); | ||
| 290 | // to | 291 | // to |
| 291 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerGBDomain()); | ||
| 292 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 293 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, sendRtpItem.getFromTag()); | 292 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerGBDomain()); |
| 293 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 294 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, sendRtpItem.getFromTag()); | ||
| 294 | 295 | ||
| 295 | // Forwards | 296 | // Forwards |
| 296 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 297 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 297 | // ceq | 298 | // ceq |
| 298 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); | ||
| 299 | - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipLayer.getSipFactory().createMessageFactory(); | 299 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); |
| 300 | + MessageFactoryImpl messageFactory = (MessageFactoryImpl) SipFactory.getInstance().createMessageFactory(); | ||
| 300 | // 设置编码, 防止中文乱码 | 301 | // 设置编码, 防止中文乱码 |
| 301 | messageFactory.setDefaultContentEncodingCharset("gb2312"); | 302 | messageFactory.setDefaultContentEncodingCharset("gb2312"); |
| 302 | 303 | ||
| 303 | - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId()); | 304 | + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId()); |
| 304 | 305 | ||
| 305 | request = (SIPRequest) messageFactory.createRequest(requestURI, Request.BYE, callIdHeader, cSeqHeader, fromHeader, | 306 | request = (SIPRequest) messageFactory.createRequest(requestURI, Request.BYE, callIdHeader, cSeqHeader, fromHeader, |
| 306 | toHeader, viaHeaders, maxForwards); | 307 | toHeader, viaHeaders, maxForwards); |
| 307 | 308 | ||
| 308 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 309 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 309 | 310 | ||
| 310 | String sipAddress = platform.getDeviceIp() + ":" + platform.getDevicePort(); | 311 | String sipAddress = platform.getDeviceIp() + ":" + platform.getDevicePort(); |
| 311 | - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory() | 312 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory() |
| 312 | .createSipURI(platform.getDeviceGBId(), sipAddress)); | 313 | .createSipURI(platform.getDeviceGBId(), sipAddress)); |
| 313 | - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress)); | 314 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); |
| 314 | 315 | ||
| 315 | return request; | 316 | return request; |
| 316 | } | 317 | } |
| @@ -320,37 +321,37 @@ public class SIPRequestHeaderPlarformProvider { | @@ -320,37 +321,37 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 320 | //请求行 | 321 | //请求行 |
| 321 | String platformHostAddress = platform.getServerIP() + ":" + platform.getServerPort(); | 322 | String platformHostAddress = platform.getServerIP() + ":" + platform.getServerPort(); |
| 322 | String localHostAddress = sipLayer.getLocalIp(platform.getDeviceIp())+":"+ platform.getDevicePort(); | 323 | String localHostAddress = sipLayer.getLocalIp(platform.getDeviceIp())+":"+ platform.getDevicePort(); |
| 323 | - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, platformHostAddress); | 324 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, platformHostAddress); |
| 324 | //via | 325 | //via |
| 325 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 326 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 326 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getDevicePort(), platform.getTransport(), viaTag); | 327 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getDevicePort(), platform.getTransport(), viaTag); |
| 327 | viaHeader.setRPort(); | 328 | viaHeader.setRPort(); |
| 328 | viaHeaders.add(viaHeader); | 329 | viaHeaders.add(viaHeader); |
| 329 | 330 | ||
| 330 | //from | 331 | //from |
| 331 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(platform.getDeviceGBId(), sipConfig.getDomain()); | ||
| 332 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 333 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | 332 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getDeviceGBId(), sipConfig.getDomain()); |
| 333 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 334 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | ||
| 334 | //to | 335 | //to |
| 335 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, platformHostAddress); | ||
| 336 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 337 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,null); | 336 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, platformHostAddress); |
| 337 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 338 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null); | ||
| 338 | 339 | ||
| 339 | //Forwards | 340 | //Forwards |
| 340 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 341 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 341 | 342 | ||
| 342 | //ceq | 343 | //ceq |
| 343 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); | ||
| 344 | - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | 344 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); |
| 345 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | ||
| 345 | 346 | ||
| 346 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 347 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 347 | 348 | ||
| 348 | - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),localHostAddress)); | ||
| 349 | - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress)); | 349 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),localHostAddress)); |
| 350 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | ||
| 350 | // Subject | 351 | // Subject |
| 351 | - SubjectHeader subjectHeader = sipLayer.getSipFactory().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); | 352 | + SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); |
| 352 | request.addHeader(subjectHeader); | 353 | request.addHeader(subjectHeader); |
| 353 | - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); | 354 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); |
| 354 | request.setContent(content, contentTypeHeader); | 355 | request.setContent(content, contentTypeHeader); |
| 355 | return request; | 356 | return request; |
| 356 | } | 357 | } |
| @@ -358,35 +359,35 @@ public class SIPRequestHeaderPlarformProvider { | @@ -358,35 +359,35 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 358 | public Request createByteRequest(ParentPlatform platform, String channelId, SipTransactionInfo transactionInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException { | 359 | public Request createByteRequest(ParentPlatform platform, String channelId, SipTransactionInfo transactionInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException { |
| 359 | String deviceHostAddress = platform.getDeviceIp() + ":" + platform.getDevicePort(); | 360 | String deviceHostAddress = platform.getDeviceIp() + ":" + platform.getDevicePort(); |
| 360 | Request request = null; | 361 | Request request = null; |
| 361 | - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, deviceHostAddress); | 362 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, deviceHostAddress); |
| 362 | 363 | ||
| 363 | // via | 364 | // via |
| 364 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 365 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 365 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getDevicePort(), platform.getTransport(), SipUtils.getNewViaTag()); | 366 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getDevicePort(), platform.getTransport(), SipUtils.getNewViaTag()); |
| 366 | viaHeaders.add(viaHeader); | 367 | viaHeaders.add(viaHeader); |
| 367 | //from | 368 | //from |
| 368 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); | ||
| 369 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 370 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.isAsSender()?transactionInfo.getFromTag():transactionInfo.getToTag()); | 369 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); |
| 370 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 371 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.isAsSender()?transactionInfo.getFromTag():transactionInfo.getToTag()); | ||
| 371 | //to | 372 | //to |
| 372 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, deviceHostAddress); | ||
| 373 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 374 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,transactionInfo.isAsSender()?transactionInfo.getToTag():transactionInfo.getFromTag()); | 373 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, deviceHostAddress); |
| 374 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 375 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,transactionInfo.isAsSender()?transactionInfo.getToTag():transactionInfo.getFromTag()); | ||
| 375 | 376 | ||
| 376 | //Forwards | 377 | //Forwards |
| 377 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 378 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 378 | 379 | ||
| 379 | //ceq | 380 | //ceq |
| 380 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); | ||
| 381 | - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | ||
| 382 | - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | 381 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); |
| 382 | + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | ||
| 383 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | ||
| 383 | 384 | ||
| 384 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 385 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 385 | 386 | ||
| 386 | - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(platform.getDeviceIp())+":"+ platform.getDevicePort())); | ||
| 387 | - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress)); | 387 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(platform.getDeviceIp())+":"+ platform.getDevicePort())); |
| 388 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | ||
| 388 | 389 | ||
| 389 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 390 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 390 | 391 | ||
| 391 | return request; | 392 | return request; |
| 392 | } | 393 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
| @@ -16,6 +16,7 @@ import org.springframework.stereotype.Component; | @@ -16,6 +16,7 @@ import org.springframework.stereotype.Component; | ||
| 16 | import javax.sip.InvalidArgumentException; | 16 | import javax.sip.InvalidArgumentException; |
| 17 | import javax.sip.PeerUnavailableException; | 17 | import javax.sip.PeerUnavailableException; |
| 18 | import javax.sip.SipException; | 18 | import javax.sip.SipException; |
| 19 | +import javax.sip.SipFactory; | ||
| 19 | import javax.sip.address.Address; | 20 | import javax.sip.address.Address; |
| 20 | import javax.sip.address.SipURI; | 21 | import javax.sip.address.SipURI; |
| 21 | import javax.sip.header.*; | 22 | import javax.sip.header.*; |
| @@ -49,32 +50,32 @@ public class SIPRequestHeaderProvider { | @@ -49,32 +50,32 @@ public class SIPRequestHeaderProvider { | ||
| 49 | public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | 50 | public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { |
| 50 | Request request = null; | 51 | Request request = null; |
| 51 | // sipuri | 52 | // sipuri |
| 52 | - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | 53 | + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); |
| 53 | // via | 54 | // via |
| 54 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 55 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 55 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); | 56 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); |
| 56 | viaHeader.setRPort(); | 57 | viaHeader.setRPort(); |
| 57 | viaHeaders.add(viaHeader); | 58 | viaHeaders.add(viaHeader); |
| 58 | // from | 59 | // from |
| 59 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | ||
| 60 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 61 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag); | 60 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); |
| 61 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 62 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); | ||
| 62 | // to | 63 | // to |
| 63 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | ||
| 64 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 65 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, toTag); | 64 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); |
| 65 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 66 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag); | ||
| 66 | 67 | ||
| 67 | // Forwards | 68 | // Forwards |
| 68 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 69 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 69 | // ceq | 70 | // ceq |
| 70 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE); | 71 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE); |
| 71 | 72 | ||
| 72 | - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, | 73 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, |
| 73 | toHeader, viaHeaders, maxForwards); | 74 | toHeader, viaHeaders, maxForwards); |
| 74 | 75 | ||
| 75 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 76 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 76 | 77 | ||
| 77 | - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | 78 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); |
| 78 | request.setContent(content, contentTypeHeader); | 79 | request.setContent(content, contentTypeHeader); |
| 79 | return request; | 80 | return request; |
| 80 | } | 81 | } |
| @@ -82,39 +83,39 @@ public class SIPRequestHeaderProvider { | @@ -82,39 +83,39 @@ public class SIPRequestHeaderProvider { | ||
| 82 | public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | 83 | public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { |
| 83 | Request request = null; | 84 | Request request = null; |
| 84 | //请求行 | 85 | //请求行 |
| 85 | - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | 86 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); |
| 86 | //via | 87 | //via |
| 87 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 88 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 88 | - HeaderFactory headerFactory = sipLayer.getSipFactory().createHeaderFactory(); | ||
| 89 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); | 89 | + HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory(); |
| 90 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); | ||
| 90 | viaHeader.setRPort(); | 91 | viaHeader.setRPort(); |
| 91 | viaHeaders.add(viaHeader); | 92 | viaHeaders.add(viaHeader); |
| 92 | 93 | ||
| 93 | //from | 94 | //from |
| 94 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | ||
| 95 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 96 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | 95 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); |
| 96 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 97 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | ||
| 97 | //to | 98 | //to |
| 98 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | ||
| 99 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 100 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,null); | 99 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); |
| 100 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 101 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null); | ||
| 101 | 102 | ||
| 102 | //Forwards | 103 | //Forwards |
| 103 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 104 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 104 | 105 | ||
| 105 | //ceq | 106 | //ceq |
| 106 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); | ||
| 107 | - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | 107 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); |
| 108 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | ||
| 108 | 109 | ||
| 109 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 110 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 110 | 111 | ||
| 111 | - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | ||
| 112 | - // Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort())); | ||
| 113 | - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress)); | 112 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); |
| 113 | + // Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort())); | ||
| 114 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | ||
| 114 | // Subject | 115 | // Subject |
| 115 | - SubjectHeader subjectHeader = sipLayer.getSipFactory().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); | 116 | + SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); |
| 116 | request.addHeader(subjectHeader); | 117 | request.addHeader(subjectHeader); |
| 117 | - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); | 118 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); |
| 118 | request.setContent(content, contentTypeHeader); | 119 | request.setContent(content, contentTypeHeader); |
| 119 | return request; | 120 | return request; |
| 120 | } | 121 | } |
| @@ -122,69 +123,74 @@ public class SIPRequestHeaderProvider { | @@ -122,69 +123,74 @@ public class SIPRequestHeaderProvider { | ||
| 122 | public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException { | 123 | public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException { |
| 123 | Request request = null; | 124 | Request request = null; |
| 124 | //请求行 | 125 | //请求行 |
| 125 | - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | 126 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); |
| 126 | // via | 127 | // via |
| 127 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 128 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 128 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); | 129 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag); |
| 129 | viaHeader.setRPort(); | 130 | viaHeader.setRPort(); |
| 130 | viaHeaders.add(viaHeader); | 131 | viaHeaders.add(viaHeader); |
| 131 | //from | 132 | //from |
| 132 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | ||
| 133 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 134 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | 133 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); |
| 134 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 135 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | ||
| 135 | //to | 136 | //to |
| 136 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | ||
| 137 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 138 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,null); | 137 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); |
| 138 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 139 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null); | ||
| 139 | 140 | ||
| 140 | //Forwards | 141 | //Forwards |
| 141 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 142 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 142 | 143 | ||
| 143 | //ceq | 144 | //ceq |
| 144 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); | ||
| 145 | - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | 145 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE); |
| 146 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | ||
| 146 | 147 | ||
| 147 | - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | ||
| 148 | - // Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort())); | ||
| 149 | - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress)); | 148 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); |
| 149 | + // Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort())); | ||
| 150 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | ||
| 150 | 151 | ||
| 151 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 152 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 152 | 153 | ||
| 153 | // Subject | 154 | // Subject |
| 154 | - SubjectHeader subjectHeader = sipLayer.getSipFactory().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); | 155 | + SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0)); |
| 155 | request.addHeader(subjectHeader); | 156 | request.addHeader(subjectHeader); |
| 156 | 157 | ||
| 157 | - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); | 158 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); |
| 158 | request.setContent(content, contentTypeHeader); | 159 | request.setContent(content, contentTypeHeader); |
| 159 | return request; | 160 | return request; |
| 160 | } | 161 | } |
| 161 | 162 | ||
| 162 | public Request createByteRequest(Device device, String channelId, SipTransactionInfo transactionInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException { | 163 | public Request createByteRequest(Device device, String channelId, SipTransactionInfo transactionInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException { |
| 163 | Request request = null; | 164 | Request request = null; |
| 164 | - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | ||
| 165 | - | 165 | + //请求行 |
| 166 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | ||
| 166 | // via | 167 | // via |
| 167 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 168 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 168 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); | 169 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); |
| 169 | viaHeaders.add(viaHeader); | 170 | viaHeaders.add(viaHeader); |
| 170 | //from | 171 | //from |
| 171 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); | ||
| 172 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 173 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, !transactionInfo.isAsSender()? transactionInfo.getToTag():transactionInfo.getFromTag()); | 172 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); |
| 173 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 174 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag()); | ||
| 174 | //to | 175 | //to |
| 175 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId,device.getHostAddress()); | ||
| 176 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 177 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, !transactionInfo.isAsSender()? transactionInfo.getToTag(): transactionInfo.getFromTag()); | 176 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress()); |
| 177 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 178 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag()); | ||
| 178 | 179 | ||
| 179 | //Forwards | 180 | //Forwards |
| 180 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 181 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 181 | 182 | ||
| 182 | //ceq | 183 | //ceq |
| 183 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); | ||
| 184 | - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | ||
| 185 | - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | 184 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); |
| 185 | + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | ||
| 186 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | ||
| 187 | + | ||
| 188 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | ||
| 186 | 189 | ||
| 187 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 190 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); |
| 191 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | ||
| 192 | + | ||
| 193 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); | ||
| 188 | 194 | ||
| 189 | return request; | 195 | return request; |
| 190 | } | 196 | } |
| @@ -192,50 +198,50 @@ public class SIPRequestHeaderProvider { | @@ -192,50 +198,50 @@ public class SIPRequestHeaderProvider { | ||
| 192 | public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | 198 | public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { |
| 193 | Request request = null; | 199 | Request request = null; |
| 194 | // sipuri | 200 | // sipuri |
| 195 | - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | 201 | + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); |
| 196 | // via | 202 | // via |
| 197 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 203 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 198 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), | 204 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), |
| 199 | device.getTransport(), SipUtils.getNewViaTag()); | 205 | device.getTransport(), SipUtils.getNewViaTag()); |
| 200 | viaHeader.setRPort(); | 206 | viaHeader.setRPort(); |
| 201 | viaHeaders.add(viaHeader); | 207 | viaHeaders.add(viaHeader); |
| 202 | // from | 208 | // from |
| 203 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | ||
| 204 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 205 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag()); | 209 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); |
| 210 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 211 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag()); | ||
| 206 | // to | 212 | // to |
| 207 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | ||
| 208 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 209 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag()); | 213 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); |
| 214 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 215 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag()); | ||
| 210 | 216 | ||
| 211 | // Forwards | 217 | // Forwards |
| 212 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 218 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 213 | 219 | ||
| 214 | // ceq | 220 | // ceq |
| 215 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.SUBSCRIBE); | 221 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.SUBSCRIBE); |
| 216 | 222 | ||
| 217 | - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader, | 223 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader, |
| 218 | toHeader, viaHeaders, maxForwards); | 224 | toHeader, viaHeaders, maxForwards); |
| 219 | 225 | ||
| 220 | 226 | ||
| 221 | - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | ||
| 222 | - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress)); | 227 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); |
| 228 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | ||
| 223 | 229 | ||
| 224 | // Expires | 230 | // Expires |
| 225 | - ExpiresHeader expireHeader = sipLayer.getSipFactory().createHeaderFactory().createExpiresHeader(expires); | 231 | + ExpiresHeader expireHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(expires); |
| 226 | request.addHeader(expireHeader); | 232 | request.addHeader(expireHeader); |
| 227 | 233 | ||
| 228 | // Event | 234 | // Event |
| 229 | - EventHeader eventHeader = sipLayer.getSipFactory().createHeaderFactory().createEventHeader(event); | 235 | + EventHeader eventHeader = SipFactory.getInstance().createHeaderFactory().createEventHeader(event); |
| 230 | 236 | ||
| 231 | int random = (int) Math.floor(Math.random() * 10000); | 237 | int random = (int) Math.floor(Math.random() * 10000); |
| 232 | eventHeader.setEventId(random + ""); | 238 | eventHeader.setEventId(random + ""); |
| 233 | request.addHeader(eventHeader); | 239 | request.addHeader(eventHeader); |
| 234 | 240 | ||
| 235 | - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | 241 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); |
| 236 | request.setContent(content, contentTypeHeader); | 242 | request.setContent(content, contentTypeHeader); |
| 237 | 243 | ||
| 238 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 244 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 239 | 245 | ||
| 240 | return request; | 246 | return request; |
| 241 | } | 247 | } |
| @@ -247,37 +253,37 @@ public class SIPRequestHeaderProvider { | @@ -247,37 +253,37 @@ public class SIPRequestHeaderProvider { | ||
| 247 | } | 253 | } |
| 248 | SIPRequest request = null; | 254 | SIPRequest request = null; |
| 249 | //请求行 | 255 | //请求行 |
| 250 | - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | 256 | + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); |
| 251 | // via | 257 | // via |
| 252 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 258 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 253 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); | 259 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); |
| 254 | viaHeaders.add(viaHeader); | 260 | viaHeaders.add(viaHeader); |
| 255 | //from | 261 | //from |
| 256 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); | ||
| 257 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 258 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag()); | 262 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); |
| 263 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 264 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag()); | ||
| 259 | //to | 265 | //to |
| 260 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId,device.getHostAddress()); | ||
| 261 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 262 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag()); | 266 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress()); |
| 267 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 268 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag()); | ||
| 263 | 269 | ||
| 264 | //Forwards | 270 | //Forwards |
| 265 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 271 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 266 | 272 | ||
| 267 | //ceq | 273 | //ceq |
| 268 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INFO); | ||
| 269 | - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | ||
| 270 | - request = (SIPRequest)sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | 274 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INFO); |
| 275 | + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId()); | ||
| 276 | + request = (SIPRequest)SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | ||
| 271 | 277 | ||
| 272 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 278 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 273 | 279 | ||
| 274 | - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); | ||
| 275 | - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress)); | 280 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort())); |
| 281 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | ||
| 276 | 282 | ||
| 277 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 283 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 278 | 284 | ||
| 279 | if (content != null) { | 285 | if (content != null) { |
| 280 | - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", | 286 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", |
| 281 | "MANSRTSP"); | 287 | "MANSRTSP"); |
| 282 | request.setContent(content, contentTypeHeader); | 288 | request.setContent(content, contentTypeHeader); |
| 283 | } | 289 | } |
| @@ -289,56 +295,55 @@ public class SIPRequestHeaderProvider { | @@ -289,56 +295,55 @@ public class SIPRequestHeaderProvider { | ||
| 289 | 295 | ||
| 290 | // via | 296 | // via |
| 291 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 297 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 292 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(localIp, sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag()); | 298 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(localIp, sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag()); |
| 293 | viaHeaders.add(viaHeader); | 299 | viaHeaders.add(viaHeader); |
| 294 | 300 | ||
| 295 | //Forwards | 301 | //Forwards |
| 296 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 302 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 297 | 303 | ||
| 298 | //ceq | 304 | //ceq |
| 299 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK); | 305 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK); |
| 300 | 306 | ||
| 301 | - Request request = sipLayer.getSipFactory().createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards); | 307 | + Request request = SipFactory.getInstance().createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards); |
| 302 | 308 | ||
| 303 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 309 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 304 | 310 | ||
| 305 | - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), localIp + ":"+sipConfig.getPort())); | ||
| 306 | - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress)); | 311 | + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), localIp + ":"+sipConfig.getPort())); |
| 312 | + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); | ||
| 307 | 313 | ||
| 308 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 314 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 309 | 315 | ||
| 310 | return request; | 316 | return request; |
| 311 | } | 317 | } |
| 312 | - | ||
| 313 | public Request createBroadcastMessageRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | 318 | public Request createBroadcastMessageRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { |
| 314 | Request request = null; | 319 | Request request = null; |
| 315 | // sipuri | 320 | // sipuri |
| 316 | - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | 321 | + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); |
| 317 | // via | 322 | // via |
| 318 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 323 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 319 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), viaTag); | 324 | + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), viaTag); |
| 320 | viaHeader.setRPort(); | 325 | viaHeader.setRPort(); |
| 321 | viaHeaders.add(viaHeader); | 326 | viaHeaders.add(viaHeader); |
| 322 | // from | 327 | // from |
| 323 | - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); | ||
| 324 | - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); | ||
| 325 | - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag); | 328 | + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); |
| 329 | + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); | ||
| 330 | + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); | ||
| 326 | // to | 331 | // to |
| 327 | - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress()); | ||
| 328 | - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | ||
| 329 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, toTag); | 332 | + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); |
| 333 | + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); | ||
| 334 | + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag); | ||
| 330 | 335 | ||
| 331 | // Forwards | 336 | // Forwards |
| 332 | - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 337 | + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| 333 | // ceq | 338 | // ceq |
| 334 | - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE); | 339 | + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE); |
| 335 | 340 | ||
| 336 | - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | 341 | + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); |
| 337 | 342 | ||
| 338 | - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, | 343 | + request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, |
| 339 | toHeader, viaHeaders, maxForwards, contentTypeHeader, content); | 344 | toHeader, viaHeaders, maxForwards, contentTypeHeader, content); |
| 340 | 345 | ||
| 341 | - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); | 346 | + request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); |
| 342 | 347 | ||
| 343 | return request; | 348 | return request; |
| 344 | } | 349 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; |
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSONObject; | 3 | import com.alibaba.fastjson2.JSONObject; |
| 4 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 4 | import com.genersoft.iot.vmp.common.StreamInfo; | 5 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 5 | import com.genersoft.iot.vmp.conf.SipConfig; | 6 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 6 | import com.genersoft.iot.vmp.conf.UserSetting; | 7 | import com.genersoft.iot.vmp.conf.UserSetting; |
| @@ -36,6 +37,7 @@ import org.springframework.util.ObjectUtils; | @@ -36,6 +37,7 @@ import org.springframework.util.ObjectUtils; | ||
| 36 | import javax.sip.InvalidArgumentException; | 37 | import javax.sip.InvalidArgumentException; |
| 37 | import javax.sip.ResponseEvent; | 38 | import javax.sip.ResponseEvent; |
| 38 | import javax.sip.SipException; | 39 | import javax.sip.SipException; |
| 40 | +import javax.sip.SipFactory; | ||
| 39 | import javax.sip.header.CallIdHeader; | 41 | import javax.sip.header.CallIdHeader; |
| 40 | import javax.sip.message.Request; | 42 | import javax.sip.message.Request; |
| 41 | import java.text.ParseException; | 43 | import java.text.ParseException; |
| @@ -358,7 +360,7 @@ public class SIPCommander implements ISIPCommander { | @@ -358,7 +360,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 358 | // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 | 360 | // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 |
| 359 | ResponseEvent responseEvent = (ResponseEvent) e.event; | 361 | ResponseEvent responseEvent = (ResponseEvent) e.event; |
| 360 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); | 362 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); |
| 361 | - streamSession.put(device.getDeviceId(), channelId, "play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.play); | 363 | + streamSession.put(device.getDeviceId(), channelId, "play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAY); |
| 362 | okEvent.response(e); | 364 | okEvent.response(e); |
| 363 | }); | 365 | }); |
| 364 | } | 366 | } |
| @@ -373,11 +375,11 @@ public class SIPCommander implements ISIPCommander { | @@ -373,11 +375,11 @@ public class SIPCommander implements ISIPCommander { | ||
| 373 | */ | 375 | */ |
| 374 | @Override | 376 | @Override |
| 375 | public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | 377 | public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 376 | - String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, | 378 | + String startTime, String endTime, ZlmHttpHookSubscribe.Event hookEvent, |
| 377 | SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | 379 | SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { |
| 378 | 380 | ||
| 379 | 381 | ||
| 380 | - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getSdpIp(), mediaServerItem.getIp(), ssrcInfo.getPort()); | 382 | + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); |
| 381 | String sdpIp; | 383 | String sdpIp; |
| 382 | if (!ObjectUtils.isEmpty(device.getSdpIp())) { | 384 | if (!ObjectUtils.isEmpty(device.getSdpIp())) { |
| 383 | sdpIp = device.getSdpIp(); | 385 | sdpIp = device.getSdpIp(); |
| @@ -450,8 +452,7 @@ public class SIPCommander implements ISIPCommander { | @@ -450,8 +452,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 450 | // 添加订阅 | 452 | // 添加订阅 |
| 451 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { | 453 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { |
| 452 | if (hookEvent != null) { | 454 | if (hookEvent != null) { |
| 453 | - InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream()); | ||
| 454 | - hookEvent.call(inviteStreamInfo); | 455 | + hookEvent.response(mediaServerItemInUse, json); |
| 455 | } | 456 | } |
| 456 | subscribe.removeSubscribe(hookSubscribe); | 457 | subscribe.removeSubscribe(hookSubscribe); |
| 457 | }); | 458 | }); |
| @@ -460,12 +461,9 @@ public class SIPCommander implements ISIPCommander { | @@ -460,12 +461,9 @@ public class SIPCommander implements ISIPCommander { | ||
| 460 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { | 461 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { |
| 461 | ResponseEvent responseEvent = (ResponseEvent) event.event; | 462 | ResponseEvent responseEvent = (ResponseEvent) event.event; |
| 462 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); | 463 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); |
| 463 | - streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.playback); | 464 | + streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAYBACK); |
| 464 | okEvent.response(event); | 465 | okEvent.response(event); |
| 465 | }); | 466 | }); |
| 466 | - if (inviteStreamCallback != null) { | ||
| 467 | - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream())); | ||
| 468 | - } | ||
| 469 | } | 467 | } |
| 470 | 468 | ||
| 471 | /** | 469 | /** |
| @@ -480,10 +478,10 @@ public class SIPCommander implements ISIPCommander { | @@ -480,10 +478,10 @@ public class SIPCommander implements ISIPCommander { | ||
| 480 | @Override | 478 | @Override |
| 481 | public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | 479 | public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 482 | String startTime, String endTime, int downloadSpeed, | 480 | String startTime, String endTime, int downloadSpeed, |
| 483 | - InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, | 481 | + ZlmHttpHookSubscribe.Event hookEvent, |
| 484 | SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | 482 | SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { |
| 485 | 483 | ||
| 486 | - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getSdpIp(), mediaServerItem.getIp(), ssrcInfo.getPort()); | 484 | + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); |
| 487 | String sdpIp; | 485 | String sdpIp; |
| 488 | if (!ObjectUtils.isEmpty(device.getSdpIp())) { | 486 | if (!ObjectUtils.isEmpty(device.getSdpIp())) { |
| 489 | sdpIp = device.getSdpIp(); | 487 | sdpIp = device.getSdpIp(); |
| @@ -551,13 +549,13 @@ public class SIPCommander implements ISIPCommander { | @@ -551,13 +549,13 @@ public class SIPCommander implements ISIPCommander { | ||
| 551 | 549 | ||
| 552 | content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc | 550 | content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc |
| 553 | logger.debug("此时请求下载信令的ssrc===>{}",ssrcInfo.getSsrc()); | 551 | logger.debug("此时请求下载信令的ssrc===>{}",ssrcInfo.getSsrc()); |
| 554 | - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId()); | 552 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); |
| 555 | // 添加订阅 | 553 | // 添加订阅 |
| 556 | CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport()); | 554 | CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport()); |
| 557 | - String callId=newCallIdHeader.getCallId(); | 555 | + String callId= newCallIdHeader.getCallId(); |
| 558 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { | 556 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { |
| 559 | logger.debug("sipc 添加订阅===callId {}",callId); | 557 | logger.debug("sipc 添加订阅===callId {}",callId); |
| 560 | - hookEvent.call(new InviteStreamInfo(mediaServerItem, json,callId, "rtp", ssrcInfo.getStream())); | 558 | + hookEvent.response(mediaServerItemInUse, json); |
| 561 | subscribe.removeSubscribe(hookSubscribe); | 559 | subscribe.removeSubscribe(hookSubscribe); |
| 562 | hookSubscribe.getContent().put("regist", false); | 560 | hookSubscribe.getContent().put("regist", false); |
| 563 | hookSubscribe.getContent().put("schema", "rtsp"); | 561 | hookSubscribe.getContent().put("schema", "rtsp"); |
| @@ -566,7 +564,7 @@ public class SIPCommander implements ISIPCommander { | @@ -566,7 +564,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 566 | (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> { | 564 | (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> { |
| 567 | logger.info("[录像]下载结束, 发送BYE"); | 565 | logger.info("[录像]下载结束, 发送BYE"); |
| 568 | try { | 566 | try { |
| 569 | - streamByeCmd(device, channelId, ssrcInfo.getStream(),callId); | 567 | + streamByeCmd(device, channelId, ssrcInfo.getStream(), callId); |
| 570 | } catch (InvalidArgumentException | ParseException | SipException | | 568 | } catch (InvalidArgumentException | ParseException | SipException | |
| 571 | SsrcTransactionNotFoundException e) { | 569 | SsrcTransactionNotFoundException e) { |
| 572 | logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage()); | 570 | logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage()); |
| @@ -575,9 +573,6 @@ public class SIPCommander implements ISIPCommander { | @@ -575,9 +573,6 @@ public class SIPCommander implements ISIPCommander { | ||
| 575 | }); | 573 | }); |
| 576 | 574 | ||
| 577 | Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc()); | 575 | Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc()); |
| 578 | - if (inviteStreamCallback != null) { | ||
| 579 | - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,callId, "rtp", ssrcInfo.getStream())); | ||
| 580 | - } | ||
| 581 | 576 | ||
| 582 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { | 577 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { |
| 583 | ResponseEvent responseEvent = (ResponseEvent) event.event; | 578 | ResponseEvent responseEvent = (ResponseEvent) event.event; |
| @@ -588,9 +583,7 @@ public class SIPCommander implements ISIPCommander { | @@ -588,9 +583,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 588 | if (ssrcIndex >= 0) { | 583 | if (ssrcIndex >= 0) { |
| 589 | ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | 584 | ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
| 590 | } | 585 | } |
| 591 | - logger.debug("接收到的下载响应ssrc====>{}",ssrcInfo.getSsrc()); | ||
| 592 | - logger.debug("接收到的下载响应ssrc====>{}",ssrc); | ||
| 593 | - streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download); | 586 | + streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, InviteSessionType.DOWNLOAD); |
| 594 | okEvent.response(event); | 587 | okEvent.response(event); |
| 595 | }); | 588 | }); |
| 596 | } | 589 | } |
| @@ -654,7 +647,7 @@ public class SIPCommander implements ISIPCommander { | @@ -654,7 +647,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 654 | // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 | 647 | // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 |
| 655 | ResponseEvent responseEvent = (ResponseEvent) e.event; | 648 | ResponseEvent responseEvent = (ResponseEvent) e.event; |
| 656 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); | 649 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); |
| 657 | - streamSession.put(device.getDeviceId(), channelId, "talk", stream, sendRtpItem.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.talk); | 650 | + streamSession.put(device.getDeviceId(), channelId, "talk", stream, sendRtpItem.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.TALK); |
| 658 | okEvent.response(e); | 651 | okEvent.response(e); |
| 659 | }); | 652 | }); |
| 660 | } | 653 | } |
| @@ -1247,7 +1240,7 @@ public class SIPCommander implements ISIPCommander { | @@ -1247,7 +1240,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 1247 | CallIdHeader callIdHeader; | 1240 | CallIdHeader callIdHeader; |
| 1248 | 1241 | ||
| 1249 | if (requestOld != null) { | 1242 | if (requestOld != null) { |
| 1250 | - callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId()); | 1243 | + callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId()); |
| 1251 | } else { | 1244 | } else { |
| 1252 | callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()); | 1245 | callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()); |
| 1253 | } | 1246 | } |
| @@ -1322,7 +1315,7 @@ public class SIPCommander implements ISIPCommander { | @@ -1322,7 +1315,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 1322 | CallIdHeader callIdHeader; | 1315 | CallIdHeader callIdHeader; |
| 1323 | 1316 | ||
| 1324 | if (requestOld != null) { | 1317 | if (requestOld != null) { |
| 1325 | - callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId()); | 1318 | + callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId()); |
| 1326 | } else { | 1319 | } else { |
| 1327 | callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()); | 1320 | callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()); |
| 1328 | } | 1321 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
| @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; | ||
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | import com.alibaba.fastjson2.JSONObject; | 4 | import com.alibaba.fastjson2.JSONObject; |
| 5 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 5 | import com.genersoft.iot.vmp.conf.DynamicTask; | 6 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 6 | import com.genersoft.iot.vmp.conf.UserSetting; | 7 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 7 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 8 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| @@ -39,6 +40,7 @@ import org.springframework.util.ObjectUtils; | @@ -39,6 +40,7 @@ import org.springframework.util.ObjectUtils; | ||
| 39 | import javax.sip.InvalidArgumentException; | 40 | import javax.sip.InvalidArgumentException; |
| 40 | import javax.sip.ResponseEvent; | 41 | import javax.sip.ResponseEvent; |
| 41 | import javax.sip.SipException; | 42 | import javax.sip.SipException; |
| 43 | +import javax.sip.SipFactory; | ||
| 42 | import javax.sip.header.CallIdHeader; | 44 | import javax.sip.header.CallIdHeader; |
| 43 | import javax.sip.header.WWWAuthenticateHeader; | 45 | import javax.sip.header.WWWAuthenticateHeader; |
| 44 | import javax.sip.message.Request; | 46 | import javax.sip.message.Request; |
| @@ -518,7 +520,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -518,7 +520,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 518 | private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent, | 520 | private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent, |
| 519 | SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent ) | 521 | SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent ) |
| 520 | throws SipException, ParseException, InvalidArgumentException { | 522 | throws SipException, ParseException, InvalidArgumentException { |
| 521 | - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipLayer.getSipFactory().createMessageFactory(); | 523 | + MessageFactoryImpl messageFactory = (MessageFactoryImpl) SipFactory.getInstance().createMessageFactory(); |
| 522 | String characterSet = parentPlatform.getCharacterSet(); | 524 | String characterSet = parentPlatform.getCharacterSet(); |
| 523 | // 设置编码, 防止中文乱码 | 525 | // 设置编码, 防止中文乱码 |
| 524 | messageFactory.setDefaultContentEncodingCharset(characterSet); | 526 | messageFactory.setDefaultContentEncodingCharset(characterSet); |
| @@ -854,7 +856,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -854,7 +856,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 854 | }), e -> { | 856 | }), e -> { |
| 855 | ResponseEvent responseEvent = (ResponseEvent) e.event; | 857 | ResponseEvent responseEvent = (ResponseEvent) e.event; |
| 856 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); | 858 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); |
| 857 | - streamSession.put(platform.getServerGBId(), channelId, callIdHeader.getCallId(), stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.broadcast); | 859 | + streamSession.put(platform.getServerGBId(), channelId, callIdHeader.getCallId(), stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.BROADCAST); |
| 858 | okEvent.response(e); | 860 | okEvent.response(e); |
| 859 | }); | 861 | }); |
| 860 | } | 862 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.common.StreamInfo; | 3 | +import com.genersoft.iot.vmp.common.InviteInfo; |
| 4 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 4 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 5 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 5 | import com.genersoft.iot.vmp.gb28181.bean.*; | 6 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 6 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | 7 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; |
| 8 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | ||
| 7 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 9 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 8 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 9 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | 11 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| @@ -13,6 +15,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP | @@ -13,6 +15,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP | ||
| 13 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 15 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 14 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 16 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 15 | import com.genersoft.iot.vmp.service.IDeviceService; | 17 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 18 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | ||
| 16 | import com.genersoft.iot.vmp.service.IMediaServerService; | 19 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 17 | import com.genersoft.iot.vmp.service.IPlayService; | 20 | import com.genersoft.iot.vmp.service.IPlayService; |
| 18 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | 21 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| @@ -29,6 +32,7 @@ import javax.sip.InvalidArgumentException; | @@ -29,6 +32,7 @@ import javax.sip.InvalidArgumentException; | ||
| 29 | import javax.sip.RequestEvent; | 32 | import javax.sip.RequestEvent; |
| 30 | import javax.sip.SipException; | 33 | import javax.sip.SipException; |
| 31 | import javax.sip.address.SipURI; | 34 | import javax.sip.address.SipURI; |
| 35 | +import javax.sip.header.CallIdHeader; | ||
| 32 | import javax.sip.header.FromHeader; | 36 | import javax.sip.header.FromHeader; |
| 33 | import javax.sip.header.HeaderAddress; | 37 | import javax.sip.header.HeaderAddress; |
| 34 | import javax.sip.header.ToHeader; | 38 | import javax.sip.header.ToHeader; |
| @@ -57,6 +61,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -57,6 +61,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 57 | private IRedisCatchStorage redisCatchStorage; | 61 | private IRedisCatchStorage redisCatchStorage; |
| 58 | 62 | ||
| 59 | @Autowired | 63 | @Autowired |
| 64 | + private IInviteStreamService inviteStreamService; | ||
| 65 | + | ||
| 66 | + @Autowired | ||
| 60 | private IDeviceService deviceService; | 67 | private IDeviceService deviceService; |
| 61 | 68 | ||
| 62 | @Autowired | 69 | @Autowired |
| @@ -69,6 +76,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -69,6 +76,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 69 | private ZLMRTPServerFactory zlmrtpServerFactory; | 76 | private ZLMRTPServerFactory zlmrtpServerFactory; |
| 70 | 77 | ||
| 71 | @Autowired | 78 | @Autowired |
| 79 | + private SSRCFactory ssrcFactory; | ||
| 80 | + | ||
| 81 | + @Autowired | ||
| 72 | private IMediaServerService mediaServerService; | 82 | private IMediaServerService mediaServerService; |
| 73 | 83 | ||
| 74 | @Autowired | 84 | @Autowired |
| @@ -100,92 +110,89 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -100,92 +110,89 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 100 | } catch (SipException | InvalidArgumentException | ParseException e) { | 110 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| 101 | logger.error("[回复BYE信息失败],{}", e.getMessage()); | 111 | logger.error("[回复BYE信息失败],{}", e.getMessage()); |
| 102 | } | 112 | } |
| 103 | - | ||
| 104 | - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, request.getCallIdHeader().getCallId()); | ||
| 105 | - | ||
| 106 | - if (sendRtpItem != null){ | ||
| 107 | - logger.info("[收到bye] {}/{}", sendRtpItem.getPlatformId(), sendRtpItem.getChannelId()); | ||
| 108 | - String streamId = sendRtpItem.getStream(); | ||
| 109 | - MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | ||
| 110 | - if (mediaServerItem == null) { | ||
| 111 | - return; | ||
| 112 | - } | ||
| 113 | - | ||
| 114 | - Boolean ready = zlmrtpServerFactory.isStreamReady(mediaServerItem, sendRtpItem.getApp(), streamId); | ||
| 115 | - if (!ready) { | ||
| 116 | - logger.info("[收到bye] 发现流{}/{}已经结束,不需处理", sendRtpItem.getApp(), sendRtpItem.getStream()); | ||
| 117 | - return; | ||
| 118 | - } | ||
| 119 | - Map<String, Object> param = new HashMap<>(); | ||
| 120 | - param.put("vhost","__defaultVhost__"); | ||
| 121 | - param.put("app",sendRtpItem.getApp()); | ||
| 122 | - param.put("stream",streamId); | ||
| 123 | - param.put("ssrc",sendRtpItem.getSsrc()); | ||
| 124 | - logger.info("[收到bye] 停止推流:{}", streamId); | ||
| 125 | - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | ||
| 126 | - redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), request.getCallIdHeader().getCallId(), null); | ||
| 127 | - zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); | ||
| 128 | - | ||
| 129 | - int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); | ||
| 130 | - if (totalReaderCount <= 0) { | ||
| 131 | - logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); | ||
| 132 | - if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { | ||
| 133 | - Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); | ||
| 134 | - if (device == null) { | ||
| 135 | - logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId); | 113 | + CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); |
| 114 | + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); | ||
| 115 | + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); | ||
| 116 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); | ||
| 117 | + logger.info("[收到bye] {}/{}", platformGbId, channelId); | ||
| 118 | + if (sendRtpItem != null){ | ||
| 119 | + String streamId = sendRtpItem.getStream(); | ||
| 120 | + Map<String, Object> param = new HashMap<>(); | ||
| 121 | + param.put("vhost","__defaultVhost__"); | ||
| 122 | + param.put("app",sendRtpItem.getApp()); | ||
| 123 | + param.put("stream",streamId); | ||
| 124 | + param.put("ssrc",sendRtpItem.getSsrc()); | ||
| 125 | + logger.info("[收到bye] 停止向上级推流:{}", streamId); | ||
| 126 | + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | ||
| 127 | + redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null); | ||
| 128 | + ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); | ||
| 129 | + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); | ||
| 130 | + int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); | ||
| 131 | + if (totalReaderCount <= 0) { | ||
| 132 | + logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); | ||
| 133 | + if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { | ||
| 134 | + Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); | ||
| 135 | + if (device == null) { | ||
| 136 | + logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId); | ||
| 137 | + } | ||
| 138 | + try { | ||
| 139 | + logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), channelId); | ||
| 140 | + cmder.streamByeCmd(device, channelId, streamId, null); | ||
| 141 | + } catch (InvalidArgumentException | ParseException | SipException | | ||
| 142 | + SsrcTransactionNotFoundException e) { | ||
| 143 | + logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage()); | ||
| 144 | + } | ||
| 136 | } | 145 | } |
| 137 | - try { | ||
| 138 | - logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | ||
| 139 | - cmder.streamByeCmd(device, sendRtpItem.getChannelId(), streamId, null); | ||
| 140 | - } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | ||
| 141 | - logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage()); | 146 | + if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { |
| 147 | + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, | ||
| 148 | + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), | ||
| 149 | + sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId()); | ||
| 150 | + redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); | ||
| 142 | } | 151 | } |
| 143 | } | 152 | } |
| 144 | - | ||
| 145 | - if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { | ||
| 146 | - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, | ||
| 147 | - sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), | ||
| 148 | - sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId()); | ||
| 149 | - redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); | ||
| 150 | - } | ||
| 151 | } | 153 | } |
| 154 | + // 可能是设备主动停止 | ||
| 155 | + Device device = storager.queryVideoDeviceByChannelId(platformGbId); | ||
| 156 | + if (device != null) { | ||
| 157 | + storager.stopPlay(device.getDeviceId(), channelId); | ||
| 158 | + SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); | ||
| 159 | + if (ssrcTransactionForPlay != null){ | ||
| 160 | + if (ssrcTransactionForPlay.getCallId().equals(callIdHeader.getCallId())){ | ||
| 161 | + // 释放ssrc | ||
| 162 | + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId()); | ||
| 163 | + if (mediaServerItem != null) { | ||
| 164 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc()); | ||
| 165 | + } | ||
| 166 | + streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream()); | ||
| 167 | + } | ||
| 168 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); | ||
| 152 | 169 | ||
| 153 | - playService.stopAudioBroadcast(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | ||
| 154 | - } | ||
| 155 | - | ||
| 156 | - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); | ||
| 157 | - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); | ||
| 158 | - | ||
| 159 | - // 可能是设备主动停止 | ||
| 160 | - Device device = storager.queryVideoDeviceByChannelId(platformGbId); | ||
| 161 | - if (device != null) { | ||
| 162 | - storager.stopPlay(device.getDeviceId(), channelId); | ||
| 163 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); | ||
| 164 | - if (streamInfo != null) { | ||
| 165 | - redisCatchStorage.stopPlay(streamInfo); | ||
| 166 | - mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream()); | ||
| 167 | - } | ||
| 168 | - SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); | ||
| 169 | - if (ssrcTransactionForPlay != null){ | ||
| 170 | - if (ssrcTransactionForPlay.getCallId().equals(request.getCallIdHeader().getCallId())){ | 170 | + if (inviteInfo != null) { |
| 171 | + inviteStreamService.removeInviteInfo(inviteInfo); | ||
| 172 | + if (inviteInfo.getStreamInfo() != null) { | ||
| 173 | + mediaServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServerId(), inviteInfo.getStream()); | ||
| 174 | + } | ||
| 175 | + } | ||
| 176 | + } | ||
| 177 | + SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null); | ||
| 178 | + if (ssrcTransactionForPlayBack != null) { | ||
| 171 | // 释放ssrc | 179 | // 释放ssrc |
| 172 | - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId()); | 180 | + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId()); |
| 173 | if (mediaServerItem != null) { | 181 | if (mediaServerItem != null) { |
| 174 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc()); | 182 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc()); |
| 183 | + } | ||
| 184 | + streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream()); | ||
| 185 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAYBACK, device.getDeviceId(), channelId); | ||
| 186 | + | ||
| 187 | + if (inviteInfo != null) { | ||
| 188 | + inviteStreamService.removeInviteInfo(inviteInfo); | ||
| 189 | + if (inviteInfo.getStreamInfo() != null) { | ||
| 190 | + mediaServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServerId(), inviteInfo.getStream()); | ||
| 191 | + } | ||
| 175 | } | 192 | } |
| 176 | - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream()); | ||
| 177 | - } | ||
| 178 | - } | ||
| 179 | - SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, request.getCallIdHeader().getCallId(), null); | ||
| 180 | - if (ssrcTransactionForPlayBack != null) { | ||
| 181 | - // 释放ssrc | ||
| 182 | - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId()); | ||
| 183 | - if (mediaServerItem != null) { | ||
| 184 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc()); | ||
| 185 | } | 193 | } |
| 186 | - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream()); | ||
| 187 | } | 194 | } |
| 188 | - } | 195 | + |
| 189 | SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, request.getCallIdHeader().getCallId(), null); | 196 | SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, request.getCallIdHeader().getCallId(), null); |
| 190 | if (ssrcTransaction != null) { | 197 | if (ssrcTransaction != null) { |
| 191 | // 释放ssrc | 198 | // 释放ssrc |
| @@ -203,7 +210,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -203,7 +210,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 203 | // break; | 210 | // break; |
| 204 | // case download: | 211 | // case download: |
| 205 | // break; | 212 | // break; |
| 206 | - case broadcast: | 213 | + case BROADCAST: |
| 207 | String channelId1 = ssrcTransaction.getChannelId(); | 214 | String channelId1 = ssrcTransaction.getChannelId(); |
| 208 | 215 | ||
| 209 | Device deviceFromTransaction = storager.queryVideoDevice(ssrcTransaction.getDeviceId()); | 216 | Device deviceFromTransaction = storager.queryVideoDevice(ssrcTransaction.getDeviceId()); |
| @@ -255,7 +262,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -255,7 +262,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 255 | List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(null, channelId1, null, null); | 262 | List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(null, channelId1, null, null); |
| 256 | if (ssrcTransactions.size() > 0) { | 263 | if (ssrcTransactions.size() > 0) { |
| 257 | for (SsrcTransaction transaction : ssrcTransactions) { | 264 | for (SsrcTransaction transaction : ssrcTransactions) { |
| 258 | - if (transaction.getType().equals(VideoStreamSessionManager.SessionType.broadcast)) { | 265 | + if (transaction.getType().equals(InviteSessionType.BROADCAST)) { |
| 259 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(transaction.getDeviceId()); | 266 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(transaction.getDeviceId()); |
| 260 | if (parentPlatform != null) { | 267 | if (parentPlatform != null) { |
| 261 | try { | 268 | try { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | ||
| 3 | -import com.alibaba.fastjson2.JSONObject; | ||
| 4 | import com.genersoft.iot.vmp.common.VideoManagerConstants; | 3 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 4 | +import com.genersoft.iot.vmp.common.StreamInfo; | ||
| 5 | import com.genersoft.iot.vmp.conf.DynamicTask; | 5 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 6 | import com.genersoft.iot.vmp.conf.SipConfig; | 6 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 7 | import com.genersoft.iot.vmp.conf.UserSetting; | 7 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 8 | import com.genersoft.iot.vmp.gb28181.bean.*; | 8 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 9 | -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | ||
| 10 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | 9 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; |
| 11 | -import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | ||
| 12 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 10 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 11 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | ||
| 13 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 12 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 14 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; |
| 15 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | 14 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| @@ -23,7 +22,12 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | @@ -23,7 +22,12 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | ||
| 23 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 22 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 24 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | 23 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| 25 | import com.genersoft.iot.vmp.media.zlm.dto.*; | 24 | import com.genersoft.iot.vmp.media.zlm.dto.*; |
| 26 | -import com.genersoft.iot.vmp.service.*; | 25 | +import com.genersoft.iot.vmp.service.IMediaServerService; |
| 26 | +import com.genersoft.iot.vmp.service.IPlayService; | ||
| 27 | +import com.genersoft.iot.vmp.service.IStreamProxyService; | ||
| 28 | +import com.genersoft.iot.vmp.service.IStreamPushService; | ||
| 29 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCallback; | ||
| 30 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCode; | ||
| 27 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | 31 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| 28 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; | 32 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 29 | import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; | 33 | import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; |
| @@ -79,6 +83,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -79,6 +83,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 79 | private IRedisCatchStorage redisCatchStorage; | 83 | private IRedisCatchStorage redisCatchStorage; |
| 80 | 84 | ||
| 81 | @Autowired | 85 | @Autowired |
| 86 | + private SSRCFactory ssrcFactory; | ||
| 87 | + | ||
| 88 | + @Autowired | ||
| 82 | private DynamicTask dynamicTask; | 89 | private DynamicTask dynamicTask; |
| 83 | 90 | ||
| 84 | @Autowired | 91 | @Autowired |
| @@ -90,8 +97,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -90,8 +97,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 90 | @Autowired | 97 | @Autowired |
| 91 | private SIPSender sipSender; | 98 | private SIPSender sipSender; |
| 92 | 99 | ||
| 93 | - @Autowired | ||
| 94 | - private AudioBroadcastManager audioBroadcastManager; | 100 | + @Autowired |
| 101 | + private AudioBroadcastManager audioBroadcastManager; | ||
| 95 | 102 | ||
| 96 | @Autowired | 103 | @Autowired |
| 97 | private ZLMRTPServerFactory zlmrtpServerFactory; | 104 | private ZLMRTPServerFactory zlmrtpServerFactory; |
| @@ -102,8 +109,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -102,8 +109,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 102 | @Autowired | 109 | @Autowired |
| 103 | private ISIPCommander commander; | 110 | private ISIPCommander commander; |
| 104 | 111 | ||
| 105 | - @Autowired | ||
| 106 | - private ZLMRESTfulUtils zlmresTfulUtils; | 112 | + @Autowired |
| 113 | + private ZLMRESTfulUtils zlmresTfulUtils; | ||
| 107 | 114 | ||
| 108 | @Autowired | 115 | @Autowired |
| 109 | private ZlmHttpHookSubscribe zlmHttpHookSubscribe; | 116 | private ZlmHttpHookSubscribe zlmHttpHookSubscribe; |
| @@ -112,28 +119,24 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -112,28 +119,24 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 112 | private SIPProcessorObserver sipProcessorObserver; | 119 | private SIPProcessorObserver sipProcessorObserver; |
| 113 | 120 | ||
| 114 | @Autowired | 121 | @Autowired |
| 115 | - private VideoStreamSessionManager sessionManager; | ||
| 116 | - | ||
| 117 | - @Autowired | ||
| 118 | private UserSetting userSetting; | 122 | private UserSetting userSetting; |
| 119 | 123 | ||
| 120 | @Autowired | 124 | @Autowired |
| 121 | private ZLMMediaListManager mediaListManager; | 125 | private ZLMMediaListManager mediaListManager; |
| 122 | 126 | ||
| 123 | - @Autowired | ||
| 124 | - private DeferredResultHolder resultHolder; | 127 | + @Autowired |
| 128 | + private DeferredResultHolder resultHolder; | ||
| 125 | 129 | ||
| 126 | - @Autowired | ||
| 127 | - private ZlmHttpHookSubscribe subscribe; | 130 | + @Autowired |
| 131 | + private ZlmHttpHookSubscribe subscribe; | ||
| 128 | 132 | ||
| 129 | - @Autowired | ||
| 130 | - private SipConfig config; | 133 | + @Autowired |
| 134 | + private SipConfig config; | ||
| 131 | 135 | ||
| 132 | @Autowired | 136 | @Autowired |
| 133 | private VideoStreamSessionManager streamSession; | 137 | private VideoStreamSessionManager streamSession; |
| 134 | 138 | ||
| 135 | 139 | ||
| 136 | - | ||
| 137 | @Autowired | 140 | @Autowired |
| 138 | private RedisGbPlayMsgListener redisGbPlayMsgListener; | 141 | private RedisGbPlayMsgListener redisGbPlayMsgListener; |
| 139 | 142 | ||
| @@ -153,7 +156,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -153,7 +156,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 153 | public void process(RequestEvent evt) { | 156 | public void process(RequestEvent evt) { |
| 154 | // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令 | 157 | // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令 |
| 155 | try { | 158 | try { |
| 156 | - SIPRequest request = (SIPRequest)evt.getRequest(); | 159 | + SIPRequest request = (SIPRequest) evt.getRequest(); |
| 157 | String channelId = SipUtils.getChannelIdFromRequest(request); | 160 | String channelId = SipUtils.getChannelIdFromRequest(request); |
| 158 | String requesterId = SipUtils.getUserIdFromFromHeader(request); | 161 | String requesterId = SipUtils.getUserIdFromFromHeader(request); |
| 159 | CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); | 162 | CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); |
| @@ -167,27 +170,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -167,27 +170,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 167 | } | 170 | } |
| 168 | return; | 171 | return; |
| 169 | } | 172 | } |
| 170 | - String ssrc = null; | ||
| 171 | - SessionDescription sdp = null; | ||
| 172 | - String ssrcDefault = "0000000000"; | ||
| 173 | - if (channelId == null) { | ||
| 174 | - // 解析sdp消息, 使用jainsip 自带的sdp解析方式 | ||
| 175 | - String contentString = new String(request.getRawContent()); | ||
| 176 | - | ||
| 177 | - // jainSip不支持y=字段, 移除以解析。 | ||
| 178 | - int ssrcIndex = contentString.indexOf("y="); | ||
| 179 | - | ||
| 180 | - if (ssrcIndex >= 0) { | ||
| 181 | - //ssrc规定长度为10个字节,不取余下长度以避免后续还有“f=”字段 | ||
| 182 | - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | ||
| 183 | - String substring = contentString.substring(0, contentString.indexOf("y=")); | ||
| 184 | - sdp = SdpFactory.getInstance().createSessionDescription(substring); | ||
| 185 | - } else { | ||
| 186 | - ssrc = ssrcDefault; | ||
| 187 | - sdp = SdpFactory.getInstance().createSessionDescription(contentString); | ||
| 188 | - } | ||
| 189 | - channelId = sdp.getOrigin().getUsername(); | ||
| 190 | - } | ||
| 191 | 173 | ||
| 192 | 174 | ||
| 193 | // 查询请求是否来自上级平台\设备 | 175 | // 查询请求是否来自上级平台\设备 |
| @@ -249,7 +231,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -249,7 +231,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 249 | } | 231 | } |
| 250 | return; | 232 | return; |
| 251 | } | 233 | } |
| 252 | - }else if("proxy".equals(gbStream.getStreamType())){ | 234 | + } else if ("proxy".equals(gbStream.getStreamType())) { |
| 253 | proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream()); | 235 | proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream()); |
| 254 | if (proxyByAppAndStream == null) { | 236 | if (proxyByAppAndStream == null) { |
| 255 | logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); | 237 | logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); |
| @@ -285,23 +267,21 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -285,23 +267,21 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 285 | } | 267 | } |
| 286 | return; | 268 | return; |
| 287 | } | 269 | } |
| 288 | - if (sdp == null || ssrc == null) { | ||
| 289 | - // 解析sdp消息, 使用jainsip 自带的sdp解析方式 | ||
| 290 | - String contentString = new String(request.getRawContent()); | ||
| 291 | - | ||
| 292 | - // jainSip不支持y=字段, 移除以解析。 | ||
| 293 | - int ssrcIndex = contentString.indexOf("y="); | ||
| 294 | - if (ssrcIndex >= 0) { | ||
| 295 | - //ssrc规定长度为10个字节,不取余下长度以避免后续还有“f=”字段 | ||
| 296 | - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | ||
| 297 | - String substring = contentString.substring(0, contentString.indexOf("y=")); | ||
| 298 | - sdp = SdpFactory.getInstance().createSessionDescription(substring); | ||
| 299 | - } else { | ||
| 300 | - ssrc = ssrcDefault; | ||
| 301 | - sdp = SdpFactory.getInstance().createSessionDescription(contentString); | ||
| 302 | - } | ||
| 303 | - } | 270 | + // 解析sdp消息, 使用jainsip 自带的sdp解析方式 |
| 271 | + String contentString = new String(request.getRawContent()); | ||
| 304 | 272 | ||
| 273 | + // jainSip不支持y=字段, 移除以解析。 | ||
| 274 | + // 检查是否有y字段 | ||
| 275 | + int ssrcIndex = contentString.indexOf("y="); | ||
| 276 | + | ||
| 277 | + SessionDescription sdp; | ||
| 278 | + if (ssrcIndex >= 0) { | ||
| 279 | + //ssrc规定长度为10个字节,不取余下长度以避免后续还有“f=”字段 | ||
| 280 | + String substring = contentString.substring(0, ssrcIndex); | ||
| 281 | + sdp = SdpFactory.getInstance().createSessionDescription(substring); | ||
| 282 | + } else { | ||
| 283 | + sdp = SdpFactory.getInstance().createSessionDescription(contentString); | ||
| 284 | + } | ||
| 305 | String sessionName = sdp.getSessionName().getValue(); | 285 | String sessionName = sdp.getSessionName().getValue(); |
| 306 | 286 | ||
| 307 | Long startTime = null; | 287 | Long startTime = null; |
| @@ -363,7 +343,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -363,7 +343,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 363 | String username = sdp.getOrigin().getUsername(); | 343 | String username = sdp.getOrigin().getUsername(); |
| 364 | String addressStr = sdp.getConnection().getAddress(); | 344 | String addressStr = sdp.getConnection().getAddress(); |
| 365 | 345 | ||
| 366 | - logger.info("[上级点播]用户:{}, 通道:{}, 地址:{}:{}, ssrc:{}", username, channelId, addressStr, port, ssrc); | 346 | + |
| 367 | Device device = null; | 347 | Device device = null; |
| 368 | // 通过 channel 和 gbStream 是否为null 值判断来源是直播流合适国标 | 348 | // 通过 channel 和 gbStream 是否为null 值判断来源是直播流合适国标 |
| 369 | if (channel != null) { | 349 | if (channel != null) { |
| @@ -387,6 +367,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -387,6 +367,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 387 | } | 367 | } |
| 388 | return; | 368 | return; |
| 389 | } | 369 | } |
| 370 | + | ||
| 371 | + String ssrc; | ||
| 372 | + if (userSetting.getUseCustomSsrcForParentInvite() || ssrcIndex < 0) { | ||
| 373 | + // 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式 | ||
| 374 | + ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); | ||
| 375 | + } else { | ||
| 376 | + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | ||
| 377 | + } | ||
| 378 | + String streamTypeStr = null; | ||
| 379 | + if (mediaTransmissionTCP) { | ||
| 380 | + if (tcpActive) { | ||
| 381 | + streamTypeStr = "TCP-ACTIVE"; | ||
| 382 | + } else { | ||
| 383 | + streamTypeStr = "TCP-PASSIVE"; | ||
| 384 | + } | ||
| 385 | + } else { | ||
| 386 | + streamTypeStr = "UDP"; | ||
| 387 | + } | ||
| 388 | + logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc); | ||
| 390 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, | 389 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| 391 | device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp()); | 390 | device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp()); |
| 392 | 391 | ||
| @@ -407,11 +406,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -407,11 +406,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 407 | 406 | ||
| 408 | Long finalStartTime = startTime; | 407 | Long finalStartTime = startTime; |
| 409 | Long finalStopTime = stopTime; | 408 | Long finalStopTime = stopTime; |
| 410 | - String finalChannelId = channelId; | ||
| 411 | - ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInUSe, responseJSON) -> { | ||
| 412 | - String app = responseJSON.getString("app"); | ||
| 413 | - String stream = responseJSON.getString("stream"); | ||
| 414 | - logger.info("[上级点播]下级已经开始推流。 回复200OK(SDP), {}/{}", app, stream); | 409 | + InviteErrorCallback<Object> hookEvent = (code, msg, data) -> { |
| 410 | + StreamInfo streamInfo = (StreamInfo) data; | ||
| 411 | + MediaServerItem mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId()); | ||
| 412 | + logger.info("[上级Invite]下级已经开始推流。 回复200OK(SDP), {}/{}", streamInfo.getApp(), streamInfo.getStream()); | ||
| 415 | // * 0 等待设备推流上来 | 413 | // * 0 等待设备推流上来 |
| 416 | // * 1 下级已经推流,等待上级平台回复ack | 414 | // * 1 下级已经推流,等待上级平台回复ack |
| 417 | // * 2 推流中 | 415 | // * 2 推流中 |
| @@ -420,7 +418,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -420,7 +418,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 420 | 418 | ||
| 421 | StringBuffer content = new StringBuffer(200); | 419 | StringBuffer content = new StringBuffer(200); |
| 422 | content.append("v=0\r\n"); | 420 | content.append("v=0\r\n"); |
| 423 | - content.append("o=" + finalChannelId + " 0 0 IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n"); | 421 | + content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n"); |
| 424 | content.append("s=" + sessionName + "\r\n"); | 422 | content.append("s=" + sessionName + "\r\n"); |
| 425 | content.append("c=IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n"); | 423 | content.append("c=IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n"); |
| 426 | if ("Playback".equalsIgnoreCase(sessionName)) { | 424 | if ("Playback".equalsIgnoreCase(sessionName)) { |
| @@ -462,111 +460,118 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -462,111 +460,118 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 462 | logger.error("[命令发送失败] 国标级联 回复SdpAck", e); | 460 | logger.error("[命令发送失败] 国标级联 回复SdpAck", e); |
| 463 | } | 461 | } |
| 464 | }; | 462 | }; |
| 465 | - SipSubscribe.Event errorEvent = ((event) -> { | 463 | + InviteErrorCallback<Object> errorEvent = ((statusCode, msg, data) -> { |
| 466 | // 未知错误。直接转发设备点播的错误 | 464 | // 未知错误。直接转发设备点播的错误 |
| 467 | try { | 465 | try { |
| 468 | - Response response = getMessageFactory().createResponse(event.statusCode, evt.getRequest()); | ||
| 469 | - sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); | ||
| 470 | - } catch (ParseException | SipException e) { | 466 | + if (statusCode > 0) { |
| 467 | + Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); | ||
| 468 | + sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); | ||
| 469 | + } | ||
| 470 | + } catch (ParseException | SipException e) { | ||
| 471 | logger.error("未处理的异常 ", e); | 471 | logger.error("未处理的异常 ", e); |
| 472 | } | 472 | } |
| 473 | }); | 473 | }); |
| 474 | sendRtpItem.setApp("rtp"); | 474 | sendRtpItem.setApp("rtp"); |
| 475 | if ("Playback".equalsIgnoreCase(sessionName)) { | 475 | if ("Playback".equalsIgnoreCase(sessionName)) { |
| 476 | sendRtpItem.setPlayType(InviteStreamType.PLAYBACK); | 476 | sendRtpItem.setPlayType(InviteStreamType.PLAYBACK); |
| 477 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, device.isSsrcCheck(), true); | 477 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); |
| 478 | sendRtpItem.setStream(ssrcInfo.getStream()); | 478 | sendRtpItem.setStream(ssrcInfo.getStream()); |
| 479 | // 写入redis, 超时时回复 | 479 | // 写入redis, 超时时回复 |
| 480 | redisCatchStorage.updateSendRTPSever(sendRtpItem); | 480 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 481 | playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), | 481 | playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), |
| 482 | - DateUtil.formatter.format(end), null, result -> { | ||
| 483 | - if (result.getCode() != 0) { | ||
| 484 | - logger.warn("录像回放失败"); | ||
| 485 | - if (result.getEvent() != null) { | ||
| 486 | - errorEvent.response(result.getEvent()); | ||
| 487 | - } | ||
| 488 | - redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), finalChannelId, callIdHeader.getCallId(), null); | ||
| 489 | - try { | ||
| 490 | - responseAck(request, Response.REQUEST_TIMEOUT); | ||
| 491 | - } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 492 | - logger.error("[命令发送失败] 国标级联 录像回放 发送REQUEST_TIMEOUT: {}", e.getMessage()); | ||
| 493 | - } | 482 | + DateUtil.formatter.format(end), |
| 483 | + (code, msg, data) -> { | ||
| 484 | + if (code == InviteErrorCode.SUCCESS.getCode()) { | ||
| 485 | + hookEvent.run(code, msg, data); | ||
| 486 | + } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) { | ||
| 487 | + logger.info("[录像回放]超时, 用户:{}, 通道:{}", username, channelId); | ||
| 488 | + redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); | ||
| 489 | + errorEvent.run(code, msg, data); | ||
| 490 | + } else { | ||
| 491 | + errorEvent.run(code, msg, data); | ||
| 492 | + } | ||
| 493 | + }); | ||
| 494 | + } else if ("Download".equalsIgnoreCase(sessionName)) { | ||
| 495 | + // 获取指定的下载速度 | ||
| 496 | + Vector sdpMediaDescriptions = sdp.getMediaDescriptions(true); | ||
| 497 | + MediaDescription mediaDescription = null; | ||
| 498 | + String downloadSpeed = "1"; | ||
| 499 | + if (sdpMediaDescriptions.size() > 0) { | ||
| 500 | + mediaDescription = (MediaDescription) sdpMediaDescriptions.get(0); | ||
| 501 | + } | ||
| 502 | + if (mediaDescription != null) { | ||
| 503 | + downloadSpeed = mediaDescription.getAttribute("downloadspeed"); | ||
| 504 | + } | ||
| 505 | + | ||
| 506 | + sendRtpItem.setPlayType(InviteStreamType.DOWNLOAD); | ||
| 507 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); | ||
| 508 | + sendRtpItem.setStream(ssrcInfo.getStream()); | ||
| 509 | + // 写入redis, 超时时回复 | ||
| 510 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 511 | + playService.download(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), | ||
| 512 | + DateUtil.formatter.format(end), Integer.parseInt(downloadSpeed), | ||
| 513 | + (code, msg, data) -> { | ||
| 514 | + if (code == InviteErrorCode.SUCCESS.getCode()) { | ||
| 515 | + hookEvent.run(code, msg, data); | ||
| 516 | + } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) { | ||
| 517 | + logger.info("[录像下载]超时, 用户:{}, 通道:{}", username, channelId); | ||
| 518 | + redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); | ||
| 519 | + errorEvent.run(code, msg, data); | ||
| 494 | } else { | 520 | } else { |
| 495 | - if (result.getMediaServerItem() != null) { | ||
| 496 | - hookEvent.response(result.getMediaServerItem(), result.getResponse()); | ||
| 497 | - } | 521 | + errorEvent.run(code, msg, data); |
| 498 | } | 522 | } |
| 499 | }); | 523 | }); |
| 500 | } else { | 524 | } else { |
| 501 | sendRtpItem.setPlayType(InviteStreamType.PLAY); | 525 | sendRtpItem.setPlayType(InviteStreamType.PLAY); |
| 502 | - SsrcTransaction playTransaction = sessionManager.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); | ||
| 503 | - if (playTransaction != null) { | ||
| 504 | - Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, "rtp", playTransaction.getStream()); | ||
| 505 | - if (!streamReady) { | ||
| 506 | - boolean hasRtpServer = mediaServerService.checkRtpServer(mediaServerItem, "rtp", playTransaction.getStream()); | ||
| 507 | - if (hasRtpServer) { | ||
| 508 | - logger.info("[上级点播]已经开启rtpServer但是尚未收到流,开启监听流的到来"); | ||
| 509 | - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", playTransaction.getStream(), true, "rtsp", mediaServerItem.getId()); | ||
| 510 | - zlmHttpHookSubscribe.addSubscribe(hookSubscribe, hookEvent); | ||
| 511 | - }else { | ||
| 512 | - playTransaction = null; | ||
| 513 | - } | ||
| 514 | - } | ||
| 515 | - } | ||
| 516 | - if (playTransaction == null) { | ||
| 517 | - String streamId = null; | ||
| 518 | - if (mediaServerItem.isRtpEnable()) { | ||
| 519 | - streamId = String.format("%s_%s", device.getDeviceId(), channelId); | ||
| 520 | - } | ||
| 521 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false); | ||
| 522 | - logger.info(JSONObject.toJSONString(ssrcInfo)); | ||
| 523 | - sendRtpItem.setStream(ssrcInfo.getStream()); | ||
| 524 | - sendRtpItem.setSsrc(ssrc.equals(ssrcDefault) ? ssrcInfo.getSsrc() : ssrc); | ||
| 525 | - | ||
| 526 | - // 写入redis, 超时时回复 | ||
| 527 | - redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 528 | - playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg) -> { | ||
| 529 | - logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, finalChannelId); | ||
| 530 | - redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), finalChannelId, callIdHeader.getCallId(), null); | ||
| 531 | - }); | 526 | + String streamId = null; |
| 527 | + if (mediaServerItem.isRtpEnable()) { | ||
| 528 | + streamId = String.format("%s_%s", device.getDeviceId(), channelId); | ||
| 532 | } else { | 529 | } else { |
| 533 | - sendRtpItem.setStream(playTransaction.getStream()); | ||
| 534 | - // 写入redis, 超时时回复 | ||
| 535 | - redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 536 | - JSONObject jsonObject = new JSONObject(); | ||
| 537 | - jsonObject.put("app", sendRtpItem.getApp()); | ||
| 538 | - jsonObject.put("stream", sendRtpItem.getStream()); | ||
| 539 | - hookEvent.response(mediaServerItem, jsonObject); | 530 | + streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); |
| 540 | } | 531 | } |
| 532 | + sendRtpItem.setStream(streamId); | ||
| 533 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 534 | + playService.play(mediaServerItem, device.getDeviceId(), channelId, ((code, msg, data) -> { | ||
| 535 | + if (code == InviteErrorCode.SUCCESS.getCode()) { | ||
| 536 | + hookEvent.run(code, msg, data); | ||
| 537 | + } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) { | ||
| 538 | + logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, channelId); | ||
| 539 | + redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); | ||
| 540 | + errorEvent.run(code, msg, data); | ||
| 541 | + } else { | ||
| 542 | + errorEvent.run(code, msg, data); | ||
| 543 | + } | ||
| 544 | + })); | ||
| 545 | + | ||
| 541 | } | 546 | } |
| 542 | } else if (gbStream != null) { | 547 | } else if (gbStream != null) { |
| 543 | - if(ssrc.equals(ssrcDefault)) | ||
| 544 | - { | ||
| 545 | - SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig(); | ||
| 546 | - if(ssrcConfig != null) | ||
| 547 | - { | ||
| 548 | - ssrc = ssrcConfig.getPlaySsrc(); | ||
| 549 | - ssrcConfig.releaseSsrc(ssrc); | ||
| 550 | - } | 548 | + |
| 549 | + String ssrc; | ||
| 550 | + if (userSetting.getUseCustomSsrcForParentInvite() || ssrcIndex < 0) { | ||
| 551 | + // 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式 | ||
| 552 | + ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); | ||
| 553 | + } else { | ||
| 554 | + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | ||
| 551 | } | 555 | } |
| 552 | - if("push".equals(gbStream.getStreamType())) { | 556 | + |
| 557 | + if ("push".equals(gbStream.getStreamType())) { | ||
| 553 | if (streamPushItem != null && streamPushItem.isPushIng()) { | 558 | if (streamPushItem != null && streamPushItem.isPushIng()) { |
| 554 | // 推流状态 | 559 | // 推流状态 |
| 555 | pushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, | 560 | pushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, |
| 556 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); | 561 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 557 | } else { | 562 | } else { |
| 558 | // 未推流 拉起 | 563 | // 未推流 拉起 |
| 559 | - notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, | 564 | + notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, |
| 560 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); | 565 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 561 | } | 566 | } |
| 562 | - }else if ("proxy".equals(gbStream.getStreamType())){ | 567 | + } else if ("proxy".equals(gbStream.getStreamType())) { |
| 563 | if (null != proxyByAppAndStream) { | 568 | if (null != proxyByAppAndStream) { |
| 564 | - if(proxyByAppAndStream.isStatus()){ | ||
| 565 | - pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, | 569 | + if (proxyByAppAndStream.isStatus()) { |
| 570 | + pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, | ||
| 566 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); | 571 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 567 | - }else{ | 572 | + } else { |
| 568 | //开启代理拉流 | 573 | //开启代理拉流 |
| 569 | - notifyStreamOnline(evt, request,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive, | 574 | + notifyStreamOnline(evt, request, gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive, |
| 570 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); | 575 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 571 | } | 576 | } |
| 572 | } | 577 | } |
| @@ -586,42 +591,43 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -586,42 +591,43 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 586 | * 安排推流 | 591 | * 安排推流 |
| 587 | */ | 592 | */ |
| 588 | private void pushProxyStream(RequestEvent evt, SIPRequest request, GbStream gbStream, ParentPlatform platform, | 593 | private void pushProxyStream(RequestEvent evt, SIPRequest request, GbStream gbStream, ParentPlatform platform, |
| 589 | - CallIdHeader callIdHeader, MediaServerItem mediaServerItem, | ||
| 590 | - int port, Boolean tcpActive, boolean mediaTransmissionTCP, | ||
| 591 | - String channelId, String addressStr, String ssrc, String requesterId) { | ||
| 592 | - Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); | ||
| 593 | - if (streamReady) { | ||
| 594 | - // 自平台内容 | ||
| 595 | - SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, | ||
| 596 | - gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); | ||
| 597 | - | ||
| 598 | - if (sendRtpItem == null) { | ||
| 599 | - logger.warn("服务器端口资源不足"); | ||
| 600 | - try { | ||
| 601 | - responseAck(request, Response.BUSY_HERE); | ||
| 602 | - } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 603 | - logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage()); | ||
| 604 | - } | ||
| 605 | - return; | ||
| 606 | - } | ||
| 607 | - if (tcpActive != null) { | ||
| 608 | - sendRtpItem.setTcpActive(tcpActive); | ||
| 609 | - } | ||
| 610 | - sendRtpItem.setPlayType(InviteStreamType.PUSH); | ||
| 611 | - // 写入redis, 超时时回复 | ||
| 612 | - sendRtpItem.setStatus(1); | ||
| 613 | - sendRtpItem.setCallId(callIdHeader.getCallId()); | ||
| 614 | - sendRtpItem.setFromTag(request.getFromTag()); | ||
| 615 | - | ||
| 616 | - SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt); | ||
| 617 | - if (response != null) { | ||
| 618 | - sendRtpItem.setToTag(response.getToTag()); | 594 | + CallIdHeader callIdHeader, MediaServerItem mediaServerItem, |
| 595 | + int port, Boolean tcpActive, boolean mediaTransmissionTCP, | ||
| 596 | + String channelId, String addressStr, String ssrc, String requesterId) { | ||
| 597 | + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); | ||
| 598 | + if (streamReady != null && streamReady) { | ||
| 599 | + // 自平台内容 | ||
| 600 | + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, | ||
| 601 | + gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); | ||
| 602 | + | ||
| 603 | + if (sendRtpItem == null) { | ||
| 604 | + logger.warn("服务器端口资源不足"); | ||
| 605 | + try { | ||
| 606 | + responseAck(request, Response.BUSY_HERE); | ||
| 607 | + } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 608 | + logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage()); | ||
| 619 | } | 609 | } |
| 620 | - redisCatchStorage.updateSendRTPSever(sendRtpItem); | 610 | + return; |
| 611 | + } | ||
| 612 | + if (tcpActive != null) { | ||
| 613 | + sendRtpItem.setTcpActive(tcpActive); | ||
| 614 | + } | ||
| 615 | + sendRtpItem.setPlayType(InviteStreamType.PUSH); | ||
| 616 | + // 写入redis, 超时时回复 | ||
| 617 | + sendRtpItem.setStatus(1); | ||
| 618 | + sendRtpItem.setCallId(callIdHeader.getCallId()); | ||
| 619 | + sendRtpItem.setFromTag(request.getFromTag()); | ||
| 620 | + | ||
| 621 | + SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt); | ||
| 622 | + if (response != null) { | ||
| 623 | + sendRtpItem.setToTag(response.getToTag()); | ||
| 624 | + } | ||
| 625 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 621 | 626 | ||
| 622 | } | 627 | } |
| 623 | 628 | ||
| 624 | } | 629 | } |
| 630 | + | ||
| 625 | private void pushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, | 631 | private void pushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, |
| 626 | CallIdHeader callIdHeader, MediaServerItem mediaServerItem, | 632 | CallIdHeader callIdHeader, MediaServerItem mediaServerItem, |
| 627 | int port, Boolean tcpActive, boolean mediaTransmissionTCP, | 633 | int port, Boolean tcpActive, boolean mediaTransmissionTCP, |
| @@ -629,7 +635,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -629,7 +635,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 629 | // 推流 | 635 | // 推流 |
| 630 | if (streamPushItem.isSelf()) { | 636 | if (streamPushItem.isSelf()) { |
| 631 | Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); | 637 | Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); |
| 632 | - if (streamReady) { | 638 | + if (streamReady != null && streamReady) { |
| 633 | // 自平台内容 | 639 | // 自平台内容 |
| 634 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, | 640 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| 635 | gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); | 641 | gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); |
| @@ -661,7 +667,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -661,7 +667,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 661 | 667 | ||
| 662 | } else { | 668 | } else { |
| 663 | // 不在线 拉起 | 669 | // 不在线 拉起 |
| 664 | - notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, | 670 | + notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, |
| 665 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); | 671 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 666 | } | 672 | } |
| 667 | 673 | ||
| @@ -671,6 +677,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -671,6 +677,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 671 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); | 677 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 672 | } | 678 | } |
| 673 | } | 679 | } |
| 680 | + | ||
| 674 | /** | 681 | /** |
| 675 | * 通知流上线 | 682 | * 通知流上线 |
| 676 | */ | 683 | */ |
| @@ -688,7 +695,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -688,7 +695,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 688 | String stream = responseJSON.getString("stream"); | 695 | String stream = responseJSON.getString("stream"); |
| 689 | logger.info("[上级点播]拉流代理已经就绪, {}/{}", app, stream); | 696 | logger.info("[上级点播]拉流代理已经就绪, {}/{}", app, stream); |
| 690 | dynamicTask.stop(callIdHeader.getCallId()); | 697 | dynamicTask.stop(callIdHeader.getCallId()); |
| 691 | - pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, | 698 | + pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, |
| 692 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); | 699 | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| 693 | }); | 700 | }); |
| 694 | dynamicTask.startDelay(callIdHeader.getCallId(), () -> { | 701 | dynamicTask.startDelay(callIdHeader.getCallId(), () -> { |
| @@ -707,7 +714,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -707,7 +714,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 707 | } | 714 | } |
| 708 | 715 | ||
| 709 | 716 | ||
| 710 | - | ||
| 711 | } else if ("push".equals(gbStream.getStreamType())) { | 717 | } else if ("push".equals(gbStream.getStreamType())) { |
| 712 | if (!platform.isStartOfflinePush()) { | 718 | if (!platform.isStartOfflinePush()) { |
| 713 | // 平台设置中关闭了拉起离线的推流则直接回复 | 719 | // 平台设置中关闭了拉起离线的推流则直接回复 |
| @@ -811,7 +817,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -811,7 +817,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 811 | // 发送redis消息 | 817 | // 发送redis消息 |
| 812 | redisGbPlayMsgListener.sendMsg(streamPushItem.getServerId(), streamPushItem.getMediaServerId(), | 818 | redisGbPlayMsgListener.sendMsg(streamPushItem.getServerId(), streamPushItem.getMediaServerId(), |
| 813 | streamPushItem.getApp(), streamPushItem.getStream(), addressStr, port, ssrc, requesterId, | 819 | streamPushItem.getApp(), streamPushItem.getStream(), addressStr, port, ssrc, requesterId, |
| 814 | - channelId, mediaTransmissionTCP, platform.isRtcp(),null, responseSendItemMsg -> { | 820 | + channelId, mediaTransmissionTCP, platform.isRtcp(), null, responseSendItemMsg -> { |
| 815 | SendRtpItem sendRtpItem = responseSendItemMsg.getSendRtpItem(); | 821 | SendRtpItem sendRtpItem = responseSendItemMsg.getSendRtpItem(); |
| 816 | if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) { | 822 | if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) { |
| 817 | logger.warn("服务器端口资源不足"); | 823 | logger.warn("服务器端口资源不足"); |
| @@ -836,7 +842,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -836,7 +842,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 836 | sendRtpItem.setCallId(callIdHeader.getCallId()); | 842 | sendRtpItem.setCallId(callIdHeader.getCallId()); |
| 837 | 843 | ||
| 838 | sendRtpItem.setFromTag(request.getFromTag()); | 844 | sendRtpItem.setFromTag(request.getFromTag()); |
| 839 | - SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), request,sendRtpItem, platform, evt); | 845 | + SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), request, sendRtpItem, platform, evt); |
| 840 | if (response != null) { | 846 | if (response != null) { |
| 841 | sendRtpItem.setToTag(response.getToTag()); | 847 | sendRtpItem.setToTag(response.getToTag()); |
| 842 | } | 848 | } |
| @@ -877,8 +883,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -877,8 +883,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 877 | content.append("t=0 0\r\n"); | 883 | content.append("t=0 0\r\n"); |
| 878 | // 非严格模式端口不统一, 增加兼容性,修改为一个不为0的端口 | 884 | // 非严格模式端口不统一, 增加兼容性,修改为一个不为0的端口 |
| 879 | int localPort = sendRtpItem.getLocalPort(); | 885 | int localPort = sendRtpItem.getLocalPort(); |
| 880 | - if(localPort == 0) | ||
| 881 | - { | 886 | + if (localPort == 0) { |
| 882 | localPort = new Random().nextInt(65535) + 1; | 887 | localPort = new Random().nextInt(65535) + 1; |
| 883 | } | 888 | } |
| 884 | content.append("m=video " + localPort + " RTP/AVP 96\r\n"); | 889 | content.append("m=video " + localPort + " RTP/AVP 96\r\n"); |
| @@ -953,7 +958,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -953,7 +958,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 953 | } | 958 | } |
| 954 | if (device != null) { | 959 | if (device != null) { |
| 955 | logger.info("收到设备" + requesterId + "的语音广播Invite请求"); | 960 | logger.info("收到设备" + requesterId + "的语音广播Invite请求"); |
| 956 | - String key = VideoManagerConstants.BROADCAST_WAITE_INVITE + device.getDeviceId() + broadcastCatch.getChannelId(); | 961 | + String key = VideoManagerConstants.BROADCAST_WAITE_INVITE + device.getDeviceId() + broadcastCatch.getChannelId(); |
| 957 | dynamicTask.stop(key); | 962 | dynamicTask.stop(key); |
| 958 | try { | 963 | try { |
| 959 | responseAck(request, Response.TRYING); | 964 | responseAck(request, Response.TRYING); |
| @@ -986,7 +991,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -986,7 +991,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 986 | boolean mediaTransmissionTCP = false; | 991 | boolean mediaTransmissionTCP = false; |
| 987 | Boolean tcpActive = null; | 992 | Boolean tcpActive = null; |
| 988 | for (int i = 0; i < mediaDescriptions.size(); i++) { | 993 | for (int i = 0; i < mediaDescriptions.size(); i++) { |
| 989 | - MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); | 994 | + MediaDescription mediaDescription = (MediaDescription) mediaDescriptions.get(i); |
| 990 | Media media = mediaDescription.getMedia(); | 995 | Media media = mediaDescription.getMedia(); |
| 991 | 996 | ||
| 992 | Vector mediaFormats = media.getMediaFormats(false); | 997 | Vector mediaFormats = media.getMediaFormats(false); |
| @@ -1022,7 +1027,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -1022,7 +1027,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 1022 | } | 1027 | } |
| 1023 | String addressStr = sdp.getOrigin().getAddress(); | 1028 | String addressStr = sdp.getOrigin().getAddress(); |
| 1024 | logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}, {}", requesterId, addressStr, port, ssrc, | 1029 | logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}, {}", requesterId, addressStr, port, ssrc, |
| 1025 | - mediaTransmissionTCP ? (tcpActive? "TCP主动":"TCP被动") : "UDP"); | 1030 | + mediaTransmissionTCP ? (tcpActive ? "TCP主动" : "TCP被动") : "UDP"); |
| 1026 | 1031 | ||
| 1027 | MediaServerItem mediaServerItem = broadcastCatch.getMediaServerItem(); | 1032 | MediaServerItem mediaServerItem = broadcastCatch.getMediaServerItem(); |
| 1028 | if (mediaServerItem == null) { | 1033 | if (mediaServerItem == null) { |
| @@ -1036,7 +1041,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -1036,7 +1041,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 1036 | return; | 1041 | return; |
| 1037 | } | 1042 | } |
| 1038 | logger.info("设备{}请求语音流, 收流地址:{}:{},ssrc:{}, {}, 对讲方式:{}", requesterId, addressStr, port, ssrc, | 1043 | logger.info("设备{}请求语音流, 收流地址:{}:{},ssrc:{}, {}, 对讲方式:{}", requesterId, addressStr, port, ssrc, |
| 1039 | - mediaTransmissionTCP ? (tcpActive? "TCP主动":"TCP被动") : "UDP", sdp.getSessionName().getValue()); | 1044 | + mediaTransmissionTCP ? (tcpActive ? "TCP主动" : "TCP被动") : "UDP", sdp.getSessionName().getValue()); |
| 1040 | 1045 | ||
| 1041 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, | 1046 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| 1042 | device.getDeviceId(), broadcastCatch.getChannelId(), | 1047 | device.getDeviceId(), broadcastCatch.getChannelId(), |
| @@ -1076,7 +1081,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -1076,7 +1081,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 1076 | Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, broadcastCatch.getApp(), broadcastCatch.getStream()); | 1081 | Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, broadcastCatch.getApp(), broadcastCatch.getStream()); |
| 1077 | if (streamReady) { | 1082 | if (streamReady) { |
| 1078 | sendOk(device, sendRtpItem, sdp, request, mediaServerItem, mediaTransmissionTCP, ssrc); | 1083 | sendOk(device, sendRtpItem, sdp, request, mediaServerItem, mediaTransmissionTCP, ssrc); |
| 1079 | - }else { | 1084 | + } else { |
| 1080 | logger.warn("[语音通话], 未发现待推送的流,app={},stream={}", broadcastCatch.getApp(), broadcastCatch.getStream()); | 1085 | logger.warn("[语音通话], 未发现待推送的流,app={},stream={}", broadcastCatch.getApp(), broadcastCatch.getStream()); |
| 1081 | try { | 1086 | try { |
| 1082 | responseAck(request, Response.GONE); | 1087 | responseAck(request, Response.GONE); |
| @@ -1093,29 +1098,30 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -1093,29 +1098,30 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 1093 | } else { | 1098 | } else { |
| 1094 | logger.warn("来自无效设备/平台的请求"); | 1099 | logger.warn("来自无效设备/平台的请求"); |
| 1095 | try { | 1100 | try { |
| 1096 | - responseAck(request, Response.BAD_REQUEST);; // 不支持的格式,发415 | 1101 | + responseAck(request, Response.BAD_REQUEST); |
| 1102 | + ; // 不支持的格式,发415 | ||
| 1097 | } catch (SipException | InvalidArgumentException | ParseException e) { | 1103 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| 1098 | logger.error("[命令发送失败] invite 来自无效设备/平台的请求, {}", e.getMessage()); | 1104 | logger.error("[命令发送失败] invite 来自无效设备/平台的请求, {}", e.getMessage()); |
| 1099 | } | 1105 | } |
| 1100 | } | 1106 | } |
| 1101 | } | 1107 | } |
| 1102 | 1108 | ||
| 1103 | - SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request, MediaServerItem mediaServerItem, boolean mediaTransmissionTCP, String ssrc){ | 1109 | + SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request, MediaServerItem mediaServerItem, boolean mediaTransmissionTCP, String ssrc) { |
| 1104 | SIPResponse sipResponse = null; | 1110 | SIPResponse sipResponse = null; |
| 1105 | try { | 1111 | try { |
| 1106 | sendRtpItem.setStatus(2); | 1112 | sendRtpItem.setStatus(2); |
| 1107 | redisCatchStorage.updateSendRTPSever(sendRtpItem); | 1113 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 1108 | StringBuffer content = new StringBuffer(200); | 1114 | StringBuffer content = new StringBuffer(200); |
| 1109 | content.append("v=0\r\n"); | 1115 | content.append("v=0\r\n"); |
| 1110 | - content.append("o="+ config.getId() +" "+ sdp.getOrigin().getSessionId() +" " + sdp.getOrigin().getSessionVersion() + " IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | 1116 | + content.append("o=" + config.getId() + " " + sdp.getOrigin().getSessionId() + " " + sdp.getOrigin().getSessionVersion() + " IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); |
| 1111 | content.append("s=Play\r\n"); | 1117 | content.append("s=Play\r\n"); |
| 1112 | - content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | 1118 | + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); |
| 1113 | content.append("t=0 0\r\n"); | 1119 | content.append("t=0 0\r\n"); |
| 1114 | 1120 | ||
| 1115 | if (mediaTransmissionTCP) { | 1121 | if (mediaTransmissionTCP) { |
| 1116 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | ||
| 1117 | - }else { | ||
| 1118 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | 1122 | + content.append("m=audio " + sendRtpItem.getLocalPort() + " TCP/RTP/AVP 8\r\n"); |
| 1123 | + } else { | ||
| 1124 | + content.append("m=audio " + sendRtpItem.getLocalPort() + " RTP/AVP 8\r\n"); | ||
| 1119 | } | 1125 | } |
| 1120 | 1126 | ||
| 1121 | content.append("a=rtpmap:8 PCMA/8000/1\r\n"); | 1127 | content.append("a=rtpmap:8 PCMA/8000/1\r\n"); |
| @@ -1125,11 +1131,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -1125,11 +1131,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 1125 | content.append("a=connection:new\r\n"); | 1131 | content.append("a=connection:new\r\n"); |
| 1126 | if (!sendRtpItem.isTcpActive()) { | 1132 | if (!sendRtpItem.isTcpActive()) { |
| 1127 | content.append("a=setup:active\r\n"); | 1133 | content.append("a=setup:active\r\n"); |
| 1128 | - }else { | 1134 | + } else { |
| 1129 | content.append("a=setup:passive\r\n"); | 1135 | content.append("a=setup:passive\r\n"); |
| 1130 | } | 1136 | } |
| 1131 | } | 1137 | } |
| 1132 | - content.append("y="+ ssrc + "\r\n"); | 1138 | + content.append("y=" + ssrc + "\r\n"); |
| 1133 | content.append("f=v/////a/1/8/1\r\n"); | 1139 | content.append("f=v/////a/1/8/1\r\n"); |
| 1134 | 1140 | ||
| 1135 | ParentPlatform parentPlatform = new ParentPlatform(); | 1141 | ParentPlatform parentPlatform = new ParentPlatform(); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.conf.DynamicTask; | ||
| 4 | +import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | ||
| 7 | +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | ||
| 8 | +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; | ||
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | ||
| 10 | +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | ||
| 11 | +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; | ||
| 12 | +import com.genersoft.iot.vmp.service.IDeviceChannelService; | ||
| 13 | +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | ||
| 14 | +import org.dom4j.DocumentException; | ||
| 15 | +import org.dom4j.Element; | ||
| 16 | +import org.slf4j.Logger; | ||
| 17 | +import org.slf4j.LoggerFactory; | ||
| 18 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 19 | +import org.springframework.stereotype.Component; | ||
| 20 | + | ||
| 21 | +import javax.sip.RequestEvent; | ||
| 22 | +import javax.sip.header.FromHeader; | ||
| 23 | +import java.util.*; | ||
| 24 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 25 | +import java.util.concurrent.CopyOnWriteArrayList; | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * SIP命令类型: NOTIFY请求中的目录请求处理 | ||
| 29 | + */ | ||
| 30 | +@Component | ||
| 31 | +public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent { | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + private final static Logger logger = LoggerFactory.getLogger(NotifyRequestForCatalogProcessor.class); | ||
| 35 | + | ||
| 36 | + private final List<DeviceChannel> updateChannelOnlineList = new CopyOnWriteArrayList<>(); | ||
| 37 | + private final List<DeviceChannel> updateChannelOfflineList = new CopyOnWriteArrayList<>(); | ||
| 38 | + private final Map<String, DeviceChannel> updateChannelMap = new ConcurrentHashMap<>(); | ||
| 39 | + | ||
| 40 | + private final Map<String, DeviceChannel> addChannelMap = new ConcurrentHashMap<>(); | ||
| 41 | + private final List<DeviceChannel> deleteChannelList = new CopyOnWriteArrayList<>(); | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + @Autowired | ||
| 45 | + private UserSetting userSetting; | ||
| 46 | + | ||
| 47 | + @Autowired | ||
| 48 | + private EventPublisher eventPublisher; | ||
| 49 | + | ||
| 50 | + @Autowired | ||
| 51 | + private IRedisCatchStorage redisCatchStorage; | ||
| 52 | + | ||
| 53 | + @Autowired | ||
| 54 | + private IDeviceChannelService deviceChannelService; | ||
| 55 | + | ||
| 56 | + @Autowired | ||
| 57 | + private DynamicTask dynamicTask; | ||
| 58 | + | ||
| 59 | + private final static String talkKey = "notify-request-for-catalog-task"; | ||
| 60 | + | ||
| 61 | + public void process(RequestEvent evt) { | ||
| 62 | + try { | ||
| 63 | + long start = System.currentTimeMillis(); | ||
| 64 | + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); | ||
| 65 | + String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader); | ||
| 66 | + | ||
| 67 | + Device device = redisCatchStorage.getDevice(deviceId); | ||
| 68 | + if (device == null || device.getOnline() == 0) { | ||
| 69 | + logger.warn("[收到目录订阅]:{}, 但是设备已经离线", (device != null ? device.getDeviceId():"" )); | ||
| 70 | + return; | ||
| 71 | + } | ||
| 72 | + Element rootElement = getRootElement(evt, device.getCharset()); | ||
| 73 | + if (rootElement == null) { | ||
| 74 | + logger.warn("[ 收到目录订阅 ] content cannot be null, {}", evt.getRequest()); | ||
| 75 | + return; | ||
| 76 | + } | ||
| 77 | + Element deviceListElement = rootElement.element("DeviceList"); | ||
| 78 | + if (deviceListElement == null) { | ||
| 79 | + return; | ||
| 80 | + } | ||
| 81 | + Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); | ||
| 82 | + if (deviceListIterator != null) { | ||
| 83 | + | ||
| 84 | + // 遍历DeviceList | ||
| 85 | + while (deviceListIterator.hasNext()) { | ||
| 86 | + Element itemDevice = deviceListIterator.next(); | ||
| 87 | + Element channelDeviceElement = itemDevice.element("DeviceID"); | ||
| 88 | + if (channelDeviceElement == null) { | ||
| 89 | + continue; | ||
| 90 | + } | ||
| 91 | + Element eventElement = itemDevice.element("Event"); | ||
| 92 | + String event; | ||
| 93 | + if (eventElement == null) { | ||
| 94 | + logger.warn("[收到目录订阅]:{}, 但是Event为空, 设为默认值 ADD", (device != null ? device.getDeviceId():"" )); | ||
| 95 | + event = CatalogEvent.ADD; | ||
| 96 | + }else { | ||
| 97 | + event = eventElement.getText().toUpperCase(); | ||
| 98 | + } | ||
| 99 | + DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event); | ||
| 100 | + | ||
| 101 | + channel.setDeviceId(device.getDeviceId()); | ||
| 102 | + logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId()); | ||
| 103 | + switch (event) { | ||
| 104 | + case CatalogEvent.ON: | ||
| 105 | + // 上线 | ||
| 106 | + logger.info("[收到通道上线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 107 | + updateChannelOnlineList.add(channel); | ||
| 108 | + if (updateChannelOnlineList.size() > 300) { | ||
| 109 | + executeSaveForOnline(); | ||
| 110 | + } | ||
| 111 | + if (userSetting.getDeviceStatusNotify()) { | ||
| 112 | + // 发送redis消息 | ||
| 113 | + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), true); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + break; | ||
| 117 | + case CatalogEvent.OFF : | ||
| 118 | + // 离线 | ||
| 119 | + logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 120 | + if (userSetting.getRefuseChannelStatusChannelFormNotify()) { | ||
| 121 | + logger.info("[收到通道离线通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 122 | + }else { | ||
| 123 | + updateChannelOfflineList.add(channel); | ||
| 124 | + if (updateChannelOfflineList.size() > 300) { | ||
| 125 | + executeSaveForOffline(); | ||
| 126 | + } | ||
| 127 | + if (userSetting.getDeviceStatusNotify()) { | ||
| 128 | + // 发送redis消息 | ||
| 129 | + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false); | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + break; | ||
| 133 | + case CatalogEvent.VLOST: | ||
| 134 | + // 视频丢失 | ||
| 135 | + logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 136 | + if (userSetting.getRefuseChannelStatusChannelFormNotify()) { | ||
| 137 | + logger.info("[收到通道视频丢失通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 138 | + }else { | ||
| 139 | + updateChannelOfflineList.add(channel); | ||
| 140 | + if (updateChannelOfflineList.size() > 300) { | ||
| 141 | + executeSaveForOffline(); | ||
| 142 | + } | ||
| 143 | + if (userSetting.getDeviceStatusNotify()) { | ||
| 144 | + // 发送redis消息 | ||
| 145 | + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false); | ||
| 146 | + } | ||
| 147 | + } | ||
| 148 | + break; | ||
| 149 | + case CatalogEvent.DEFECT: | ||
| 150 | + // 故障 | ||
| 151 | + logger.info("[收到通道视频故障通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 152 | + if (userSetting.getRefuseChannelStatusChannelFormNotify()) { | ||
| 153 | + logger.info("[收到通道视频故障通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 154 | + }else { | ||
| 155 | + updateChannelOfflineList.add(channel); | ||
| 156 | + if (updateChannelOfflineList.size() > 300) { | ||
| 157 | + executeSaveForOffline(); | ||
| 158 | + } | ||
| 159 | + if (userSetting.getDeviceStatusNotify()) { | ||
| 160 | + // 发送redis消息 | ||
| 161 | + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false); | ||
| 162 | + } | ||
| 163 | + } | ||
| 164 | + break; | ||
| 165 | + case CatalogEvent.ADD: | ||
| 166 | + // 增加 | ||
| 167 | + logger.info("[收到增加通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 168 | + // 判断此通道是否存在 | ||
| 169 | + DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, channel.getChannelId()); | ||
| 170 | + if (deviceChannel != null) { | ||
| 171 | + channel.setId(deviceChannel.getId()); | ||
| 172 | + updateChannelMap.put(channel.getChannelId(), channel); | ||
| 173 | + if (updateChannelMap.keySet().size() > 300) { | ||
| 174 | + executeSaveForUpdate(); | ||
| 175 | + } | ||
| 176 | + }else { | ||
| 177 | + addChannelMap.put(channel.getChannelId(), channel); | ||
| 178 | + if (addChannelMap.keySet().size() > 300) { | ||
| 179 | + executeSaveForAdd(); | ||
| 180 | + } | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + break; | ||
| 184 | + case CatalogEvent.DEL: | ||
| 185 | + // 删除 | ||
| 186 | + logger.info("[收到删除通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 187 | + deleteChannelList.add(channel); | ||
| 188 | + if (deleteChannelList.size() > 300) { | ||
| 189 | + executeSaveForDelete(); | ||
| 190 | + } | ||
| 191 | + break; | ||
| 192 | + case CatalogEvent.UPDATE: | ||
| 193 | + // 更新 | ||
| 194 | + logger.info("[收到更新通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 195 | + // 判断此通道是否存在 | ||
| 196 | + DeviceChannel deviceChannelForUpdate = deviceChannelService.getOne(deviceId, channel.getChannelId()); | ||
| 197 | + if (deviceChannelForUpdate != null) { | ||
| 198 | + channel.setId(deviceChannelForUpdate.getId()); | ||
| 199 | + updateChannelMap.put(channel.getChannelId(), channel); | ||
| 200 | + if (updateChannelMap.keySet().size() > 300) { | ||
| 201 | + executeSaveForUpdate(); | ||
| 202 | + } | ||
| 203 | + }else { | ||
| 204 | + addChannelMap.put(channel.getChannelId(), channel); | ||
| 205 | + if (addChannelMap.keySet().size() > 300) { | ||
| 206 | + executeSaveForAdd(); | ||
| 207 | + } | ||
| 208 | + } | ||
| 209 | + break; | ||
| 210 | + default: | ||
| 211 | + logger.warn("[ NotifyCatalog ] event not found : {}", event ); | ||
| 212 | + | ||
| 213 | + } | ||
| 214 | + // 转发变化信息 | ||
| 215 | + eventPublisher.catalogEventPublish(null, channel, event); | ||
| 216 | + | ||
| 217 | + if (updateChannelMap.keySet().size() > 0 | ||
| 218 | + || addChannelMap.keySet().size() > 0 | ||
| 219 | + || updateChannelOnlineList.size() > 0 | ||
| 220 | + || updateChannelOfflineList.size() > 0 | ||
| 221 | + || deleteChannelList.size() > 0) { | ||
| 222 | + | ||
| 223 | + if (!dynamicTask.contains(talkKey)) { | ||
| 224 | + dynamicTask.startDelay(talkKey, this::executeSave, 1000); | ||
| 225 | + } | ||
| 226 | + } | ||
| 227 | + } | ||
| 228 | + } | ||
| 229 | + } catch (DocumentException e) { | ||
| 230 | + logger.error("未处理的异常 ", e); | ||
| 231 | + } | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + private void executeSave(){ | ||
| 235 | + System.out.println("定时存储数据"); | ||
| 236 | + executeSaveForUpdate(); | ||
| 237 | + executeSaveForDelete(); | ||
| 238 | + executeSaveForOnline(); | ||
| 239 | + executeSaveForOffline(); | ||
| 240 | + dynamicTask.stop(talkKey); | ||
| 241 | + } | ||
| 242 | + | ||
| 243 | + private void executeSaveForUpdate(){ | ||
| 244 | + if (updateChannelMap.values().size() > 0) { | ||
| 245 | + ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(updateChannelMap.values()); | ||
| 246 | + updateChannelMap.clear(); | ||
| 247 | + deviceChannelService.batchUpdateChannel(deviceChannels); | ||
| 248 | + } | ||
| 249 | + | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | + private void executeSaveForAdd(){ | ||
| 253 | + if (addChannelMap.values().size() > 0) { | ||
| 254 | + ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(addChannelMap.values()); | ||
| 255 | + addChannelMap.clear(); | ||
| 256 | + deviceChannelService.batchAddChannel(deviceChannels); | ||
| 257 | + } | ||
| 258 | + } | ||
| 259 | + | ||
| 260 | + private void executeSaveForDelete(){ | ||
| 261 | + if (deleteChannelList.size() > 0) { | ||
| 262 | + deviceChannelService.deleteChannels(deleteChannelList); | ||
| 263 | + deleteChannelList.clear(); | ||
| 264 | + } | ||
| 265 | + } | ||
| 266 | + | ||
| 267 | + private void executeSaveForOnline(){ | ||
| 268 | + if (updateChannelOnlineList.size() > 0) { | ||
| 269 | + deviceChannelService.channelsOnline(updateChannelOnlineList); | ||
| 270 | + updateChannelOnlineList.clear(); | ||
| 271 | + } | ||
| 272 | + } | ||
| 273 | + | ||
| 274 | + private void executeSaveForOffline(){ | ||
| 275 | + if (updateChannelOfflineList.size() > 0) { | ||
| 276 | + deviceChannelService.channelsOffline(updateChannelOfflineList); | ||
| 277 | + updateChannelOfflineList.clear(); | ||
| 278 | + } | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | +} |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
| @@ -76,12 +76,17 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -76,12 +76,17 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 76 | @Autowired | 76 | @Autowired |
| 77 | private IDeviceChannelService deviceChannelService; | 77 | private IDeviceChannelService deviceChannelService; |
| 78 | 78 | ||
| 79 | + @Autowired | ||
| 80 | + private NotifyRequestForCatalogProcessor notifyRequestForCatalogProcessor; | ||
| 81 | + | ||
| 79 | private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>(); | 82 | private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>(); |
| 80 | 83 | ||
| 81 | @Qualifier("taskExecutor") | 84 | @Qualifier("taskExecutor") |
| 82 | @Autowired | 85 | @Autowired |
| 83 | private ThreadPoolTaskExecutor taskExecutor; | 86 | private ThreadPoolTaskExecutor taskExecutor; |
| 84 | 87 | ||
| 88 | + private int maxQueueCount = 30000; | ||
| 89 | + | ||
| 85 | @Override | 90 | @Override |
| 86 | public void afterPropertiesSet() throws Exception { | 91 | public void afterPropertiesSet() throws Exception { |
| 87 | // 添加消息处理的订阅 | 92 | // 添加消息处理的订阅 |
| @@ -91,43 +96,52 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -91,43 +96,52 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 91 | @Override | 96 | @Override |
| 92 | public void process(RequestEvent evt) { | 97 | public void process(RequestEvent evt) { |
| 93 | try { | 98 | try { |
| 94 | - responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null); | 99 | + |
| 100 | + if (taskQueue.size() >= userSetting.getMaxNotifyCountQueue()) { | ||
| 101 | + responseAck((SIPRequest) evt.getRequest(), Response.BUSY_HERE, null, null); | ||
| 102 | + logger.error("[notify] 待处理消息队列已满 {},返回486 BUSY_HERE,消息不做处理", userSetting.getMaxNotifyCountQueue()); | ||
| 103 | + return; | ||
| 104 | + }else { | ||
| 105 | + responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null); | ||
| 106 | + } | ||
| 107 | + | ||
| 95 | }catch (SipException | InvalidArgumentException | ParseException e) { | 108 | }catch (SipException | InvalidArgumentException | ParseException e) { |
| 96 | logger.error("未处理的异常 ", e); | 109 | logger.error("未处理的异常 ", e); |
| 97 | } | 110 | } |
| 98 | boolean runed = !taskQueue.isEmpty(); | 111 | boolean runed = !taskQueue.isEmpty(); |
| 112 | + logger.info("[notify] 待处理消息数量: {}", taskQueue.size()); | ||
| 99 | taskQueue.offer(new HandlerCatchData(evt, null, null)); | 113 | taskQueue.offer(new HandlerCatchData(evt, null, null)); |
| 100 | if (!runed) { | 114 | if (!runed) { |
| 101 | taskExecutor.execute(()-> { | 115 | taskExecutor.execute(()-> { |
| 102 | - try { | ||
| 103 | - while (!taskQueue.isEmpty()) { | ||
| 104 | - try { | ||
| 105 | - HandlerCatchData take = taskQueue.poll(); | ||
| 106 | - Element rootElement = getRootElement(take.getEvt()); | ||
| 107 | - if (rootElement == null) { | ||
| 108 | - logger.error("处理NOTIFY消息时未获取到消息体,{}", take.getEvt().getRequest()); | ||
| 109 | - continue; | ||
| 110 | - } | ||
| 111 | - String cmd = XmlUtil.getText(rootElement, "CmdType"); | ||
| 112 | - | ||
| 113 | - if (CmdType.CATALOG.equals(cmd)) { | ||
| 114 | - logger.info("接收到Catalog通知"); | ||
| 115 | - processNotifyCatalogList(take.getEvt()); | ||
| 116 | - } else if (CmdType.ALARM.equals(cmd)) { | ||
| 117 | - logger.info("接收到Alarm通知"); | ||
| 118 | - processNotifyAlarm(take.getEvt()); | ||
| 119 | - } else if (CmdType.MOBILE_POSITION.equals(cmd)) { | ||
| 120 | - logger.info("接收到MobilePosition通知"); | ||
| 121 | - processNotifyMobilePosition(take.getEvt()); | ||
| 122 | - } else { | ||
| 123 | - logger.info("接收到消息:" + cmd); | ||
| 124 | - } | ||
| 125 | - } catch (DocumentException e) { | ||
| 126 | - logger.error("处理NOTIFY消息时错误", e); | 116 | + while (!taskQueue.isEmpty()) { |
| 117 | + try { | ||
| 118 | + HandlerCatchData take = taskQueue.poll(); | ||
| 119 | + if (take == null) { | ||
| 120 | + continue; | ||
| 121 | + } | ||
| 122 | + Element rootElement = getRootElement(take.getEvt()); | ||
| 123 | + if (rootElement == null) { | ||
| 124 | + logger.error("处理NOTIFY消息时未获取到消息体,{}", take.getEvt().getRequest()); | ||
| 125 | + continue; | ||
| 126 | + } | ||
| 127 | + String cmd = XmlUtil.getText(rootElement, "CmdType"); | ||
| 128 | + | ||
| 129 | + if (CmdType.CATALOG.equals(cmd)) { | ||
| 130 | + logger.info("接收到Catalog通知"); | ||
| 131 | +// processNotifyCatalogList(take.getEvt()); | ||
| 132 | + notifyRequestForCatalogProcessor.process(take.getEvt()); | ||
| 133 | + } else if (CmdType.ALARM.equals(cmd)) { | ||
| 134 | + logger.info("接收到Alarm通知"); | ||
| 135 | + processNotifyAlarm(take.getEvt()); | ||
| 136 | + } else if (CmdType.MOBILE_POSITION.equals(cmd)) { | ||
| 137 | + logger.info("接收到MobilePosition通知"); | ||
| 138 | + processNotifyMobilePosition(take.getEvt()); | ||
| 139 | + } else { | ||
| 140 | + logger.info("接收到消息:" + cmd); | ||
| 127 | } | 141 | } |
| 142 | + } catch (DocumentException e) { | ||
| 143 | + logger.error("处理NOTIFY消息时错误", e); | ||
| 128 | } | 144 | } |
| 129 | - }catch (Exception e) { | ||
| 130 | - logger.error("处理NOTIFY消息时错误", e); | ||
| 131 | } | 145 | } |
| 132 | }); | 146 | }); |
| 133 | } | 147 | } |
| @@ -135,7 +149,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -135,7 +149,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 135 | 149 | ||
| 136 | /** | 150 | /** |
| 137 | * 处理MobilePosition移动位置Notify | 151 | * 处理MobilePosition移动位置Notify |
| 138 | - * | 152 | + * |
| 139 | * @param evt | 153 | * @param evt |
| 140 | */ | 154 | */ |
| 141 | private void processNotifyMobilePosition(RequestEvent evt) { | 155 | private void processNotifyMobilePosition(RequestEvent evt) { |
| @@ -239,7 +253,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -239,7 +253,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 239 | 253 | ||
| 240 | /*** | 254 | /*** |
| 241 | * 处理alarm设备报警Notify | 255 | * 处理alarm设备报警Notify |
| 242 | - * | 256 | + * |
| 243 | * @param evt | 257 | * @param evt |
| 244 | */ | 258 | */ |
| 245 | private void processNotifyAlarm(RequestEvent evt) { | 259 | private void processNotifyAlarm(RequestEvent evt) { |
| @@ -349,7 +363,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -349,7 +363,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 349 | 363 | ||
| 350 | /*** | 364 | /*** |
| 351 | * 处理catalog设备目录列表Notify | 365 | * 处理catalog设备目录列表Notify |
| 352 | - * | 366 | + * |
| 353 | * @param evt | 367 | * @param evt |
| 354 | */ | 368 | */ |
| 355 | private void processNotifyCatalogList(RequestEvent evt) { | 369 | private void processNotifyCatalogList(RequestEvent evt) { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
| @@ -83,21 +83,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | @@ -83,21 +83,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | ||
| 83 | public void process(RequestEvent evt) { | 83 | public void process(RequestEvent evt) { |
| 84 | try { | 84 | try { |
| 85 | RequestEventExt evtExt = (RequestEventExt) evt; | 85 | RequestEventExt evtExt = (RequestEventExt) evt; |
| 86 | - String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort(); | ||
| 87 | - | ||
| 88 | -// MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer(); | ||
| 89 | -// QueryExp protocol = Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")); | ||
| 90 | -//// ObjectName name = new ObjectName("*:type=Connector,*"); | ||
| 91 | -// ObjectName name = new ObjectName("*:*"); | ||
| 92 | -// Set<ObjectName> objectNames = beanServer.queryNames(name, protocol); | ||
| 93 | -// for (ObjectName objectName : objectNames) { | ||
| 94 | -// String catalina = objectName.getDomain(); | ||
| 95 | -// if ("Catalina".equals(catalina)) { | ||
| 96 | -// System.out.println(objectName.getKeyProperty("port")); | ||
| 97 | -// } | ||
| 98 | -// } | ||
| 99 | - | ||
| 100 | -// System.out.println(ServiceInfo.getServerPort()); | 86 | + |
| 101 | SIPRequest request = (SIPRequest)evt.getRequest(); | 87 | SIPRequest request = (SIPRequest)evt.getRequest(); |
| 102 | Response response = null; | 88 | Response response = null; |
| 103 | boolean passwordCorrect = false; | 89 | boolean passwordCorrect = false; |
| @@ -107,12 +93,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | @@ -107,12 +93,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | ||
| 107 | AddressImpl address = (AddressImpl) fromHeader.getAddress(); | 93 | AddressImpl address = (AddressImpl) fromHeader.getAddress(); |
| 108 | SipUri uri = (SipUri) address.getURI(); | 94 | SipUri uri = (SipUri) address.getURI(); |
| 109 | String deviceId = uri.getUser(); | 95 | String deviceId = uri.getUser(); |
| 110 | - logger.info("[注册请求] 设备:{}, 开始处理: {}", deviceId, requestAddress); | 96 | + |
| 111 | Device device = deviceService.getDevice(deviceId); | 97 | Device device = deviceService.getDevice(deviceId); |
| 112 | 98 | ||
| 113 | RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, | 99 | RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, |
| 114 | userSetting.getSipUseSourceIpAsRemoteAddress()); | 100 | userSetting.getSipUseSourceIpAsRemoteAddress()); |
| 115 | - | 101 | + String requestAddress = remoteAddressInfo.getIp() + ":" + remoteAddressInfo.getPort(); |
| 102 | + logger.info("[注册请求] 设备:{}, 开始处理: {}", deviceId, requestAddress); | ||
| 116 | if (device != null && | 103 | if (device != null && |
| 117 | device.getSipTransactionInfo() != null && | 104 | device.getSipTransactionInfo() != null && |
| 118 | request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) { | 105 | request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.info; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.info; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.common.StreamInfo; | 3 | +import com.genersoft.iot.vmp.common.InviteInfo; |
| 4 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 4 | import com.genersoft.iot.vmp.gb28181.bean.*; | 5 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 5 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 6 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 6 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 7 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| @@ -9,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | @@ -9,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 9 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; | 10 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | 11 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 11 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | 12 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| 13 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | ||
| 12 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 14 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 13 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 15 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 14 | import gov.nist.javax.sip.message.SIPRequest; | 16 | import gov.nist.javax.sip.message.SIPRequest; |
| @@ -17,10 +19,12 @@ import org.slf4j.LoggerFactory; | @@ -17,10 +19,12 @@ import org.slf4j.LoggerFactory; | ||
| 17 | import org.springframework.beans.factory.InitializingBean; | 19 | import org.springframework.beans.factory.InitializingBean; |
| 18 | import org.springframework.beans.factory.annotation.Autowired; | 20 | import org.springframework.beans.factory.annotation.Autowired; |
| 19 | import org.springframework.stereotype.Component; | 21 | import org.springframework.stereotype.Component; |
| 22 | + | ||
| 20 | import javax.sip.InvalidArgumentException; | 23 | import javax.sip.InvalidArgumentException; |
| 21 | import javax.sip.RequestEvent; | 24 | import javax.sip.RequestEvent; |
| 22 | import javax.sip.SipException; | 25 | import javax.sip.SipException; |
| 23 | -import javax.sip.header.*; | 26 | +import javax.sip.header.CallIdHeader; |
| 27 | +import javax.sip.header.ContentTypeHeader; | ||
| 24 | import javax.sip.message.Response; | 28 | import javax.sip.message.Response; |
| 25 | import java.text.ParseException; | 29 | import java.text.ParseException; |
| 26 | 30 | ||
| @@ -44,6 +48,9 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I | @@ -44,6 +48,9 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I | ||
| 44 | private IRedisCatchStorage redisCatchStorage; | 48 | private IRedisCatchStorage redisCatchStorage; |
| 45 | 49 | ||
| 46 | @Autowired | 50 | @Autowired |
| 51 | + private IInviteStreamService inviteStreamService; | ||
| 52 | + | ||
| 53 | + @Autowired | ||
| 47 | private IVideoManagerStorage storager; | 54 | private IVideoManagerStorage storager; |
| 48 | 55 | ||
| 49 | @Autowired | 56 | @Autowired |
| @@ -103,27 +110,30 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I | @@ -103,27 +110,30 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I | ||
| 103 | if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) { | 110 | if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) { |
| 104 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); | 111 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); |
| 105 | String streamId = sendRtpItem.getStream(); | 112 | String streamId = sendRtpItem.getStream(); |
| 106 | - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); | ||
| 107 | - if (null == streamInfo) { | 113 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); |
| 114 | + if (null == inviteInfo) { | ||
| 108 | responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found"); | 115 | responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found"); |
| 109 | return; | 116 | return; |
| 110 | } | 117 | } |
| 111 | - Device device1 = storager.queryVideoDevice(streamInfo.getDeviceID()); | ||
| 112 | - cmder.playbackControlCmd(device1,streamInfo,new String(evt.getRequest().getRawContent()),eventResult -> { | ||
| 113 | - // 失败的回复 | ||
| 114 | - try { | ||
| 115 | - responseAck(request, eventResult.statusCode, eventResult.msg); | ||
| 116 | - } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 117 | - logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage()); | ||
| 118 | - } | ||
| 119 | - }, eventResult -> { | ||
| 120 | - // 成功的回复 | ||
| 121 | - try { | ||
| 122 | - responseAck(request, eventResult.statusCode); | ||
| 123 | - } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 124 | - logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage()); | ||
| 125 | - } | ||
| 126 | - }); | 118 | + Device device1 = storager.queryVideoDevice(inviteInfo.getDeviceId()); |
| 119 | + if (inviteInfo.getStreamInfo() != null) { | ||
| 120 | + cmder.playbackControlCmd(device1,inviteInfo.getStreamInfo(),new String(evt.getRequest().getRawContent()),eventResult -> { | ||
| 121 | + // 失败的回复 | ||
| 122 | + try { | ||
| 123 | + responseAck(request, eventResult.statusCode, eventResult.msg); | ||
| 124 | + } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 125 | + logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage()); | ||
| 126 | + } | ||
| 127 | + }, eventResult -> { | ||
| 128 | + // 成功的回复 | ||
| 129 | + try { | ||
| 130 | + responseAck(request, eventResult.statusCode); | ||
| 131 | + } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 132 | + logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage()); | ||
| 133 | + } | ||
| 134 | + }); | ||
| 135 | + } | ||
| 136 | + | ||
| 127 | } | 137 | } |
| 128 | } | 138 | } |
| 129 | } catch (SipException e) { | 139 | } catch (SipException e) { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
| @@ -69,6 +69,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp | @@ -69,6 +69,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp | ||
| 69 | 69 | ||
| 70 | RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress()); | 70 | RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress()); |
| 71 | if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) { | 71 | if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) { |
| 72 | + logger.info("[心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort()); | ||
| 72 | device.setPort(remoteAddressInfo.getPort()); | 73 | device.setPort(remoteAddressInfo.getPort()); |
| 73 | device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); | 74 | device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); |
| 74 | device.setIp(remoteAddressInfo.getIp()); | 75 | device.setIp(remoteAddressInfo.getIp()); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.common.StreamInfo; | 3 | +import com.genersoft.iot.vmp.common.InviteInfo; |
| 4 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 4 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 5 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 5 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 6 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 6 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | 7 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| @@ -12,6 +13,10 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | @@ -12,6 +13,10 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | ||
| 12 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 13 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; | 14 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
| 14 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; | 15 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; |
| 16 | +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | ||
| 17 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | ||
| 18 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; | ||
| 19 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | ||
| 15 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 20 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 16 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 21 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 17 | import gov.nist.javax.sip.message.SIPRequest; | 22 | import gov.nist.javax.sip.message.SIPRequest; |
| @@ -58,6 +63,15 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | @@ -58,6 +63,15 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | ||
| 58 | @Autowired | 63 | @Autowired |
| 59 | private VideoStreamSessionManager sessionManager; | 64 | private VideoStreamSessionManager sessionManager; |
| 60 | 65 | ||
| 66 | + @Autowired | ||
| 67 | + private ZlmHttpHookSubscribe subscribe; | ||
| 68 | + | ||
| 69 | + @Autowired | ||
| 70 | + private IInviteStreamService inviteStreamService; | ||
| 71 | + | ||
| 72 | + @Autowired | ||
| 73 | + private VideoStreamSessionManager streamSession; | ||
| 74 | + | ||
| 61 | @Override | 75 | @Override |
| 62 | public void afterPropertiesSet() throws Exception { | 76 | public void afterPropertiesSet() throws Exception { |
| 63 | notifyMessageHandler.addHandler(cmdType, this); | 77 | notifyMessageHandler.addHandler(cmdType, this); |
| @@ -76,23 +90,24 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | @@ -76,23 +90,24 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | ||
| 76 | String NotifyType =getText(rootElement, "NotifyType"); | 90 | String NotifyType =getText(rootElement, "NotifyType"); |
| 77 | if ("121".equals(NotifyType)){ | 91 | if ("121".equals(NotifyType)){ |
| 78 | logger.info("[录像流]推送完毕,收到关流通知"); | 92 | logger.info("[录像流]推送完毕,收到关流通知"); |
| 79 | - // 查询是设备 | ||
| 80 | - StreamInfo streamInfo = redisCatchStorage.queryDownload(null, null, null, callIdHeader.getCallId()); | ||
| 81 | - if (streamInfo != null) { | ||
| 82 | - // 设置进度100% | ||
| 83 | - streamInfo.setProgress(1); | ||
| 84 | - redisCatchStorage.startDownload(streamInfo, callIdHeader.getCallId()); | ||
| 85 | - } | ||
| 86 | 93 | ||
| 87 | - // 先从会话内查找 | ||
| 88 | - SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); | ||
| 89 | - if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题 | 94 | + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); |
| 95 | + if (ssrcTransaction != null) { | ||
| 96 | + logger.info("[录像流]推送完毕,关流通知, device: {}, channelId: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); | ||
| 97 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); | ||
| 98 | + if (inviteInfo.getStreamInfo() != null) { | ||
| 99 | + inviteInfo.getStreamInfo().setProgress(1); | ||
| 100 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 101 | + } | ||
| 90 | 102 | ||
| 91 | try { | 103 | try { |
| 92 | cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId()); | 104 | cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId()); |
| 93 | } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | 105 | } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { |
| 94 | logger.error("[录像流]推送完毕,收到关流通知, 发送BYE失败 {}", e.getMessage()); | 106 | logger.error("[录像流]推送完毕,收到关流通知, 发送BYE失败 {}", e.getMessage()); |
| 95 | } | 107 | } |
| 108 | + // 去除监听流注销自动停止下载的监听 | ||
| 109 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcTransaction.getStream(), false, "rtsp", ssrcTransaction.getMediaServerId()); | ||
| 110 | + subscribe.removeSubscribe(hookSubscribe); | ||
| 96 | 111 | ||
| 97 | // 如果级联播放,需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题,需要将点播CallId进行上下级绑定 | 112 | // 如果级联播放,需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题,需要将点播CallId进行上下级绑定 |
| 98 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null); | 113 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null); |
| @@ -108,6 +123,8 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | @@ -108,6 +123,8 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | ||
| 108 | logger.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage()); | 123 | logger.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage()); |
| 109 | } | 124 | } |
| 110 | } | 125 | } |
| 126 | + }else { | ||
| 127 | + logger.info("[录像流]推送完毕,关流通知, 但是未找到对应的下载信息"); | ||
| 111 | } | 128 | } |
| 112 | } | 129 | } |
| 113 | } | 130 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
| @@ -18,6 +18,10 @@ import javax.sdp.SessionDescription; | @@ -18,6 +18,10 @@ import javax.sdp.SessionDescription; | ||
| 18 | import javax.sip.InvalidArgumentException; | 18 | import javax.sip.InvalidArgumentException; |
| 19 | import javax.sip.ResponseEvent; | 19 | import javax.sip.ResponseEvent; |
| 20 | import javax.sip.SipException; | 20 | import javax.sip.SipException; |
| 21 | +import javax.sip.InvalidArgumentException; | ||
| 22 | +import javax.sip.ResponseEvent; | ||
| 23 | +import javax.sip.SipException; | ||
| 24 | +import javax.sip.SipFactory; | ||
| 21 | import javax.sip.address.SipURI; | 25 | import javax.sip.address.SipURI; |
| 22 | import javax.sip.message.Request; | 26 | import javax.sip.message.Request; |
| 23 | import javax.sip.message.Response; | 27 | import javax.sip.message.Response; |
| @@ -91,7 +95,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { | @@ -91,7 +95,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { | ||
| 91 | } | 95 | } |
| 92 | // 查看是否是来自设备的,此是回复 | 96 | // 查看是否是来自设备的,此是回复 |
| 93 | 97 | ||
| 94 | - SipURI requestUri = sipLayer.getSipFactory().createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), event.getRemoteIpAddress() + ":" + event.getRemotePort()); | 98 | + SipURI requestUri = SipFactory.getInstance().createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), event.getRemoteIpAddress() + ":" + event.getRemotePort()); |
| 95 | Request reqAck = headerProvider.createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response); | 99 | Request reqAck = headerProvider.createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response); |
| 96 | 100 | ||
| 97 | logger.info("[回复ack] {}-> {}:{} ", sdp.getOrigin().getUsername(), event.getRemoteIpAddress(), event.getRemotePort()); | 101 | logger.info("[回复ack] {}-> {}:{} ", sdp.getOrigin().getUsername(), event.getRemoteIpAddress(), event.getRemotePort()); |
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
| @@ -54,7 +54,7 @@ public class SipUtils { | @@ -54,7 +54,7 @@ public class SipUtils { | ||
| 54 | return "z9hG4bK" + System.currentTimeMillis(); | 54 | return "z9hG4bK" + System.currentTimeMillis(); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | - public static UserAgentHeader createUserAgentHeader(SipFactory sipFactory, GitUtil gitUtil) throws PeerUnavailableException, ParseException { | 57 | + public static UserAgentHeader createUserAgentHeader(GitUtil gitUtil) throws PeerUnavailableException, ParseException { |
| 58 | List<String> agentParam = new ArrayList<>(); | 58 | List<String> agentParam = new ArrayList<>(); |
| 59 | agentParam.add("WVP-Pro "); | 59 | agentParam.add("WVP-Pro "); |
| 60 | if (gitUtil != null ) { | 60 | if (gitUtil != null ) { |
| @@ -66,7 +66,7 @@ public class SipUtils { | @@ -66,7 +66,7 @@ public class SipUtils { | ||
| 66 | agentParam.add(gitUtil.getCommitTime()); | 66 | agentParam.add(gitUtil.getCommitTime()); |
| 67 | } | 67 | } |
| 68 | } | 68 | } |
| 69 | - return sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); | 69 | + return SipFactory.getInstance().createHeaderFactory().createUserAgentHeader(agentParam); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | public static String getNewFromTag(){ | 72 | public static String getNewFromTag(){ |
| @@ -153,8 +153,9 @@ public class SipUtils { | @@ -153,8 +153,9 @@ public class SipUtils { | ||
| 153 | String remoteAddress; | 153 | String remoteAddress; |
| 154 | int remotePort; | 154 | int remotePort; |
| 155 | if (sipUseSourceIpAsRemoteAddress) { | 155 | if (sipUseSourceIpAsRemoteAddress) { |
| 156 | - remoteAddress = request.getRemoteAddress().getHostAddress(); | ||
| 157 | - remotePort = request.getRemotePort(); | 156 | + remoteAddress = request.getPeerPacketSourceAddress().getHostAddress(); |
| 157 | + remotePort = request.getPeerPacketSourcePort(); | ||
| 158 | + | ||
| 158 | }else { | 159 | }else { |
| 159 | // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息 | 160 | // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息 |
| 160 | // 获取到通信地址等信息 | 161 | // 获取到通信地址等信息 |
| @@ -162,8 +163,8 @@ public class SipUtils { | @@ -162,8 +163,8 @@ public class SipUtils { | ||
| 162 | remotePort = request.getTopmostViaHeader().getRPort(); | 163 | remotePort = request.getTopmostViaHeader().getRPort(); |
| 163 | // 解析本地地址替代 | 164 | // 解析本地地址替代 |
| 164 | if (ObjectUtils.isEmpty(remoteAddress) || remotePort == -1) { | 165 | if (ObjectUtils.isEmpty(remoteAddress) || remotePort == -1) { |
| 165 | - remoteAddress = request.getTopmostViaHeader().getHost(); | ||
| 166 | - remotePort = request.getTopmostViaHeader().getPort(); | 166 | + remoteAddress = request.getPeerPacketSourceAddress().getHostAddress(); |
| 167 | + remotePort = request.getPeerPacketSourcePort(); | ||
| 167 | } | 168 | } |
| 168 | } | 169 | } |
| 169 | 170 |
src/main/java/com/genersoft/iot/vmp/jt1078/annotation/MsgId.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.annotation; | ||
| 2 | + | ||
| 3 | +import java.lang.annotation.*; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * @author QingtaiJiang | ||
| 7 | + * @date 2023/4/27 18:31 | ||
| 8 | + * @email qingtaij@163.com | ||
| 9 | + */ | ||
| 10 | +@Target(ElementType.TYPE) | ||
| 11 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 12 | +@Documented | ||
| 13 | +public @interface MsgId { | ||
| 14 | + String id(); | ||
| 15 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/cmd/JT1078Template.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.cmd; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.proc.entity.Cmd; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.response.*; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.session.SessionManager; | ||
| 6 | + | ||
| 7 | +import java.util.Random; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * @author QingtaiJiang | ||
| 11 | + * @date 2023/4/27 18:58 | ||
| 12 | + * @email qingtaij@163.com | ||
| 13 | + */ | ||
| 14 | +public class JT1078Template { | ||
| 15 | + | ||
| 16 | + private final Random random = new Random(); | ||
| 17 | + | ||
| 18 | + private static final String H9101 = "9101"; | ||
| 19 | + private static final String H9102 = "9102"; | ||
| 20 | + private static final String H9201 = "9201"; | ||
| 21 | + private static final String H9202 = "9202"; | ||
| 22 | + private static final String H9205 = "9205"; | ||
| 23 | + | ||
| 24 | + private static final String H0001 = "0001"; | ||
| 25 | + private static final String H1205 = "1205"; | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 开启直播视频 | ||
| 29 | + * | ||
| 30 | + * @param devId 设备号 | ||
| 31 | + * @param j9101 开启视频参数 | ||
| 32 | + */ | ||
| 33 | + public String startLive(String devId, J9101 j9101, Integer timeOut) { | ||
| 34 | + Cmd cmd = new Cmd.Builder() | ||
| 35 | + .setDevId(devId) | ||
| 36 | + .setPackageNo(randomInt()) | ||
| 37 | + .setMsgId(H9101) | ||
| 38 | + .setRespId(H0001) | ||
| 39 | + .setRs(j9101) | ||
| 40 | + .build(); | ||
| 41 | + return SessionManager.INSTANCE.request(cmd, timeOut); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * 关闭直播视频 | ||
| 46 | + * | ||
| 47 | + * @param devId 设备号 | ||
| 48 | + * @param j9102 关闭视频参数 | ||
| 49 | + */ | ||
| 50 | + public String stopLive(String devId, J9102 j9102, Integer timeOut) { | ||
| 51 | + Cmd cmd = new Cmd.Builder() | ||
| 52 | + .setDevId(devId) | ||
| 53 | + .setPackageNo(randomInt()) | ||
| 54 | + .setMsgId(H9102) | ||
| 55 | + .setRespId(H0001) | ||
| 56 | + .setRs(j9102) | ||
| 57 | + .build(); | ||
| 58 | + return SessionManager.INSTANCE.request(cmd, timeOut); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * 查询音视频列表 | ||
| 63 | + * | ||
| 64 | + * @param devId 设备号 | ||
| 65 | + * @param j9205 查询音视频列表 | ||
| 66 | + */ | ||
| 67 | + public String queryBackTime(String devId, J9205 j9205, Integer timeOut) { | ||
| 68 | + Cmd cmd = new Cmd.Builder() | ||
| 69 | + .setDevId(devId) | ||
| 70 | + .setPackageNo(randomInt()) | ||
| 71 | + .setMsgId(H9205) | ||
| 72 | + .setRespId(H1205) | ||
| 73 | + .setRs(j9205) | ||
| 74 | + .build(); | ||
| 75 | + return SessionManager.INSTANCE.request(cmd, timeOut); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + /** | ||
| 79 | + * 开启视频回放 | ||
| 80 | + * | ||
| 81 | + * @param devId 设备号 | ||
| 82 | + * @param j9201 视频回放参数 | ||
| 83 | + */ | ||
| 84 | + public String startBackLive(String devId, J9201 j9201, Integer timeOut) { | ||
| 85 | + Cmd cmd = new Cmd.Builder() | ||
| 86 | + .setDevId(devId) | ||
| 87 | + .setPackageNo(randomInt()) | ||
| 88 | + .setMsgId(H9201) | ||
| 89 | + .setRespId(H1205) | ||
| 90 | + .setRs(j9201) | ||
| 91 | + .build(); | ||
| 92 | + return SessionManager.INSTANCE.request(cmd, timeOut); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + /** | ||
| 96 | + * 视频回放控制 | ||
| 97 | + * | ||
| 98 | + * @param devId 设备号 | ||
| 99 | + * @param j9202 控制视频回放参数 | ||
| 100 | + */ | ||
| 101 | + public String controlBackLive(String devId, J9202 j9202, Integer timeOut) { | ||
| 102 | + Cmd cmd = new Cmd.Builder() | ||
| 103 | + .setDevId(devId) | ||
| 104 | + .setPackageNo(randomInt()) | ||
| 105 | + .setMsgId(H9202) | ||
| 106 | + .setRespId(H0001) | ||
| 107 | + .setRs(j9202) | ||
| 108 | + .build(); | ||
| 109 | + return SessionManager.INSTANCE.request(cmd, timeOut); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + private Long randomInt() { | ||
| 113 | + return (long) random.nextInt(1000) + 1; | ||
| 114 | + } | ||
| 115 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/codec/decode/Jt808Decoder.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.codec.decode; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.factory.CodecFactory; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.proc.request.Re; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 7 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 8 | +import io.netty.buffer.ByteBuf; | ||
| 9 | +import io.netty.buffer.ByteBufUtil; | ||
| 10 | +import io.netty.buffer.CompositeByteBuf; | ||
| 11 | +import io.netty.buffer.UnpooledByteBufAllocator; | ||
| 12 | +import io.netty.channel.ChannelHandlerContext; | ||
| 13 | +import io.netty.handler.codec.ByteToMessageDecoder; | ||
| 14 | +import org.slf4j.Logger; | ||
| 15 | +import org.slf4j.LoggerFactory; | ||
| 16 | + | ||
| 17 | +import java.util.ArrayList; | ||
| 18 | +import java.util.List; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * @author QingtaiJiang | ||
| 22 | + * @date 2023/4/27 18:10 | ||
| 23 | + * @email qingtaij@163.com | ||
| 24 | + */ | ||
| 25 | +public class Jt808Decoder extends ByteToMessageDecoder { | ||
| 26 | + private final static Logger log = LoggerFactory.getLogger(Jt808Decoder.class); | ||
| 27 | + | ||
| 28 | + @Override | ||
| 29 | + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { | ||
| 30 | + Session session = ctx.channel().attr(Session.KEY).get(); | ||
| 31 | + log.info("> {} hex:{}", session, ByteBufUtil.hexDump(in)); | ||
| 32 | + | ||
| 33 | + try { | ||
| 34 | + ByteBuf buf = unEscapeAndCheck(in); | ||
| 35 | + | ||
| 36 | + Header header = new Header(); | ||
| 37 | + header.setMsgId(ByteBufUtil.hexDump(buf.readSlice(2))); | ||
| 38 | + header.setMsgPro(buf.readUnsignedShort()); | ||
| 39 | + if (header.is2019Version()) { | ||
| 40 | + header.setVersion(buf.readUnsignedByte()); | ||
| 41 | + String devId = ByteBufUtil.hexDump(buf.readSlice(10)); | ||
| 42 | + header.setDevId(devId.replaceFirst("^0*", "")); | ||
| 43 | + } else { | ||
| 44 | + header.setDevId(ByteBufUtil.hexDump(buf.readSlice(6)).replaceFirst("^0*", "")); | ||
| 45 | + } | ||
| 46 | + header.setSn(buf.readUnsignedShort()); | ||
| 47 | + | ||
| 48 | + Re handler = CodecFactory.getHandler(header.getMsgId()); | ||
| 49 | + if (handler == null) { | ||
| 50 | + log.error("get msgId is null {}", header.getMsgId()); | ||
| 51 | + return; | ||
| 52 | + } | ||
| 53 | + Rs decode = handler.decode(buf, header, session); | ||
| 54 | + if (decode != null) { | ||
| 55 | + out.add(decode); | ||
| 56 | + } | ||
| 57 | + } finally { | ||
| 58 | + in.skipBytes(in.readableBytes()); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + | ||
| 65 | + /** | ||
| 66 | + * 转义与验证校验码 | ||
| 67 | + * | ||
| 68 | + * @param byteBuf 转义Buf | ||
| 69 | + * @return 转义好的数据 | ||
| 70 | + */ | ||
| 71 | + public ByteBuf unEscapeAndCheck(ByteBuf byteBuf) throws Exception { | ||
| 72 | + int low = byteBuf.readerIndex(); | ||
| 73 | + int high = byteBuf.writerIndex(); | ||
| 74 | + byte checkSum = 0; | ||
| 75 | + int calculationCheckSum = 0; | ||
| 76 | + | ||
| 77 | + byte aByte = byteBuf.getByte(high - 2); | ||
| 78 | + byte protocolEscapeFlag7d = 0x7d; | ||
| 79 | + //0x7d转义 | ||
| 80 | + byte protocolEscapeFlag01 = 0x01; | ||
| 81 | + //0x7e转义 | ||
| 82 | + byte protocolEscapeFlag02 = 0x02; | ||
| 83 | + if (aByte == protocolEscapeFlag7d) { | ||
| 84 | + byte b2 = byteBuf.getByte(high - 1); | ||
| 85 | + if (b2 == protocolEscapeFlag01) { | ||
| 86 | + checkSum = protocolEscapeFlag7d; | ||
| 87 | + } else if (b2 == protocolEscapeFlag02) { | ||
| 88 | + checkSum = 0x7e; | ||
| 89 | + } else { | ||
| 90 | + log.error("转义1异常:{}", ByteBufUtil.hexDump(byteBuf)); | ||
| 91 | + throw new Exception("转义错误"); | ||
| 92 | + } | ||
| 93 | + high = high - 2; | ||
| 94 | + } else { | ||
| 95 | + high = high - 1; | ||
| 96 | + checkSum = byteBuf.getByte(high); | ||
| 97 | + } | ||
| 98 | + List<ByteBuf> bufList = new ArrayList<>(); | ||
| 99 | + int index = low; | ||
| 100 | + while (index < high) { | ||
| 101 | + byte b = byteBuf.getByte(index); | ||
| 102 | + if (b == protocolEscapeFlag7d) { | ||
| 103 | + byte c = byteBuf.getByte(index + 1); | ||
| 104 | + if (c == protocolEscapeFlag01) { | ||
| 105 | + ByteBuf slice = slice0x01(byteBuf, low, index); | ||
| 106 | + bufList.add(slice); | ||
| 107 | + b = protocolEscapeFlag7d; | ||
| 108 | + } else if (c == protocolEscapeFlag02) { | ||
| 109 | + ByteBuf slice = slice0x02(byteBuf, low, index); | ||
| 110 | + bufList.add(slice); | ||
| 111 | + b = 0x7e; | ||
| 112 | + } else { | ||
| 113 | + log.error("转义2异常:{}", ByteBufUtil.hexDump(byteBuf)); | ||
| 114 | + throw new Exception("转义错误"); | ||
| 115 | + } | ||
| 116 | + index += 2; | ||
| 117 | + low = index; | ||
| 118 | + } else { | ||
| 119 | + index += 1; | ||
| 120 | + } | ||
| 121 | + calculationCheckSum = calculationCheckSum ^ b; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + if (calculationCheckSum == checkSum) { | ||
| 125 | + if (bufList.size() == 0) { | ||
| 126 | + return byteBuf.slice(low, high); | ||
| 127 | + } else { | ||
| 128 | + bufList.add(byteBuf.slice(low, high - low)); | ||
| 129 | + return new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, false, bufList.size(), bufList); | ||
| 130 | + } | ||
| 131 | + } else { | ||
| 132 | + log.info("{} 解析校验码:{}--计算校验码:{}", ByteBufUtil.hexDump(byteBuf), checkSum, calculationCheckSum); | ||
| 133 | + throw new Exception("校验码错误!"); | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + | ||
| 138 | + private ByteBuf slice0x01(ByteBuf buf, int low, int sign) { | ||
| 139 | + return buf.slice(low, sign - low + 1); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + private ByteBuf slice0x02(ByteBuf buf, int low, int sign) { | ||
| 143 | + buf.setByte(sign, 0x7e); | ||
| 144 | + return buf.slice(low, sign - low + 1); | ||
| 145 | + } | ||
| 146 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/codec/encode/Jt808Encoder.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.codec.encode; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 6 | +import io.netty.buffer.ByteBuf; | ||
| 7 | +import io.netty.buffer.ByteBufUtil; | ||
| 8 | +import io.netty.channel.ChannelHandlerContext; | ||
| 9 | +import io.netty.handler.codec.MessageToByteEncoder; | ||
| 10 | +import org.slf4j.Logger; | ||
| 11 | +import org.slf4j.LoggerFactory; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * @author QingtaiJiang | ||
| 15 | + * @date 2023/4/27 18:10 | ||
| 16 | + * @email qingtaij@163.com | ||
| 17 | + */ | ||
| 18 | +public class Jt808Encoder extends MessageToByteEncoder<Rs> { | ||
| 19 | + private final static Logger log = LoggerFactory.getLogger(Jt808Encoder.class); | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + protected void encode(ChannelHandlerContext ctx, Rs msg, ByteBuf out) throws Exception { | ||
| 23 | + Session session = ctx.channel().attr(Session.KEY).get(); | ||
| 24 | + | ||
| 25 | + ByteBuf encode = Jt808EncoderCmd.encode(msg, session, session.nextSerialNo()); | ||
| 26 | + if(encode!=null){ | ||
| 27 | + log.info("< {} hex:{}", session, ByteBufUtil.hexDump(encode)); | ||
| 28 | + out.writeBytes(encode); | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/codec/encode/Jt808EncoderCmd.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.codec.encode; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.proc.entity.Cmd; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 7 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 8 | +import com.genersoft.iot.vmp.jt1078.util.Bin; | ||
| 9 | +import io.netty.buffer.ByteBuf; | ||
| 10 | +import io.netty.buffer.ByteBufUtil; | ||
| 11 | +import io.netty.buffer.CompositeByteBuf; | ||
| 12 | +import io.netty.buffer.Unpooled; | ||
| 13 | +import io.netty.channel.ChannelHandlerContext; | ||
| 14 | +import io.netty.handler.codec.MessageToByteEncoder; | ||
| 15 | +import io.netty.util.ByteProcessor; | ||
| 16 | +import org.slf4j.Logger; | ||
| 17 | +import org.slf4j.LoggerFactory; | ||
| 18 | +import org.springframework.util.StringUtils; | ||
| 19 | + | ||
| 20 | +import java.util.LinkedList; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * @author QingtaiJiang | ||
| 24 | + * @date 2023/4/27 18:25 | ||
| 25 | + * @email qingtaij@163.com | ||
| 26 | + */ | ||
| 27 | +public class Jt808EncoderCmd extends MessageToByteEncoder<Cmd> { | ||
| 28 | + private final static Logger log = LoggerFactory.getLogger(Jt808EncoderCmd.class); | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + protected void encode(ChannelHandlerContext ctx, Cmd cmd, ByteBuf out) throws Exception { | ||
| 32 | + Session session = ctx.channel().attr(Session.KEY).get(); | ||
| 33 | + Rs msg = cmd.getRs(); | ||
| 34 | + ByteBuf encode = encode(msg, session, cmd.getPackageNo().intValue()); | ||
| 35 | + if (encode != null) { | ||
| 36 | + log.info("< {} hex:{}", session, ByteBufUtil.hexDump(encode)); | ||
| 37 | + out.writeBytes(encode); | ||
| 38 | + } | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + public static ByteBuf encode(Rs msg, Session session, Integer packageNo) { | ||
| 43 | + String id = msg.getClass().getAnnotation(MsgId.class).id(); | ||
| 44 | + if (!StringUtils.hasLength(id)) { | ||
| 45 | + log.error("Not find msgId"); | ||
| 46 | + return null; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + ByteBuf byteBuf = Unpooled.buffer(); | ||
| 50 | + | ||
| 51 | + byteBuf.writeBytes(ByteBufUtil.decodeHexDump(id)); | ||
| 52 | + | ||
| 53 | + ByteBuf encode = msg.encode(); | ||
| 54 | + | ||
| 55 | + Header header = msg.getHeader(); | ||
| 56 | + if (header == null) { | ||
| 57 | + header = session.getHeader(); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + if (header.is2019Version()) { | ||
| 61 | + // 消息体属性 | ||
| 62 | + byteBuf.writeShort(encode.readableBytes() | 1 << 14); | ||
| 63 | + | ||
| 64 | + // 版本号 | ||
| 65 | + byteBuf.writeByte(header.getVersion()); | ||
| 66 | + | ||
| 67 | + // 终端手机号 | ||
| 68 | + byteBuf.writeBytes(ByteBufUtil.decodeHexDump(Bin.strHexPaddingLeft(header.getDevId(), 20))); | ||
| 69 | + } else { | ||
| 70 | + // 消息体属性 | ||
| 71 | + byteBuf.writeShort(encode.readableBytes()); | ||
| 72 | + | ||
| 73 | + byteBuf.writeBytes(ByteBufUtil.decodeHexDump(Bin.strHexPaddingLeft(header.getDevId(), 12))); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + // 消息体流水号 | ||
| 77 | + byteBuf.writeShort(packageNo); | ||
| 78 | + | ||
| 79 | + // 写入消息体 | ||
| 80 | + byteBuf.writeBytes(encode); | ||
| 81 | + | ||
| 82 | + // 计算校验码,并反转义 | ||
| 83 | + byteBuf = escapeAndCheck0(byteBuf); | ||
| 84 | + return byteBuf; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + | ||
| 88 | + private static final ByteProcessor searcher = value -> !(value == 0x7d || value == 0x7e); | ||
| 89 | + | ||
| 90 | + //转义与校验 | ||
| 91 | + public static ByteBuf escapeAndCheck0(ByteBuf source) { | ||
| 92 | + | ||
| 93 | + sign(source); | ||
| 94 | + | ||
| 95 | + int low = source.readerIndex(); | ||
| 96 | + int high = source.writerIndex(); | ||
| 97 | + | ||
| 98 | + LinkedList<ByteBuf> bufList = new LinkedList<>(); | ||
| 99 | + int mark, len; | ||
| 100 | + while ((mark = source.forEachByte(low, high - low, searcher)) > 0) { | ||
| 101 | + | ||
| 102 | + len = mark + 1 - low; | ||
| 103 | + ByteBuf[] slice = slice(source, low, len); | ||
| 104 | + bufList.add(slice[0]); | ||
| 105 | + bufList.add(slice[1]); | ||
| 106 | + low += len; | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + if (bufList.size() > 0) { | ||
| 110 | + bufList.add(source.slice(low, high - low)); | ||
| 111 | + } else { | ||
| 112 | + bufList.add(source); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + ByteBuf delimiter = Unpooled.buffer(1, 1).writeByte(0x7e).retain(); | ||
| 116 | + bufList.addFirst(delimiter); | ||
| 117 | + bufList.addLast(delimiter); | ||
| 118 | + | ||
| 119 | + CompositeByteBuf byteBufLs = Unpooled.compositeBuffer(bufList.size()); | ||
| 120 | + byteBufLs.addComponents(true, bufList); | ||
| 121 | + return byteBufLs; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + public static void sign(ByteBuf buf) { | ||
| 125 | + byte checkCode = bcc(buf); | ||
| 126 | + buf.writeByte(checkCode); | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + public static byte bcc(ByteBuf byteBuf) { | ||
| 130 | + byte cs = 0; | ||
| 131 | + while (byteBuf.isReadable()) | ||
| 132 | + cs ^= byteBuf.readByte(); | ||
| 133 | + byteBuf.resetReaderIndex(); | ||
| 134 | + return cs; | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + protected static ByteBuf[] slice(ByteBuf byteBuf, int index, int length) { | ||
| 138 | + byte first = byteBuf.getByte(index + length - 1); | ||
| 139 | + | ||
| 140 | + ByteBuf[] byteBufList = new ByteBuf[2]; | ||
| 141 | + byteBufList[0] = byteBuf.retainedSlice(index, length); | ||
| 142 | + | ||
| 143 | + if (first == 0x7d) { | ||
| 144 | + byteBufList[1] = Unpooled.buffer(1, 1).writeByte(0x01); | ||
| 145 | + } else { | ||
| 146 | + byteBuf.setByte(index + length - 1, 0x7d); | ||
| 147 | + byteBufList[1] = Unpooled.buffer(1, 1).writeByte(0x02); | ||
| 148 | + } | ||
| 149 | + return byteBufList; | ||
| 150 | + } | ||
| 151 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/codec/netty/Jt808Handler.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.codec.netty; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.session.SessionManager; | ||
| 6 | +import io.netty.channel.Channel; | ||
| 7 | +import io.netty.channel.ChannelHandlerContext; | ||
| 8 | +import io.netty.channel.ChannelInboundHandlerAdapter; | ||
| 9 | +import io.netty.handler.timeout.IdleState; | ||
| 10 | +import io.netty.handler.timeout.IdleStateEvent; | ||
| 11 | +import org.slf4j.Logger; | ||
| 12 | +import org.slf4j.LoggerFactory; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * @author QingtaiJiang | ||
| 16 | + * @date 2023/4/27 18:14 | ||
| 17 | + * @email qingtaij@163.com | ||
| 18 | + */ | ||
| 19 | +public class Jt808Handler extends ChannelInboundHandlerAdapter { | ||
| 20 | + | ||
| 21 | + private final static Logger log = LoggerFactory.getLogger(Jt808Handler.class); | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { | ||
| 25 | + if (msg instanceof Rs) { | ||
| 26 | + ctx.writeAndFlush(msg); | ||
| 27 | + } else { | ||
| 28 | + ctx.fireChannelRead(msg); | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + @Override | ||
| 33 | + public void channelActive(ChannelHandlerContext ctx) { | ||
| 34 | + Channel channel = ctx.channel(); | ||
| 35 | + Session session = SessionManager.INSTANCE.newSession(channel); | ||
| 36 | + channel.attr(Session.KEY).set(session); | ||
| 37 | + log.info("> Tcp connect {}", session); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + @Override | ||
| 41 | + public void channelInactive(ChannelHandlerContext ctx) { | ||
| 42 | + Session session = ctx.channel().attr(Session.KEY).get(); | ||
| 43 | + log.info("< Tcp disconnect {}", session); | ||
| 44 | + ctx.close(); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + @Override | ||
| 48 | + public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) { | ||
| 49 | + Session session = ctx.channel().attr(Session.KEY).get(); | ||
| 50 | + String message = e.getMessage(); | ||
| 51 | + if (message.toLowerCase().contains("Connection reset by peer".toLowerCase())) { | ||
| 52 | + log.info("< exception{} {}", session, e.getMessage()); | ||
| 53 | + } else { | ||
| 54 | + log.info("< exception{} {}", session, e.getMessage(), e); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + @Override | ||
| 60 | + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { | ||
| 61 | + if (evt instanceof IdleStateEvent) { | ||
| 62 | + IdleStateEvent event = (IdleStateEvent) evt; | ||
| 63 | + IdleState state = event.state(); | ||
| 64 | + if (state == IdleState.READER_IDLE || state == IdleState.WRITER_IDLE) { | ||
| 65 | + Session session = ctx.channel().attr(Session.KEY).get(); | ||
| 66 | + log.warn("< Proactively disconnect{}", session); | ||
| 67 | + ctx.close(); | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/codec/netty/TcpServer.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.codec.netty; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.codec.decode.Jt808Decoder; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.codec.encode.Jt808Encoder; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.codec.encode.Jt808EncoderCmd; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.proc.factory.CodecFactory; | ||
| 7 | +import io.netty.bootstrap.ServerBootstrap; | ||
| 8 | +import io.netty.buffer.ByteBuf; | ||
| 9 | +import io.netty.buffer.Unpooled; | ||
| 10 | +import io.netty.channel.ChannelFuture; | ||
| 11 | +import io.netty.channel.ChannelInitializer; | ||
| 12 | +import io.netty.channel.EventLoopGroup; | ||
| 13 | +import io.netty.channel.nio.NioEventLoopGroup; | ||
| 14 | +import io.netty.channel.socket.nio.NioChannelOption; | ||
| 15 | +import io.netty.channel.socket.nio.NioServerSocketChannel; | ||
| 16 | +import io.netty.channel.socket.nio.NioSocketChannel; | ||
| 17 | +import io.netty.handler.codec.DelimiterBasedFrameDecoder; | ||
| 18 | +import io.netty.handler.timeout.IdleStateHandler; | ||
| 19 | +import io.netty.util.concurrent.Future; | ||
| 20 | +import org.slf4j.Logger; | ||
| 21 | +import org.slf4j.LoggerFactory; | ||
| 22 | + | ||
| 23 | +import java.util.concurrent.TimeUnit; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * @author QingtaiJiang | ||
| 27 | + * @date 2023/4/27 18:01 | ||
| 28 | + * @email qingtaij@163.com | ||
| 29 | + */ | ||
| 30 | + | ||
| 31 | +public class TcpServer { | ||
| 32 | + private final static Logger log = LoggerFactory.getLogger(TcpServer.class); | ||
| 33 | + | ||
| 34 | + private final Integer port; | ||
| 35 | + private boolean isRunning = false; | ||
| 36 | + private EventLoopGroup bossGroup = null; | ||
| 37 | + private EventLoopGroup workerGroup = null; | ||
| 38 | + | ||
| 39 | + private final ByteBuf DECODER_JT808 = Unpooled.wrappedBuffer(new byte[]{0x7e}); | ||
| 40 | + | ||
| 41 | + public TcpServer(Integer port) { | ||
| 42 | + this.port = port; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + private void startTcpServer() { | ||
| 46 | + try { | ||
| 47 | + CodecFactory.init(); | ||
| 48 | + this.bossGroup = new NioEventLoopGroup(); | ||
| 49 | + this.workerGroup = new NioEventLoopGroup(); | ||
| 50 | + ServerBootstrap bootstrap = new ServerBootstrap(); | ||
| 51 | + bootstrap.channel(NioServerSocketChannel.class); | ||
| 52 | + bootstrap.group(bossGroup, workerGroup); | ||
| 53 | + | ||
| 54 | + bootstrap.option(NioChannelOption.SO_BACKLOG, 1024) | ||
| 55 | + .option(NioChannelOption.SO_REUSEADDR, true) | ||
| 56 | + .childOption(NioChannelOption.TCP_NODELAY, true) | ||
| 57 | + .childHandler(new ChannelInitializer<NioSocketChannel>() { | ||
| 58 | + @Override | ||
| 59 | + public void initChannel(NioSocketChannel channel) { | ||
| 60 | + channel.pipeline() | ||
| 61 | + .addLast(new IdleStateHandler(10, 0, 0, TimeUnit.MINUTES)) | ||
| 62 | + .addLast(new DelimiterBasedFrameDecoder(1024 * 2, DECODER_JT808)) | ||
| 63 | + .addLast(new Jt808Decoder()) | ||
| 64 | + .addLast(new Jt808Encoder()) | ||
| 65 | + .addLast(new Jt808EncoderCmd()) | ||
| 66 | + .addLast(new Jt808Handler()); | ||
| 67 | + } | ||
| 68 | + }); | ||
| 69 | + ChannelFuture channelFuture = bootstrap.bind(port).sync(); | ||
| 70 | + // 监听设备TCP端口是否启动成功 | ||
| 71 | + channelFuture.addListener(future -> { | ||
| 72 | + if (!future.isSuccess()) { | ||
| 73 | + log.error("Binding port:{} fail! cause: {}", port, future.cause().getCause(), future.cause()); | ||
| 74 | + } | ||
| 75 | + }); | ||
| 76 | + log.info("服务:JT808 Server 启动成功, port:{}", port); | ||
| 77 | + channelFuture.channel().closeFuture().sync(); | ||
| 78 | + } catch (Exception e) { | ||
| 79 | + log.warn("服务:JT808 Server 启动异常, port:{},{}", port, e.getMessage(), e); | ||
| 80 | + } finally { | ||
| 81 | + stop(); | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + /** | ||
| 86 | + * 开启一个新的线程,拉起来Netty | ||
| 87 | + */ | ||
| 88 | + public synchronized void start() { | ||
| 89 | + if (this.isRunning) { | ||
| 90 | + log.warn("服务:JT808 Server 已经启动, port:{}", port); | ||
| 91 | + return; | ||
| 92 | + } | ||
| 93 | + this.isRunning = true; | ||
| 94 | + new Thread(this::startTcpServer).start(); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + public synchronized void stop() { | ||
| 98 | + if (!this.isRunning) { | ||
| 99 | + log.warn("服务:JT808 Server 已经停止, port:{}", port); | ||
| 100 | + } | ||
| 101 | + this.isRunning = false; | ||
| 102 | + Future<?> future = this.bossGroup.shutdownGracefully(); | ||
| 103 | + if (!future.isSuccess()) { | ||
| 104 | + log.warn("bossGroup 无法正常停止", future.cause()); | ||
| 105 | + } | ||
| 106 | + future = this.workerGroup.shutdownGracefully(); | ||
| 107 | + if (!future.isSuccess()) { | ||
| 108 | + log.warn("workerGroup 无法正常停止", future.cause()); | ||
| 109 | + } | ||
| 110 | + log.warn("服务:JT808 Server 已经停止, port:{}", port); | ||
| 111 | + } | ||
| 112 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/config/JT1078AutoConfiguration.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.config; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.cmd.JT1078Template; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.codec.netty.TcpServer; | ||
| 5 | +import org.springframework.beans.factory.annotation.Value; | ||
| 6 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| 7 | +import org.springframework.context.annotation.Bean; | ||
| 8 | +import org.springframework.context.annotation.Configuration; | ||
| 9 | +import org.springframework.core.annotation.Order; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * @author QingtaiJiang | ||
| 13 | + * @date 2023/4/27 19:35 | ||
| 14 | + * @email qingtaij@163.com | ||
| 15 | + */ | ||
| 16 | +@Order(Integer.MIN_VALUE) | ||
| 17 | +@Configuration | ||
| 18 | +@ConditionalOnProperty(value = "jt1078.enable", havingValue = "true") | ||
| 19 | +public class JT1078AutoConfiguration { | ||
| 20 | + | ||
| 21 | + @Bean(initMethod = "start", destroyMethod = "stop") | ||
| 22 | + public TcpServer jt1078Server(@Value("${jt1078.port}") Integer port) { | ||
| 23 | + return new TcpServer(port); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + @Bean | ||
| 27 | + public JT1078Template jt1078Template() { | ||
| 28 | + return new JT1078Template(); | ||
| 29 | + } | ||
| 30 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/config/JT1078Controller.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.config; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.cmd.JT1078Template; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.response.*; | ||
| 5 | +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | ||
| 6 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| 7 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 8 | +import org.springframework.web.bind.annotation.PathVariable; | ||
| 9 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 10 | +import org.springframework.web.bind.annotation.RestController; | ||
| 11 | + | ||
| 12 | +import javax.annotation.Resource; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * curl http://localhost:18080/api/jt1078/start/live/18864197066/1 | ||
| 16 | + * | ||
| 17 | + * @author QingtaiJiang | ||
| 18 | + * @date 2023/4/27 18:12 | ||
| 19 | + * @email qingtaij@163.com | ||
| 20 | + */ | ||
| 21 | +@ConditionalOnProperty(value = "jt1078.enable", havingValue = "true") | ||
| 22 | +@RestController | ||
| 23 | +@RequestMapping("/api/jt1078") | ||
| 24 | +public class JT1078Controller { | ||
| 25 | + | ||
| 26 | + @Resource | ||
| 27 | + JT1078Template jt1078Template; | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * jt1078Template 调用示例 | ||
| 31 | + */ | ||
| 32 | + @GetMapping("/start/live/{deviceId}/{channelId}") | ||
| 33 | + public WVPResult<?> startLive(@PathVariable String deviceId, @PathVariable String channelId) { | ||
| 34 | + J9101 j9101 = new J9101(); | ||
| 35 | + j9101.setChannel(Integer.valueOf(channelId)); | ||
| 36 | + j9101.setIp("192.168.1.1"); | ||
| 37 | + j9101.setRate(1); | ||
| 38 | + j9101.setTcpPort(7618); | ||
| 39 | + j9101.setUdpPort(7618); | ||
| 40 | + j9101.setType(0); | ||
| 41 | + // TODO 分配ZLM,获取IP、端口 | ||
| 42 | + String s = jt1078Template.startLive(deviceId, j9101, 6); | ||
| 43 | + // TODO 设备响应成功后,封装拉流结果集 | ||
| 44 | + WVPResult<String> wvpResult = new WVPResult<>(); | ||
| 45 | + wvpResult.setCode(200); | ||
| 46 | + wvpResult.setData(String.format("http://192.168.1.1/rtp/%s_%s.live.mp4", deviceId, channelId)); | ||
| 47 | + return wvpResult; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | +} | ||
| 51 | + |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/Header.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.util.Bin; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * @author QingtaiJiang | ||
| 7 | + * @date 2023/4/27 18:22 | ||
| 8 | + * @email qingtaij@163.com | ||
| 9 | + */ | ||
| 10 | +public class Header { | ||
| 11 | + // 消息ID | ||
| 12 | + String msgId; | ||
| 13 | + | ||
| 14 | + // 消息体属性 | ||
| 15 | + Integer msgPro; | ||
| 16 | + | ||
| 17 | + // 标识 | ||
| 18 | + String devId; | ||
| 19 | + | ||
| 20 | + // 消息体流水号 | ||
| 21 | + Integer sn; | ||
| 22 | + | ||
| 23 | + // 协议版本号 | ||
| 24 | + Short version = -1; | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + public String getMsgId() { | ||
| 28 | + return msgId; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + public void setMsgId(String msgId) { | ||
| 32 | + this.msgId = msgId; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + public Integer getMsgPro() { | ||
| 36 | + return msgPro; | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + public void setMsgPro(Integer msgPro) { | ||
| 40 | + this.msgPro = msgPro; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + public String getDevId() { | ||
| 44 | + return devId; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + public void setDevId(String devId) { | ||
| 48 | + this.devId = devId; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + public Integer getSn() { | ||
| 52 | + return sn; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + public void setSn(Integer sn) { | ||
| 56 | + this.sn = sn; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + public Short getVersion() { | ||
| 60 | + return version; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + public void setVersion(Short version) { | ||
| 64 | + this.version = version; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * 判断是否是2019的版本 | ||
| 69 | + * | ||
| 70 | + * @return true 2019后的版本。false 2013 | ||
| 71 | + */ | ||
| 72 | + public boolean is2019Version() { | ||
| 73 | + return Bin.get(msgPro, 14); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/entity/Cmd.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.entity; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * @author QingtaiJiang | ||
| 7 | + * @date 2023/4/27 18:23 | ||
| 8 | + * @email qingtaij@163.com | ||
| 9 | + */ | ||
| 10 | +public class Cmd { | ||
| 11 | + String devId; | ||
| 12 | + Long packageNo; | ||
| 13 | + String msgId; | ||
| 14 | + String respId; | ||
| 15 | + Rs rs; | ||
| 16 | + | ||
| 17 | + public Cmd() { | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + public Cmd(Builder builder) { | ||
| 21 | + this.devId = builder.devId; | ||
| 22 | + this.packageNo = builder.packageNo; | ||
| 23 | + this.msgId = builder.msgId; | ||
| 24 | + this.respId = builder.respId; | ||
| 25 | + this.rs = builder.rs; | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + public String getDevId() { | ||
| 29 | + return devId; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + public void setDevId(String devId) { | ||
| 33 | + this.devId = devId; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + public Long getPackageNo() { | ||
| 37 | + return packageNo; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + public void setPackageNo(Long packageNo) { | ||
| 41 | + this.packageNo = packageNo; | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + public String getMsgId() { | ||
| 45 | + return msgId; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + public void setMsgId(String msgId) { | ||
| 49 | + this.msgId = msgId; | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + public String getRespId() { | ||
| 53 | + return respId; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + public void setRespId(String respId) { | ||
| 57 | + this.respId = respId; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + public Rs getRs() { | ||
| 61 | + return rs; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + public void setRs(Rs rs) { | ||
| 65 | + this.rs = rs; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + public static class Builder { | ||
| 69 | + String devId; | ||
| 70 | + Long packageNo; | ||
| 71 | + String msgId; | ||
| 72 | + String respId; | ||
| 73 | + Rs rs; | ||
| 74 | + | ||
| 75 | + public Builder setDevId(String devId) { | ||
| 76 | + this.devId = devId.replaceFirst("^0*", ""); | ||
| 77 | + return this; | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + public Builder setPackageNo(Long packageNo) { | ||
| 81 | + this.packageNo = packageNo; | ||
| 82 | + return this; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + public Builder setMsgId(String msgId) { | ||
| 86 | + this.msgId = msgId; | ||
| 87 | + return this; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + public Builder setRespId(String respId) { | ||
| 91 | + this.respId = respId; | ||
| 92 | + return this; | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + public Builder setRs(Rs re) { | ||
| 96 | + this.rs = re; | ||
| 97 | + return this; | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + public Cmd build() { | ||
| 101 | + return new Cmd(this); | ||
| 102 | + } | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + | ||
| 106 | + @Override | ||
| 107 | + public String toString() { | ||
| 108 | + return "Cmd{" + | ||
| 109 | + "devId='" + devId + '\'' + | ||
| 110 | + ", packageNo=" + packageNo + | ||
| 111 | + ", msgId='" + msgId + '\'' + | ||
| 112 | + ", respId='" + respId + '\'' + | ||
| 113 | + ", rs=" + rs + | ||
| 114 | + '}'; | ||
| 115 | + } | ||
| 116 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/factory/CodecFactory.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.factory; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.request.Re; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.util.ClassUtil; | ||
| 6 | +import org.slf4j.Logger; | ||
| 7 | +import org.slf4j.LoggerFactory; | ||
| 8 | + | ||
| 9 | +import java.util.HashMap; | ||
| 10 | +import java.util.List; | ||
| 11 | +import java.util.Map; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * @author QingtaiJiang | ||
| 15 | + * @date 2023/4/27 18:29 | ||
| 16 | + * @email qingtaij@163.com | ||
| 17 | + */ | ||
| 18 | + | ||
| 19 | +public class CodecFactory { | ||
| 20 | + private final static Logger log = LoggerFactory.getLogger(CodecFactory.class); | ||
| 21 | + | ||
| 22 | + private static Map<String, Class<?>> protocolHash; | ||
| 23 | + | ||
| 24 | + public static void init() { | ||
| 25 | + protocolHash = new HashMap<>(); | ||
| 26 | + List<Class<?>> classList = ClassUtil.getClassList("com.genersoft.iot.vmp.jt1078.proc", MsgId.class); | ||
| 27 | + for (Class<?> handlerClass : classList) { | ||
| 28 | + String id = handlerClass.getAnnotation(MsgId.class).id(); | ||
| 29 | + protocolHash.put(id, handlerClass); | ||
| 30 | + } | ||
| 31 | + if (log.isDebugEnabled()) { | ||
| 32 | + log.debug("消息ID缓存表 protocolHash:{}", protocolHash); | ||
| 33 | + } | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + public static Re getHandler(String msgId) { | ||
| 37 | + Class<?> aClass = protocolHash.get(msgId); | ||
| 38 | + Object bean = ClassUtil.getBean(aClass); | ||
| 39 | + if (bean instanceof Re) { | ||
| 40 | + return (Re) bean; | ||
| 41 | + } | ||
| 42 | + return null; | ||
| 43 | + } | ||
| 44 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/request/J0001.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.request; | ||
| 2 | + | ||
| 3 | +import com.alibaba.fastjson2.JSON; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 7 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 8 | +import com.genersoft.iot.vmp.jt1078.session.SessionManager; | ||
| 9 | +import io.netty.buffer.ByteBuf; | ||
| 10 | +import io.netty.buffer.ByteBufUtil; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 终端通用应答 | ||
| 14 | + * | ||
| 15 | + * @author QingtaiJiang | ||
| 16 | + * @date 2023/4/27 18:04 | ||
| 17 | + * @email qingtaij@163.com | ||
| 18 | + */ | ||
| 19 | +@MsgId(id = "0001") | ||
| 20 | +public class J0001 extends Re { | ||
| 21 | + int respNo; | ||
| 22 | + String respId; | ||
| 23 | + int result; | ||
| 24 | + | ||
| 25 | + @Override | ||
| 26 | + protected Rs decode0(ByteBuf buf, Header header, Session session) { | ||
| 27 | + respNo = buf.readUnsignedShort(); | ||
| 28 | + respId = ByteBufUtil.hexDump(buf.readSlice(2)); | ||
| 29 | + result = buf.readUnsignedByte(); | ||
| 30 | + return null; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + protected Rs handler(Header header, Session session) { | ||
| 35 | + SessionManager.INSTANCE.response(header.getDevId(), "0001", (long) respNo, JSON.toJSONString(this)); | ||
| 36 | + return null; | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + public int getRespNo() { | ||
| 40 | + return respNo; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + public String getRespId() { | ||
| 44 | + return respId; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + public int getResult() { | ||
| 48 | + return result; | ||
| 49 | + } | ||
| 50 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/request/J0002.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.request; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.proc.response.J8001; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 7 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 8 | +import io.netty.buffer.ByteBuf; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 终端心跳 | ||
| 12 | + * | ||
| 13 | + * @author QingtaiJiang | ||
| 14 | + * @date 2023/4/27 18:04 | ||
| 15 | + * @email qingtaij@163.com | ||
| 16 | + */ | ||
| 17 | +@MsgId(id = "0002") | ||
| 18 | +public class J0002 extends Re { | ||
| 19 | + @Override | ||
| 20 | + protected Rs decode0(ByteBuf buf, Header header, Session session) { | ||
| 21 | + return null; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + protected Rs handler(Header header, Session session) { | ||
| 26 | + J8001 j8001 = new J8001(); | ||
| 27 | + j8001.setRespNo(header.getSn()); | ||
| 28 | + j8001.setRespId(header.getMsgId()); | ||
| 29 | + j8001.setResult(J8001.SUCCESS); | ||
| 30 | + return j8001; | ||
| 31 | + } | ||
| 32 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/request/J0004.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.request; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 7 | +import io.netty.buffer.ByteBuf; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 查询服务器时间 | ||
| 11 | + * | ||
| 12 | + * @author QingtaiJiang | ||
| 13 | + * @date 2023/4/27 18:06 | ||
| 14 | + * @email qingtaij@163.com | ||
| 15 | + */ | ||
| 16 | +@MsgId(id = "0004") | ||
| 17 | +public class J0004 extends Re { | ||
| 18 | + @Override | ||
| 19 | + protected Rs decode0(ByteBuf buf, Header header, Session session) { | ||
| 20 | + return null; | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + protected Rs handler(Header header, Session session) { | ||
| 25 | + return null; | ||
| 26 | + } | ||
| 27 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/request/J0100.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.request; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.proc.response.J8100; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 7 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 8 | +import io.netty.buffer.ByteBuf; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 终端注册 | ||
| 12 | + * | ||
| 13 | + * @author QingtaiJiang | ||
| 14 | + * @date 2023/4/27 18:06 | ||
| 15 | + * @email qingtaij@163.com | ||
| 16 | + */ | ||
| 17 | +@MsgId(id = "0100") | ||
| 18 | +public class J0100 extends Re { | ||
| 19 | + | ||
| 20 | + private int provinceId; | ||
| 21 | + | ||
| 22 | + private int cityId; | ||
| 23 | + | ||
| 24 | + private String makerId; | ||
| 25 | + | ||
| 26 | + private String deviceModel; | ||
| 27 | + | ||
| 28 | + private String deviceId; | ||
| 29 | + | ||
| 30 | + private int plateColor; | ||
| 31 | + | ||
| 32 | + private String plateNo; | ||
| 33 | + | ||
| 34 | + @Override | ||
| 35 | + protected Rs decode0(ByteBuf buf, Header header, Session session) { | ||
| 36 | + Short version = header.getVersion(); | ||
| 37 | + provinceId = buf.readUnsignedShort(); | ||
| 38 | + if (version > 1) { | ||
| 39 | + cityId = buf.readUnsignedShort(); | ||
| 40 | + // decode as 2019 | ||
| 41 | + } else { | ||
| 42 | + int i = buf.readUnsignedShort(); | ||
| 43 | + // decode as 2013 | ||
| 44 | + } | ||
| 45 | + return null; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @Override | ||
| 49 | + protected Rs handler(Header header, Session session) { | ||
| 50 | + J8100 j8100 = new J8100(); | ||
| 51 | + j8100.setRespNo(header.getSn()); | ||
| 52 | + j8100.setResult(J8100.SUCCESS); | ||
| 53 | + j8100.setCode("WVP_YYDS"); | ||
| 54 | + return j8100; | ||
| 55 | + } | ||
| 56 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/request/J0102.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.request; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.proc.response.J8001; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 7 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 8 | +import io.netty.buffer.ByteBuf; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 终端鉴权 | ||
| 12 | + * | ||
| 13 | + * @author QingtaiJiang | ||
| 14 | + * @date 2023/4/27 18:06 | ||
| 15 | + * @email qingtaij@163.com | ||
| 16 | + */ | ||
| 17 | +@MsgId(id = "0102") | ||
| 18 | +public class J0102 extends Re { | ||
| 19 | + @Override | ||
| 20 | + protected Rs decode0(ByteBuf buf, Header header, Session session) { | ||
| 21 | + int lenCode = buf.readUnsignedByte(); | ||
| 22 | +// String code = buf.readCharSequence(lenCode, CharsetUtil.UTF_8).toString(); | ||
| 23 | + // if 2019 to decode next | ||
| 24 | + return null; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + protected Rs handler(Header header, Session session) { | ||
| 29 | + J8001 j8001 = new J8001(); | ||
| 30 | + j8001.setRespNo(header.getSn()); | ||
| 31 | + j8001.setRespId(header.getMsgId()); | ||
| 32 | + j8001.setResult(J8001.SUCCESS); | ||
| 33 | + return j8001; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/request/J0200.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.request; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.proc.response.J8001; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 7 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 8 | +import io.netty.buffer.ByteBuf; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 实时消息上报 | ||
| 12 | + * | ||
| 13 | + * @author QingtaiJiang | ||
| 14 | + * @date 2023/4/27 18:06 | ||
| 15 | + * @email qingtaij@163.com | ||
| 16 | + */ | ||
| 17 | +@MsgId(id = "0200") | ||
| 18 | +public class J0200 extends Re { | ||
| 19 | + @Override | ||
| 20 | + protected Rs decode0(ByteBuf buf, Header header, Session session) { | ||
| 21 | + return null; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + protected Rs handler(Header header, Session session) { | ||
| 26 | + J8001 j8001 = new J8001(); | ||
| 27 | + j8001.setRespNo(header.getSn()); | ||
| 28 | + j8001.setRespId(header.getMsgId()); | ||
| 29 | + j8001.setResult(J8001.SUCCESS); | ||
| 30 | + return j8001; | ||
| 31 | + } | ||
| 32 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/request/J1205.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.request; | ||
| 2 | + | ||
| 3 | +import com.alibaba.fastjson2.JSON; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.proc.response.J8001; | ||
| 7 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 8 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 9 | +import com.genersoft.iot.vmp.jt1078.session.SessionManager; | ||
| 10 | +import io.netty.buffer.ByteBuf; | ||
| 11 | +import io.netty.buffer.ByteBufUtil; | ||
| 12 | + | ||
| 13 | +import java.util.ArrayList; | ||
| 14 | +import java.util.List; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * 终端上传音视频资源列表 | ||
| 18 | + * | ||
| 19 | + * @author QingtaiJiang | ||
| 20 | + * @date 2023/4/28 10:36 | ||
| 21 | + * @email qingtaij@163.com | ||
| 22 | + */ | ||
| 23 | +@MsgId(id = "1205") | ||
| 24 | +public class J1205 extends Re { | ||
| 25 | + Integer respNo; | ||
| 26 | + | ||
| 27 | + private List<JRecordItem> recordList = new ArrayList<JRecordItem>(); | ||
| 28 | + | ||
| 29 | + @Override | ||
| 30 | + protected Rs decode0(ByteBuf buf, Header header, Session session) { | ||
| 31 | + respNo = buf.readUnsignedShort(); | ||
| 32 | + long size = buf.readUnsignedInt(); | ||
| 33 | + | ||
| 34 | + for (int i = 0; i < size; i++) { | ||
| 35 | + JRecordItem item = new JRecordItem(); | ||
| 36 | + item.setChannelId(buf.readUnsignedByte()); | ||
| 37 | + item.setStartTime(ByteBufUtil.hexDump(buf.readSlice(6))); | ||
| 38 | + item.setEndTime(ByteBufUtil.hexDump(buf.readSlice(6))); | ||
| 39 | + item.setWarn(buf.readLong()); | ||
| 40 | + item.setMediaType(buf.readUnsignedByte()); | ||
| 41 | + item.setStreamType(buf.readUnsignedByte()); | ||
| 42 | + item.setStorageType(buf.readUnsignedByte()); | ||
| 43 | + item.setSize(buf.readUnsignedInt()); | ||
| 44 | + recordList.add(item); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + return null; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + @Override | ||
| 51 | + protected Rs handler(Header header, Session session) { | ||
| 52 | + SessionManager.INSTANCE.response(header.getDevId(), "1205", (long) respNo, JSON.toJSONString(this)); | ||
| 53 | + | ||
| 54 | + J8001 j8001 = new J8001(); | ||
| 55 | + j8001.setRespNo(header.getSn()); | ||
| 56 | + j8001.setRespId(header.getMsgId()); | ||
| 57 | + j8001.setResult(J8001.SUCCESS); | ||
| 58 | + return j8001; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + | ||
| 62 | + public Integer getRespNo() { | ||
| 63 | + return respNo; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + public void setRespNo(Integer respNo) { | ||
| 67 | + this.respNo = respNo; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + public List<JRecordItem> getRecordList() { | ||
| 71 | + return recordList; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + public void setRecordList(List<JRecordItem> recordList) { | ||
| 75 | + this.recordList = recordList; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + public static class JRecordItem { | ||
| 79 | + | ||
| 80 | + // 逻辑通道号 | ||
| 81 | + private int channelId; | ||
| 82 | + | ||
| 83 | + // 开始时间 | ||
| 84 | + private String startTime; | ||
| 85 | + | ||
| 86 | + // 结束时间 | ||
| 87 | + private String endTime; | ||
| 88 | + | ||
| 89 | + // 报警标志 | ||
| 90 | + private long warn; | ||
| 91 | + | ||
| 92 | + // 音视频资源类型 | ||
| 93 | + private int mediaType; | ||
| 94 | + | ||
| 95 | + // 码流类型 | ||
| 96 | + private int streamType = 1; | ||
| 97 | + | ||
| 98 | + // 存储器类型 | ||
| 99 | + private int storageType; | ||
| 100 | + | ||
| 101 | + // 文件大小 | ||
| 102 | + private long size; | ||
| 103 | + | ||
| 104 | + public int getChannelId() { | ||
| 105 | + return channelId; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + public void setChannelId(int channelId) { | ||
| 109 | + this.channelId = channelId; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + public String getStartTime() { | ||
| 113 | + return startTime; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + public void setStartTime(String startTime) { | ||
| 117 | + this.startTime = startTime; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + public String getEndTime() { | ||
| 121 | + return endTime; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + public void setEndTime(String endTime) { | ||
| 125 | + this.endTime = endTime; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + public long getWarn() { | ||
| 129 | + return warn; | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + public void setWarn(long warn) { | ||
| 133 | + this.warn = warn; | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + public int getMediaType() { | ||
| 137 | + return mediaType; | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + public void setMediaType(int mediaType) { | ||
| 141 | + this.mediaType = mediaType; | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + public int getStreamType() { | ||
| 145 | + return streamType; | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + public void setStreamType(int streamType) { | ||
| 149 | + this.streamType = streamType; | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + public int getStorageType() { | ||
| 153 | + return storageType; | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + public void setStorageType(int storageType) { | ||
| 157 | + this.storageType = storageType; | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + public long getSize() { | ||
| 161 | + return size; | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + public void setSize(long size) { | ||
| 165 | + this.size = size; | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + @Override | ||
| 169 | + public String toString() { | ||
| 170 | + return "JRecordItem{" + | ||
| 171 | + "channelId=" + channelId + | ||
| 172 | + ", startTime='" + startTime + '\'' + | ||
| 173 | + ", endTime='" + endTime + '\'' + | ||
| 174 | + ", warn=" + warn + | ||
| 175 | + ", mediaType=" + mediaType + | ||
| 176 | + ", streamType=" + streamType + | ||
| 177 | + ", storageType=" + storageType + | ||
| 178 | + ", size=" + size + | ||
| 179 | + '}'; | ||
| 180 | + } | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + @Override | ||
| 184 | + public String toString() { | ||
| 185 | + return "J1205{" + | ||
| 186 | + "respNo=" + respNo + | ||
| 187 | + ", recordList=" + recordList + | ||
| 188 | + '}'; | ||
| 189 | + } | ||
| 190 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/request/Re.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.request; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.session.Session; | ||
| 6 | +import io.netty.buffer.ByteBuf; | ||
| 7 | +import org.slf4j.Logger; | ||
| 8 | +import org.slf4j.LoggerFactory; | ||
| 9 | +import org.springframework.util.StringUtils; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * @author QingtaiJiang | ||
| 13 | + * @date 2023/4/27 18:50 | ||
| 14 | + * @email qingtaij@163.com | ||
| 15 | + */ | ||
| 16 | +public abstract class Re { | ||
| 17 | + private final static Logger log = LoggerFactory.getLogger(Re.class); | ||
| 18 | + | ||
| 19 | + protected abstract Rs decode0(ByteBuf buf, Header header, Session session); | ||
| 20 | + | ||
| 21 | + protected abstract Rs handler(Header header, Session session); | ||
| 22 | + | ||
| 23 | + public Rs decode(ByteBuf buf, Header header, Session session) { | ||
| 24 | + if (session != null && !StringUtils.hasLength(session.getDevId())) { | ||
| 25 | + session.register(header.getDevId(), (int) header.getVersion(), header); | ||
| 26 | + } | ||
| 27 | + Rs rs = decode0(buf, header, session); | ||
| 28 | + Rs rsHand = handler(header, session); | ||
| 29 | + if (rs == null && rsHand != null) { | ||
| 30 | + rs = rsHand; | ||
| 31 | + } else if (rs != null && rsHand != null) { | ||
| 32 | + log.warn("decode0:{} 与 handler:{} 返回值冲突,采用decode0返回值", rs, rsHand); | ||
| 33 | + } | ||
| 34 | + if (rs != null) { | ||
| 35 | + rs.setHeader(header); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + return rs; | ||
| 39 | + } | ||
| 40 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/response/J8001.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.response; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import io.netty.buffer.ByteBuf; | ||
| 5 | +import io.netty.buffer.ByteBufUtil; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * @author QingtaiJiang | ||
| 10 | + * @date 2023/4/27 18:48 | ||
| 11 | + * @email qingtaij@163.com | ||
| 12 | + */ | ||
| 13 | +@MsgId(id = "8001") | ||
| 14 | +public class J8001 extends Rs { | ||
| 15 | + public static final Integer SUCCESS = 0; | ||
| 16 | + | ||
| 17 | + Integer respNo; | ||
| 18 | + String respId; | ||
| 19 | + Integer result; | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + public ByteBuf encode() { | ||
| 23 | + ByteBuf buffer = Unpooled.buffer(); | ||
| 24 | + buffer.writeShort(respNo); | ||
| 25 | + buffer.writeBytes(ByteBufUtil.decodeHexDump(respId)); | ||
| 26 | + buffer.writeByte(result); | ||
| 27 | + | ||
| 28 | + return buffer; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + public void setRespNo(Integer respNo) { | ||
| 33 | + this.respNo = respNo; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + public void setRespId(String respId) { | ||
| 37 | + this.respId = respId; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + public void setResult(Integer result) { | ||
| 41 | + this.result = result; | ||
| 42 | + } | ||
| 43 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/response/J8100.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.response; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import io.netty.buffer.ByteBuf; | ||
| 5 | +import io.netty.buffer.Unpooled; | ||
| 6 | +import io.netty.util.CharsetUtil; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * @author QingtaiJiang | ||
| 10 | + * @date 2023/4/27 18:40 | ||
| 11 | + * @email qingtaij@163.com | ||
| 12 | + */ | ||
| 13 | +@MsgId(id = "8100") | ||
| 14 | +public class J8100 extends Rs { | ||
| 15 | + public static final Integer SUCCESS = 0; | ||
| 16 | + | ||
| 17 | + Integer respNo; | ||
| 18 | + Integer result; | ||
| 19 | + String code; | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + public ByteBuf encode() { | ||
| 23 | + ByteBuf buffer = Unpooled.buffer(); | ||
| 24 | + buffer.writeShort(respNo); | ||
| 25 | + buffer.writeByte(result); | ||
| 26 | + buffer.writeCharSequence(code, CharsetUtil.UTF_8); | ||
| 27 | + return buffer; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + public void setRespNo(Integer respNo) { | ||
| 31 | + this.respNo = respNo; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + public void setResult(Integer result) { | ||
| 35 | + this.result = result; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + public void setCode(String code) { | ||
| 39 | + this.code = code; | ||
| 40 | + } | ||
| 41 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/response/J9101.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.response; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import io.netty.buffer.ByteBuf; | ||
| 5 | +import io.netty.buffer.Unpooled; | ||
| 6 | +import io.netty.util.CharsetUtil; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 实时音视频传输请求 | ||
| 10 | + * | ||
| 11 | + * @author QingtaiJiang | ||
| 12 | + * @date 2023/4/27 18:25 | ||
| 13 | + * @email qingtaij@163.com | ||
| 14 | + */ | ||
| 15 | +@MsgId(id = "9101") | ||
| 16 | +public class J9101 extends Rs { | ||
| 17 | + String ip; | ||
| 18 | + | ||
| 19 | + // TCP端口 | ||
| 20 | + Integer tcpPort; | ||
| 21 | + | ||
| 22 | + // UDP端口 | ||
| 23 | + Integer udpPort; | ||
| 24 | + | ||
| 25 | + // 逻辑通道号 | ||
| 26 | + Integer channel; | ||
| 27 | + | ||
| 28 | + // 数据类型 | ||
| 29 | + /** | ||
| 30 | + * 0:音视频,1:视频,2:双向对讲,3:监听,4:中心广播,5:透传 | ||
| 31 | + */ | ||
| 32 | + Integer type; | ||
| 33 | + | ||
| 34 | + // 码流类型 | ||
| 35 | + /** | ||
| 36 | + * 0:主码流,1:子码流 | ||
| 37 | + */ | ||
| 38 | + Integer rate; | ||
| 39 | + | ||
| 40 | + @Override | ||
| 41 | + public ByteBuf encode() { | ||
| 42 | + ByteBuf buffer = Unpooled.buffer(); | ||
| 43 | + buffer.writeByte(ip.getBytes().length); | ||
| 44 | + buffer.writeCharSequence(ip, CharsetUtil.UTF_8); | ||
| 45 | + buffer.writeShort(tcpPort); | ||
| 46 | + buffer.writeShort(udpPort); | ||
| 47 | + buffer.writeByte(channel); | ||
| 48 | + buffer.writeByte(type); | ||
| 49 | + buffer.writeByte(rate); | ||
| 50 | + return buffer; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + public String getIp() { | ||
| 54 | + return ip; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + public void setIp(String ip) { | ||
| 58 | + this.ip = ip; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + public Integer getTcpPort() { | ||
| 62 | + return tcpPort; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + public void setTcpPort(Integer tcpPort) { | ||
| 66 | + this.tcpPort = tcpPort; | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + public Integer getUdpPort() { | ||
| 70 | + return udpPort; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + public void setUdpPort(Integer udpPort) { | ||
| 74 | + this.udpPort = udpPort; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + public Integer getChannel() { | ||
| 78 | + return channel; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + public void setChannel(Integer channel) { | ||
| 82 | + this.channel = channel; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + public Integer getType() { | ||
| 86 | + return type; | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + public void setType(Integer type) { | ||
| 90 | + this.type = type; | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + public Integer getRate() { | ||
| 94 | + return rate; | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + public void setRate(Integer rate) { | ||
| 98 | + this.rate = rate; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + @Override | ||
| 102 | + public String toString() { | ||
| 103 | + return "J9101{" + | ||
| 104 | + "ip='" + ip + '\'' + | ||
| 105 | + ", tcpPort=" + tcpPort + | ||
| 106 | + ", udpPort=" + udpPort + | ||
| 107 | + ", channel=" + channel + | ||
| 108 | + ", type=" + type + | ||
| 109 | + ", rate=" + rate + | ||
| 110 | + '}'; | ||
| 111 | + } | ||
| 112 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/response/J9102.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.response; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import io.netty.buffer.ByteBuf; | ||
| 5 | +import io.netty.buffer.Unpooled; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 音视频实时传输控制 | ||
| 9 | + * | ||
| 10 | + * @author QingtaiJiang | ||
| 11 | + * @date 2023/4/27 18:49 | ||
| 12 | + * @email qingtaij@163.com | ||
| 13 | + */ | ||
| 14 | +@MsgId(id = "9102") | ||
| 15 | +public class J9102 extends Rs { | ||
| 16 | + | ||
| 17 | + // 通道号 | ||
| 18 | + Integer channel; | ||
| 19 | + | ||
| 20 | + // 控制指令 | ||
| 21 | + /** | ||
| 22 | + * 0:关闭音视频传输指令; | ||
| 23 | + * 1:切换码流(增加暂停和继续); | ||
| 24 | + * 2:暂停该通道所有流的发送; | ||
| 25 | + * 3:恢复暂停前流的发送,与暂停前的流类型一致; | ||
| 26 | + * 4:关闭双向对讲 | ||
| 27 | + */ | ||
| 28 | + Integer command; | ||
| 29 | + | ||
| 30 | + // 数据类型 | ||
| 31 | + /** | ||
| 32 | + * 0:关闭该通道有关的音视频数据; | ||
| 33 | + * 1:只关闭该通道有关的音频,保留该通道 | ||
| 34 | + * 有关的视频; | ||
| 35 | + * 2:只关闭该通道有关的视频,保留该通道 | ||
| 36 | + * 有关的音频 | ||
| 37 | + */ | ||
| 38 | + Integer closeType; | ||
| 39 | + | ||
| 40 | + // 数据类型 | ||
| 41 | + /** | ||
| 42 | + * 0:主码流; | ||
| 43 | + * 1:子码流 | ||
| 44 | + */ | ||
| 45 | + Integer streamType; | ||
| 46 | + | ||
| 47 | + @Override | ||
| 48 | + public ByteBuf encode() { | ||
| 49 | + ByteBuf buffer = Unpooled.buffer(); | ||
| 50 | + buffer.writeByte(channel); | ||
| 51 | + buffer.writeByte(command); | ||
| 52 | + buffer.writeByte(closeType); | ||
| 53 | + buffer.writeByte(streamType); | ||
| 54 | + return buffer; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + | ||
| 58 | + public Integer getChannel() { | ||
| 59 | + return channel; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + public void setChannel(Integer channel) { | ||
| 63 | + this.channel = channel; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + public Integer getCommand() { | ||
| 67 | + return command; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + public void setCommand(Integer command) { | ||
| 71 | + this.command = command; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + public Integer getCloseType() { | ||
| 75 | + return closeType; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + public void setCloseType(Integer closeType) { | ||
| 79 | + this.closeType = closeType; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + public Integer getStreamType() { | ||
| 83 | + return streamType; | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + public void setStreamType(Integer streamType) { | ||
| 87 | + this.streamType = streamType; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + @Override | ||
| 91 | + public String toString() { | ||
| 92 | + return "J9102{" + | ||
| 93 | + "channel=" + channel + | ||
| 94 | + ", command=" + command + | ||
| 95 | + ", closeType=" + closeType + | ||
| 96 | + ", streamType=" + streamType + | ||
| 97 | + '}'; | ||
| 98 | + } | ||
| 99 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/response/J9201.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.response; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import io.netty.buffer.ByteBuf; | ||
| 5 | +import io.netty.buffer.ByteBufUtil; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | +import io.netty.util.CharsetUtil; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 回放请求 | ||
| 11 | + * | ||
| 12 | + * @author QingtaiJiang | ||
| 13 | + * @date 2023/4/28 10:37 | ||
| 14 | + * @email qingtaij@163.com | ||
| 15 | + */ | ||
| 16 | +@MsgId(id = "9201") | ||
| 17 | +public class J9201 extends Rs { | ||
| 18 | + // 服务器IP地址 | ||
| 19 | + private String ip; | ||
| 20 | + | ||
| 21 | + // 实时视频服务器TCP端口号 | ||
| 22 | + private int tcpPort; | ||
| 23 | + | ||
| 24 | + // 实时视频服务器UDP端口号 | ||
| 25 | + private int udpPort; | ||
| 26 | + | ||
| 27 | + // 逻辑通道号 | ||
| 28 | + private int channel; | ||
| 29 | + | ||
| 30 | + // 音视频资源类型:0.音视频 1.音频 2.视频 3.视频或音视频 | ||
| 31 | + private int type; | ||
| 32 | + | ||
| 33 | + // 码流类型:0.所有码流 1.主码流 2.子码流(如果此通道只传输音频,此字段置0) | ||
| 34 | + private int rate; | ||
| 35 | + | ||
| 36 | + // 存储器类型:0.所有存储器 1.主存储器 2.灾备存储器" | ||
| 37 | + private int storageType; | ||
| 38 | + | ||
| 39 | + // 回放方式:0.正常回放 1.快进回放 2.关键帧快退回放 3.关键帧播放 4.单帧上传 | ||
| 40 | + private int playbackType; | ||
| 41 | + | ||
| 42 | + // 快进或快退倍数:0.无效 1.1倍 2.2倍 3.4倍 4.8倍 5.16倍 (回放控制为1和2时,此字段内容有效,否则置0) | ||
| 43 | + private int playbackSpeed; | ||
| 44 | + | ||
| 45 | + // 开始时间YYMMDDHHMMSS,回放方式为4时,该字段表示单帧上传时间 | ||
| 46 | + private String startTime; | ||
| 47 | + | ||
| 48 | + // 结束时间YYMMDDHHMMSS,回放方式为4时,该字段无效,为0表示一直回放 | ||
| 49 | + private String endTime; | ||
| 50 | + | ||
| 51 | + @Override | ||
| 52 | + public ByteBuf encode() { | ||
| 53 | + ByteBuf buffer = Unpooled.buffer(); | ||
| 54 | + buffer.writeByte(ip.getBytes().length); | ||
| 55 | + buffer.writeCharSequence(ip, CharsetUtil.UTF_8); | ||
| 56 | + buffer.writeShort(tcpPort); | ||
| 57 | + buffer.writeShort(udpPort); | ||
| 58 | + buffer.writeByte(channel); | ||
| 59 | + buffer.writeByte(type); | ||
| 60 | + buffer.writeByte(rate); | ||
| 61 | + buffer.writeByte(storageType); | ||
| 62 | + buffer.writeByte(playbackType); | ||
| 63 | + buffer.writeByte(playbackSpeed); | ||
| 64 | + buffer.writeBytes(ByteBufUtil.decodeHexDump(startTime)); | ||
| 65 | + buffer.writeBytes(ByteBufUtil.decodeHexDump(endTime)); | ||
| 66 | + return buffer; | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + public String getIp() { | ||
| 70 | + return ip; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + public void setIp(String ip) { | ||
| 74 | + this.ip = ip; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + public int getTcpPort() { | ||
| 78 | + return tcpPort; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + public void setTcpPort(int tcpPort) { | ||
| 82 | + this.tcpPort = tcpPort; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + public int getUdpPort() { | ||
| 86 | + return udpPort; | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + public void setUdpPort(int udpPort) { | ||
| 90 | + this.udpPort = udpPort; | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + public int getChannel() { | ||
| 94 | + return channel; | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + public void setChannel(int channel) { | ||
| 98 | + this.channel = channel; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + public int getType() { | ||
| 102 | + return type; | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + public void setType(int type) { | ||
| 106 | + this.type = type; | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + public int getRate() { | ||
| 110 | + return rate; | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + public void setRate(int rate) { | ||
| 114 | + this.rate = rate; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + public int getStorageType() { | ||
| 118 | + return storageType; | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + public void setStorageType(int storageType) { | ||
| 122 | + this.storageType = storageType; | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + public int getPlaybackType() { | ||
| 126 | + return playbackType; | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + public void setPlaybackType(int playbackType) { | ||
| 130 | + this.playbackType = playbackType; | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + public int getPlaybackSpeed() { | ||
| 134 | + return playbackSpeed; | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + public void setPlaybackSpeed(int playbackSpeed) { | ||
| 138 | + this.playbackSpeed = playbackSpeed; | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + public String getStartTime() { | ||
| 142 | + return startTime; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + public void setStartTime(String startTime) { | ||
| 146 | + this.startTime = startTime; | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + public String getEndTime() { | ||
| 150 | + return endTime; | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + public void setEndTime(String endTime) { | ||
| 154 | + this.endTime = endTime; | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + @Override | ||
| 158 | + public String toString() { | ||
| 159 | + return "J9201{" + | ||
| 160 | + "ip='" + ip + '\'' + | ||
| 161 | + ", tcpPort=" + tcpPort + | ||
| 162 | + ", udpPort=" + udpPort + | ||
| 163 | + ", channel=" + channel + | ||
| 164 | + ", type=" + type + | ||
| 165 | + ", rate=" + rate + | ||
| 166 | + ", storageType=" + storageType + | ||
| 167 | + ", playbackType=" + playbackType + | ||
| 168 | + ", playbackSpeed=" + playbackSpeed + | ||
| 169 | + ", startTime='" + startTime + '\'' + | ||
| 170 | + ", endTime='" + endTime + '\'' + | ||
| 171 | + '}'; | ||
| 172 | + } | ||
| 173 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/response/J9202.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.response; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import io.netty.buffer.ByteBuf; | ||
| 5 | +import io.netty.buffer.ByteBufUtil; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 平台下发远程录像回放控制 | ||
| 10 | + * | ||
| 11 | + * @author QingtaiJiang | ||
| 12 | + * @date 2023/4/28 10:37 | ||
| 13 | + * @email qingtaij@163.com | ||
| 14 | + */ | ||
| 15 | +@MsgId(id = "9202") | ||
| 16 | +public class J9202 extends Rs { | ||
| 17 | + // 逻辑通道号 | ||
| 18 | + private int channel; | ||
| 19 | + | ||
| 20 | + // 回放控制:0.开始回放 1.暂停回放 2.结束回放 3.快进回放 4.关键帧快退回放 5.拖动回放 6.关键帧播放 | ||
| 21 | + private int playbackType; | ||
| 22 | + | ||
| 23 | + // 快进或快退倍数:0.无效 1.1倍 2.2倍 3.4倍 4.8倍 5.16倍 (回放控制为3和4时,此字段内容有效,否则置0) | ||
| 24 | + private int playbackSpeed; | ||
| 25 | + | ||
| 26 | + // 拖动回放位置(YYMMDDHHMMSS,回放控制为5时,此字段有效) | ||
| 27 | + private String playbackTime; | ||
| 28 | + | ||
| 29 | + @Override | ||
| 30 | + public ByteBuf encode() { | ||
| 31 | + ByteBuf buffer = Unpooled.buffer(); | ||
| 32 | + buffer.writeByte(channel); | ||
| 33 | + buffer.writeByte(playbackType); | ||
| 34 | + buffer.writeByte(playbackSpeed); | ||
| 35 | + buffer.writeBytes(ByteBufUtil.decodeHexDump(playbackTime)); | ||
| 36 | + return buffer; | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + public int getChannel() { | ||
| 40 | + return channel; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + public void setChannel(int channel) { | ||
| 44 | + this.channel = channel; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + public int getPlaybackType() { | ||
| 48 | + return playbackType; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + public void setPlaybackType(int playbackType) { | ||
| 52 | + this.playbackType = playbackType; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + public int getPlaybackSpeed() { | ||
| 56 | + return playbackSpeed; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + public void setPlaybackSpeed(int playbackSpeed) { | ||
| 60 | + this.playbackSpeed = playbackSpeed; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + public String getPlaybackTime() { | ||
| 64 | + return playbackTime; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + public void setPlaybackTime(String playbackTime) { | ||
| 68 | + this.playbackTime = playbackTime; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + @Override | ||
| 72 | + public String toString() { | ||
| 73 | + return "J9202{" + | ||
| 74 | + "channel=" + channel + | ||
| 75 | + ", playbackType=" + playbackType + | ||
| 76 | + ", playbackSpeed=" + playbackSpeed + | ||
| 77 | + ", playbackTime='" + playbackTime + '\'' + | ||
| 78 | + '}'; | ||
| 79 | + } | ||
| 80 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/response/J9205.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.response; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.annotation.MsgId; | ||
| 4 | +import io.netty.buffer.ByteBuf; | ||
| 5 | +import io.netty.buffer.ByteBufUtil; | ||
| 6 | +import io.netty.buffer.Unpooled; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 查询资源列表 | ||
| 10 | + * | ||
| 11 | + * @author QingtaiJiang | ||
| 12 | + * @date 2023/4/28 10:36 | ||
| 13 | + * @email qingtaij@163.com | ||
| 14 | + */ | ||
| 15 | +@MsgId(id = "9205") | ||
| 16 | +public class J9205 extends Rs { | ||
| 17 | + // 逻辑通道号 | ||
| 18 | + private int channelId; | ||
| 19 | + | ||
| 20 | + // 开始时间YYMMDDHHMMSS,全0表示无起始时间 | ||
| 21 | + private String startTime; | ||
| 22 | + | ||
| 23 | + // 结束时间YYMMDDHHMMSS,全0表示无终止时间 | ||
| 24 | + private String endTime; | ||
| 25 | + | ||
| 26 | + // 报警标志 | ||
| 27 | + private final int warnType = 0; | ||
| 28 | + | ||
| 29 | + // 音视频资源类型:0.音视频 1.音频 2.视频 3.视频或音视频 | ||
| 30 | + private int mediaType; | ||
| 31 | + | ||
| 32 | + // 码流类型:0.所有码流 1.主码流 2.子码流 | ||
| 33 | + private int streamType = 0; | ||
| 34 | + | ||
| 35 | + // 存储器类型:0.所有存储器 1.主存储器 2.灾备存储器 | ||
| 36 | + private int storageType = 0; | ||
| 37 | + | ||
| 38 | + @Override | ||
| 39 | + public ByteBuf encode() { | ||
| 40 | + ByteBuf buffer = Unpooled.buffer(); | ||
| 41 | + | ||
| 42 | + buffer.writeByte(channelId); | ||
| 43 | + buffer.writeBytes(ByteBufUtil.decodeHexDump(startTime)); | ||
| 44 | + buffer.writeBytes(ByteBufUtil.decodeHexDump(endTime)); | ||
| 45 | + buffer.writeLong(warnType); | ||
| 46 | + buffer.writeByte(mediaType); | ||
| 47 | + buffer.writeByte(streamType); | ||
| 48 | + buffer.writeByte(storageType); | ||
| 49 | + | ||
| 50 | + return buffer; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + | ||
| 54 | + public void setChannelId(int channelId) { | ||
| 55 | + this.channelId = channelId; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + public void setStartTime(String startTime) { | ||
| 59 | + this.startTime = startTime; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + public void setEndTime(String endTime) { | ||
| 63 | + this.endTime = endTime; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + public void setMediaType(int mediaType) { | ||
| 67 | + this.mediaType = mediaType; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + public void setStreamType(int streamType) { | ||
| 71 | + this.streamType = streamType; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + public void setStorageType(int storageType) { | ||
| 75 | + this.storageType = storageType; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + public int getWarnType() { | ||
| 79 | + return warnType; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + @Override | ||
| 83 | + public String toString() { | ||
| 84 | + return "J9205{" + | ||
| 85 | + "channelId=" + channelId + | ||
| 86 | + ", startTime='" + startTime + '\'' + | ||
| 87 | + ", endTime='" + endTime + '\'' + | ||
| 88 | + ", warnType=" + warnType + | ||
| 89 | + ", mediaType=" + mediaType + | ||
| 90 | + ", streamType=" + streamType + | ||
| 91 | + ", storageType=" + storageType + | ||
| 92 | + '}'; | ||
| 93 | + } | ||
| 94 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/proc/response/Rs.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.proc.response; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 5 | +import io.netty.buffer.ByteBuf; | ||
| 6 | + | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * @author QingtaiJiang | ||
| 10 | + * @date 2021/8/30 18:54 | ||
| 11 | + * @email qingtaij@163.com | ||
| 12 | + */ | ||
| 13 | + | ||
| 14 | +public abstract class Rs { | ||
| 15 | + private Header header; | ||
| 16 | + | ||
| 17 | + public abstract ByteBuf encode(); | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + public Header getHeader() { | ||
| 21 | + return header; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + public void setHeader(Header header) { | ||
| 25 | + this.header = header; | ||
| 26 | + } | ||
| 27 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/session/Session.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.session; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.proc.Header; | ||
| 4 | +import io.netty.channel.Channel; | ||
| 5 | +import io.netty.util.AttributeKey; | ||
| 6 | +import org.slf4j.Logger; | ||
| 7 | +import org.slf4j.LoggerFactory; | ||
| 8 | + | ||
| 9 | +import java.util.concurrent.atomic.AtomicInteger; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * @author QingtaiJiang | ||
| 13 | + * @date 2023/4/27 18:54 | ||
| 14 | + * @email qingtaij@163.com | ||
| 15 | + */ | ||
| 16 | +public class Session { | ||
| 17 | + private final static Logger log = LoggerFactory.getLogger(Session.class); | ||
| 18 | + | ||
| 19 | + public static final AttributeKey<Session> KEY = AttributeKey.newInstance(Session.class.getName()); | ||
| 20 | + | ||
| 21 | + // Netty的channel | ||
| 22 | + protected final Channel channel; | ||
| 23 | + | ||
| 24 | + // 原子类的自增ID | ||
| 25 | + private final AtomicInteger serialNo = new AtomicInteger(0); | ||
| 26 | + | ||
| 27 | + // 是否注册成功 | ||
| 28 | + private boolean registered = false; | ||
| 29 | + | ||
| 30 | + // 设备ID | ||
| 31 | + private String devId; | ||
| 32 | + | ||
| 33 | + // 创建时间 | ||
| 34 | + private final long creationTime; | ||
| 35 | + | ||
| 36 | + // 协议版本号 | ||
| 37 | + private Integer protocolVersion; | ||
| 38 | + | ||
| 39 | + private Header header; | ||
| 40 | + | ||
| 41 | + protected Session(Channel channel) { | ||
| 42 | + this.channel = channel; | ||
| 43 | + this.creationTime = System.currentTimeMillis(); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + public void writeObject(Object message) { | ||
| 47 | + log.info("<<<<<<<<<< cmd{},{}", this, message); | ||
| 48 | + channel.writeAndFlush(message); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * 获得下一个流水号 | ||
| 53 | + * | ||
| 54 | + * @return 流水号 | ||
| 55 | + */ | ||
| 56 | + public int nextSerialNo() { | ||
| 57 | + int current; | ||
| 58 | + int next; | ||
| 59 | + do { | ||
| 60 | + current = serialNo.get(); | ||
| 61 | + next = current > 0xffff ? 0 : current; | ||
| 62 | + } while (!serialNo.compareAndSet(current, next + 1)); | ||
| 63 | + return next; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + /** | ||
| 67 | + * 注册session | ||
| 68 | + * | ||
| 69 | + * @param devId 设备ID | ||
| 70 | + */ | ||
| 71 | + public void register(String devId, Integer version, Header header) { | ||
| 72 | + this.devId = devId; | ||
| 73 | + this.registered = true; | ||
| 74 | + this.protocolVersion = version; | ||
| 75 | + this.header = header; | ||
| 76 | + SessionManager.INSTANCE.put(devId, this); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 获取设备号 | ||
| 81 | + * | ||
| 82 | + * @return 设备号 | ||
| 83 | + */ | ||
| 84 | + public String getDevId() { | ||
| 85 | + return devId; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + | ||
| 89 | + public boolean isRegistered() { | ||
| 90 | + return registered; | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + public long getCreationTime() { | ||
| 94 | + return creationTime; | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + public Integer getProtocolVersion() { | ||
| 98 | + return protocolVersion; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + public Header getHeader() { | ||
| 102 | + return header; | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + @Override | ||
| 106 | + public String toString() { | ||
| 107 | + return "[" + | ||
| 108 | + "devId=" + devId + | ||
| 109 | + ", reg=" + registered + | ||
| 110 | + ", version=" + protocolVersion + | ||
| 111 | + ",ip=" + channel.remoteAddress() + | ||
| 112 | + ']'; | ||
| 113 | + } | ||
| 114 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/session/SessionManager.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.session; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.proc.entity.Cmd; | ||
| 4 | +import io.netty.channel.Channel; | ||
| 5 | +import org.slf4j.Logger; | ||
| 6 | +import org.slf4j.LoggerFactory; | ||
| 7 | + | ||
| 8 | +import java.util.Map; | ||
| 9 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 10 | +import java.util.concurrent.SynchronousQueue; | ||
| 11 | +import java.util.concurrent.TimeUnit; | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * @author QingtaiJiang | ||
| 16 | + * @date 2023/4/27 19:54 | ||
| 17 | + * @email qingtaij@163.com | ||
| 18 | + */ | ||
| 19 | +public enum SessionManager { | ||
| 20 | + INSTANCE; | ||
| 21 | + private final static Logger log = LoggerFactory.getLogger(SessionManager.class); | ||
| 22 | + | ||
| 23 | + // 用与消息的缓存 | ||
| 24 | + private final Map<String, SynchronousQueue<String>> topicSubscribers = new ConcurrentHashMap<>(); | ||
| 25 | + | ||
| 26 | + // session的缓存 | ||
| 27 | + private final Map<Object, Session> sessionMap; | ||
| 28 | + | ||
| 29 | + SessionManager() { | ||
| 30 | + this.sessionMap = new ConcurrentHashMap<>(); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * 创建新的Session | ||
| 35 | + * | ||
| 36 | + * @param channel netty通道 | ||
| 37 | + * @return 创建的session对象 | ||
| 38 | + */ | ||
| 39 | + public Session newSession(Channel channel) { | ||
| 40 | + return new Session(channel); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * 获取指定设备的Session | ||
| 46 | + * | ||
| 47 | + * @param clientId 设备Id | ||
| 48 | + * @return Session | ||
| 49 | + */ | ||
| 50 | + public Session get(Object clientId) { | ||
| 51 | + return sessionMap.get(clientId); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * 放入新设备连接的session | ||
| 56 | + * | ||
| 57 | + * @param clientId 设备ID | ||
| 58 | + * @param newSession session | ||
| 59 | + */ | ||
| 60 | + protected void put(Object clientId, Session newSession) { | ||
| 61 | + sessionMap.put(clientId, newSession); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + | ||
| 65 | + /** | ||
| 66 | + * 发送同步消息,接收响应 | ||
| 67 | + * 默认超时时间6秒 | ||
| 68 | + */ | ||
| 69 | + public String request(Cmd cmd) { | ||
| 70 | + // 默认6秒 | ||
| 71 | + int timeOut = 6000; | ||
| 72 | + return request(cmd, timeOut); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + public String request(Cmd cmd, Integer timeOut) { | ||
| 76 | + Session session = this.get(cmd.getDevId()); | ||
| 77 | + if (session == null) { | ||
| 78 | + log.error("DevId: {} not online!", cmd.getDevId()); | ||
| 79 | + return null; | ||
| 80 | + } | ||
| 81 | + String requestKey = requestKey(cmd.getDevId(), cmd.getRespId(), cmd.getPackageNo()); | ||
| 82 | + SynchronousQueue<String> subscribe = subscribe(requestKey); | ||
| 83 | + if (subscribe == null) { | ||
| 84 | + log.error("DevId: {} key:{} send repaid", cmd.getDevId(), requestKey); | ||
| 85 | + return null; | ||
| 86 | + } | ||
| 87 | + session.writeObject(cmd); | ||
| 88 | + try { | ||
| 89 | + return subscribe.poll(timeOut, TimeUnit.SECONDS); | ||
| 90 | + } catch (InterruptedException e) { | ||
| 91 | + log.warn("<<<<<<<<<< timeout" + session, e); | ||
| 92 | + } finally { | ||
| 93 | + this.unsubscribe(requestKey); | ||
| 94 | + } | ||
| 95 | + return null; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + public Boolean response(String devId, String respId, Long responseNo, String data) { | ||
| 99 | + String requestKey = requestKey(devId, respId, responseNo); | ||
| 100 | + SynchronousQueue<String> queue = topicSubscribers.get(requestKey); | ||
| 101 | + if (queue != null) { | ||
| 102 | + try { | ||
| 103 | + return queue.offer(data, 2, TimeUnit.SECONDS); | ||
| 104 | + } catch (InterruptedException e) { | ||
| 105 | + log.error("{}", e.getMessage(), e); | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | + log.warn("Not find response,key:{} data:{} ", requestKey, data); | ||
| 109 | + return false; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + private void unsubscribe(String key) { | ||
| 113 | + topicSubscribers.remove(key); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + private SynchronousQueue<String> subscribe(String key) { | ||
| 117 | + SynchronousQueue<String> queue = null; | ||
| 118 | + if (!topicSubscribers.containsKey(key)) | ||
| 119 | + topicSubscribers.put(key, queue = new SynchronousQueue<String>()); | ||
| 120 | + return queue; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + private String requestKey(String devId, String respId, Long requestNo) { | ||
| 124 | + return String.join("_", devId.replaceFirst("^0*", ""), respId, requestNo.toString()); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/util/Bin.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.util; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 32位整型的二进制读写 | ||
| 5 | + */ | ||
| 6 | +public class Bin { | ||
| 7 | + | ||
| 8 | + private static final int[] bits = new int[32]; | ||
| 9 | + | ||
| 10 | + static { | ||
| 11 | + bits[0] = 1; | ||
| 12 | + for (int i = 1; i < bits.length; i++) { | ||
| 13 | + bits[i] = bits[i - 1] << 1; | ||
| 14 | + } | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * 读取n的第i位 | ||
| 19 | + * | ||
| 20 | + * @param n int32 | ||
| 21 | + * @param i 取值范围0-31 | ||
| 22 | + */ | ||
| 23 | + public static boolean get(int n, int i) { | ||
| 24 | + return (n & bits[i]) == bits[i]; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 不足位数从左边加0 | ||
| 29 | + */ | ||
| 30 | + public static String strHexPaddingLeft(String data, int length) { | ||
| 31 | + int dataLength = data.length(); | ||
| 32 | + if (dataLength < length) { | ||
| 33 | + StringBuilder dataBuilder = new StringBuilder(data); | ||
| 34 | + for (int i = dataLength; i < length; i++) { | ||
| 35 | + dataBuilder.insert(0, "0"); | ||
| 36 | + } | ||
| 37 | + data = dataBuilder.toString(); | ||
| 38 | + } | ||
| 39 | + return data; | ||
| 40 | + } | ||
| 41 | +} |
src/main/java/com/genersoft/iot/vmp/jt1078/util/ClassUtil.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078.util; | ||
| 2 | + | ||
| 3 | +import org.slf4j.Logger; | ||
| 4 | +import org.slf4j.LoggerFactory; | ||
| 5 | +import org.springframework.core.io.Resource; | ||
| 6 | +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; | ||
| 7 | +import org.springframework.core.io.support.ResourcePatternResolver; | ||
| 8 | + | ||
| 9 | +import java.lang.annotation.Annotation; | ||
| 10 | +import java.util.LinkedList; | ||
| 11 | +import java.util.List; | ||
| 12 | + | ||
| 13 | +public class ClassUtil { | ||
| 14 | + | ||
| 15 | + private static final Logger logger = LoggerFactory.getLogger(ClassUtil.class); | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + public static Object getBean(Class<?> clazz) { | ||
| 19 | + if (clazz != null) { | ||
| 20 | + try { | ||
| 21 | + return clazz.getDeclaredConstructor().newInstance(); | ||
| 22 | + } catch (Exception ex) { | ||
| 23 | + logger.error("ClassUtil:找不到指定的类", ex); | ||
| 24 | + } | ||
| 25 | + } | ||
| 26 | + return null; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + public static Object getBean(String className) { | ||
| 31 | + Class<?> clazz = null; | ||
| 32 | + try { | ||
| 33 | + clazz = Class.forName(className); | ||
| 34 | + } catch (Exception ex) { | ||
| 35 | + logger.error("ClassUtil:找不到指定的类"); | ||
| 36 | + } | ||
| 37 | + if (clazz != null) { | ||
| 38 | + try { | ||
| 39 | + //获取声明的构造器--》创建实例 | ||
| 40 | + return clazz.getDeclaredConstructor().newInstance(); | ||
| 41 | + } catch (Exception ex) { | ||
| 42 | + logger.error("ClassUtil:找不到指定的类", ex); | ||
| 43 | + } | ||
| 44 | + } | ||
| 45 | + return null; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 获取包下所有带注解的class | ||
| 51 | + * | ||
| 52 | + * @param packageName 包名 | ||
| 53 | + * @param annotationClass 注解类型 | ||
| 54 | + * @return list | ||
| 55 | + */ | ||
| 56 | + public static List<Class<?>> getClassList(String packageName, Class<? extends Annotation> annotationClass) { | ||
| 57 | + List<Class<?>> classList = getClassList(packageName); | ||
| 58 | + classList.removeIf(next -> !next.isAnnotationPresent(annotationClass)); | ||
| 59 | + return classList; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + public static List<Class<?>> getClassList(String... packageName) { | ||
| 63 | + List<Class<?>> classList = new LinkedList<>(); | ||
| 64 | + for (String s : packageName) { | ||
| 65 | + List<Class<?>> c = getClassList(s); | ||
| 66 | + classList.addAll(c); | ||
| 67 | + } | ||
| 68 | + return classList; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + public static List<Class<?>> getClassList(String packageName) { | ||
| 72 | + List<Class<?>> classList = new LinkedList<>(); | ||
| 73 | + try { | ||
| 74 | + ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); | ||
| 75 | + Resource[] resources = resourcePatternResolver.getResources(packageName.replace(".", "/") + "/**/*.class"); | ||
| 76 | + for (Resource resource : resources) { | ||
| 77 | + String url = resource.getURL().toString(); | ||
| 78 | + | ||
| 79 | + String[] split = url.split(packageName.replace(".", "/")); | ||
| 80 | + String s = split[split.length - 1]; | ||
| 81 | + String className = s.replace("/", "."); | ||
| 82 | + className = className.substring(0, className.lastIndexOf(".")); | ||
| 83 | + doAddClass(classList, packageName + className); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + } catch (Exception e) { | ||
| 87 | + throw new RuntimeException(e); | ||
| 88 | + } | ||
| 89 | + return classList; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + private static void doAddClass(List<Class<?>> classList, String className) { | ||
| 93 | + Class<?> cls = loadClass(className, false); | ||
| 94 | + classList.add(cls); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + public static Class<?> loadClass(String className, boolean isInitialized) { | ||
| 98 | + Class<?> cls; | ||
| 99 | + try { | ||
| 100 | + cls = Class.forName(className, isInitialized, getClassLoader()); | ||
| 101 | + } catch (ClassNotFoundException e) { | ||
| 102 | + throw new RuntimeException(e); | ||
| 103 | + } | ||
| 104 | + return cls; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + | ||
| 108 | + public static ClassLoader getClassLoader() { | ||
| 109 | + return Thread.currentThread().getContextClassLoader(); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | +} |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| @@ -2,12 +2,16 @@ package com.genersoft.iot.vmp.media.zlm; | @@ -2,12 +2,16 @@ package com.genersoft.iot.vmp.media.zlm; | ||
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | import com.alibaba.fastjson2.JSONObject; | 4 | import com.alibaba.fastjson2.JSONObject; |
| 5 | +import com.genersoft.iot.vmp.common.InviteInfo; | ||
| 6 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 5 | import com.genersoft.iot.vmp.common.StreamInfo; | 7 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 6 | import com.genersoft.iot.vmp.conf.UserSetting; | 8 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 7 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 9 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 8 | import com.genersoft.iot.vmp.gb28181.bean.*; | 10 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 9 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | 11 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 10 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | 12 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; |
| 13 | +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; | ||
| 14 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | ||
| 11 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 15 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 12 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | 16 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 13 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | 17 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| @@ -21,10 +25,8 @@ import com.genersoft.iot.vmp.media.zlm.dto.hook.*; | @@ -21,10 +25,8 @@ import com.genersoft.iot.vmp.media.zlm.dto.hook.*; | ||
| 21 | import com.genersoft.iot.vmp.service.*; | 25 | import com.genersoft.iot.vmp.service.*; |
| 22 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 26 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 23 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 27 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 24 | -import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx; | ||
| 25 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 28 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 26 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | 29 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; |
| 27 | -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | ||
| 28 | import org.slf4j.Logger; | 30 | import org.slf4j.Logger; |
| 29 | import org.slf4j.LoggerFactory; | 31 | import org.slf4j.LoggerFactory; |
| 30 | import org.springframework.beans.factory.annotation.Autowired; | 32 | import org.springframework.beans.factory.annotation.Autowired; |
| @@ -57,14 +59,14 @@ public class ZLMHttpHookListener { | @@ -57,14 +59,14 @@ public class ZLMHttpHookListener { | ||
| 57 | @Autowired | 59 | @Autowired |
| 58 | private SIPCommander cmder; | 60 | private SIPCommander cmder; |
| 59 | 61 | ||
| 60 | - @Autowired | ||
| 61 | - private ISIPCommanderForPlatform commanderFroPlatform; | 62 | + @Autowired |
| 63 | + private ISIPCommanderForPlatform commanderFroPlatform; | ||
| 62 | 64 | ||
| 63 | - @Autowired | ||
| 64 | - private AudioBroadcastManager audioBroadcastManager; | 65 | + @Autowired |
| 66 | + private AudioBroadcastManager audioBroadcastManager; | ||
| 65 | 67 | ||
| 66 | - @Autowired | ||
| 67 | - private ZLMRTPServerFactory zlmrtpServerFactory; | 68 | + @Autowired |
| 69 | + private ZLMRTPServerFactory zlmrtpServerFactory; | ||
| 68 | 70 | ||
| 69 | @Autowired | 71 | @Autowired |
| 70 | private IPlayService playService; | 72 | private IPlayService playService; |
| @@ -76,6 +78,9 @@ public class ZLMHttpHookListener { | @@ -76,6 +78,9 @@ public class ZLMHttpHookListener { | ||
| 76 | private IRedisCatchStorage redisCatchStorage; | 78 | private IRedisCatchStorage redisCatchStorage; |
| 77 | 79 | ||
| 78 | @Autowired | 80 | @Autowired |
| 81 | + private IInviteStreamService inviteStreamService; | ||
| 82 | + | ||
| 83 | + @Autowired | ||
| 79 | private IDeviceService deviceService; | 84 | private IDeviceService deviceService; |
| 80 | 85 | ||
| 81 | @Autowired | 86 | @Autowired |
| @@ -111,6 +116,9 @@ public class ZLMHttpHookListener { | @@ -111,6 +116,9 @@ public class ZLMHttpHookListener { | ||
| 111 | @Autowired | 116 | @Autowired |
| 112 | private AssistRESTfulUtils assistRESTfulUtils; | 117 | private AssistRESTfulUtils assistRESTfulUtils; |
| 113 | 118 | ||
| 119 | + @Autowired | ||
| 120 | + private SSRCFactory ssrcFactory; | ||
| 121 | + | ||
| 114 | @Qualifier("taskExecutor") | 122 | @Qualifier("taskExecutor") |
| 115 | @Autowired | 123 | @Autowired |
| 116 | private ThreadPoolTaskExecutor taskExecutor; | 124 | private ThreadPoolTaskExecutor taskExecutor; |
| @@ -255,13 +263,13 @@ public class ZLMHttpHookListener { | @@ -255,13 +263,13 @@ public class ZLMHttpHookListener { | ||
| 255 | result.setEnable_audio(deviceChannel.isHasAudio()); | 263 | result.setEnable_audio(deviceChannel.isHasAudio()); |
| 256 | } | 264 | } |
| 257 | // 如果是录像下载就设置视频间隔十秒 | 265 | // 如果是录像下载就设置视频间隔十秒 |
| 258 | - if (ssrcTransactionForAll.get(0).getType() == VideoStreamSessionManager.SessionType.download) { | 266 | + if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.DOWNLOAD) { |
| 259 | result.setMp4_max_second(10); | 267 | result.setMp4_max_second(10); |
| 260 | result.setEnable_audio(true); | 268 | result.setEnable_audio(true); |
| 261 | result.setEnable_mp4(true); | 269 | result.setEnable_mp4(true); |
| 262 | } | 270 | } |
| 263 | // 如果是talk对讲,则默认获取声音 | 271 | // 如果是talk对讲,则默认获取声音 |
| 264 | - if (ssrcTransactionForAll.get(0).getType() == VideoStreamSessionManager.SessionType.talk) { | 272 | + if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.TALK) { |
| 265 | result.setEnable_audio(true); | 273 | result.setEnable_audio(true); |
| 266 | } | 274 | } |
| 267 | 275 | ||
| @@ -269,7 +277,7 @@ public class ZLMHttpHookListener { | @@ -269,7 +277,7 @@ public class ZLMHttpHookListener { | ||
| 269 | if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) { | 277 | if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) { |
| 270 | logger.info("推流时发现尚未设置录像路径,从assist服务中读取"); | 278 | logger.info("推流时发现尚未设置录像路径,从assist服务中读取"); |
| 271 | JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null); | 279 | JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null); |
| 272 | - if (info != null && info.getInteger("code") != null && info.getInteger("code") == 0 ) { | 280 | + if (info != null && info.getInteger("code") != null && info.getInteger("code") == 0) { |
| 273 | JSONObject dataJson = info.getJSONObject("data"); | 281 | JSONObject dataJson = info.getJSONObject("data"); |
| 274 | if (dataJson != null) { | 282 | if (dataJson != null) { |
| 275 | String recordPath = dataJson.getString("record"); | 283 | String recordPath = dataJson.getString("record"); |
| @@ -301,29 +309,30 @@ public class ZLMHttpHookListener { | @@ -301,29 +309,30 @@ public class ZLMHttpHookListener { | ||
| 301 | logger.info("[ZLM HOOK] 流注销, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | 309 | logger.info("[ZLM HOOK] 流注销, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); |
| 302 | } | 310 | } |
| 303 | 311 | ||
| 304 | - JSONObject ret = new JSONObject(); | ||
| 305 | - ret.put("code", 0); | ||
| 306 | - ret.put("msg", "success"); | 312 | + JSONObject ret = new JSONObject(); |
| 313 | + ret.put("code", 0); | ||
| 314 | + ret.put("msg", "success"); | ||
| 307 | MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); | 315 | MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); |
| 308 | JSONObject json = (JSONObject) JSON.toJSON(param); | 316 | JSONObject json = (JSONObject) JSON.toJSON(param); |
| 309 | taskExecutor.execute(() -> { | 317 | taskExecutor.execute(() -> { |
| 310 | ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json); | 318 | ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json); |
| 319 | + if (mediaInfo == null) { | ||
| 320 | + logger.info("[ZLM HOOK] 流变化未找到ZLM, {}", param.getMediaServerId()); | ||
| 321 | + return; | ||
| 322 | + } | ||
| 311 | if (subscribe != null) { | 323 | if (subscribe != null) { |
| 312 | - | ||
| 313 | - if (mediaInfo != null) { | ||
| 314 | - subscribe.response(mediaInfo, json); | ||
| 315 | - } | 324 | + subscribe.response(mediaInfo, json); |
| 316 | } | 325 | } |
| 317 | 326 | ||
| 318 | List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks(); | 327 | List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks(); |
| 319 | // TODO 重构此处逻辑 | 328 | // TODO 重构此处逻辑 |
| 320 | - | 329 | + boolean isPush = false; |
| 321 | if (param.isRegist()) { | 330 | if (param.isRegist()) { |
| 322 | // 处理流注册的鉴权信息 | 331 | // 处理流注册的鉴权信息 |
| 323 | if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal() | 332 | if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal() |
| 324 | || param.getOriginType() == OriginType.RTSP_PUSH.ordinal() | 333 | || param.getOriginType() == OriginType.RTSP_PUSH.ordinal() |
| 325 | || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { | 334 | || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { |
| 326 | - | 335 | + isPush = true; |
| 327 | StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); | 336 | StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); |
| 328 | if (streamAuthorityInfo == null) { | 337 | if (streamAuthorityInfo == null) { |
| 329 | streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); | 338 | streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); |
| @@ -337,123 +346,122 @@ public class ZLMHttpHookListener { | @@ -337,123 +346,122 @@ public class ZLMHttpHookListener { | ||
| 337 | redisCatchStorage.removeStreamAuthorityInfo(param.getApp(), param.getStream()); | 346 | redisCatchStorage.removeStreamAuthorityInfo(param.getApp(), param.getStream()); |
| 338 | } | 347 | } |
| 339 | 348 | ||
| 340 | - if ("rtsp".equals(param.getSchema())){ | ||
| 341 | - logger.info("流变化:注册->{}, app->{}, stream->{}", param.isRegist(), param.getApp(), param.getStream()); | ||
| 342 | - if (param.isRegist()) { | ||
| 343 | - mediaServerService.addCount(param.getMediaServerId()); | ||
| 344 | - }else { | ||
| 345 | - mediaServerService.removeCount(param.getMediaServerId()); | ||
| 346 | - } | ||
| 347 | - if (param.getOriginType() == OriginType.PULL.ordinal() | ||
| 348 | - || param.getOriginType() == OriginType.FFMPEG_PULL.ordinal()) { | ||
| 349 | - // 设置拉流代理上线/离线 | ||
| 350 | - streamProxyService.updateStatus(param.isRegist(), param.getApp(), param.getStream()); | ||
| 351 | - } | ||
| 352 | - if ("rtp".equals(param.getApp()) && !param.isRegist() ) { | ||
| 353 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(param.getStream()); | ||
| 354 | - if (streamInfo!=null){ | ||
| 355 | - redisCatchStorage.stopPlay(streamInfo); | ||
| 356 | - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); | ||
| 357 | - }else{ | ||
| 358 | - streamInfo = redisCatchStorage.queryPlayback(null, null, param.getStream(), null); | ||
| 359 | - if (streamInfo != null) { | ||
| 360 | - redisCatchStorage.stopPlayback(streamInfo.getDeviceID(), streamInfo.getChannelId(), | ||
| 361 | - streamInfo.getStream(), null); | ||
| 362 | - } | ||
| 363 | - } | ||
| 364 | - }else if ("broadcast".equals(param.getApp())){ | ||
| 365 | - // 语音对讲推流 stream需要满足格式deviceId_channelId | ||
| 366 | - if (param.getStream().indexOf("_") > 0) { | ||
| 367 | - String[] streamArray = param.getStream().split("_"); | ||
| 368 | - if (streamArray.length == 2) { | ||
| 369 | - String deviceId = streamArray[0]; | ||
| 370 | - String channelId = streamArray[1]; | ||
| 371 | - Device device = deviceService.getDevice(deviceId); | ||
| 372 | - if (device != null) { | ||
| 373 | - if (param.isRegist()) { | ||
| 374 | - if (audioBroadcastManager.exit(deviceId, channelId)) { | 349 | + if ("rtsp".equals(param.getSchema())) { |
| 350 | + logger.info("流变化:注册->{}, app->{}, stream->{}", param.isRegist(), param.getApp(), param.getStream()); | ||
| 351 | + if (param.isRegist()) { | ||
| 352 | + mediaServerService.addCount(param.getMediaServerId()); | ||
| 353 | + } else { | ||
| 354 | + mediaServerService.removeCount(param.getMediaServerId()); | ||
| 355 | + } | ||
| 356 | + | ||
| 357 | + int updateStatusResult = streamProxyService.updateStatus(param.isRegist(), param.getApp(), param.getStream()); | ||
| 358 | + if (updateStatusResult > 0) { | ||
| 359 | + | ||
| 360 | + } | ||
| 361 | + | ||
| 362 | + if ("rtp".equals(param.getApp()) && !param.isRegist()) { | ||
| 363 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); | ||
| 364 | + if (inviteInfo != null && (inviteInfo.getType() == InviteSessionType.PLAY || inviteInfo.getType() == InviteSessionType.PLAYBACK)) { | ||
| 365 | + inviteStreamService.removeInviteInfo(inviteInfo); | ||
| 366 | + storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); | ||
| 367 | + } | ||
| 368 | + } else if ("broadcast".equals(param.getApp())) { | ||
| 369 | + // 语音对讲推流 stream需要满足格式deviceId_channelId | ||
| 370 | + if (param.getStream().indexOf("_") > 0) { | ||
| 371 | + String[] streamArray = param.getStream().split("_"); | ||
| 372 | + if (streamArray.length == 2) { | ||
| 373 | + String deviceId = streamArray[0]; | ||
| 374 | + String channelId = streamArray[1]; | ||
| 375 | + Device device = deviceService.getDevice(deviceId); | ||
| 376 | + if (device != null) { | ||
| 377 | + if (param.isRegist()) { | ||
| 378 | + if (audioBroadcastManager.exit(deviceId, channelId)) { | ||
| 379 | + playService.stopAudioBroadcast(deviceId, channelId); | ||
| 380 | + } | ||
| 381 | + // 开启语音对讲通道 | ||
| 382 | + try { | ||
| 383 | + playService.audioBroadcastCmd(device, channelId, mediaInfo, param.getApp(), param.getStream(), 60, false, (msg) -> { | ||
| 384 | + logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); | ||
| 385 | + }); | ||
| 386 | + } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 387 | + logger.error("[命令发送失败] 语音对讲: {}", e.getMessage()); | ||
| 388 | + } | ||
| 389 | + } else { | ||
| 390 | + // 流注销 | ||
| 375 | playService.stopAudioBroadcast(deviceId, channelId); | 391 | playService.stopAudioBroadcast(deviceId, channelId); |
| 376 | } | 392 | } |
| 377 | - // 开启语音对讲通道 | ||
| 378 | - try { | ||
| 379 | - playService.audioBroadcastCmd(device, channelId, mediaInfo, param.getApp(), param.getStream(), 60, false, (msg)->{ | ||
| 380 | - logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); | ||
| 381 | - }); | ||
| 382 | - } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 383 | - logger.error("[命令发送失败] 语音对讲: {}", e.getMessage()); | ||
| 384 | - } | ||
| 385 | - }else { | ||
| 386 | - // 流注销 | ||
| 387 | - playService.stopAudioBroadcast(deviceId, channelId); | 393 | + } else { |
| 394 | + logger.info("[语音对讲] 未找到设备:{}", deviceId); | ||
| 388 | } | 395 | } |
| 389 | - } else{ | ||
| 390 | - logger.info("[语音对讲] 未找到设备:{}", deviceId); | ||
| 391 | } | 396 | } |
| 392 | } | 397 | } |
| 393 | - } | ||
| 394 | - }else if ("talk".equals(param.getApp())){ | ||
| 395 | - // 语音对讲推流 stream需要满足格式deviceId_channelId | ||
| 396 | - if (param.getStream().indexOf("_") > 0) { | ||
| 397 | - String[] streamArray = param.getStream().split("_"); | ||
| 398 | - if (streamArray.length == 2) { | ||
| 399 | - String deviceId = streamArray[0]; | ||
| 400 | - String channelId = streamArray[1]; | ||
| 401 | - Device device = deviceService.getDevice(deviceId); | ||
| 402 | - if (device != null) { | ||
| 403 | - if (param.isRegist()) { | ||
| 404 | - if (audioBroadcastManager.exit(deviceId, channelId)) { | ||
| 405 | - playService.stopAudioBroadcast(deviceId, channelId); | 398 | + } else if ("talk".equals(param.getApp())) { |
| 399 | + // 语音对讲推流 stream需要满足格式deviceId_channelId | ||
| 400 | + if (param.getStream().indexOf("_") > 0) { | ||
| 401 | + String[] streamArray = param.getStream().split("_"); | ||
| 402 | + if (streamArray.length == 2) { | ||
| 403 | + String deviceId = streamArray[0]; | ||
| 404 | + String channelId = streamArray[1]; | ||
| 405 | + Device device = deviceService.getDevice(deviceId); | ||
| 406 | + if (device != null) { | ||
| 407 | + if (param.isRegist()) { | ||
| 408 | + if (audioBroadcastManager.exit(deviceId, channelId)) { | ||
| 409 | + playService.stopAudioBroadcast(deviceId, channelId); | ||
| 410 | + } | ||
| 411 | + // 开启语音对讲通道 | ||
| 412 | + playService.talkCmd(device, channelId, mediaInfo, param.getStream(), (msg) -> { | ||
| 413 | + logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); | ||
| 414 | + }); | ||
| 415 | + } else { | ||
| 416 | + // 流注销 | ||
| 417 | + playService.stopTalk(device, channelId, param.isRegist()); | ||
| 406 | } | 418 | } |
| 407 | - // 开启语音对讲通道 | ||
| 408 | - playService.talkCmd(device, channelId, mediaInfo, param.getStream(), (msg)->{ | ||
| 409 | - logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); | ||
| 410 | - }); | ||
| 411 | - }else { | ||
| 412 | - // 流注销 | ||
| 413 | - playService.stopTalk(device, channelId, param.isRegist()); | 419 | + } else { |
| 420 | + logger.info("[语音对讲] 未找到设备:{}", deviceId); | ||
| 414 | } | 421 | } |
| 415 | - } else{ | ||
| 416 | - logger.info("[语音对讲] 未找到设备:{}", deviceId); | ||
| 417 | } | 422 | } |
| 418 | } | 423 | } |
| 419 | - } | ||
| 420 | 424 | ||
| 421 | - }else{ | ||
| 422 | - if (!"rtp".equals(param.getApp())){ | ||
| 423 | - String type = OriginType.values()[param.getOriginType()].getType(); | ||
| 424 | - MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); | ||
| 425 | - | ||
| 426 | - if (mediaServerItem != null){ | ||
| 427 | - if (param.isRegist()) { | ||
| 428 | - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); | ||
| 429 | - String callId = null; | ||
| 430 | - if (streamAuthorityInfo != null) { | ||
| 431 | - callId = streamAuthorityInfo.getCallId(); | ||
| 432 | - } | ||
| 433 | - StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, | ||
| 434 | - param.getApp(), param.getStream(), param.getTracks(), callId); | ||
| 435 | - param.setStreamInfo(new StreamContent(streamInfoByAppAndStream)); | ||
| 436 | - redisCatchStorage.addStream(mediaServerItem, type, param.getApp(), param.getStream(), param); | ||
| 437 | - if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal() | ||
| 438 | - || param.getOriginType() == OriginType.RTMP_PUSH.ordinal() | ||
| 439 | - || param.getOriginType() == OriginType.RTC_PUSH.ordinal() ) { | ||
| 440 | - param.setSeverId(userSetting.getServerId()); | ||
| 441 | - zlmMediaListManager.addPush(param); | ||
| 442 | - } | ||
| 443 | - }else { | ||
| 444 | - // 兼容流注销时类型从redis记录获取 | ||
| 445 | - OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo( | ||
| 446 | - param.getApp(), param.getStream(), param.getMediaServerId()); | ||
| 447 | - if (onStreamChangedHookParam != null) { | ||
| 448 | - type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType(); | ||
| 449 | - redisCatchStorage.removeStream(mediaServerItem.getId(), type, param.getApp(), param.getStream()); | ||
| 450 | - } | ||
| 451 | - GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream()); | ||
| 452 | - if (gbStream != null) { | 425 | + } else { |
| 426 | + if (!"rtp".equals(param.getApp())) { | ||
| 427 | + String type = OriginType.values()[param.getOriginType()].getType(); | ||
| 428 | + MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); | ||
| 429 | + | ||
| 430 | + if (mediaServerItem != null) { | ||
| 431 | + if (param.isRegist()) { | ||
| 432 | + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); | ||
| 433 | + String callId = null; | ||
| 434 | + if (streamAuthorityInfo != null) { | ||
| 435 | + callId = streamAuthorityInfo.getCallId(); | ||
| 436 | + } | ||
| 437 | + StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, | ||
| 438 | + param.getApp(), param.getStream(), param.getTracks(), callId); | ||
| 439 | + param.setStreamInfo(new StreamContent(streamInfoByAppAndStream)); | ||
| 440 | + redisCatchStorage.addStream(mediaServerItem, type, param.getApp(), param.getStream(), param); | ||
| 441 | + if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal() | ||
| 442 | + || param.getOriginType() == OriginType.RTMP_PUSH.ordinal() | ||
| 443 | + || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { | ||
| 444 | + param.setSeverId(userSetting.getServerId()); | ||
| 445 | + zlmMediaListManager.addPush(param); | ||
| 446 | + } | ||
| 447 | + } else { | ||
| 448 | + // 兼容流注销时类型从redis记录获取 | ||
| 449 | + OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo( | ||
| 450 | + param.getApp(), param.getStream(), param.getMediaServerId()); | ||
| 451 | + if (onStreamChangedHookParam != null) { | ||
| 452 | + type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType(); | ||
| 453 | + redisCatchStorage.removeStream(mediaServerItem.getId(), type, param.getApp(), param.getStream()); | ||
| 454 | + } | ||
| 455 | + GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream()); | ||
| 456 | + if (gbStream != null) { | ||
| 453 | // eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF); | 457 | // eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF); |
| 454 | } | 458 | } |
| 455 | zlmMediaListManager.removeMedia(param.getApp(), param.getStream()); | 459 | zlmMediaListManager.removeMedia(param.getApp(), param.getStream()); |
| 456 | } | 460 | } |
| 461 | + GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream()); | ||
| 462 | + if (gbStream != null) { | ||
| 463 | + eventPublisher.catalogEventPublishForStream(null, gbStream, param.isRegist() ? CatalogEvent.ON : CatalogEvent.OFF); | ||
| 464 | + } | ||
| 457 | if (type != null) { | 465 | if (type != null) { |
| 458 | // 发送流变化redis消息 | 466 | // 发送流变化redis消息 |
| 459 | JSONObject jsonObject = new JSONObject(); | 467 | JSONObject jsonObject = new JSONObject(); |
| @@ -466,38 +474,35 @@ public class ZLMHttpHookListener { | @@ -466,38 +474,35 @@ public class ZLMHttpHookListener { | ||
| 466 | } | 474 | } |
| 467 | } | 475 | } |
| 468 | } | 476 | } |
| 469 | - } | ||
| 470 | - if (!param.isRegist()) { | ||
| 471 | - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(param.getStream()); | ||
| 472 | - if (sendRtpItems.size() > 0) { | ||
| 473 | - for (SendRtpItem sendRtpItem : sendRtpItems) { | ||
| 474 | - if (sendRtpItem.getApp().equals(param.getApp())) { | ||
| 475 | - String platformId = sendRtpItem.getPlatformId(); | ||
| 476 | - ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); | ||
| 477 | - Device device = deviceService.getDevice(platformId); | ||
| 478 | - | ||
| 479 | - | ||
| 480 | - if (platform != null) { | ||
| 481 | - try { | 477 | + if (!param.isRegist()) { |
| 478 | + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(param.getStream()); | ||
| 479 | + if (sendRtpItems.size() > 0) { | ||
| 480 | + for (SendRtpItem sendRtpItem : sendRtpItems) { | ||
| 481 | + if (sendRtpItem != null && sendRtpItem.getApp().equals(param.getApp())) { | ||
| 482 | + String platformId = sendRtpItem.getPlatformId(); | ||
| 483 | + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); | ||
| 484 | + Device device = deviceService.getDevice(platformId); | ||
| 485 | + | ||
| 486 | + try { | ||
| 487 | + if (platform != null) { | ||
| 482 | commanderFroPlatform.streamByeCmd(platform, sendRtpItem); | 488 | commanderFroPlatform.streamByeCmd(platform, sendRtpItem); |
| 483 | - } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 484 | - logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | ||
| 485 | - } | ||
| 486 | - } else { | ||
| 487 | - try { | 489 | + redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), |
| 490 | + sendRtpItem.getCallId(), sendRtpItem.getStream()); | ||
| 491 | + } else { | ||
| 488 | cmder.streamByeCmd(device, sendRtpItem.getChannelId(), param.getStream(), sendRtpItem.getCallId()); | 492 | cmder.streamByeCmd(device, sendRtpItem.getChannelId(), param.getStream(), sendRtpItem.getCallId()); |
| 489 | - } catch (SipException | InvalidArgumentException | ParseException | | ||
| 490 | - SsrcTransactionNotFoundException e) { | ||
| 491 | - logger.error("[命令发送失败] 发送BYE: {}", e.getMessage()); | ||
| 492 | } | 493 | } |
| 494 | + } catch (SipException | InvalidArgumentException | ParseException | | ||
| 495 | + SsrcTransactionNotFoundException e) { | ||
| 496 | + logger.error("[命令发送失败] 发送BYE: {}", e.getMessage()); | ||
| 493 | } | 497 | } |
| 498 | + } | ||
| 494 | } | 499 | } |
| 495 | } | 500 | } |
| 496 | } | 501 | } |
| 497 | } | 502 | } |
| 503 | + | ||
| 498 | } | 504 | } |
| 499 | }); | 505 | }); |
| 500 | - | ||
| 501 | return HookResult.SUCCESS(); | 506 | return HookResult.SUCCESS(); |
| 502 | } | 507 | } |
| 503 | 508 | ||
| @@ -508,82 +513,65 @@ public class ZLMHttpHookListener { | @@ -508,82 +513,65 @@ public class ZLMHttpHookListener { | ||
| 508 | @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8") | 513 | @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8") |
| 509 | public JSONObject onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) { | 514 | public JSONObject onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) { |
| 510 | 515 | ||
| 511 | - logger.info("[ZLM HOOK]流无人观看:{]->{}->{}/{}" + param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | ||
| 512 | - JSONObject ret = new JSONObject(); | ||
| 513 | - ret.put("code", 0); | ||
| 514 | - // 国标类型的流 | ||
| 515 | - if ("rtp".equals(param.getApp())){ | ||
| 516 | - ret.put("close", userSetting.getStreamOnDemand()); | ||
| 517 | - // 国标流, 点播/录像回放/录像下载 | ||
| 518 | - StreamInfo streamInfoForPlayCatch = redisCatchStorage.queryPlayByStreamId(param.getStream()); | ||
| 519 | - // 点播 | ||
| 520 | - if (streamInfoForPlayCatch != null) { | ||
| 521 | - // 收到无人观看说明流也没有在往上级推送 | ||
| 522 | - if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) { | ||
| 523 | - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId(streamInfoForPlayCatch.getChannelId()); | ||
| 524 | - if (sendRtpItems.size() > 0) { | ||
| 525 | - for (SendRtpItem sendRtpItem : sendRtpItems) { | ||
| 526 | - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); | ||
| 527 | - if (parentPlatform == null) { | ||
| 528 | - continue; | ||
| 529 | - } | ||
| 530 | - try { | ||
| 531 | - commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); | ||
| 532 | - } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 533 | - logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | ||
| 534 | - } | ||
| 535 | - redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), | ||
| 536 | - sendRtpItem.getCallId(), sendRtpItem.getStream()); | ||
| 537 | - } | ||
| 538 | - } | ||
| 539 | - } | ||
| 540 | - Device device = deviceService.getDevice(streamInfoForPlayCatch.getDeviceID()); | ||
| 541 | - if (device != null) { | ||
| 542 | - try { | ||
| 543 | - cmder.streamByeCmd(device, streamInfoForPlayCatch.getChannelId(), | ||
| 544 | - streamInfoForPlayCatch.getStream(), null); | ||
| 545 | - } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | ||
| 546 | - logger.error("[无人观看]点播, 发送BYE失败 {}", e.getMessage()); | ||
| 547 | - } | ||
| 548 | - } | ||
| 549 | - | ||
| 550 | - redisCatchStorage.stopPlay(streamInfoForPlayCatch); | ||
| 551 | - storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); | ||
| 552 | - return ret; | ||
| 553 | - } | ||
| 554 | - // 录像回放 | ||
| 555 | - StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, param.getStream(), null); | ||
| 556 | - if (streamInfoForPlayBackCatch != null) { | ||
| 557 | - if (streamInfoForPlayBackCatch.isPause()) { | 516 | + logger.info("[ZLM HOOK]流无人观看:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), |
| 517 | + param.getApp(), param.getStream()); | ||
| 518 | + JSONObject ret = new JSONObject(); | ||
| 519 | + ret.put("code", 0); | ||
| 520 | + // 国标类型的流 | ||
| 521 | + if ("rtp".equals(param.getApp())) { | ||
| 522 | + ret.put("close", userSetting.getStreamOnDemand()); | ||
| 523 | + // 国标流, 点播/录像回放/录像下载 | ||
| 524 | +// StreamInfo streamInfoForPlayCatch = redisCatchStorage.queryPlayByStreamId(param.getStream()); | ||
| 525 | + | ||
| 526 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); | ||
| 527 | + // 点播 | ||
| 528 | + if (inviteInfo != null) { | ||
| 529 | + // 录像下载 | ||
| 530 | + if (inviteInfo.getType() == InviteSessionType.DOWNLOAD) { | ||
| 558 | ret.put("close", false); | 531 | ret.put("close", false); |
| 559 | - } else { | ||
| 560 | - Device device = deviceService.getDevice(streamInfoForPlayBackCatch.getDeviceID()); | ||
| 561 | - if (device != null) { | ||
| 562 | - try { | ||
| 563 | - cmder.streamByeCmd(device, streamInfoForPlayBackCatch.getChannelId(), | ||
| 564 | - streamInfoForPlayBackCatch.getStream(), null); | ||
| 565 | - } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | ||
| 566 | - logger.error("[无人观看]回放, 发送BYE失败 {}", e.getMessage()); | 532 | + return ret; |
| 533 | + } | ||
| 534 | + // 收到无人观看说明流也没有在往上级推送 | ||
| 535 | + if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) { | ||
| 536 | + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId( | ||
| 537 | + inviteInfo.getChannelId()); | ||
| 538 | + if (sendRtpItems.size() > 0) { | ||
| 539 | + for (SendRtpItem sendRtpItem : sendRtpItems) { | ||
| 540 | + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); | ||
| 541 | + try { | ||
| 542 | + commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); | ||
| 543 | + } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 544 | + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | ||
| 545 | + } | ||
| 546 | + redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), | ||
| 547 | + sendRtpItem.getCallId(), sendRtpItem.getStream()); | ||
| 567 | } | 548 | } |
| 568 | } | 549 | } |
| 569 | - redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(), | ||
| 570 | - streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null); | ||
| 571 | } | 550 | } |
| 572 | - return ret; | ||
| 573 | - } | ||
| 574 | - // 录像下载 | ||
| 575 | - StreamInfo streamInfoForDownload = redisCatchStorage.queryDownload(null, null, param.getStream(), null); | ||
| 576 | - // 进行录像下载时无人观看不断流 | ||
| 577 | - if (streamInfoForDownload != null) { | ||
| 578 | - ret.put("close", false); | 551 | + Device device = deviceService.getDevice(inviteInfo.getDeviceId()); |
| 552 | + if (device != null) { | ||
| 553 | + try { | ||
| 554 | + if (inviteStreamService.getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()) != null) { | ||
| 555 | + cmder.streamByeCmd(device, inviteInfo.getChannelId(), | ||
| 556 | + inviteInfo.getStream(), null); | ||
| 557 | + } | ||
| 558 | + } catch (InvalidArgumentException | ParseException | SipException | | ||
| 559 | + SsrcTransactionNotFoundException e) { | ||
| 560 | + logger.error("[无人观看]点播, 发送BYE失败 {}", e.getMessage()); | ||
| 561 | + } | ||
| 562 | + } | ||
| 563 | + | ||
| 564 | + inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), | ||
| 565 | + inviteInfo.getChannelId(), inviteInfo.getStream()); | ||
| 566 | + storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); | ||
| 579 | return ret; | 567 | return ret; |
| 580 | } | 568 | } |
| 581 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, param.getStream(), null); | 569 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, param.getStream(), null); |
| 582 | - if ("talk".equals(sendRtpItem.getApp())){ | 570 | + if ("talk".equals(sendRtpItem.getApp())) { |
| 583 | ret.put("close", false); | 571 | ret.put("close", false); |
| 584 | return ret; | 572 | return ret; |
| 585 | } | 573 | } |
| 586 | - }else if ("talk".equals(param.getApp()) || "broadcast".equals(param.getApp())){ | 574 | + } else if ("talk".equals(param.getApp()) || "broadcast".equals(param.getApp())) { |
| 587 | ret.put("close", false); | 575 | ret.put("close", false); |
| 588 | } else { | 576 | } else { |
| 589 | // 非国标流 推流/拉流代理 | 577 | // 非国标流 推流/拉流代理 |
| @@ -652,6 +640,7 @@ public class ZLMHttpHookListener { | @@ -652,6 +640,7 @@ public class ZLMHttpHookListener { | ||
| 652 | return defaultResult; | 640 | return defaultResult; |
| 653 | } | 641 | } |
| 654 | logger.info("[ZLM HOOK] 流未找到, 发起自动点播:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | 642 | logger.info("[ZLM HOOK] 流未找到, 发起自动点播:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); |
| 643 | + | ||
| 655 | RequestMessage msg = new RequestMessage(); | 644 | RequestMessage msg = new RequestMessage(); |
| 656 | String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; | 645 | String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; |
| 657 | boolean exist = resultHolder.exist(key, null); | 646 | boolean exist = resultHolder.exist(key, null); |
| @@ -659,31 +648,22 @@ public class ZLMHttpHookListener { | @@ -659,31 +648,22 @@ public class ZLMHttpHookListener { | ||
| 659 | String uuid = UUID.randomUUID().toString(); | 648 | String uuid = UUID.randomUUID().toString(); |
| 660 | msg.setId(uuid); | 649 | msg.setId(uuid); |
| 661 | DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); | 650 | DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); |
| 662 | - DeferredResultEx<HookResult> deferredResultEx = new DeferredResultEx<>(result); | ||
| 663 | 651 | ||
| 664 | result.onTimeout(() -> { | 652 | result.onTimeout(() -> { |
| 665 | - logger.info("点播接口等待超时"); | 653 | + logger.info("[ZLM HOOK] 自动点播, 等待超时"); |
| 666 | // 释放rtpserver | 654 | // 释放rtpserver |
| 667 | msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时")); | 655 | msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时")); |
| 668 | resultHolder.invokeResult(msg); | 656 | resultHolder.invokeResult(msg); |
| 669 | }); | 657 | }); |
| 670 | - // TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误 | ||
| 671 | - deferredResultEx.setFilter(result1 -> { | ||
| 672 | - WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>) result1; | ||
| 673 | - HookResult resultForEnd = new HookResult(); | ||
| 674 | - resultForEnd.setCode(wvpResult1.getCode()); | ||
| 675 | - resultForEnd.setMsg(wvpResult1.getMsg()); | ||
| 676 | - return resultForEnd; | ||
| 677 | - }); | ||
| 678 | 658 | ||
| 679 | // 录像查询以channelId作为deviceId查询 | 659 | // 录像查询以channelId作为deviceId查询 |
| 680 | - resultHolder.put(key, uuid, deferredResultEx); | 660 | + resultHolder.put(key, uuid, result); |
| 681 | 661 | ||
| 682 | if (!exist) { | 662 | if (!exist) { |
| 683 | - playService.play(mediaInfo, deviceId, channelId, null, eventResult -> { | ||
| 684 | - msg.setData(new HookResult(eventResult.statusCode, eventResult.msg)); | 663 | + playService.play(mediaInfo, deviceId, channelId, (code, message, data) -> { |
| 664 | + msg.setData(new HookResult(code, message)); | ||
| 685 | resultHolder.invokeResult(msg); | 665 | resultHolder.invokeResult(msg); |
| 686 | - }, null); | 666 | + }); |
| 687 | } | 667 | } |
| 688 | return result; | 668 | return result; |
| 689 | } else { | 669 | } else { |
| @@ -740,6 +720,7 @@ public class ZLMHttpHookListener { | @@ -740,6 +720,7 @@ public class ZLMHttpHookListener { | ||
| 740 | if (sendRtpItems.size() > 0) { | 720 | if (sendRtpItems.size() > 0) { |
| 741 | for (SendRtpItem sendRtpItem : sendRtpItems) { | 721 | for (SendRtpItem sendRtpItem : sendRtpItems) { |
| 742 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); | 722 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); |
| 723 | + ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); | ||
| 743 | try { | 724 | try { |
| 744 | commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); | 725 | commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); |
| 745 | } catch (SipException | InvalidArgumentException | ParseException e) { | 726 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| @@ -759,7 +740,8 @@ public class ZLMHttpHookListener { | @@ -759,7 +740,8 @@ public class ZLMHttpHookListener { | ||
| 759 | */ | 740 | */ |
| 760 | @ResponseBody | 741 | @ResponseBody |
| 761 | @PostMapping(value = "/on_rtp_server_timeout", produces = "application/json;charset=UTF-8") | 742 | @PostMapping(value = "/on_rtp_server_timeout", produces = "application/json;charset=UTF-8") |
| 762 | - public HookResult onRtpServerTimeout(HttpServletRequest request, @RequestBody OnRtpServerTimeoutHookParam param) { | 743 | + public HookResult onRtpServerTimeout(HttpServletRequest request, @RequestBody OnRtpServerTimeoutHookParam |
| 744 | + param) { | ||
| 763 | logger.info("[ZLM HOOK] rtpServer收流超时:{}->{}({})", param.getMediaServerId(), param.getStream_id(), param.getSsrc()); | 745 | logger.info("[ZLM HOOK] rtpServer收流超时:{}->{}({})", param.getMediaServerId(), param.getStream_id(), param.getSsrc()); |
| 764 | 746 | ||
| 765 | taskExecutor.execute(() -> { | 747 | taskExecutor.execute(() -> { |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
| @@ -97,7 +97,8 @@ public class ZLMMediaListManager { | @@ -97,7 +97,8 @@ public class ZLMMediaListManager { | ||
| 97 | public void sendStreamEvent(String app, String stream, String mediaServerId) { | 97 | public void sendStreamEvent(String app, String stream, String mediaServerId) { |
| 98 | MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); | 98 | MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); |
| 99 | // 查看推流状态 | 99 | // 查看推流状态 |
| 100 | - if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) { | 100 | + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream); |
| 101 | + if (streamReady != null && streamReady) { | ||
| 101 | ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(app, stream); | 102 | ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(app, stream); |
| 102 | if (channelOnlineEventLister != null) { | 103 | if (channelOnlineEventLister != null) { |
| 103 | try { | 104 | try { |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
| @@ -25,6 +25,8 @@ public class ZLMRESTfulUtils { | @@ -25,6 +25,8 @@ public class ZLMRESTfulUtils { | ||
| 25 | 25 | ||
| 26 | private OkHttpClient client; | 26 | private OkHttpClient client; |
| 27 | 27 | ||
| 28 | + | ||
| 29 | + | ||
| 28 | public interface RequestCallback{ | 30 | public interface RequestCallback{ |
| 29 | void run(JSONObject response); | 31 | void run(JSONObject response); |
| 30 | } | 32 | } |
| @@ -279,6 +281,10 @@ public class ZLMRESTfulUtils { | @@ -279,6 +281,10 @@ public class ZLMRESTfulUtils { | ||
| 279 | return sendPost(mediaServerItem, "closeRtpServer",param, null); | 281 | return sendPost(mediaServerItem, "closeRtpServer",param, null); |
| 280 | } | 282 | } |
| 281 | 283 | ||
| 284 | + public void closeRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param, RequestCallback callback) { | ||
| 285 | + sendPost(mediaServerItem, "closeRtpServer",param, callback); | ||
| 286 | + } | ||
| 287 | + | ||
| 282 | public JSONObject listRtpServer(MediaServerItem mediaServerItem) { | 288 | public JSONObject listRtpServer(MediaServerItem mediaServerItem) { |
| 283 | return sendPost(mediaServerItem, "listRtpServer",null, null); | 289 | return sendPost(mediaServerItem, "listRtpServer",null, null); |
| 284 | } | 290 | } |
| @@ -353,4 +359,19 @@ public class ZLMRESTfulUtils { | @@ -353,4 +359,19 @@ public class ZLMRESTfulUtils { | ||
| 353 | param.put("stream_id", streamId); | 359 | param.put("stream_id", streamId); |
| 354 | return sendPost(mediaServerItem, "resumeRtpCheck",param, null); | 360 | return sendPost(mediaServerItem, "resumeRtpCheck",param, null); |
| 355 | } | 361 | } |
| 362 | + | ||
| 363 | + public JSONObject connectRtpServer(MediaServerItem mediaServerItem, String dst_url, int dst_port, String stream_id) { | ||
| 364 | + Map<String, Object> param = new HashMap<>(1); | ||
| 365 | + param.put("dst_url", dst_url); | ||
| 366 | + param.put("dst_port", dst_port); | ||
| 367 | + param.put("stream_id", stream_id); | ||
| 368 | + return sendPost(mediaServerItem, "connectRtpServer",param, null); | ||
| 369 | + } | ||
| 370 | + | ||
| 371 | + public JSONObject updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) { | ||
| 372 | + Map<String, Object> param = new HashMap<>(1); | ||
| 373 | + param.put("ssrc", ssrc); | ||
| 374 | + param.put("stream_id", streamId); | ||
| 375 | + return sendPost(mediaServerItem, "updateRtpServerSSRC",param, null); | ||
| 376 | + } | ||
| 356 | } | 377 | } |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
| @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.media.zlm; | @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.media.zlm; | ||
| 3 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | import com.alibaba.fastjson2.JSONArray; | 4 | import com.alibaba.fastjson2.JSONArray; |
| 5 | import com.alibaba.fastjson2.JSONObject; | 5 | import com.alibaba.fastjson2.JSONObject; |
| 6 | +import com.genersoft.iot.vmp.common.CommonCallback; | ||
| 6 | import com.genersoft.iot.vmp.conf.UserSetting; | 7 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 7 | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | 8 | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
| 8 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | 9 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; |
| @@ -92,7 +93,17 @@ public class ZLMRTPServerFactory { | @@ -92,7 +93,17 @@ public class ZLMRTPServerFactory { | ||
| 92 | return result; | 93 | return result; |
| 93 | } | 94 | } |
| 94 | 95 | ||
| 95 | - public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc, Integer port, Boolean onlyAuto) { | 96 | + /** |
| 97 | + * 开启rtpServer | ||
| 98 | + * @param mediaServerItem zlm服务实例 | ||
| 99 | + * @param streamId 流Id | ||
| 100 | + * @param ssrc ssrc | ||
| 101 | + * @param port 端口, 0/null为使用随机 | ||
| 102 | + * @param reUsePort 是否重用端口 | ||
| 103 | + * @param tcpMode 0/null udp 模式,1 tcp 被动模式, 2 tcp 主动模式。 | ||
| 104 | + * @return | ||
| 105 | + */ | ||
| 106 | + public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { | ||
| 96 | int result = -1; | 107 | int result = -1; |
| 97 | // 查询此rtp server 是否已经存在 | 108 | // 查询此rtp server 是否已经存在 |
| 98 | JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId); | 109 | JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId); |
| @@ -108,7 +119,7 @@ public class ZLMRTPServerFactory { | @@ -108,7 +119,7 @@ public class ZLMRTPServerFactory { | ||
| 108 | JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param); | 119 | JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param); |
| 109 | if (jsonObject != null ) { | 120 | if (jsonObject != null ) { |
| 110 | if (jsonObject.getInteger("code") == 0) { | 121 | if (jsonObject.getInteger("code") == 0) { |
| 111 | - return createRTPServer(mediaServerItem, streamId, ssrc, port, onlyAuto); | 122 | + return createRTPServer(mediaServerItem, streamId, ssrc, port,onlyAuto, reUsePort, tcpMode); |
| 112 | }else { | 123 | }else { |
| 113 | logger.warn("[开启rtpServer], 重启RtpServer错误"); | 124 | logger.warn("[开启rtpServer], 重启RtpServer错误"); |
| 114 | } | 125 | } |
| @@ -122,8 +133,14 @@ public class ZLMRTPServerFactory { | @@ -122,8 +133,14 @@ public class ZLMRTPServerFactory { | ||
| 122 | 133 | ||
| 123 | Map<String, Object> param = new HashMap<>(); | 134 | Map<String, Object> param = new HashMap<>(); |
| 124 | 135 | ||
| 125 | - param.put("enable_tcp", 1); | 136 | + if (tcpMode == null) { |
| 137 | + tcpMode = 0; | ||
| 138 | + } | ||
| 139 | + param.put("tcp_mode", tcpMode); | ||
| 126 | param.put("stream_id", streamId); | 140 | param.put("stream_id", streamId); |
| 141 | + if (reUsePort != null) { | ||
| 142 | + param.put("re_use_port", reUsePort?"1":"0"); | ||
| 143 | + } | ||
| 127 | // 推流端口设置0则使用随机端口 | 144 | // 推流端口设置0则使用随机端口 |
| 128 | if (port == null) { | 145 | if (port == null) { |
| 129 | param.put("port", 0); | 146 | param.put("port", 0); |
| @@ -169,6 +186,31 @@ public class ZLMRTPServerFactory { | @@ -169,6 +186,31 @@ public class ZLMRTPServerFactory { | ||
| 169 | return result; | 186 | return result; |
| 170 | } | 187 | } |
| 171 | 188 | ||
| 189 | + public void closeRtpServer(MediaServerItem serverItem, String streamId, CommonCallback<Boolean> callback) { | ||
| 190 | + if (serverItem == null) { | ||
| 191 | + callback.run(false); | ||
| 192 | + return; | ||
| 193 | + } | ||
| 194 | + Map<String, Object> param = new HashMap<>(); | ||
| 195 | + param.put("stream_id", streamId); | ||
| 196 | + zlmresTfulUtils.closeRtpServer(serverItem, param, jsonObject -> { | ||
| 197 | + if (jsonObject != null ) { | ||
| 198 | + if (jsonObject.getInteger("code") == 0) { | ||
| 199 | + callback.run(jsonObject.getInteger("hit") == 1); | ||
| 200 | + return; | ||
| 201 | + }else { | ||
| 202 | + logger.error("关闭RTP Server 失败: " + jsonObject.getString("msg")); | ||
| 203 | + } | ||
| 204 | + }else { | ||
| 205 | + // 检查ZLM状态 | ||
| 206 | + logger.error("关闭RTP Server 失败: 请检查ZLM服务"); | ||
| 207 | + } | ||
| 208 | + callback.run(false); | ||
| 209 | + }); | ||
| 210 | + | ||
| 211 | + | ||
| 212 | + } | ||
| 213 | + | ||
| 172 | 214 | ||
| 173 | /** | 215 | /** |
| 174 | * 创建一个国标推流 | 216 | * 创建一个国标推流 |
| @@ -256,11 +298,14 @@ public class ZLMRTPServerFactory { | @@ -256,11 +298,14 @@ public class ZLMRTPServerFactory { | ||
| 256 | if (jsonObject.getInteger("code") == 0) { | 298 | if (jsonObject.getInteger("code") == 0) { |
| 257 | localPort = jsonObject.getInteger("port"); | 299 | localPort = jsonObject.getInteger("port"); |
| 258 | HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); | 300 | HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); |
| 259 | - // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 | ||
| 260 | hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout, | 301 | hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout, |
| 261 | (MediaServerItem mediaServerItem, JSONObject response)->{ | 302 | (MediaServerItem mediaServerItem, JSONObject response)->{ |
| 262 | - logger.info("[保持端口] {}->监听端口到期继续保持监听", ssrc); | ||
| 263 | - keepPort(serverItem, ssrc); | 303 | + logger.info("[上级点播] {}->监听端口到期继续保持监听", ssrc); |
| 304 | + int port = keepPort(serverItem, ssrc); | ||
| 305 | + if (port == 0) { | ||
| 306 | + logger.info("[上级点播] {}->监听端口失败,移除监听", ssrc); | ||
| 307 | + hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout); | ||
| 308 | + } | ||
| 264 | }); | 309 | }); |
| 265 | logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort); | 310 | logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort); |
| 266 | logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort); | 311 | logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort); |
| @@ -305,6 +350,9 @@ public class ZLMRTPServerFactory { | @@ -305,6 +350,9 @@ public class ZLMRTPServerFactory { | ||
| 305 | */ | 350 | */ |
| 306 | public Boolean isRtpReady(MediaServerItem mediaServerItem, String streamId) { | 351 | public Boolean isRtpReady(MediaServerItem mediaServerItem, String streamId) { |
| 307 | JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem,"rtp", "rtsp", streamId); | 352 | JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem,"rtp", "rtsp", streamId); |
| 353 | + if (mediaInfo.getInteger("code") == -2) { | ||
| 354 | + return null; | ||
| 355 | + } | ||
| 308 | return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")); | 356 | return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")); |
| 309 | } | 357 | } |
| 310 | 358 | ||
| @@ -313,8 +361,10 @@ public class ZLMRTPServerFactory { | @@ -313,8 +361,10 @@ public class ZLMRTPServerFactory { | ||
| 313 | */ | 361 | */ |
| 314 | public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) { | 362 | public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) { |
| 315 | JSONObject mediaInfo = zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId); | 363 | JSONObject mediaInfo = zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId); |
| 316 | - return mediaInfo != null && (mediaInfo.getInteger("code") == 0 | ||
| 317 | - | 364 | + if (mediaInfo == null || (mediaInfo.getInteger("code") == -2)) { |
| 365 | + return null; | ||
| 366 | + } | ||
| 367 | + return (mediaInfo.getInteger("code") == 0 | ||
| 318 | && mediaInfo.getJSONArray("data") != null | 368 | && mediaInfo.getJSONArray("data") != null |
| 319 | && mediaInfo.getJSONArray("data").size() > 0); | 369 | && mediaInfo.getJSONArray("data").size() > 0); |
| 320 | } | 370 | } |
| @@ -406,4 +456,19 @@ public class ZLMRTPServerFactory { | @@ -406,4 +456,19 @@ public class ZLMRTPServerFactory { | ||
| 406 | } | 456 | } |
| 407 | return startSendRtpStreamResult; | 457 | return startSendRtpStreamResult; |
| 408 | } | 458 | } |
| 459 | + | ||
| 460 | + public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) { | ||
| 461 | + boolean result = false; | ||
| 462 | + JSONObject jsonObject = zlmresTfulUtils.updateRtpServerSSRC(mediaServerItem, streamId, ssrc); | ||
| 463 | + if (jsonObject == null) { | ||
| 464 | + logger.error("[更新RTPServer] 失败: 请检查ZLM服务"); | ||
| 465 | + } else if (jsonObject.getInteger("code") == 0) { | ||
| 466 | + result= true; | ||
| 467 | + logger.info("[更新RTPServer] 成功"); | ||
| 468 | + } else { | ||
| 469 | + logger.error("[更新RTPServer] 失败: {}, streamId:{},ssrc:{}->\r\n{}",jsonObject.getString("msg"), | ||
| 470 | + streamId, ssrc, jsonObject); | ||
| 471 | + } | ||
| 472 | + return result; | ||
| 473 | + } | ||
| 409 | } | 474 | } |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZlmHttpHookSubscribe.java
| @@ -100,7 +100,10 @@ public class ZlmHttpHookSubscribe { | @@ -100,7 +100,10 @@ public class ZlmHttpHookSubscribe { | ||
| 100 | 100 | ||
| 101 | if (!CollectionUtils.isEmpty(entriesToRemove)) { | 101 | if (!CollectionUtils.isEmpty(entriesToRemove)) { |
| 102 | for (Map.Entry<IHookSubscribe, ZlmHttpHookSubscribe.Event> entry : entriesToRemove) { | 102 | for (Map.Entry<IHookSubscribe, ZlmHttpHookSubscribe.Event> entry : entriesToRemove) { |
| 103 | - entries.remove(entry); | 103 | + eventMap.remove(entry.getKey()); |
| 104 | + } | ||
| 105 | + if (eventMap.size() == 0) { | ||
| 106 | + allSubscribes.remove(hookSubscribe.getHookType()); | ||
| 104 | } | 107 | } |
| 105 | } | 108 | } |
| 106 | 109 | ||
| @@ -136,9 +139,9 @@ public class ZlmHttpHookSubscribe { | @@ -136,9 +139,9 @@ public class ZlmHttpHookSubscribe { | ||
| 136 | /** | 139 | /** |
| 137 | * 对订阅数据进行过期清理 | 140 | * 对订阅数据进行过期清理 |
| 138 | */ | 141 | */ |
| 139 | - @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次 | 142 | +// @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次 |
| 143 | + @Scheduled(fixedRate = 2 * 1000) | ||
| 140 | public void execute(){ | 144 | public void execute(){ |
| 141 | - | ||
| 142 | Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5)); | 145 | Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5)); |
| 143 | int total = 0; | 146 | int total = 0; |
| 144 | for (HookType hookType : allSubscribes.keySet()) { | 147 | for (HookType hookType : allSubscribes.keySet()) { |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
| 1 | package com.genersoft.iot.vmp.media.zlm.dto; | 1 | package com.genersoft.iot.vmp.media.zlm.dto; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | -import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | ||
| 5 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; | 4 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; |
| 6 | import io.swagger.v3.oas.annotations.media.Schema; | 5 | import io.swagger.v3.oas.annotations.media.Schema; |
| 7 | import org.springframework.util.ObjectUtils; | 6 | import org.springframework.util.ObjectUtils; |
| 8 | 7 | ||
| 9 | -import java.util.HashMap; | ||
| 10 | - | ||
| 11 | @Schema(description = "流媒体服务信息") | 8 | @Schema(description = "流媒体服务信息") |
| 12 | public class MediaServerItem{ | 9 | public class MediaServerItem{ |
| 13 | 10 | ||
| @@ -80,20 +77,10 @@ public class MediaServerItem{ | @@ -80,20 +77,10 @@ public class MediaServerItem{ | ||
| 80 | @Schema(description = "是否是默认ZLM") | 77 | @Schema(description = "是否是默认ZLM") |
| 81 | private boolean defaultServer; | 78 | private boolean defaultServer; |
| 82 | 79 | ||
| 83 | - @Schema(description = "SSRC信息") | ||
| 84 | - private SsrcConfig ssrcConfig; | ||
| 85 | - | ||
| 86 | @Schema(description = "当前使用到的端口") | 80 | @Schema(description = "当前使用到的端口") |
| 87 | private int currentPort; | 81 | private int currentPort; |
| 88 | 82 | ||
| 89 | 83 | ||
| 90 | - /** | ||
| 91 | - * 每一台ZLM都有一套独立的SSRC列表 | ||
| 92 | - * 在ApplicationCheckRunner里对mediaServerSsrcMap进行初始化 | ||
| 93 | - */ | ||
| 94 | - @Schema(description = "ID") | ||
| 95 | - private HashMap<String, SsrcConfig> mediaServerSsrcMap; | ||
| 96 | - | ||
| 97 | public MediaServerItem() { | 84 | public MediaServerItem() { |
| 98 | } | 85 | } |
| 99 | 86 | ||
| @@ -279,22 +266,6 @@ public class MediaServerItem{ | @@ -279,22 +266,6 @@ public class MediaServerItem{ | ||
| 279 | this.updateTime = updateTime; | 266 | this.updateTime = updateTime; |
| 280 | } | 267 | } |
| 281 | 268 | ||
| 282 | - public HashMap<String, SsrcConfig> getMediaServerSsrcMap() { | ||
| 283 | - return mediaServerSsrcMap; | ||
| 284 | - } | ||
| 285 | - | ||
| 286 | - public void setMediaServerSsrcMap(HashMap<String, SsrcConfig> mediaServerSsrcMap) { | ||
| 287 | - this.mediaServerSsrcMap = mediaServerSsrcMap; | ||
| 288 | - } | ||
| 289 | - | ||
| 290 | - public SsrcConfig getSsrcConfig() { | ||
| 291 | - return ssrcConfig; | ||
| 292 | - } | ||
| 293 | - | ||
| 294 | - public void setSsrcConfig(SsrcConfig ssrcConfig) { | ||
| 295 | - this.ssrcConfig = ssrcConfig; | ||
| 296 | - } | ||
| 297 | - | ||
| 298 | public int getCurrentPort() { | 269 | public int getCurrentPort() { |
| 299 | return currentPort; | 270 | return currentPort; |
| 300 | } | 271 | } |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResult.java
| @@ -18,6 +18,10 @@ public class HookResult { | @@ -18,6 +18,10 @@ public class HookResult { | ||
| 18 | return new HookResult(0, "success"); | 18 | return new HookResult(0, "success"); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | + public static HookResult Fail(){ | ||
| 22 | + return new HookResult(-1, "fail"); | ||
| 23 | + } | ||
| 24 | + | ||
| 21 | public int getCode() { | 25 | public int getCode() { |
| 22 | return code; | 26 | return code; |
| 23 | } | 27 | } |
src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java
| @@ -56,4 +56,35 @@ public interface IDeviceChannelService { | @@ -56,4 +56,35 @@ public interface IDeviceChannelService { | ||
| 56 | * 查询通道所属的设备 | 56 | * 查询通道所属的设备 |
| 57 | */ | 57 | */ |
| 58 | List<Device> getDeviceByChannelId(String channelId); | 58 | List<Device> getDeviceByChannelId(String channelId); |
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * 批量删除通道 | ||
| 62 | + * @param deleteChannelList 待删除的通道列表 | ||
| 63 | + */ | ||
| 64 | + int deleteChannels(List<DeviceChannel> deleteChannelList); | ||
| 65 | + | ||
| 66 | + /** | ||
| 67 | + * 批量上线 | ||
| 68 | + */ | ||
| 69 | + int channelsOnline(List<DeviceChannel> channels); | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * 批量下线 | ||
| 73 | + */ | ||
| 74 | + int channelsOffline(List<DeviceChannel> channels); | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * 获取一个通道 | ||
| 78 | + */ | ||
| 79 | + DeviceChannel getOne(String deviceId, String channelId); | ||
| 80 | + | ||
| 81 | + /** | ||
| 82 | + * 直接批量更新通道 | ||
| 83 | + */ | ||
| 84 | + void batchUpdateChannel(List<DeviceChannel> channels); | ||
| 85 | + | ||
| 86 | + /** | ||
| 87 | + * 直接批量添加 | ||
| 88 | + */ | ||
| 89 | + void batchAddChannel(List<DeviceChannel> deviceChannels); | ||
| 59 | } | 90 | } |
src/main/java/com/genersoft/iot/vmp/service/IInviteStreamService.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.service; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.common.InviteInfo; | ||
| 4 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 5 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCallback; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 记录国标点播的状态,包括实时预览,下载,录像回放 | ||
| 9 | + */ | ||
| 10 | +public interface IInviteStreamService { | ||
| 11 | + | ||
| 12 | + /** | ||
| 13 | + * 更新点播的状态信息 | ||
| 14 | + */ | ||
| 15 | + void updateInviteInfo(InviteInfo inviteInfo); | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * 获取点播的状态信息 | ||
| 19 | + */ | ||
| 20 | + InviteInfo getInviteInfo(InviteSessionType type, | ||
| 21 | + String deviceId, | ||
| 22 | + String channelId, | ||
| 23 | + String stream); | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 移除点播的状态信息 | ||
| 27 | + */ | ||
| 28 | + void removeInviteInfo(InviteSessionType type, | ||
| 29 | + String deviceId, | ||
| 30 | + String channelId, | ||
| 31 | + String stream); | ||
| 32 | + /** | ||
| 33 | + * 移除点播的状态信息 | ||
| 34 | + */ | ||
| 35 | + void removeInviteInfo(InviteInfo inviteInfo); | ||
| 36 | + /** | ||
| 37 | + * 移除点播的状态信息 | ||
| 38 | + */ | ||
| 39 | + void removeInviteInfoByDeviceAndChannel(InviteSessionType inviteSessionType, String deviceId, String channelId); | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 获取点播的状态信息 | ||
| 43 | + */ | ||
| 44 | + InviteInfo getInviteInfoByDeviceAndChannel(InviteSessionType type, | ||
| 45 | + String deviceId, | ||
| 46 | + String channelId); | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 获取点播的状态信息 | ||
| 50 | + */ | ||
| 51 | + InviteInfo getInviteInfoByStream(InviteSessionType type, String stream); | ||
| 52 | + | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * 添加一个invite回调 | ||
| 56 | + */ | ||
| 57 | + void once(InviteSessionType type, String deviceId, String channelId, String stream, InviteErrorCallback<Object> callback); | ||
| 58 | + | ||
| 59 | + /** | ||
| 60 | + * 调用一个invite回调 | ||
| 61 | + */ | ||
| 62 | + void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data); | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 清空一个设备的所有invite信息 | ||
| 66 | + */ | ||
| 67 | + void clearInviteInfo(String deviceId); | ||
| 68 | +} |
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
| 1 | package com.genersoft.iot.vmp.service; | 1 | package com.genersoft.iot.vmp.service; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.common.CommonCallback; | ||
| 3 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; | 4 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; |
| 4 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 5 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 5 | import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; | 6 | import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; |
| @@ -43,14 +44,16 @@ public interface IMediaServerService { | @@ -43,14 +44,16 @@ public interface IMediaServerService { | ||
| 43 | 44 | ||
| 44 | void updateVmServer(List<MediaServerItem> mediaServerItemList); | 45 | void updateVmServer(List<MediaServerItem> mediaServerItemList); |
| 45 | 46 | ||
| 46 | - SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback); | ||
| 47 | - | ||
| 48 | - SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback); | 47 | + SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, |
| 48 | + boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode); | ||
| 49 | 49 | ||
| 50 | SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto); | 50 | SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto); |
| 51 | 51 | ||
| 52 | void closeRTPServer(MediaServerItem mediaServerItem, String streamId); | 52 | void closeRTPServer(MediaServerItem mediaServerItem, String streamId); |
| 53 | 53 | ||
| 54 | + void closeRTPServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback); | ||
| 55 | + Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc); | ||
| 56 | + | ||
| 54 | void closeRTPServer(String mediaServerId, String streamId); | 57 | void closeRTPServer(String mediaServerId, String streamId); |
| 55 | 58 | ||
| 56 | void clearRTPServer(MediaServerItem mediaServerItem); | 59 | void clearRTPServer(MediaServerItem mediaServerItem); |
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
| @@ -3,12 +3,11 @@ package com.genersoft.iot.vmp.service; | @@ -3,12 +3,11 @@ package com.genersoft.iot.vmp.service; | ||
| 3 | import com.alibaba.fastjson2.JSONObject; | 3 | import com.alibaba.fastjson2.JSONObject; |
| 4 | import com.genersoft.iot.vmp.common.StreamInfo; | 4 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 5 | import com.genersoft.iot.vmp.conf.exception.ServiceException; | 5 | import com.genersoft.iot.vmp.conf.exception.ServiceException; |
| 6 | -import com.genersoft.iot.vmp.gb28181.bean.*; | ||
| 7 | -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | ||
| 8 | -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | 6 | +import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 7 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | ||
| 8 | +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | ||
| 9 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 9 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 10 | -import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; | ||
| 11 | -import com.genersoft.iot.vmp.service.bean.PlayBackCallback; | 10 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCallback; |
| 12 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; | 11 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 13 | import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | 12 | import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; |
| 14 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; | 13 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; |
| @@ -25,12 +24,11 @@ import java.util.Map; | @@ -25,12 +24,11 @@ import java.util.Map; | ||
| 25 | */ | 24 | */ |
| 26 | public interface IPlayService { | 25 | public interface IPlayService { |
| 27 | 26 | ||
| 28 | - void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId); | ||
| 29 | - | ||
| 30 | void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | 27 | void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 31 | - ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | ||
| 32 | - InviteTimeOutCallback timeoutCallback); | ||
| 33 | - void play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent, Runnable timeoutCallback); | 28 | + InviteErrorCallback<Object> callback); |
| 29 | + SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, InviteErrorCallback<Object> callback); | ||
| 30 | + | ||
| 31 | + StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId); | ||
| 34 | 32 | ||
| 35 | MediaServerItem getNewMediaServerItem(Device device); | 33 | MediaServerItem getNewMediaServerItem(Device device); |
| 36 | 34 | ||
| @@ -39,15 +37,13 @@ public interface IPlayService { | @@ -39,15 +37,13 @@ public interface IPlayService { | ||
| 39 | */ | 37 | */ |
| 40 | MediaServerItem getNewMediaServerItemHasAssist(Device device); | 38 | MediaServerItem getNewMediaServerItemHasAssist(Device device); |
| 41 | 39 | ||
| 42 | - void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String toString); | ||
| 43 | - | ||
| 44 | - void playBack(String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback); | ||
| 45 | - void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); | 40 | + void playBack(String deviceId, String channelId, String startTime, String endTime, InviteErrorCallback<Object> callback); |
| 41 | + void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteErrorCallback<Object> callback); | ||
| 46 | 42 | ||
| 47 | void zlmServerOffline(String mediaServerId); | 43 | void zlmServerOffline(String mediaServerId); |
| 48 | 44 | ||
| 49 | - void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback); | ||
| 50 | - void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); | 45 | + void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback); |
| 46 | + void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback); | ||
| 51 | 47 | ||
| 52 | StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream); | 48 | StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream); |
| 53 | 49 |
src/main/java/com/genersoft/iot/vmp/service/bean/InviteErrorCallback.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/service/bean/InviteErrorCode.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.service.bean; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 全局错误码 | ||
| 5 | + */ | ||
| 6 | +public enum InviteErrorCode { | ||
| 7 | + SUCCESS(0, "成功"), | ||
| 8 | + ERROR_FOR_SIGNALLING_TIMEOUT(-1, "信令超时"), | ||
| 9 | + ERROR_FOR_STREAM_TIMEOUT(-2, "收流超时"), | ||
| 10 | + ERROR_FOR_RESOURCE_EXHAUSTION(-3, "资源耗尽"), | ||
| 11 | + ERROR_FOR_CATCH_DATA(-4, "缓存数据异常"), | ||
| 12 | + ERROR_FOR_SIGNALLING_ERROR(-5, "收到信令错误"), | ||
| 13 | + ERROR_FOR_STREAM_PARSING_EXCEPTIONS(-6, "流地址解析错误"), | ||
| 14 | + ERROR_FOR_SDP_PARSING_EXCEPTIONS(-7, "SDP信息解析失败"), | ||
| 15 | + ERROR_FOR_SSRC_UNAVAILABLE(-8, "SSRC不可用"), | ||
| 16 | + ERROR_FOR_RESET_SSRC(-9, "重新设置收流信息失败"), | ||
| 17 | + ERROR_FOR_SIP_SENDING_FAILED(-10, "命令发送失败"), | ||
| 18 | + ERROR_FOR_ASSIST_NOT_READY(-11, "没有可用的assist服务"), | ||
| 19 | + ERROR_FOR_PARAMETER_ERROR(-13, "参数异常"); | ||
| 20 | + | ||
| 21 | + private final int code; | ||
| 22 | + private final String msg; | ||
| 23 | + | ||
| 24 | + InviteErrorCode(int code, String msg) { | ||
| 25 | + this.code = code; | ||
| 26 | + this.msg = msg; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + public int getCode() { | ||
| 30 | + return code; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + public String getMsg() { | ||
| 34 | + return msg; | ||
| 35 | + } | ||
| 36 | +} |
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
| 1 | package com.genersoft.iot.vmp.service.impl; | 1 | package com.genersoft.iot.vmp.service.impl; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.common.StreamInfo; | 3 | +import com.genersoft.iot.vmp.common.InviteInfo; |
| 4 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 4 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 5 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 5 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | 6 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| 6 | import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; | 7 | import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; |
| 7 | import com.genersoft.iot.vmp.service.IDeviceChannelService; | 8 | import com.genersoft.iot.vmp.service.IDeviceChannelService; |
| 9 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | ||
| 8 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 10 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 9 | import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; | 11 | import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; |
| 10 | import com.genersoft.iot.vmp.storager.dao.DeviceMapper; | 12 | import com.genersoft.iot.vmp.storager.dao.DeviceMapper; |
| @@ -33,6 +35,9 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | @@ -33,6 +35,9 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | ||
| 33 | private IRedisCatchStorage redisCatchStorage; | 35 | private IRedisCatchStorage redisCatchStorage; |
| 34 | 36 | ||
| 35 | @Autowired | 37 | @Autowired |
| 38 | + private IInviteStreamService inviteStreamService; | ||
| 39 | + | ||
| 40 | + @Autowired | ||
| 36 | private DeviceChannelMapper channelMapper; | 41 | private DeviceChannelMapper channelMapper; |
| 37 | 42 | ||
| 38 | @Autowired | 43 | @Autowired |
| @@ -45,6 +50,8 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | @@ -45,6 +50,8 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | ||
| 45 | device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId()); | 50 | device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId()); |
| 46 | } | 51 | } |
| 47 | 52 | ||
| 53 | + | ||
| 54 | + | ||
| 48 | if ("WGS84".equals(device.getGeoCoordSys())) { | 55 | if ("WGS84".equals(device.getGeoCoordSys())) { |
| 49 | deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); | 56 | deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); |
| 50 | deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude()); | 57 | deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude()); |
| @@ -76,9 +83,10 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | @@ -76,9 +83,10 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | ||
| 76 | public void updateChannel(String deviceId, DeviceChannel channel) { | 83 | public void updateChannel(String deviceId, DeviceChannel channel) { |
| 77 | String channelId = channel.getChannelId(); | 84 | String channelId = channel.getChannelId(); |
| 78 | channel.setDeviceId(deviceId); | 85 | channel.setDeviceId(deviceId); |
| 79 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); | ||
| 80 | - if (streamInfo != null) { | ||
| 81 | - channel.setStreamId(streamInfo.getStream()); | 86 | +// StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); |
| 87 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); | ||
| 88 | + if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { | ||
| 89 | + channel.setStreamId(inviteInfo.getStreamInfo().getStream()); | ||
| 82 | } | 90 | } |
| 83 | String now = DateUtil.getNow(); | 91 | String now = DateUtil.getNow(); |
| 84 | channel.setUpdateTime(now); | 92 | channel.setUpdateTime(now); |
| @@ -104,9 +112,9 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | @@ -104,9 +112,9 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | ||
| 104 | if (channelList.size() == 0) { | 112 | if (channelList.size() == 0) { |
| 105 | for (DeviceChannel channel : channels) { | 113 | for (DeviceChannel channel : channels) { |
| 106 | channel.setDeviceId(deviceId); | 114 | channel.setDeviceId(deviceId); |
| 107 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId()); | ||
| 108 | - if (streamInfo != null) { | ||
| 109 | - channel.setStreamId(streamInfo.getStream()); | 115 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channel.getChannelId()); |
| 116 | + if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { | ||
| 117 | + channel.setStreamId(inviteInfo.getStreamInfo().getStream()); | ||
| 110 | } | 118 | } |
| 111 | String now = DateUtil.getNow(); | 119 | String now = DateUtil.getNow(); |
| 112 | channel.setUpdateTime(now); | 120 | channel.setUpdateTime(now); |
| @@ -120,9 +128,9 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | @@ -120,9 +128,9 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | ||
| 120 | } | 128 | } |
| 121 | for (DeviceChannel channel : channels) { | 129 | for (DeviceChannel channel : channels) { |
| 122 | channel.setDeviceId(deviceId); | 130 | channel.setDeviceId(deviceId); |
| 123 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId()); | ||
| 124 | - if (streamInfo != null) { | ||
| 125 | - channel.setStreamId(streamInfo.getStream()); | 131 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channel.getChannelId()); |
| 132 | + if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { | ||
| 133 | + channel.setStreamId(inviteInfo.getStreamInfo().getStream()); | ||
| 126 | } | 134 | } |
| 127 | String now = DateUtil.getNow(); | 135 | String now = DateUtil.getNow(); |
| 128 | channel.setUpdateTime(now); | 136 | channel.setUpdateTime(now); |
| @@ -207,6 +215,47 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | @@ -207,6 +215,47 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | ||
| 207 | 215 | ||
| 208 | @Override | 216 | @Override |
| 209 | public List<Device> getDeviceByChannelId(String channelId) { | 217 | public List<Device> getDeviceByChannelId(String channelId) { |
| 218 | + | ||
| 210 | return channelMapper.getDeviceByChannelId(channelId); | 219 | return channelMapper.getDeviceByChannelId(channelId); |
| 211 | } | 220 | } |
| 221 | + | ||
| 222 | + @Override | ||
| 223 | + public int deleteChannels(List<DeviceChannel> deleteChannelList) { | ||
| 224 | + return channelMapper.batchDel(deleteChannelList); | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + @Override | ||
| 228 | + public int channelsOnline(List<DeviceChannel> channels) { | ||
| 229 | + return channelMapper.batchOnline(channels); | ||
| 230 | + } | ||
| 231 | + | ||
| 232 | + @Override | ||
| 233 | + public int channelsOffline(List<DeviceChannel> channels) { | ||
| 234 | + return channelMapper.batchOffline(channels); | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + @Override | ||
| 238 | + public DeviceChannel getOne(String deviceId, String channelId){ | ||
| 239 | + return channelMapper.queryChannel(deviceId, channelId); | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + @Override | ||
| 243 | + public void batchUpdateChannel(List<DeviceChannel> channels) { | ||
| 244 | + channelMapper.batchUpdate(channels); | ||
| 245 | + for (DeviceChannel channel : channels) { | ||
| 246 | + if (channel.getParentId() != null) { | ||
| 247 | + channelMapper.updateChannelSubCount(channel.getDeviceId(), channel.getParentId()); | ||
| 248 | + } | ||
| 249 | + } | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | + @Override | ||
| 253 | + public void batchAddChannel(List<DeviceChannel> channels) { | ||
| 254 | + channelMapper.batchAdd(channels); | ||
| 255 | + for (DeviceChannel channel : channels) { | ||
| 256 | + if (channel.getParentId() != null) { | ||
| 257 | + channelMapper.updateChannelSubCount(channel.getDeviceId(), channel.getParentId()); | ||
| 258 | + } | ||
| 259 | + } | ||
| 260 | + } | ||
| 212 | } | 261 | } |
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
| @@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | @@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | ||
| 15 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 15 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 16 | import com.genersoft.iot.vmp.service.IDeviceChannelService; | 16 | import com.genersoft.iot.vmp.service.IDeviceChannelService; |
| 17 | import com.genersoft.iot.vmp.service.IDeviceService; | 17 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 18 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | ||
| 18 | import com.genersoft.iot.vmp.service.IMediaServerService; | 19 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 19 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 20 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 20 | import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; | 21 | import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; |
| @@ -60,6 +61,9 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -60,6 +61,9 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 60 | private IRedisCatchStorage redisCatchStorage; | 61 | private IRedisCatchStorage redisCatchStorage; |
| 61 | 62 | ||
| 62 | @Autowired | 63 | @Autowired |
| 64 | + private IInviteStreamService inviteStreamService; | ||
| 65 | + | ||
| 66 | + @Autowired | ||
| 63 | private DeviceMapper deviceMapper; | 67 | private DeviceMapper deviceMapper; |
| 64 | 68 | ||
| 65 | @Autowired | 69 | @Autowired |
| @@ -104,7 +108,7 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -104,7 +108,7 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 104 | String now = DateUtil.getNow(); | 108 | String now = DateUtil.getNow(); |
| 105 | if (deviceInRedis != null && deviceInDb == null) { | 109 | if (deviceInRedis != null && deviceInDb == null) { |
| 106 | // redis 存在脏数据 | 110 | // redis 存在脏数据 |
| 107 | - redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); | 111 | + inviteStreamService.clearInviteInfo(device.getDeviceId()); |
| 108 | } | 112 | } |
| 109 | device.setUpdateTime(now); | 113 | device.setUpdateTime(now); |
| 110 | if (device.getKeepaliveIntervalTime() == 0) { | 114 | if (device.getKeepaliveIntervalTime() == 0) { |
| @@ -172,6 +176,11 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -172,6 +176,11 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 172 | String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); | 176 | String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); |
| 173 | // 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线 | 177 | // 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线 |
| 174 | dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "首次注册后未能收到心跳"), device.getKeepaliveIntervalTime() * 1000 * 3); | 178 | dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "首次注册后未能收到心跳"), device.getKeepaliveIntervalTime() * 1000 * 3); |
| 179 | + if (userSetting.getDeviceStatusNotify()) { | ||
| 180 | + // 发送redis消息 | ||
| 181 | + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, true); | ||
| 182 | + } | ||
| 183 | + | ||
| 175 | } | 184 | } |
| 176 | 185 | ||
| 177 | @Override | 186 | @Override |
| @@ -200,6 +209,11 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -200,6 +209,11 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 200 | // 移除订阅 | 209 | // 移除订阅 |
| 201 | removeCatalogSubscribe(device); | 210 | removeCatalogSubscribe(device); |
| 202 | removeMobilePositionSubscribe(device); | 211 | removeMobilePositionSubscribe(device); |
| 212 | + if (userSetting.getDeviceStatusNotify()) { | ||
| 213 | + // 发送redis消息 | ||
| 214 | + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, false); | ||
| 215 | + } | ||
| 216 | + | ||
| 203 | List<AudioBroadcastCatch> audioBroadcastCatches = audioBroadcastManager.get(deviceId); | 217 | List<AudioBroadcastCatch> audioBroadcastCatches = audioBroadcastManager.get(deviceId); |
| 204 | if (audioBroadcastCatches.size() > 0) { | 218 | if (audioBroadcastCatches.size() > 0) { |
| 205 | for (AudioBroadcastCatch audioBroadcastCatch : audioBroadcastCatches) { | 219 | for (AudioBroadcastCatch audioBroadcastCatch : audioBroadcastCatches) { |
| @@ -512,8 +526,10 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -512,8 +526,10 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 512 | node.setBasicData(channel); | 526 | node.setBasicData(channel); |
| 513 | node.setParent(false); | 527 | node.setParent(false); |
| 514 | if (channel.getChannelId().length() > 8) { | 528 | if (channel.getChannelId().length() > 8) { |
| 515 | - String gbCodeType = channel.getChannelId().substring(10, 13); | ||
| 516 | - node.setParent(gbCodeType.equals(ChannelIdType.BUSINESS_GROUP) || gbCodeType.equals(ChannelIdType.VIRTUAL_ORGANIZATION) ); | 529 | + if (channel.getChannelId().length() > 13) { |
| 530 | + String gbCodeType = channel.getChannelId().substring(10, 13); | ||
| 531 | + node.setParent(gbCodeType.equals(ChannelIdType.BUSINESS_GROUP) || gbCodeType.equals(ChannelIdType.VIRTUAL_ORGANIZATION) ); | ||
| 532 | + } | ||
| 517 | }else { | 533 | }else { |
| 518 | node.setParent(true); | 534 | node.setParent(true); |
| 519 | } | 535 | } |
| @@ -669,4 +685,6 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -669,4 +685,6 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 669 | public List<Device> getAll() { | 685 | public List<Device> getAll() { |
| 670 | return deviceMapper.getAll(); | 686 | return deviceMapper.getAll(); |
| 671 | } | 687 | } |
| 688 | + | ||
| 689 | + | ||
| 672 | } | 690 | } |
src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.service.impl; | ||
| 2 | + | ||
| 3 | +import com.alibaba.fastjson2.JSON; | ||
| 4 | +import com.genersoft.iot.vmp.common.InviteInfo; | ||
| 5 | +import com.genersoft.iot.vmp.common.InviteSessionStatus; | ||
| 6 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 7 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | ||
| 8 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | ||
| 9 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCallback; | ||
| 10 | +import com.genersoft.iot.vmp.utils.redis.RedisUtil; | ||
| 11 | +import org.slf4j.Logger; | ||
| 12 | +import org.slf4j.LoggerFactory; | ||
| 13 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 14 | +import org.springframework.data.redis.core.RedisTemplate; | ||
| 15 | +import org.springframework.stereotype.Service; | ||
| 16 | + | ||
| 17 | +import java.util.List; | ||
| 18 | +import java.util.Map; | ||
| 19 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 20 | +import java.util.concurrent.CopyOnWriteArrayList; | ||
| 21 | + | ||
| 22 | +@Service | ||
| 23 | +public class InviteStreamServiceImpl implements IInviteStreamService { | ||
| 24 | + | ||
| 25 | + private final Logger logger = LoggerFactory.getLogger(InviteStreamServiceImpl.class); | ||
| 26 | + | ||
| 27 | + private final Map<String, List<InviteErrorCallback<Object>>> inviteErrorCallbackMap = new ConcurrentHashMap<>(); | ||
| 28 | + | ||
| 29 | + @Autowired | ||
| 30 | + private RedisTemplate<Object, Object> redisTemplate; | ||
| 31 | + | ||
| 32 | + @Override | ||
| 33 | + public void updateInviteInfo(InviteInfo inviteInfo) { | ||
| 34 | + if (inviteInfo == null || (inviteInfo.getDeviceId() == null || inviteInfo.getChannelId() == null)) { | ||
| 35 | + logger.warn("[更新Invite信息],参数不全: {}", JSON.toJSON(inviteInfo)); | ||
| 36 | + return; | ||
| 37 | + } | ||
| 38 | + InviteInfo inviteInfoForUpdate = null; | ||
| 39 | + | ||
| 40 | + if (InviteSessionStatus.ready == inviteInfo.getStatus()) { | ||
| 41 | + if (inviteInfo.getDeviceId() == null | ||
| 42 | + || inviteInfo.getChannelId() == null | ||
| 43 | + || inviteInfo.getType() == null | ||
| 44 | + || inviteInfo.getStream() == null | ||
| 45 | + ) { | ||
| 46 | + return; | ||
| 47 | + } | ||
| 48 | + inviteInfoForUpdate = inviteInfo; | ||
| 49 | + } else { | ||
| 50 | + InviteInfo inviteInfoInRedis = getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), | ||
| 51 | + inviteInfo.getChannelId(), inviteInfo.getStream()); | ||
| 52 | + if (inviteInfoInRedis == null) { | ||
| 53 | + logger.warn("[更新Invite信息],未从缓存中读取到Invite信息: deviceId: {}, channel: {}, stream: {}", | ||
| 54 | + inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()); | ||
| 55 | + return; | ||
| 56 | + } | ||
| 57 | + if (inviteInfo.getStreamInfo() != null) { | ||
| 58 | + inviteInfoInRedis.setStreamInfo(inviteInfo.getStreamInfo()); | ||
| 59 | + } | ||
| 60 | + if (inviteInfo.getSsrcInfo() != null) { | ||
| 61 | + inviteInfoInRedis.setSsrcInfo(inviteInfo.getSsrcInfo()); | ||
| 62 | + } | ||
| 63 | + if (inviteInfo.getStreamMode() != null) { | ||
| 64 | + inviteInfoInRedis.setStreamMode(inviteInfo.getStreamMode()); | ||
| 65 | + } | ||
| 66 | + if (inviteInfo.getReceiveIp() != null) { | ||
| 67 | + inviteInfoInRedis.setReceiveIp(inviteInfo.getReceiveIp()); | ||
| 68 | + } | ||
| 69 | + if (inviteInfo.getReceivePort() != null) { | ||
| 70 | + inviteInfoInRedis.setReceivePort(inviteInfo.getReceivePort()); | ||
| 71 | + } | ||
| 72 | + if (inviteInfo.getStatus() != null) { | ||
| 73 | + inviteInfoInRedis.setStatus(inviteInfo.getStatus()); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + inviteInfoForUpdate = inviteInfoInRedis; | ||
| 77 | + | ||
| 78 | + } | ||
| 79 | + String key = VideoManagerConstants.INVITE_PREFIX + | ||
| 80 | + "_" + inviteInfoForUpdate.getType() + | ||
| 81 | + "_" + inviteInfoForUpdate.getDeviceId() + | ||
| 82 | + "_" + inviteInfoForUpdate.getChannelId() + | ||
| 83 | + "_" + inviteInfoForUpdate.getStream(); | ||
| 84 | + redisTemplate.opsForValue().set(key, inviteInfoForUpdate); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + @Override | ||
| 88 | + public InviteInfo getInviteInfo(InviteSessionType type, String deviceId, String channelId, String stream) { | ||
| 89 | + String key = VideoManagerConstants.INVITE_PREFIX + | ||
| 90 | + "_" + (type != null ? type : "*") + | ||
| 91 | + "_" + (deviceId != null ? deviceId : "*") + | ||
| 92 | + "_" + (channelId != null ? channelId : "*") + | ||
| 93 | + "_" + (stream != null ? stream : "*"); | ||
| 94 | + List<Object> scanResult = RedisUtil.scan(redisTemplate, key); | ||
| 95 | + if (scanResult.size() != 1) { | ||
| 96 | + return null; | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + return (InviteInfo) redisTemplate.opsForValue().get(scanResult.get(0)); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + @Override | ||
| 103 | + public InviteInfo getInviteInfoByDeviceAndChannel(InviteSessionType type, String deviceId, String channelId) { | ||
| 104 | + return getInviteInfo(type, deviceId, channelId, null); | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + @Override | ||
| 108 | + public InviteInfo getInviteInfoByStream(InviteSessionType type, String stream) { | ||
| 109 | + return getInviteInfo(type, null, null, stream); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + @Override | ||
| 113 | + public void removeInviteInfo(InviteSessionType type, String deviceId, String channelId, String stream) { | ||
| 114 | + String scanKey = VideoManagerConstants.INVITE_PREFIX + | ||
| 115 | + "_" + (type != null ? type : "*") + | ||
| 116 | + "_" + (deviceId != null ? deviceId : "*") + | ||
| 117 | + "_" + (channelId != null ? channelId : "*") + | ||
| 118 | + "_" + (stream != null ? stream : "*"); | ||
| 119 | + List<Object> scanResult = RedisUtil.scan(redisTemplate, scanKey); | ||
| 120 | + if (scanResult.size() > 0) { | ||
| 121 | + for (Object keyObj : scanResult) { | ||
| 122 | + String key = (String) keyObj; | ||
| 123 | + InviteInfo inviteInfo = (InviteInfo) redisTemplate.opsForValue().get(key); | ||
| 124 | + if (inviteInfo == null) { | ||
| 125 | + continue; | ||
| 126 | + } | ||
| 127 | + redisTemplate.delete(key); | ||
| 128 | + inviteErrorCallbackMap.remove(buildKey(type, deviceId, channelId, inviteInfo.getStream())); | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + @Override | ||
| 134 | + public void removeInviteInfoByDeviceAndChannel(InviteSessionType inviteSessionType, String deviceId, String channelId) { | ||
| 135 | + removeInviteInfo(inviteSessionType, deviceId, channelId, null); | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + @Override | ||
| 139 | + public void removeInviteInfo(InviteInfo inviteInfo) { | ||
| 140 | + removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()); | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + @Override | ||
| 144 | + public void once(InviteSessionType type, String deviceId, String channelId, String stream, InviteErrorCallback<Object> callback) { | ||
| 145 | + String key = buildKey(type, deviceId, channelId, stream); | ||
| 146 | + List<InviteErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key); | ||
| 147 | + if (callbacks == null) { | ||
| 148 | + callbacks = new CopyOnWriteArrayList<>(); | ||
| 149 | + inviteErrorCallbackMap.put(key, callbacks); | ||
| 150 | + } | ||
| 151 | + callbacks.add(callback); | ||
| 152 | + | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + @Override | ||
| 156 | + public void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data) { | ||
| 157 | + String key = buildKey(type, deviceId, channelId, stream); | ||
| 158 | + List<InviteErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key); | ||
| 159 | + if (callbacks == null) { | ||
| 160 | + return; | ||
| 161 | + } | ||
| 162 | + for (InviteErrorCallback<Object> callback : callbacks) { | ||
| 163 | + callback.run(code, msg, data); | ||
| 164 | + } | ||
| 165 | + inviteErrorCallbackMap.remove(key); | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + private String buildKey(InviteSessionType type, String deviceId, String channelId, String stream) { | ||
| 169 | + String key = type + "_" + deviceId + "_" + channelId; | ||
| 170 | + // 如果ssrc未null那么可以实现一个通道只能一次操作,ssrc不为null则可以支持一个通道多次invite | ||
| 171 | + if (stream != null) { | ||
| 172 | + key += ("_" + stream); | ||
| 173 | + } | ||
| 174 | + return key; | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + | ||
| 178 | + @Override | ||
| 179 | + public void clearInviteInfo(String deviceId) { | ||
| 180 | + removeInviteInfo(null, deviceId, null, null); | ||
| 181 | + } | ||
| 182 | +} |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| @@ -3,13 +3,14 @@ package com.genersoft.iot.vmp.service.impl; | @@ -3,13 +3,14 @@ package com.genersoft.iot.vmp.service.impl; | ||
| 3 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | import com.alibaba.fastjson2.JSONArray; | 4 | import com.alibaba.fastjson2.JSONArray; |
| 5 | import com.alibaba.fastjson2.JSONObject; | 5 | import com.alibaba.fastjson2.JSONObject; |
| 6 | +import com.genersoft.iot.vmp.common.CommonCallback; | ||
| 6 | import com.genersoft.iot.vmp.common.VideoManagerConstants; | 7 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 7 | import com.genersoft.iot.vmp.conf.DynamicTask; | 8 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 8 | import com.genersoft.iot.vmp.conf.SipConfig; | 9 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 9 | import com.genersoft.iot.vmp.conf.UserSetting; | 10 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 10 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 11 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 11 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | 12 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 12 | -import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | 13 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; |
| 13 | import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; | 14 | import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; |
| 14 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | 15 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 15 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 16 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| @@ -56,6 +57,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -56,6 +57,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 56 | @Autowired | 57 | @Autowired |
| 57 | private SipConfig sipConfig; | 58 | private SipConfig sipConfig; |
| 58 | 59 | ||
| 60 | + @Autowired | ||
| 61 | + private SSRCFactory ssrcFactory; | ||
| 62 | + | ||
| 59 | @Value("${server.ssl.enabled:false}") | 63 | @Value("${server.ssl.enabled:false}") |
| 60 | private boolean sslEnabled; | 64 | private boolean sslEnabled; |
| 61 | 65 | ||
| @@ -96,6 +100,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -96,6 +100,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 96 | @Autowired | 100 | @Autowired |
| 97 | private RedisTemplate<Object, Object> redisTemplate; | 101 | private RedisTemplate<Object, Object> redisTemplate; |
| 98 | 102 | ||
| 103 | + | ||
| 104 | + | ||
| 105 | + | ||
| 99 | /** | 106 | /** |
| 100 | * 初始化 | 107 | * 初始化 |
| 101 | */ | 108 | */ |
| @@ -107,10 +114,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -107,10 +114,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 107 | continue; | 114 | continue; |
| 108 | } | 115 | } |
| 109 | // 更新 | 116 | // 更新 |
| 110 | - if (mediaServerItem.getSsrcConfig() == null) { | ||
| 111 | - SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain()); | ||
| 112 | - mediaServerItem.setSsrcConfig(ssrcConfig); | ||
| 113 | - redisTemplate.opsForValue().set(VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(), mediaServerItem); | 117 | + if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) { |
| 118 | + ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); | ||
| 114 | } | 119 | } |
| 115 | // 查询redis是否存在此mediaServer | 120 | // 查询redis是否存在此mediaServer |
| 116 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); | 121 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); |
| @@ -122,56 +127,44 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -122,56 +127,44 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 122 | } | 127 | } |
| 123 | } | 128 | } |
| 124 | 129 | ||
| 125 | - @Override | ||
| 126 | - public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback) { | ||
| 127 | - return openRTPServer(mediaServerItem, streamId, null, ssrcCheck,isPlayback); | ||
| 128 | - } | ||
| 129 | 130 | ||
| 130 | @Override | 131 | @Override |
| 131 | public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, | 132 | public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, |
| 132 | - boolean isPlayback, Integer port, Boolean onlyAuto) { | 133 | + boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { |
| 133 | if (mediaServerItem == null || mediaServerItem.getId() == null) { | 134 | if (mediaServerItem == null || mediaServerItem.getId() == null) { |
| 134 | logger.info("[openRTPServer] 失败, mediaServerItem == null || mediaServerItem.getId() == null"); | 135 | logger.info("[openRTPServer] 失败, mediaServerItem == null || mediaServerItem.getId() == null"); |
| 135 | return null; | 136 | return null; |
| 136 | } | 137 | } |
| 137 | // 获取mediaServer可用的ssrc | 138 | // 获取mediaServer可用的ssrc |
| 138 | - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); | ||
| 139 | - | ||
| 140 | - SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig(); | ||
| 141 | - if (ssrcConfig == null) { | ||
| 142 | - logger.info("media server [ {} ] ssrcConfig is null", mediaServerItem.getId()); | ||
| 143 | - return null; | 139 | + String ssrc; |
| 140 | + if (presetSsrc != null) { | ||
| 141 | + ssrc = presetSsrc; | ||
| 144 | }else { | 142 | }else { |
| 145 | - String ssrc; | ||
| 146 | - if (presetSsrc != null) { | ||
| 147 | - ssrc = presetSsrc; | 143 | + if (isPlayback) { |
| 144 | + ssrc = ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); | ||
| 148 | }else { | 145 | }else { |
| 149 | - if (isPlayback) { | ||
| 150 | - ssrc = ssrcConfig.getPlayBackSsrc(); | ||
| 151 | - }else { | ||
| 152 | - ssrc = ssrcConfig.getPlaySsrc(); | ||
| 153 | - } | 146 | + ssrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId()); |
| 154 | } | 147 | } |
| 148 | + } | ||
| 155 | 149 | ||
| 156 | - if (streamId == null) { | ||
| 157 | - streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); | ||
| 158 | - } | ||
| 159 | - int rtpServerPort; | ||
| 160 | - if (mediaServerItem.isRtpEnable()) { | ||
| 161 | - rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port, onlyAuto); | ||
| 162 | - } else { | ||
| 163 | - rtpServerPort = mediaServerItem.getRtpProxyPort(); | ||
| 164 | - } | ||
| 165 | - redisTemplate.opsForValue().set(key, mediaServerItem); | ||
| 166 | - return new SSRCInfo(rtpServerPort, ssrc, streamId); | 150 | + if (streamId == null) { |
| 151 | + streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); | ||
| 152 | + } | ||
| 153 | + int rtpServerPort; | ||
| 154 | + if (mediaServerItem.isRtpEnable()) { | ||
| 155 | + rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port, onlyAuto, reUsePort, tcpMode); | ||
| 156 | + } else { | ||
| 157 | + rtpServerPort = mediaServerItem.getRtpProxyPort(); | ||
| 167 | } | 158 | } |
| 159 | + return new SSRCInfo(rtpServerPort, ssrc, streamId); | ||
| 168 | } | 160 | } |
| 169 | 161 | ||
| 170 | @Override | 162 | @Override |
| 171 | - public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback) { | 163 | + public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto) { |
| 172 | return openRTPServer(mediaServerItem, streamId, ssrc, ssrcCheck, isPlayback, null, null); | 164 | return openRTPServer(mediaServerItem, streamId, ssrc, ssrcCheck, isPlayback, null, null); |
| 173 | } | 165 | } |
| 174 | 166 | ||
| 167 | + | ||
| 175 | @Override | 168 | @Override |
| 176 | public void closeRTPServer(MediaServerItem mediaServerItem, String streamId) { | 169 | public void closeRTPServer(MediaServerItem mediaServerItem, String streamId) { |
| 177 | if (mediaServerItem == null) { | 170 | if (mediaServerItem == null) { |
| @@ -181,22 +174,32 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -181,22 +174,32 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 181 | } | 174 | } |
| 182 | 175 | ||
| 183 | @Override | 176 | @Override |
| 177 | + public void closeRTPServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback) { | ||
| 178 | + if (mediaServerItem == null) { | ||
| 179 | + callback.run(false); | ||
| 180 | + return; | ||
| 181 | + } | ||
| 182 | + zlmrtpServerFactory.closeRtpServer(mediaServerItem, streamId, callback); | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + @Override | ||
| 184 | public void closeRTPServer(String mediaServerId, String streamId) { | 186 | public void closeRTPServer(String mediaServerId, String streamId) { |
| 185 | MediaServerItem mediaServerItem = this.getOne(mediaServerId); | 187 | MediaServerItem mediaServerItem = this.getOne(mediaServerId); |
| 186 | closeRTPServer(mediaServerItem, streamId); | 188 | closeRTPServer(mediaServerItem, streamId); |
| 187 | } | 189 | } |
| 188 | 190 | ||
| 189 | @Override | 191 | @Override |
| 192 | + public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) { | ||
| 193 | + return zlmrtpServerFactory.updateRtpServerSSRC(mediaServerItem, streamId, ssrc); | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + @Override | ||
| 190 | public void releaseSsrc(String mediaServerItemId, String ssrc) { | 197 | public void releaseSsrc(String mediaServerItemId, String ssrc) { |
| 191 | MediaServerItem mediaServerItem = getOne(mediaServerItemId); | 198 | MediaServerItem mediaServerItem = getOne(mediaServerItemId); |
| 192 | if (mediaServerItem == null || ssrc == null) { | 199 | if (mediaServerItem == null || ssrc == null) { |
| 193 | return; | 200 | return; |
| 194 | } | 201 | } |
| 195 | - SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig(); | ||
| 196 | - ssrcConfig.releaseSsrc(ssrc); | ||
| 197 | - mediaServerItem.setSsrcConfig(ssrcConfig); | ||
| 198 | - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); | ||
| 199 | - redisTemplate.opsForValue().set(key, mediaServerItem); | 202 | + ssrcFactory.releaseSsrc(mediaServerItemId, ssrc); |
| 200 | } | 203 | } |
| 201 | 204 | ||
| 202 | /** | 205 | /** |
| @@ -204,8 +207,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -204,8 +207,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 204 | */ | 207 | */ |
| 205 | @Override | 208 | @Override |
| 206 | public void clearRTPServer(MediaServerItem mediaServerItem) { | 209 | public void clearRTPServer(MediaServerItem mediaServerItem) { |
| 207 | - mediaServerItem.setSsrcConfig(new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain())); | ||
| 208 | - redisTemplate.opsForZSet().add(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), mediaServerItem.getId(), 0); | 210 | + ssrcFactory.reset(mediaServerItem.getId()); |
| 209 | 211 | ||
| 210 | } | 212 | } |
| 211 | 213 | ||
| @@ -215,16 +217,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -215,16 +217,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 215 | mediaServerMapper.update(mediaSerItem); | 217 | mediaServerMapper.update(mediaSerItem); |
| 216 | MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId()); | 218 | MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId()); |
| 217 | MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId()); | 219 | MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId()); |
| 218 | - if (mediaServerItemInRedis != null && mediaServerItemInRedis.getSsrcConfig() != null) { | ||
| 219 | - mediaServerItemInDataBase.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig()); | ||
| 220 | - }else { | ||
| 221 | - mediaServerItemInDataBase.setSsrcConfig( | ||
| 222 | - new SsrcConfig( | ||
| 223 | - mediaServerItemInDataBase.getId(), | ||
| 224 | - null, | ||
| 225 | - sipConfig.getDomain() | ||
| 226 | - ) | ||
| 227 | - ); | 220 | + if (mediaServerItemInRedis == null || ssrcFactory.hasMediaServerSSRC(mediaSerItem.getId())) { |
| 221 | + ssrcFactory.initMediaServerSSRC(mediaServerItemInDataBase.getId(),null); | ||
| 228 | } | 222 | } |
| 229 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId(); | 223 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId(); |
| 230 | redisTemplate.opsForValue().set(key, mediaServerItemInDataBase); | 224 | redisTemplate.opsForValue().set(key, mediaServerItemInDataBase); |
| @@ -406,14 +400,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -406,14 +400,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 406 | } | 400 | } |
| 407 | mediaServerMapper.update(serverItem); | 401 | mediaServerMapper.update(serverItem); |
| 408 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId(); | 402 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId(); |
| 409 | - if (redisTemplate.opsForValue().get(key) == null) { | ||
| 410 | - SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain()); | ||
| 411 | - serverItem.setSsrcConfig(ssrcConfig); | ||
| 412 | - }else { | ||
| 413 | - MediaServerItem mediaServerItemInRedis = JsonUtil.redisJsonToObject(redisTemplate, key, MediaServerItem.class); | ||
| 414 | - if (Objects.nonNull(mediaServerItemInRedis)) { | ||
| 415 | - serverItem.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig()); | ||
| 416 | - } | 403 | + if (ssrcFactory.hasMediaServerSSRC(serverItem.getId())) { |
| 404 | + ssrcFactory.initMediaServerSSRC(zlmServerConfig.getGeneralMediaServerId(), null); | ||
| 417 | } | 405 | } |
| 418 | redisTemplate.opsForValue().set(key, serverItem); | 406 | redisTemplate.opsForValue().set(key, serverItem); |
| 419 | resetOnlineServerItem(serverItem); | 407 | resetOnlineServerItem(serverItem); |
| @@ -711,8 +699,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -711,8 +699,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 711 | } | 699 | } |
| 712 | // zlm连接重试 | 700 | // zlm连接重试 |
| 713 | logger.warn("[更新ZLM 保活信息]尝试链接zml id {}", mediaServerId); | 701 | logger.warn("[更新ZLM 保活信息]尝试链接zml id {}", mediaServerId); |
| 714 | - SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain()); | ||
| 715 | - mediaServerItem.setSsrcConfig(ssrcConfig); | 702 | + ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); |
| 716 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); | 703 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); |
| 717 | redisTemplate.opsForValue().set(key, mediaServerItem); | 704 | redisTemplate.opsForValue().set(key, mediaServerItem); |
| 718 | clearRTPServer(mediaServerItem); | 705 | clearRTPServer(mediaServerItem); |
| @@ -761,4 +748,5 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -761,4 +748,5 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 761 | result.setGbSend(redisCatchStorage.getGbSendCount(mediaServerItem.getId())); | 748 | result.setGbSend(redisCatchStorage.getGbSendCount(mediaServerItem.getId())); |
| 762 | return result; | 749 | return result; |
| 763 | } | 750 | } |
| 751 | + | ||
| 764 | } | 752 | } |
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
| 1 | package com.genersoft.iot.vmp.service.impl; | 1 | package com.genersoft.iot.vmp.service.impl; |
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSONObject; | 3 | import com.alibaba.fastjson2.JSONObject; |
| 4 | -import com.genersoft.iot.vmp.common.StreamInfo; | 4 | +import com.genersoft.iot.vmp.common.InviteInfo; |
| 5 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 5 | import com.genersoft.iot.vmp.conf.DynamicTask; | 6 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 6 | import com.genersoft.iot.vmp.conf.UserSetting; | 7 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 7 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 8 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 8 | import com.genersoft.iot.vmp.gb28181.bean.*; | 9 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 9 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 10 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 11 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | ||
| 10 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 12 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 11 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| 12 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 14 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| @@ -14,6 +16,7 @@ import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | @@ -14,6 +16,7 @@ import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | ||
| 14 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | 16 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; |
| 15 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; | 17 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; |
| 16 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 18 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 19 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | ||
| 17 | import com.genersoft.iot.vmp.service.IMediaServerService; | 20 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 18 | import com.genersoft.iot.vmp.service.IPlatformService; | 21 | import com.genersoft.iot.vmp.service.IPlatformService; |
| 19 | import com.genersoft.iot.vmp.service.IPlayService; | 22 | import com.genersoft.iot.vmp.service.IPlayService; |
| @@ -66,6 +69,9 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -66,6 +69,9 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 66 | private IRedisCatchStorage redisCatchStorage; | 69 | private IRedisCatchStorage redisCatchStorage; |
| 67 | 70 | ||
| 68 | @Autowired | 71 | @Autowired |
| 72 | + private SSRCFactory ssrcFactory; | ||
| 73 | + | ||
| 74 | + @Autowired | ||
| 69 | private IMediaServerService mediaServerService; | 75 | private IMediaServerService mediaServerService; |
| 70 | 76 | ||
| 71 | @Autowired | 77 | @Autowired |
| @@ -96,6 +102,8 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -96,6 +102,8 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 96 | @Autowired | 102 | @Autowired |
| 97 | private IPlayService playService; | 103 | private IPlayService playService; |
| 98 | 104 | ||
| 105 | + @Autowired | ||
| 106 | + private IInviteStreamService inviteStreamService; | ||
| 99 | 107 | ||
| 100 | 108 | ||
| 101 | @Override | 109 | @Override |
| @@ -198,6 +206,7 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -198,6 +206,7 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 198 | // 保存时启用就发送注册 | 206 | // 保存时启用就发送注册 |
| 199 | // 注册成功时由程序直接调用了online方法 | 207 | // 注册成功时由程序直接调用了online方法 |
| 200 | try { | 208 | try { |
| 209 | + logger.info("[国标级联] 平台注册 {}", parentPlatform.getDeviceGBId()); | ||
| 201 | commanderForPlatform.register(parentPlatform, eventResult -> { | 210 | commanderForPlatform.register(parentPlatform, eventResult -> { |
| 202 | logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId()); | 211 | logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId()); |
| 203 | }, null); | 212 | }, null); |
| @@ -349,6 +358,7 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -349,6 +358,7 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 349 | List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(platformId); | 358 | List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(platformId); |
| 350 | if (sendRtpItems != null && sendRtpItems.size() > 0) { | 359 | if (sendRtpItems != null && sendRtpItems.size() > 0) { |
| 351 | for (SendRtpItem sendRtpItem : sendRtpItems) { | 360 | for (SendRtpItem sendRtpItem : sendRtpItems) { |
| 361 | + ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); | ||
| 352 | redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), null, null); | 362 | redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), null, null); |
| 353 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | 363 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 354 | Map<String, Object> param = new HashMap<>(3); | 364 | Map<String, Object> param = new HashMap<>(3); |
| @@ -420,20 +430,22 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -420,20 +430,22 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 420 | logger.info("[国标级联] 语音喊话未找到可用的zlm. platform: {}", platform.getServerGBId()); | 430 | logger.info("[国标级联] 语音喊话未找到可用的zlm. platform: {}", platform.getServerGBId()); |
| 421 | return; | 431 | return; |
| 422 | } | 432 | } |
| 423 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(platform.getServerGBId(), channelId); | ||
| 424 | - if (streamInfo != null) { | 433 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, platform.getServerGBId(), channelId); |
| 434 | + | ||
| 435 | + | ||
| 436 | + if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { | ||
| 425 | // 如果zlm不存在这个流,则删除数据即可 | 437 | // 如果zlm不存在这个流,则删除数据即可 |
| 426 | - MediaServerItem mediaServerItemForStreamInfo = mediaServerService.getOne(streamInfo.getMediaServerId()); | 438 | + MediaServerItem mediaServerItemForStreamInfo = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); |
| 427 | if (mediaServerItemForStreamInfo != null) { | 439 | if (mediaServerItemForStreamInfo != null) { |
| 428 | - Boolean ready = zlmrtpServerFactory.isStreamReady(mediaServerItemForStreamInfo, streamInfo.getApp(), streamInfo.getStream()); | 440 | + Boolean ready = zlmrtpServerFactory.isStreamReady(mediaServerItemForStreamInfo, inviteInfo.getStreamInfo().getApp(), inviteInfo.getStreamInfo().getStream()); |
| 429 | if (!ready) { | 441 | if (!ready) { |
| 430 | // 错误存在于redis中的数据 | 442 | // 错误存在于redis中的数据 |
| 431 | - redisCatchStorage.stopPlay(streamInfo); | 443 | + inviteStreamService.removeInviteInfo(inviteInfo); |
| 432 | }else { | 444 | }else { |
| 433 | // 流确实尚在推流,直接回调结果 | 445 | // 流确实尚在推流,直接回调结果 |
| 434 | JSONObject json = new JSONObject(); | 446 | JSONObject json = new JSONObject(); |
| 435 | - json.put("app", streamInfo.getApp()); | ||
| 436 | - json.put("stream", streamInfo.getStream()); | 447 | + json.put("app", inviteInfo.getStreamInfo().getApp()); |
| 448 | + json.put("stream", inviteInfo.getStreamInfo().getStream()); | ||
| 437 | hookEvent.response(mediaServerItemForStreamInfo, json); | 449 | hookEvent.response(mediaServerItemForStreamInfo, json); |
| 438 | return; | 450 | return; |
| 439 | } | 451 | } |
| @@ -449,7 +461,11 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -449,7 +461,11 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 449 | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, ssrcCheck, false, null, true); | 461 | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, ssrcCheck, false, null, true); |
| 450 | if (ssrcInfo == null || ssrcInfo.getPort() < 0) { | 462 | if (ssrcInfo == null || ssrcInfo.getPort() < 0) { |
| 451 | logger.info("[国标级联] 发起语音喊话 开启端口监听失败, platform: {}, channel: {}", platform.getServerGBId(), channelId); | 463 | logger.info("[国标级联] 发起语音喊话 开启端口监听失败, platform: {}, channel: {}", platform.getServerGBId(), channelId); |
| 452 | - errorEvent.response(new SipSubscribe.EventResult(-1, "端口监听失败")); | 464 | + SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>(); |
| 465 | + eventResult.statusCode = -1; | ||
| 466 | + eventResult.msg = "端口监听失败"; | ||
| 467 | + eventResult.type = SipSubscribe.EventResultType.failedToGetPort; | ||
| 468 | + errorEvent.response(eventResult); | ||
| 453 | return; | 469 | return; |
| 454 | } | 470 | } |
| 455 | logger.info("[国标级联] 语音喊话,发起Invite消息 deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", | 471 | logger.info("[国标级联] 语音喊话,发起Invite消息 deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", |
| @@ -458,7 +474,8 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -458,7 +474,8 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 458 | String timeOutTaskKey = UUID.randomUUID().toString(); | 474 | String timeOutTaskKey = UUID.randomUUID().toString(); |
| 459 | dynamicTask.startDelay(timeOutTaskKey, () -> { | 475 | dynamicTask.startDelay(timeOutTaskKey, () -> { |
| 460 | // 执行超时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况 | 476 | // 执行超时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况 |
| 461 | - if (redisCatchStorage.queryPlayByDevice(platform.getServerGBId(), channelId) == null) { | 477 | + InviteInfo inviteInfoForBroadcast = inviteStreamService.getInviteInfo(InviteSessionType.BROADCAST, platform.getServerGBId(), channelId, null); |
| 478 | + if (inviteInfoForBroadcast == null) { | ||
| 462 | logger.info("[国标级联] 发起语音喊话 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", platform.getServerGBId(), channelId, ssrcInfo.getPort(), ssrcInfo.getSsrc()); | 479 | logger.info("[国标级联] 发起语音喊话 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", platform.getServerGBId(), channelId, ssrcInfo.getPort(), ssrcInfo.getSsrc()); |
| 463 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 | 480 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 |
| 464 | try { | 481 | try { |
| @@ -501,7 +518,7 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -501,7 +518,7 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 501 | if (!mediaServerItem.isRtpEnable()) { | 518 | if (!mediaServerItem.isRtpEnable()) { |
| 502 | logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | 519 | logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); |
| 503 | 520 | ||
| 504 | - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | 521 | + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(), ssrcInResponse)) { |
| 505 | // ssrc 不可用 | 522 | // ssrc 不可用 |
| 506 | // 释放ssrc | 523 | // 释放ssrc |
| 507 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 524 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| 1 | package com.genersoft.iot.vmp.service.impl; | 1 | package com.genersoft.iot.vmp.service.impl; |
| 2 | 2 | ||
| 3 | -import com.alibaba.fastjson2.JSON; | ||
| 4 | import com.alibaba.fastjson2.JSONArray; | 3 | import com.alibaba.fastjson2.JSONArray; |
| 5 | import com.alibaba.fastjson2.JSONObject; | 4 | import com.alibaba.fastjson2.JSONObject; |
| 5 | +import com.genersoft.iot.vmp.common.InviteInfo; | ||
| 6 | +import com.genersoft.iot.vmp.common.InviteSessionStatus; | ||
| 7 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 6 | import com.genersoft.iot.vmp.common.StreamInfo; | 8 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 7 | import com.genersoft.iot.vmp.conf.DynamicTask; | 9 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 8 | import com.genersoft.iot.vmp.conf.SipConfig; | 10 | import com.genersoft.iot.vmp.conf.SipConfig; |
| @@ -13,9 +15,9 @@ import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | @@ -13,9 +15,9 @@ import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | ||
| 13 | import com.genersoft.iot.vmp.gb28181.bean.*; | 15 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 14 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 16 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 15 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | 17 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; |
| 18 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | ||
| 16 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 19 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 17 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | 20 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 18 | -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | ||
| 19 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | 21 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 20 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 22 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 21 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | 23 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| @@ -27,11 +29,11 @@ import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | @@ -27,11 +29,11 @@ import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | ||
| 27 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout; | 29 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout; |
| 28 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; | 30 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; |
| 29 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 31 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 30 | -import com.genersoft.iot.vmp.service.IDeviceService; | ||
| 31 | -import com.genersoft.iot.vmp.service.IMediaServerService; | ||
| 32 | -import com.genersoft.iot.vmp.service.IMediaService; | ||
| 33 | -import com.genersoft.iot.vmp.service.IPlayService; | ||
| 34 | -import com.genersoft.iot.vmp.service.bean.*; | 32 | +import com.genersoft.iot.vmp.service.*; |
| 33 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCallback; | ||
| 34 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCode; | ||
| 35 | +import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg; | ||
| 36 | +import com.genersoft.iot.vmp.service.bean.SSRCInfo; | ||
| 35 | import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; | 37 | import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; |
| 36 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 38 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 37 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 39 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| @@ -39,7 +41,6 @@ import com.genersoft.iot.vmp.utils.DateUtil; | @@ -39,7 +41,6 @@ import com.genersoft.iot.vmp.utils.DateUtil; | ||
| 39 | import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | 41 | import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; |
| 40 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 42 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 41 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | 43 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; |
| 42 | -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | ||
| 43 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; | 44 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; |
| 44 | import gov.nist.javax.sip.message.SIPResponse; | 45 | import gov.nist.javax.sip.message.SIPResponse; |
| 45 | import org.slf4j.Logger; | 46 | import org.slf4j.Logger; |
| @@ -51,6 +52,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | @@ -51,6 +52,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | ||
| 51 | import org.springframework.stereotype.Service; | 52 | import org.springframework.stereotype.Service; |
| 52 | import org.springframework.util.ObjectUtils; | 53 | import org.springframework.util.ObjectUtils; |
| 53 | 54 | ||
| 55 | +import javax.sdp.*; | ||
| 54 | import javax.sip.InvalidArgumentException; | 56 | import javax.sip.InvalidArgumentException; |
| 55 | import javax.sip.ResponseEvent; | 57 | import javax.sip.ResponseEvent; |
| 56 | import javax.sip.SipException; | 58 | import javax.sip.SipException; |
| @@ -88,6 +90,9 @@ public class PlayServiceImpl implements IPlayService { | @@ -88,6 +90,9 @@ public class PlayServiceImpl implements IPlayService { | ||
| 88 | private ZLMRTPServerFactory zlmrtpServerFactory; | 90 | private ZLMRTPServerFactory zlmrtpServerFactory; |
| 89 | 91 | ||
| 90 | @Autowired | 92 | @Autowired |
| 93 | + private IInviteStreamService inviteStreamService; | ||
| 94 | + | ||
| 95 | + @Autowired | ||
| 91 | private DeferredResultHolder resultHolder; | 96 | private DeferredResultHolder resultHolder; |
| 92 | 97 | ||
| 93 | @Autowired | 98 | @Autowired |
| @@ -132,125 +137,81 @@ public class PlayServiceImpl implements IPlayService { | @@ -132,125 +137,81 @@ public class PlayServiceImpl implements IPlayService { | ||
| 132 | private ZlmHttpHookSubscribe hookSubscribe; | 137 | private ZlmHttpHookSubscribe hookSubscribe; |
| 133 | 138 | ||
| 134 | @Autowired | 139 | @Autowired |
| 140 | + private SSRCFactory ssrcFactory; | ||
| 141 | + | ||
| 142 | + @Autowired | ||
| 135 | private RedisTemplate<Object, Object> redisTemplate; | 143 | private RedisTemplate<Object, Object> redisTemplate; |
| 136 | 144 | ||
| 137 | 145 | ||
| 138 | @Override | 146 | @Override |
| 139 | - public void play(MediaServerItem mediaServerItem, String deviceId, String channelId, | ||
| 140 | - ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | ||
| 141 | - Runnable timeoutCallback) { | 147 | + public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, InviteErrorCallback<Object> callback) { |
| 142 | if (mediaServerItem == null) { | 148 | if (mediaServerItem == null) { |
| 143 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm"); | 149 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm"); |
| 144 | } | 150 | } |
| 145 | - String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; | ||
| 146 | - | ||
| 147 | - RequestMessage msg = new RequestMessage(); | ||
| 148 | - msg.setKey(key); | ||
| 149 | 151 | ||
| 150 | Device device = redisCatchStorage.getDevice(deviceId); | 152 | Device device = redisCatchStorage.getDevice(deviceId); |
| 151 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); | ||
| 152 | - | ||
| 153 | - if (streamInfo != null) { | ||
| 154 | - String streamId = streamInfo.getStream(); | ||
| 155 | - if (streamId == null) { | ||
| 156 | - WVPResult wvpResult = new WVPResult(); | ||
| 157 | - wvpResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 158 | - wvpResult.setMsg("点播失败, redis缓存streamId等于null"); | ||
| 159 | - msg.setData(wvpResult); | ||
| 160 | - resultHolder.invokeAllResult(msg); | ||
| 161 | - return; | ||
| 162 | - } | ||
| 163 | - String mediaServerId = streamInfo.getMediaServerId(); | ||
| 164 | - MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); | ||
| 165 | - | ||
| 166 | - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); | ||
| 167 | - if (rtpInfo.getInteger("code") == 0) { | ||
| 168 | - if (rtpInfo.getBoolean("exist")) { | ||
| 169 | - int localPort = rtpInfo.getInteger("local_port"); | ||
| 170 | - if (localPort == 0) { | ||
| 171 | - logger.warn("[点播],点播时发现rtpServerC存在,但是尚未开始推流"); | ||
| 172 | - // 此时说明rtpServer已经创建但是流还没有推上来 | ||
| 173 | - WVPResult wvpResult = new WVPResult(); | ||
| 174 | - wvpResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 175 | - wvpResult.setMsg("点播已经在进行中,请稍候重试"); | ||
| 176 | - msg.setData(wvpResult); | ||
| 177 | - | ||
| 178 | - resultHolder.invokeAllResult(msg); | ||
| 179 | - return; | ||
| 180 | - } else { | ||
| 181 | - WVPResult wvpResult = new WVPResult(); | ||
| 182 | - wvpResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 183 | - wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 184 | - wvpResult.setData(streamInfo); | ||
| 185 | - msg.setData(wvpResult); | ||
| 186 | - resultHolder.invokeAllResult(msg); | ||
| 187 | - if (hookEvent != null) { | ||
| 188 | - hookEvent.response(mediaServerItem, JSON.parseObject(JSON.toJSONString(streamInfo))); | ||
| 189 | - } | ||
| 190 | - } | ||
| 191 | - | ||
| 192 | - } else { | ||
| 193 | - redisCatchStorage.stopPlay(streamInfo); | 153 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| 154 | + | ||
| 155 | + if (inviteInfo != null ) { | ||
| 156 | + if (inviteInfo.getStreamInfo() == null) { | ||
| 157 | + // 点播发起了但是尚未成功, 仅注册回调等待结果即可 | ||
| 158 | + inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); | ||
| 159 | + return inviteInfo.getSsrcInfo(); | ||
| 160 | + }else { | ||
| 161 | + StreamInfo streamInfo = inviteInfo.getStreamInfo(); | ||
| 162 | + String streamId = streamInfo.getStream(); | ||
| 163 | + if (streamId == null) { | ||
| 164 | + callback.run(InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), "点播失败, redis缓存streamId等于null", null); | ||
| 165 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 166 | + InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), | ||
| 167 | + "点播失败, redis缓存streamId等于null", | ||
| 168 | + null); | ||
| 169 | + return inviteInfo.getSsrcInfo(); | ||
| 170 | + } | ||
| 171 | + String mediaServerId = streamInfo.getMediaServerId(); | ||
| 172 | + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); | ||
| 173 | + | ||
| 174 | + Boolean ready = zlmrtpServerFactory.isStreamReady(mediaInfo, "rtp", streamId); | ||
| 175 | + if (ready != null && ready) { | ||
| 176 | + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); | ||
| 177 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 178 | + InviteErrorCode.SUCCESS.getCode(), | ||
| 179 | + InviteErrorCode.SUCCESS.getMsg(), | ||
| 180 | + streamInfo); | ||
| 181 | + return inviteInfo.getSsrcInfo(); | ||
| 182 | + }else { | ||
| 183 | + // 点播发起了但是尚未成功, 仅注册回调等待结果即可 | ||
| 184 | + inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); | ||
| 194 | storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); | 185 | storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); |
| 195 | - streamInfo = null; | 186 | + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| 196 | } | 187 | } |
| 197 | - } else { | ||
| 198 | - //zlm连接失败 | ||
| 199 | - redisCatchStorage.stopPlay(streamInfo); | ||
| 200 | - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); | ||
| 201 | - streamInfo = null; | ||
| 202 | } | 188 | } |
| 203 | } | 189 | } |
| 204 | - if (streamInfo == null) { | ||
| 205 | - String streamId = null; | ||
| 206 | - if (mediaServerItem.isRtpEnable()) { | ||
| 207 | - streamId = String.format("%s_%s", device.getDeviceId(), channelId); | ||
| 208 | - } | ||
| 209 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); | ||
| 210 | - if (ssrcInfo == null) { | ||
| 211 | - WVPResult wvpResult = new WVPResult(); | ||
| 212 | - wvpResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 213 | - wvpResult.setMsg("开启收流失败"); | ||
| 214 | - msg.setData(wvpResult); | ||
| 215 | - | ||
| 216 | - resultHolder.invokeAllResult(msg); | ||
| 217 | - return; | ||
| 218 | - } | ||
| 219 | - play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response) -> { | ||
| 220 | - if (hookEvent != null) { | ||
| 221 | - hookEvent.response(mediaServerItem, response); | ||
| 222 | - } | ||
| 223 | - }, event -> { | ||
| 224 | - // sip error错误 | ||
| 225 | - WVPResult wvpResult = new WVPResult(); | ||
| 226 | - wvpResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 227 | - wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg)); | ||
| 228 | - msg.setData(wvpResult); | ||
| 229 | - resultHolder.invokeAllResult(msg); | ||
| 230 | - if (errorEvent != null) { | ||
| 231 | - errorEvent.response(event); | ||
| 232 | - } | ||
| 233 | - }, (code, msgStr) -> { | ||
| 234 | - // invite点播超时 | ||
| 235 | - WVPResult wvpResult = new WVPResult(); | ||
| 236 | - wvpResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 237 | - if (code == 0) { | ||
| 238 | - wvpResult.setMsg("点播超时,请稍候重试"); | ||
| 239 | - } else if (code == 1) { | ||
| 240 | - wvpResult.setMsg("收流超时,请稍候重试"); | ||
| 241 | - } | ||
| 242 | - msg.setData(wvpResult); | ||
| 243 | - // 回复之前所有的点播请求 | ||
| 244 | - resultHolder.invokeAllResult(msg); | ||
| 245 | - }); | 190 | + |
| 191 | + String streamId = null; | ||
| 192 | + if (mediaServerItem.isRtpEnable()) { | ||
| 193 | + streamId = String.format("%s_%s", device.getDeviceId(), channelId); | ||
| 194 | + } | ||
| 195 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false, 0, false, false, device.getStreamModeForParam()); | ||
| 196 | + if (ssrcInfo == null) { | ||
| 197 | + callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null); | ||
| 198 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 199 | + InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), | ||
| 200 | + InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), | ||
| 201 | + null); | ||
| 202 | + return null; | ||
| 246 | } | 203 | } |
| 204 | + // TODO 记录点播的状态 | ||
| 205 | + play(mediaServerItem, ssrcInfo, device, channelId, callback); | ||
| 206 | + return ssrcInfo; | ||
| 247 | } | 207 | } |
| 248 | 208 | ||
| 249 | private void talk(MediaServerItem mediaServerItem, Device device, String channelId, String stream, | 209 | private void talk(MediaServerItem mediaServerItem, Device device, String channelId, String stream, |
| 250 | ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | 210 | ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, |
| 251 | Runnable timeoutCallback, AudioBroadcastEvent audioEvent) { | 211 | Runnable timeoutCallback, AudioBroadcastEvent audioEvent) { |
| 252 | 212 | ||
| 253 | - String playSsrc = mediaServerItem.getSsrcConfig().getPlaySsrc(); | 213 | + String playSsrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId()); |
| 214 | + | ||
| 254 | if (playSsrc == null) { | 215 | if (playSsrc == null) { |
| 255 | audioEvent.call("ssrc已经用尽"); | 216 | audioEvent.call("ssrc已经用尽"); |
| 256 | return; | 217 | return; |
| @@ -353,7 +314,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -353,7 +314,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 353 | 314 | ||
| 354 | streamSession.put(device.getDeviceId(), channelId, "talk", | 315 | streamSession.put(device.getDeviceId(), channelId, "talk", |
| 355 | sendRtpItem.getStream(), sendRtpItem.getSsrc(), sendRtpItem.getMediaServerId(), | 316 | sendRtpItem.getStream(), sendRtpItem.getSsrc(), sendRtpItem.getMediaServerId(), |
| 356 | - response, VideoStreamSessionManager.SessionType.talk); | 317 | + response, InviteSessionType.TALK); |
| 357 | } else { | 318 | } else { |
| 358 | logger.error("[语音对讲]收到的消息错误,response不是SIPResponse"); | 319 | logger.error("[语音对讲]收到的消息错误,response不是SIPResponse"); |
| 359 | } | 320 | } |
| @@ -378,7 +339,9 @@ public class PlayServiceImpl implements IPlayService { | @@ -378,7 +339,9 @@ public class PlayServiceImpl implements IPlayService { | ||
| 378 | mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); | 339 | mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); |
| 379 | 340 | ||
| 380 | streamSession.remove(device.getDeviceId(), channelId, sendRtpItem.getStream()); | 341 | streamSession.remove(device.getDeviceId(), channelId, sendRtpItem.getStream()); |
| 381 | - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null)); | 342 | + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(); |
| 343 | + eventResult.type = SipSubscribe.EventResultType.cmdSendFailEvent; | ||
| 344 | + eventResult.statusCode = -1; | ||
| 382 | eventResult.msg = "命令发送失败"; | 345 | eventResult.msg = "命令发送失败"; |
| 383 | errorEvent.response(eventResult); | 346 | errorEvent.response(eventResult); |
| 384 | } | 347 | } |
| @@ -390,24 +353,62 @@ public class PlayServiceImpl implements IPlayService { | @@ -390,24 +353,62 @@ public class PlayServiceImpl implements IPlayService { | ||
| 390 | 353 | ||
| 391 | @Override | 354 | @Override |
| 392 | public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | 355 | public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 393 | - ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | ||
| 394 | - InviteTimeOutCallback timeoutCallback) { | 356 | + InviteErrorCallback<Object> callback) { |
| 357 | + | ||
| 358 | + if (mediaServerItem == null || ssrcInfo == null) { | ||
| 359 | + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), | ||
| 360 | + InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), | ||
| 361 | + null); | ||
| 362 | + return; | ||
| 363 | + } | ||
| 364 | + logger.info("[点播开始] deviceId: {}, channelId: {},收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); | ||
| 365 | + | ||
| 366 | + //端口获取失败的ssrcInfo 没有必要发送点播指令 | ||
| 367 | + if (ssrcInfo.getPort() <= 0) { | ||
| 368 | + logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); | ||
| 369 | + // 释放ssrc | ||
| 370 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 371 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 395 | 372 | ||
| 396 | - logger.info("[点播开始] deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); | 373 | + callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null); |
| 374 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 375 | + InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null); | ||
| 376 | + return; | ||
| 377 | + } | ||
| 378 | + | ||
| 379 | + // 初始化redis中的invite消息状态 | ||
| 380 | + InviteInfo inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, | ||
| 381 | + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY, | ||
| 382 | + InviteSessionStatus.ready); | ||
| 383 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 397 | // 超时处理 | 384 | // 超时处理 |
| 398 | String timeOutTaskKey = UUID.randomUUID().toString(); | 385 | String timeOutTaskKey = UUID.randomUUID().toString(); |
| 399 | dynamicTask.startDelay(timeOutTaskKey, () -> { | 386 | dynamicTask.startDelay(timeOutTaskKey, () -> { |
| 400 | // 执行超时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况 | 387 | // 执行超时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况 |
| 401 | - if (redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId) == null) { | 388 | + InviteInfo inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); |
| 389 | + if (inviteInfoForTimeOut == null || inviteInfoForTimeOut.getStreamInfo() == null) { | ||
| 402 | logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, ssrcInfo.getPort(), ssrcInfo.getSsrc()); | 390 | logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, ssrcInfo.getPort(), ssrcInfo.getSsrc()); |
| 403 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 | 391 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 |
| 392 | +// InviteInfo inviteInfoForTimeout = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.play, device.getDeviceId(), channelId); | ||
| 393 | +// if (inviteInfoForTimeout == null) { | ||
| 394 | +// return; | ||
| 395 | +// } | ||
| 396 | +// if (InviteSessionStatus.ok == inviteInfoForTimeout.getStatus() ) { | ||
| 397 | +// // TODO 发送bye | ||
| 398 | +// }else { | ||
| 399 | +// // TODO 发送cancel | ||
| 400 | +// } | ||
| 401 | + callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); | ||
| 402 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 403 | + InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); | ||
| 404 | + | ||
| 405 | + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); | ||
| 404 | try { | 406 | try { |
| 405 | cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); | 407 | cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); |
| 406 | } catch (InvalidArgumentException | ParseException | SipException | | 408 | } catch (InvalidArgumentException | ParseException | SipException | |
| 407 | SsrcTransactionNotFoundException e) { | 409 | SsrcTransactionNotFoundException e) { |
| 408 | logger.error("[点播超时], 发送BYE失败 {}", e.getMessage()); | 410 | logger.error("[点播超时], 发送BYE失败 {}", e.getMessage()); |
| 409 | } finally { | 411 | } finally { |
| 410 | - timeoutCallback.run(1, "收流超时"); | ||
| 411 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 412 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 412 | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | 413 | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| 413 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | 414 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| @@ -418,28 +419,26 @@ public class PlayServiceImpl implements IPlayService { | @@ -418,28 +419,26 @@ public class PlayServiceImpl implements IPlayService { | ||
| 418 | } | 419 | } |
| 419 | } | 420 | } |
| 420 | }, userSetting.getPlayTimeout()); | 421 | }, userSetting.getPlayTimeout()); |
| 421 | - //端口获取失败的ssrcInfo 没有必要发送点播指令 | ||
| 422 | - if (ssrcInfo.getPort() <= 0) { | ||
| 423 | - logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); | ||
| 424 | - dynamicTask.stop(timeOutTaskKey); | ||
| 425 | - // 释放ssrc | ||
| 426 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 427 | - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 428 | 422 | ||
| 429 | - RequestMessage msg = new RequestMessage(); | ||
| 430 | - msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + device.getDeviceId() + channelId); | ||
| 431 | - msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "点播端口分配异常")); | ||
| 432 | - resultHolder.invokeAllResult(msg); | ||
| 433 | - return; | ||
| 434 | - } | ||
| 435 | try { | 423 | try { |
| 436 | cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { | 424 | cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { |
| 437 | logger.info("收到订阅消息: " + response.toJSONString()); | 425 | logger.info("收到订阅消息: " + response.toJSONString()); |
| 438 | dynamicTask.stop(timeOutTaskKey); | 426 | dynamicTask.stop(timeOutTaskKey); |
| 439 | - | ||
| 440 | // hook响应 | 427 | // hook响应 |
| 441 | - onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); | ||
| 442 | - hookEvent.response(mediaServerItemInuse, response); | 428 | + StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); |
| 429 | + if (streamInfo == null){ | ||
| 430 | + callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), | ||
| 431 | + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 432 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 433 | + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), | ||
| 434 | + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 435 | + return; | ||
| 436 | + } | ||
| 437 | + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); | ||
| 438 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 439 | + InviteErrorCode.SUCCESS.getCode(), | ||
| 440 | + InviteErrorCode.SUCCESS.getMsg(), | ||
| 441 | + streamInfo); | ||
| 443 | logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); | 442 | logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); |
| 444 | String streamUrl; | 443 | String streamUrl; |
| 445 | if (mediaServerItemInuse.getRtspPort() != 0) { | 444 | if (mediaServerItemInuse.getRtspPort() != 0) { |
| @@ -454,6 +453,8 @@ public class PlayServiceImpl implements IPlayService { | @@ -454,6 +453,8 @@ public class PlayServiceImpl implements IPlayService { | ||
| 454 | zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); | 453 | zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); |
| 455 | 454 | ||
| 456 | }, (event) -> { | 455 | }, (event) -> { |
| 456 | + inviteInfo.setStatus(InviteSessionStatus.ok); | ||
| 457 | + | ||
| 457 | ResponseEvent responseEvent = (ResponseEvent) event.event; | 458 | ResponseEvent responseEvent = (ResponseEvent) event.event; |
| 458 | String contentString = new String(responseEvent.getResponse().getRawContent()); | 459 | String contentString = new String(responseEvent.getResponse().getRawContent()); |
| 459 | // 获取ssrc | 460 | // 获取ssrc |
| @@ -464,44 +465,124 @@ public class PlayServiceImpl implements IPlayService { | @@ -464,44 +465,124 @@ public class PlayServiceImpl implements IPlayService { | ||
| 464 | String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim(); | 465 | String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim(); |
| 465 | // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 | 466 | // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 |
| 466 | if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { | 467 | if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { |
| 468 | + if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { | ||
| 469 | + String substring = contentString.substring(0, contentString.indexOf("y=")); | ||
| 470 | + try { | ||
| 471 | + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); | ||
| 472 | + int port = -1; | ||
| 473 | + Vector mediaDescriptions = sdp.getMediaDescriptions(true); | ||
| 474 | + for (Object description : mediaDescriptions) { | ||
| 475 | + MediaDescription mediaDescription = (MediaDescription) description; | ||
| 476 | + Media media = mediaDescription.getMedia(); | ||
| 477 | + | ||
| 478 | + Vector mediaFormats = media.getMediaFormats(false); | ||
| 479 | + if (mediaFormats.contains("96")) { | ||
| 480 | + port = media.getMediaPort(); | ||
| 481 | + break; | ||
| 482 | + } | ||
| 483 | + } | ||
| 484 | + logger.info("[点播-TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); | ||
| 485 | + JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); | ||
| 486 | + logger.info("[点播-TCP主动连接对方] 结果: {}", jsonObject); | ||
| 487 | + } catch (SdpException e) { | ||
| 488 | + logger.error("[点播-TCP主动连接对方] deviceId: {}, channelId: {}, 解析200OK的SDP信息失败", device.getDeviceId(), channelId, e); | ||
| 489 | + dynamicTask.stop(timeOutTaskKey); | ||
| 490 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | ||
| 491 | + // 释放ssrc | ||
| 492 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 493 | + | ||
| 494 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 495 | + | ||
| 496 | + callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), | ||
| 497 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 498 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 499 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), | ||
| 500 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 501 | + } | ||
| 502 | + } | ||
| 467 | return; | 503 | return; |
| 468 | } | 504 | } |
| 469 | logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); | 505 | logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); |
| 470 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | 506 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { |
| 471 | logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | 507 | logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); |
| 472 | - | ||
| 473 | - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | 508 | + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { |
| 474 | // ssrc 不可用 | 509 | // ssrc 不可用 |
| 510 | + logger.info("[点播消息] SSRC修正时发现ssrc不可使用 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | ||
| 475 | // 释放ssrc | 511 | // 释放ssrc |
| 476 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 512 | + ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 477 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | 513 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 478 | - event.msg = "下级自定义了ssrc,但是此ssrc不可用"; | ||
| 479 | - event.statusCode = 400; | ||
| 480 | - errorEvent.response(event); | 514 | + |
| 515 | + callback.run(InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getCode(), | ||
| 516 | + InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getMsg(), null); | ||
| 517 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 518 | + InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getCode(), | ||
| 519 | + InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getMsg(), null); | ||
| 520 | + | ||
| 481 | return; | 521 | return; |
| 482 | } | 522 | } |
| 483 | - | ||
| 484 | - // 单端口模式streamId也有变化,需要重新设置监听 | 523 | + // 单端口模式streamId也有变化,重新设置监听即可 |
| 485 | if (!mediaServerItem.isRtpEnable()) { | 524 | if (!mediaServerItem.isRtpEnable()) { |
| 486 | // 添加订阅 | 525 | // 添加订阅 |
| 487 | HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | 526 | HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); |
| 488 | subscribe.removeSubscribe(hookSubscribe); | 527 | subscribe.removeSubscribe(hookSubscribe); |
| 489 | - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); | 528 | + String stream = String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase(); |
| 529 | + hookSubscribe.getContent().put("stream", stream); | ||
| 530 | + inviteInfo.setStream(stream); | ||
| 490 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { | 531 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { |
| 491 | logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); | 532 | logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); |
| 492 | dynamicTask.stop(timeOutTaskKey); | 533 | dynamicTask.stop(timeOutTaskKey); |
| 493 | // hook响应 | 534 | // hook响应 |
| 494 | - onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId); | ||
| 495 | - hookEvent.response(mediaServerItemInUse, response); | 535 | + StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId); |
| 536 | + if (streamInfo == null){ | ||
| 537 | + callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), | ||
| 538 | + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 539 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 540 | + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), | ||
| 541 | + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 542 | + return; | ||
| 543 | + } | ||
| 544 | + callback.run(InviteErrorCode.SUCCESS.getCode(), | ||
| 545 | + InviteErrorCode.SUCCESS.getMsg(), null); | ||
| 546 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 547 | + InviteErrorCode.SUCCESS.getCode(), | ||
| 548 | + InviteErrorCode.SUCCESS.getMsg(), | ||
| 549 | + streamInfo); | ||
| 496 | }); | 550 | }); |
| 551 | + return; | ||
| 497 | } | 552 | } |
| 498 | - // 关闭rtp server | ||
| 499 | - mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | ||
| 500 | - // 重新开启ssrc server | ||
| 501 | - mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, ssrcInfo.getPort(), false); | ||
| 502 | 553 | ||
| 554 | + // 更新ssrc | ||
| 555 | + Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse); | ||
| 556 | + if (!result) { | ||
| 557 | + try { | ||
| 558 | + logger.warn("[点播] 更新ssrc失败,停止点播 {}/{}", device.getDeviceId(), channelId); | ||
| 559 | + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null); | ||
| 560 | + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { | ||
| 561 | + logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage()); | ||
| 562 | + } | ||
| 563 | + | ||
| 564 | + dynamicTask.stop(timeOutTaskKey); | ||
| 565 | + // 释放ssrc | ||
| 566 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 567 | + | ||
| 568 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 569 | + | ||
| 570 | + callback.run(InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), | ||
| 571 | + "下级自定义了ssrc,重新设置收流信息失败", null); | ||
| 572 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 573 | + InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), | ||
| 574 | + "下级自定义了ssrc,重新设置收流信息失败", null); | ||
| 575 | + | ||
| 576 | + }else { | ||
| 577 | + ssrcInfo.setSsrc(ssrcInResponse); | ||
| 578 | + inviteInfo.setSsrcInfo(ssrcInfo); | ||
| 579 | + inviteInfo.setStream(ssrcInfo.getStream()); | ||
| 580 | + } | ||
| 581 | + }else { | ||
| 582 | + logger.info("[点播消息] 收到invite 200, 下级自定义了ssrc, 但是当前模式无需修正"); | ||
| 503 | } | 583 | } |
| 504 | } | 584 | } |
| 585 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 505 | }, (event) -> { | 586 | }, (event) -> { |
| 506 | dynamicTask.stop(timeOutTaskKey); | 587 | dynamicTask.stop(timeOutTaskKey); |
| 507 | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | 588 | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| @@ -509,7 +590,14 @@ public class PlayServiceImpl implements IPlayService { | @@ -509,7 +590,14 @@ public class PlayServiceImpl implements IPlayService { | ||
| 509 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 590 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 510 | 591 | ||
| 511 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | 592 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 512 | - errorEvent.response(event); | 593 | + |
| 594 | + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(), | ||
| 595 | + String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null); | ||
| 596 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 597 | + InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), | ||
| 598 | + String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null); | ||
| 599 | + | ||
| 600 | + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); | ||
| 513 | }); | 601 | }); |
| 514 | } catch (InvalidArgumentException | SipException | ParseException e) { | 602 | } catch (InvalidArgumentException | SipException | ParseException e) { |
| 515 | 603 | ||
| @@ -520,63 +608,58 @@ public class PlayServiceImpl implements IPlayService { | @@ -520,63 +608,58 @@ public class PlayServiceImpl implements IPlayService { | ||
| 520 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 608 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 521 | 609 | ||
| 522 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | 610 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 523 | - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null)); | ||
| 524 | - eventResult.msg = "命令发送失败"; | ||
| 525 | - errorEvent.response(eventResult); | 611 | + |
| 612 | + callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), | ||
| 613 | + InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); | ||
| 614 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 615 | + InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), | ||
| 616 | + InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); | ||
| 617 | + | ||
| 618 | + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); | ||
| 526 | } | 619 | } |
| 527 | } | 620 | } |
| 528 | 621 | ||
| 529 | @Override | 622 | @Override |
| 530 | - public void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId) { | 623 | + public StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId) { |
| 531 | StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); | 624 | StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); |
| 532 | - RequestMessage msg = new RequestMessage(); | ||
| 533 | - msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId); | ||
| 534 | if (streamInfo != null) { | 625 | if (streamInfo != null) { |
| 535 | DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); | 626 | DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); |
| 536 | if (deviceChannel != null) { | 627 | if (deviceChannel != null) { |
| 537 | deviceChannel.setStreamId(streamInfo.getStream()); | 628 | deviceChannel.setStreamId(streamInfo.getStream()); |
| 538 | storager.startPlay(deviceId, channelId, streamInfo.getStream()); | 629 | storager.startPlay(deviceId, channelId, streamInfo.getStream()); |
| 539 | } | 630 | } |
| 540 | - redisCatchStorage.startPlay(streamInfo); | ||
| 541 | - | ||
| 542 | - WVPResult wvpResult = new WVPResult(); | ||
| 543 | - wvpResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 544 | - wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 545 | - wvpResult.setData(streamInfo); | ||
| 546 | - | ||
| 547 | - msg.setData(wvpResult); | ||
| 548 | - resultHolder.invokeAllResult(msg); | ||
| 549 | - | ||
| 550 | - } else { | ||
| 551 | - logger.warn("设备预览API调用失败!"); | ||
| 552 | - msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "设备预览API调用失败!")); | ||
| 553 | - resultHolder.invokeAllResult(msg); | 631 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| 632 | + if (inviteInfo != null) { | ||
| 633 | + inviteInfo.setStatus(InviteSessionStatus.ok); | ||
| 634 | + inviteInfo.setStreamInfo(streamInfo); | ||
| 635 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 636 | + } | ||
| 554 | } | 637 | } |
| 638 | + return streamInfo; | ||
| 639 | + | ||
| 555 | } | 640 | } |
| 556 | 641 | ||
| 557 | - private void onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, PlayBackCallback playBackCallback) { | 642 | + private StreamInfo onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String startTime, String endTime) { |
| 558 | 643 | ||
| 559 | StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); | 644 | StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); |
| 560 | - PlayBackResult<StreamInfo> playBackResult = new PlayBackResult<>(); | ||
| 561 | if (streamInfo != null) { | 645 | if (streamInfo != null) { |
| 646 | + streamInfo.setStartTime(startTime); | ||
| 647 | + streamInfo.setEndTime(endTime); | ||
| 562 | DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); | 648 | DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); |
| 563 | if (deviceChannel != null) { | 649 | if (deviceChannel != null) { |
| 564 | deviceChannel.setStreamId(streamInfo.getStream()); | 650 | deviceChannel.setStreamId(streamInfo.getStream()); |
| 565 | storager.startPlay(deviceId, channelId, streamInfo.getStream()); | 651 | storager.startPlay(deviceId, channelId, streamInfo.getStream()); |
| 566 | } | 652 | } |
| 567 | - redisCatchStorage.startPlay(streamInfo); | 653 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAYBACK, deviceId, channelId); |
| 654 | + if (inviteInfo != null) { | ||
| 655 | + inviteInfo.setStatus(InviteSessionStatus.ok); | ||
| 568 | 656 | ||
| 657 | + inviteInfo.setStreamInfo(streamInfo); | ||
| 658 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 659 | + } | ||
| 569 | 660 | ||
| 570 | - playBackResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 571 | - playBackResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 572 | - playBackResult.setData(streamInfo); | ||
| 573 | - playBackCallback.call(playBackResult); | ||
| 574 | - } else { | ||
| 575 | - logger.warn("录像回放调用失败!"); | ||
| 576 | - playBackResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 577 | - playBackResult.setMsg("录像回放调用失败!"); | ||
| 578 | - playBackCallback.call(playBackResult); | ||
| 579 | } | 661 | } |
| 662 | + return streamInfo; | ||
| 580 | } | 663 | } |
| 581 | 664 | ||
| 582 | @Override | 665 | @Override |
| @@ -615,24 +698,24 @@ public class PlayServiceImpl implements IPlayService { | @@ -615,24 +698,24 @@ public class PlayServiceImpl implements IPlayService { | ||
| 615 | 698 | ||
| 616 | @Override | 699 | @Override |
| 617 | public void playBack(String deviceId, String channelId, String startTime, | 700 | public void playBack(String deviceId, String channelId, String startTime, |
| 618 | - String endTime, InviteStreamCallback inviteStreamCallback, | ||
| 619 | - PlayBackCallback callback) { | 701 | + String endTime, InviteErrorCallback<Object> callback) { |
| 620 | Device device = storager.queryVideoDevice(deviceId); | 702 | Device device = storager.queryVideoDevice(deviceId); |
| 621 | if (device == null) { | 703 | if (device == null) { |
| 622 | return; | 704 | return; |
| 623 | } | 705 | } |
| 624 | MediaServerItem newMediaServerItem = getNewMediaServerItem(device); | 706 | MediaServerItem newMediaServerItem = getNewMediaServerItem(device); |
| 625 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true); | ||
| 626 | - | ||
| 627 | - playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback); | 707 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false,false, device.getStreamModeForParam()); |
| 708 | + playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, callback); | ||
| 628 | } | 709 | } |
| 629 | 710 | ||
| 630 | @Override | 711 | @Override |
| 631 | public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, | 712 | public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, |
| 632 | - String deviceId, String channelId, String startTime, | ||
| 633 | - String endTime, InviteStreamCallback infoCallBack, | ||
| 634 | - PlayBackCallback playBackCallback) { | 713 | + String deviceId, String channelId, String startTime, |
| 714 | + String endTime, InviteErrorCallback<Object> callback) { | ||
| 635 | if (mediaServerItem == null || ssrcInfo == null) { | 715 | if (mediaServerItem == null || ssrcInfo == null) { |
| 716 | + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), | ||
| 717 | + InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), | ||
| 718 | + null); | ||
| 636 | return; | 719 | return; |
| 637 | } | 720 | } |
| 638 | 721 | ||
| @@ -640,115 +723,176 @@ public class PlayServiceImpl implements IPlayService { | @@ -640,115 +723,176 @@ public class PlayServiceImpl implements IPlayService { | ||
| 640 | if (device == null) { | 723 | if (device == null) { |
| 641 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备: " + deviceId + "不存在"); | 724 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备: " + deviceId + "不存在"); |
| 642 | } | 725 | } |
| 643 | - | ||
| 644 | - PlayBackResult<StreamInfo> playBackResult = new PlayBackResult<>(); | 726 | + logger.info("[录像回放] deviceId: {}, channelId: {}, 开始时间: {}, 结束时间: {}, 收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", |
| 727 | + device.getDeviceId(), channelId, startTime, endTime, ssrcInfo.getPort(), device.getStreamMode(), | ||
| 728 | + ssrcInfo.getSsrc(), device.isSsrcCheck()); | ||
| 729 | + // 初始化redis中的invite消息状态 | ||
| 730 | + InviteInfo inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, | ||
| 731 | + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAYBACK, | ||
| 732 | + InviteSessionStatus.ready); | ||
| 733 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 645 | String playBackTimeOutTaskKey = UUID.randomUUID().toString(); | 734 | String playBackTimeOutTaskKey = UUID.randomUUID().toString(); |
| 646 | dynamicTask.startDelay(playBackTimeOutTaskKey, () -> { | 735 | dynamicTask.startDelay(playBackTimeOutTaskKey, () -> { |
| 647 | - logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId)); | ||
| 648 | - playBackResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 649 | - playBackResult.setMsg("回放超时"); | 736 | + logger.warn("[录像回放] 超时,deviceId:{} ,channelId:{}", deviceId, channelId); |
| 737 | + inviteStreamService.removeInviteInfo(inviteInfo); | ||
| 738 | + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getMsg(), null); | ||
| 650 | 739 | ||
| 651 | try { | 740 | try { |
| 652 | cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); | 741 | cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); |
| 653 | } catch (InvalidArgumentException | ParseException | SipException e) { | 742 | } catch (InvalidArgumentException | ParseException | SipException e) { |
| 654 | - logger.error("[录像流]回放超时 发送BYE失败 {}", e.getMessage()); | 743 | + logger.error("[录像回放] 超时 发送BYE失败 {}", e.getMessage()); |
| 655 | } catch (SsrcTransactionNotFoundException e) { | 744 | } catch (SsrcTransactionNotFoundException e) { |
| 656 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 | 745 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 |
| 657 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 746 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 658 | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | 747 | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| 659 | streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); | 748 | streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); |
| 660 | } | 749 | } |
| 661 | - // 回复之前所有的点播请求 | ||
| 662 | - playBackCallback.call(playBackResult); | ||
| 663 | }, userSetting.getPlayTimeout()); | 750 | }, userSetting.getPlayTimeout()); |
| 664 | 751 | ||
| 665 | SipSubscribe.Event errorEvent = event -> { | 752 | SipSubscribe.Event errorEvent = event -> { |
| 753 | + logger.info("[录像回放] 失败,{} {}", event.statusCode, event.msg); | ||
| 666 | dynamicTask.stop(playBackTimeOutTaskKey); | 754 | dynamicTask.stop(playBackTimeOutTaskKey); |
| 667 | - playBackResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 668 | - playBackResult.setMsg(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); | ||
| 669 | - playBackResult.setEvent(event); | ||
| 670 | - playBackCallback.call(playBackResult); | 755 | + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(), |
| 756 | + String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg), null); | ||
| 757 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 758 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | ||
| 671 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | 759 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 760 | + inviteStreamService.removeInviteInfo(inviteInfo); | ||
| 672 | }; | 761 | }; |
| 673 | 762 | ||
| 674 | - InviteStreamCallback hookEvent = (InviteStreamInfo inviteStreamInfo) -> { | ||
| 675 | - logger.info("收到回放订阅消息: " + inviteStreamInfo.getResponse().toJSONString()); | 763 | + ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInuse, jsonObject) -> { |
| 764 | + logger.info("收到回放订阅消息: " + jsonObject); | ||
| 676 | dynamicTask.stop(playBackTimeOutTaskKey); | 765 | dynamicTask.stop(playBackTimeOutTaskKey); |
| 677 | - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); | 766 | + StreamInfo streamInfo = onPublishHandlerForPlayback(mediaServerItemInuse, jsonObject, deviceId, channelId, startTime, endTime); |
| 678 | if (streamInfo == null) { | 767 | if (streamInfo == null) { |
| 679 | logger.warn("设备回放API调用失败!"); | 768 | logger.warn("设备回放API调用失败!"); |
| 680 | - playBackResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 681 | - playBackResult.setMsg("设备回放API调用失败!"); | ||
| 682 | - playBackCallback.call(playBackResult); | 769 | + callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), |
| 770 | + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 683 | return; | 771 | return; |
| 684 | } | 772 | } |
| 685 | - redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId()); | ||
| 686 | - playBackResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 687 | - playBackResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 688 | - playBackResult.setData(streamInfo); | ||
| 689 | - playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); | ||
| 690 | - playBackResult.setResponse(inviteStreamInfo.getResponse()); | ||
| 691 | - playBackCallback.call(playBackResult); | 773 | + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); |
| 774 | + logger.info("[录像回放] 成功 deviceId: {}, channelId: {}, 开始时间: {}, 结束时间: {}", device.getDeviceId(), channelId, startTime, endTime); | ||
| 692 | }; | 775 | }; |
| 693 | 776 | ||
| 694 | try { | 777 | try { |
| 695 | - cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack, | 778 | + cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, |
| 696 | hookEvent, eventResult -> { | 779 | hookEvent, eventResult -> { |
| 697 | - if (eventResult.type == SipSubscribe.EventResultType.response) { | ||
| 698 | - ResponseEvent responseEvent = (ResponseEvent) eventResult.event; | ||
| 699 | - String contentString = new String(responseEvent.getResponse().getRawContent()); | ||
| 700 | - // 获取ssrc | ||
| 701 | - int ssrcIndex = contentString.indexOf("y="); | ||
| 702 | - // 检查是否有y字段 | ||
| 703 | - if (ssrcIndex >= 0) { | ||
| 704 | - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容 | ||
| 705 | - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | ||
| 706 | - // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 | ||
| 707 | - if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { | ||
| 708 | - return; | ||
| 709 | - } | ||
| 710 | - logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); | ||
| 711 | - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | ||
| 712 | - logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | ||
| 713 | - | ||
| 714 | - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | ||
| 715 | - // ssrc 不可用 | 780 | + inviteInfo.setStatus(InviteSessionStatus.ok); |
| 781 | + ResponseEvent responseEvent = (ResponseEvent) eventResult.event; | ||
| 782 | + String contentString = new String(responseEvent.getResponse().getRawContent()); | ||
| 783 | + // 获取ssrc | ||
| 784 | + int ssrcIndex = contentString.indexOf("y="); | ||
| 785 | + // 检查是否有y字段 | ||
| 786 | + if (ssrcIndex >= 0) { | ||
| 787 | + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容 | ||
| 788 | + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | ||
| 789 | + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 | ||
| 790 | + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { | ||
| 791 | + if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { | ||
| 792 | + String substring = contentString.substring(0, contentString.indexOf("y=")); | ||
| 793 | + try { | ||
| 794 | + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); | ||
| 795 | + int port = -1; | ||
| 796 | + Vector mediaDescriptions = sdp.getMediaDescriptions(true); | ||
| 797 | + for (Object description : mediaDescriptions) { | ||
| 798 | + MediaDescription mediaDescription = (MediaDescription) description; | ||
| 799 | + Media media = mediaDescription.getMedia(); | ||
| 800 | + | ||
| 801 | + Vector mediaFormats = media.getMediaFormats(false); | ||
| 802 | + if (mediaFormats.contains("96")) { | ||
| 803 | + port = media.getMediaPort(); | ||
| 804 | + break; | ||
| 805 | + } | ||
| 806 | + } | ||
| 807 | + logger.info("[录像回放-TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); | ||
| 808 | + JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); | ||
| 809 | + logger.info("[录像回放-TCP主动连接对方] 结果: {}", jsonObject); | ||
| 810 | + } catch (SdpException e) { | ||
| 811 | + logger.error("[录像回放-TCP主动连接对方] deviceId: {}, channelId: {}, 解析200OK的SDP信息失败", device.getDeviceId(), channelId, e); | ||
| 812 | + dynamicTask.stop(playBackTimeOutTaskKey); | ||
| 813 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | ||
| 716 | // 释放ssrc | 814 | // 释放ssrc |
| 717 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 815 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 816 | + | ||
| 718 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | 817 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 719 | - eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用"; | ||
| 720 | - eventResult.statusCode = 400; | ||
| 721 | - errorEvent.response(eventResult); | ||
| 722 | - return; | 818 | + |
| 819 | + callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), | ||
| 820 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 821 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 822 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), | ||
| 823 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 723 | } | 824 | } |
| 825 | + } | ||
| 826 | + return; | ||
| 827 | + } | ||
| 828 | + logger.info("[录像回放] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); | ||
| 829 | + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | ||
| 830 | + logger.info("[录像回放] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | ||
| 831 | + | ||
| 832 | + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { | ||
| 833 | + // ssrc 不可用 | ||
| 834 | + logger.info("[录像回放] SSRC修正时发现ssrc不可使用 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | ||
| 835 | + // 释放ssrc | ||
| 836 | + dynamicTask.stop(playBackTimeOutTaskKey); | ||
| 837 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 838 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 839 | + callback.run(InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getCode(), | ||
| 840 | + InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getMsg(), null); | ||
| 841 | + return; | ||
| 842 | + } | ||
| 843 | + | ||
| 844 | + // 单端口模式streamId也有变化,需要重新设置监听 | ||
| 845 | + if (!mediaServerItem.isRtpEnable()) { | ||
| 846 | + // 添加订阅 | ||
| 847 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | ||
| 848 | + subscribe.removeSubscribe(hookSubscribe); | ||
| 849 | + String stream = String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase(); | ||
| 850 | + hookSubscribe.getContent().put("stream", stream); | ||
| 851 | + inviteInfo.setStream(stream); | ||
| 852 | + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { | ||
| 853 | + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); | ||
| 854 | + dynamicTask.stop(playBackTimeOutTaskKey); | ||
| 855 | + // hook响应 | ||
| 856 | + hookEvent.response(mediaServerItemInUse, response); | ||
| 857 | + }); | ||
| 858 | + } | ||
| 859 | + // 更新ssrc | ||
| 860 | + Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse); | ||
| 861 | + if (!result) { | ||
| 862 | + try { | ||
| 863 | + logger.warn("[录像回放] 更新ssrc失败,停止录像回放 {}/{}", device.getDeviceId(), channelId); | ||
| 864 | + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null); | ||
| 865 | + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { | ||
| 866 | + logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage()); | ||
| 724 | 867 | ||
| 725 | - // 单端口模式streamId也有变化,需要重新设置监听 | ||
| 726 | - if (!mediaServerItem.isRtpEnable()) { | ||
| 727 | - // 添加订阅 | ||
| 728 | - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | ||
| 729 | - subscribe.removeSubscribe(hookSubscribe); | ||
| 730 | - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); | ||
| 731 | - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { | ||
| 732 | - logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); | ||
| 733 | - dynamicTask.stop(playBackTimeOutTaskKey); | ||
| 734 | - // hook响应 | ||
| 735 | - onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, playBackCallback); | ||
| 736 | - hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream())); | ||
| 737 | - }); | ||
| 738 | } | 868 | } |
| 739 | - // 关闭rtp server | ||
| 740 | - mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | ||
| 741 | - // 重新开启ssrc server | ||
| 742 | - mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort(), false); | 869 | + |
| 870 | + dynamicTask.stop(playBackTimeOutTaskKey); | ||
| 871 | + // 释放ssrc | ||
| 872 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 873 | + | ||
| 874 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 875 | + | ||
| 876 | + callback.run(InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), | ||
| 877 | + "下级自定义了ssrc,重新设置收流信息失败", null); | ||
| 878 | + | ||
| 879 | + }else { | ||
| 880 | + ssrcInfo.setSsrc(ssrcInResponse); | ||
| 881 | + inviteInfo.setSsrcInfo(ssrcInfo); | ||
| 882 | + inviteInfo.setStream(ssrcInfo.getStream()); | ||
| 743 | } | 883 | } |
| 884 | + }else { | ||
| 885 | + logger.info("[点播消息] 收到invite 200, 下级自定义了ssrc, 但是当前模式无需修正"); | ||
| 744 | } | 886 | } |
| 745 | } | 887 | } |
| 746 | - | 888 | + inviteStreamService.updateInviteInfo(inviteInfo); |
| 747 | }, errorEvent); | 889 | }, errorEvent); |
| 748 | } catch (InvalidArgumentException | SipException | ParseException e) { | 890 | } catch (InvalidArgumentException | SipException | ParseException e) { |
| 749 | logger.error("[命令发送失败] 回放: {}", e.getMessage()); | 891 | logger.error("[命令发送失败] 回放: {}", e.getMessage()); |
| 750 | 892 | ||
| 751 | - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null)); | 893 | + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(); |
| 894 | + eventResult.type = SipSubscribe.EventResultType.cmdSendFailEvent; | ||
| 895 | + eventResult.statusCode = -1; | ||
| 752 | eventResult.msg = "命令发送失败"; | 896 | eventResult.msg = "命令发送失败"; |
| 753 | errorEvent.response(eventResult); | 897 | errorEvent.response(eventResult); |
| 754 | } | 898 | } |
| @@ -756,43 +900,50 @@ public class PlayServiceImpl implements IPlayService { | @@ -756,43 +900,50 @@ public class PlayServiceImpl implements IPlayService { | ||
| 756 | 900 | ||
| 757 | 901 | ||
| 758 | @Override | 902 | @Override |
| 759 | - public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback) { | 903 | + public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback) { |
| 760 | Device device = storager.queryVideoDevice(deviceId); | 904 | Device device = storager.queryVideoDevice(deviceId); |
| 761 | if (device == null) { | 905 | if (device == null) { |
| 762 | return; | 906 | return; |
| 763 | } | 907 | } |
| 764 | MediaServerItem newMediaServerItem = getNewMediaServerItemHasAssist(device); | 908 | MediaServerItem newMediaServerItem = getNewMediaServerItemHasAssist(device); |
| 765 | if (newMediaServerItem == null) { | 909 | if (newMediaServerItem == null) { |
| 766 | - PlayBackResult<StreamInfo> downloadResult = new PlayBackResult<>(); | ||
| 767 | - downloadResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 768 | - downloadResult.setMsg("未找到assist服务"); | ||
| 769 | - playBackCallback.call(downloadResult); | 910 | + callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(), |
| 911 | + InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getMsg(), | ||
| 912 | + null); | ||
| 770 | return; | 913 | return; |
| 771 | } | 914 | } |
| 772 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true); | ||
| 773 | - | ||
| 774 | - download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, infoCallBack, playBackCallback); | 915 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false,false, device.getStreamModeForParam()); |
| 916 | + download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, callback); | ||
| 775 | } | 917 | } |
| 776 | 918 | ||
| 777 | 919 | ||
| 778 | @Override | 920 | @Override |
| 779 | - public void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) { | 921 | + public void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback) { |
| 780 | if (mediaServerItem == null || ssrcInfo == null) { | 922 | if (mediaServerItem == null || ssrcInfo == null) { |
| 923 | + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), | ||
| 924 | + InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), | ||
| 925 | + null); | ||
| 781 | return; | 926 | return; |
| 782 | } | 927 | } |
| 783 | - | ||
| 784 | Device device = storager.queryVideoDevice(deviceId); | 928 | Device device = storager.queryVideoDevice(deviceId); |
| 785 | if (device == null) { | 929 | if (device == null) { |
| 786 | - throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "不存在"); | 930 | + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), |
| 931 | + "设备:" + deviceId + "不存在", | ||
| 932 | + null); | ||
| 933 | + return; | ||
| 787 | } | 934 | } |
| 788 | - PlayBackResult<StreamInfo> downloadResult = new PlayBackResult<>(); | ||
| 789 | - | 935 | + logger.info("[录像下载] deviceId: {}, channelId: {}, 下载速度:{}, 收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, downloadSpeed, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); |
| 936 | + // 初始化redis中的invite消息状态 | ||
| 937 | + InviteInfo inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, | ||
| 938 | + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.DOWNLOAD, | ||
| 939 | + InviteSessionStatus.ready); | ||
| 940 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 790 | String downLoadTimeOutTaskKey = UUID.randomUUID().toString(); | 941 | String downLoadTimeOutTaskKey = UUID.randomUUID().toString(); |
| 791 | dynamicTask.startDelay(downLoadTimeOutTaskKey, () -> { | 942 | dynamicTask.startDelay(downLoadTimeOutTaskKey, () -> { |
| 792 | logger.warn(String.format("录像下载请求超时,deviceId:%s ,channelId:%s", deviceId, channelId)); | 943 | logger.warn(String.format("录像下载请求超时,deviceId:%s ,channelId:%s", deviceId, channelId)); |
| 793 | - downloadResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 794 | - downloadResult.setMsg("录像下载请求超时"); | ||
| 795 | - hookCallBack.call(downloadResult); | 944 | + inviteStreamService.removeInviteInfo(inviteInfo); |
| 945 | + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode(), | ||
| 946 | + InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getMsg(), null); | ||
| 796 | 947 | ||
| 797 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 | 948 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 |
| 798 | try { | 949 | try { |
| @@ -808,85 +959,137 @@ public class PlayServiceImpl implements IPlayService { | @@ -808,85 +959,137 @@ public class PlayServiceImpl implements IPlayService { | ||
| 808 | 959 | ||
| 809 | SipSubscribe.Event errorEvent = event -> { | 960 | SipSubscribe.Event errorEvent = event -> { |
| 810 | dynamicTask.stop(downLoadTimeOutTaskKey); | 961 | dynamicTask.stop(downLoadTimeOutTaskKey); |
| 811 | - downloadResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 812 | - downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg)); | ||
| 813 | - downloadResult.setEvent(event); | ||
| 814 | - hookCallBack.call(downloadResult); | 962 | + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode(), |
| 963 | + String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg), null); | ||
| 815 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | 964 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 965 | + inviteStreamService.removeInviteInfo(inviteInfo); | ||
| 816 | }; | 966 | }; |
| 817 | - InviteStreamCallback hookEvent = (InviteStreamInfo inviteStreamInfo) -> { | ||
| 818 | - logger.info("收到订阅消息: " + inviteStreamInfo.getCallId()); | 967 | + ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInuse, jsonObject) -> { |
| 968 | + logger.info("[录像下载]收到订阅消息: " + jsonObject); | ||
| 819 | dynamicTask.stop(downLoadTimeOutTaskKey); | 969 | dynamicTask.stop(downLoadTimeOutTaskKey); |
| 820 | - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); | ||
| 821 | - streamInfo.setStartTime(startTime); | ||
| 822 | - streamInfo.setEndTime(endTime); | ||
| 823 | - redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); | ||
| 824 | - downloadResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 825 | - downloadResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 826 | - downloadResult.setData(streamInfo); | ||
| 827 | - downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); | ||
| 828 | - downloadResult.setResponse(inviteStreamInfo.getResponse()); | ||
| 829 | - hookCallBack.call(downloadResult); | 970 | + StreamInfo streamInfo = onPublishHandlerForDownload(mediaServerItemInuse, jsonObject, deviceId, channelId, startTime, endTime); |
| 971 | + if (streamInfo == null) { | ||
| 972 | + logger.warn("[录像下载] 获取流地址信息失败"); | ||
| 973 | + callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), | ||
| 974 | + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 975 | + return; | ||
| 976 | + } | ||
| 977 | + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); | ||
| 978 | + logger.info("[录像下载] 调用成功 deviceId: {}, channelId: {}, 开始时间: {}, 结束时间: {}", device.getDeviceId(), channelId, startTime, endTime); | ||
| 830 | }; | 979 | }; |
| 831 | try { | 980 | try { |
| 832 | - cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack, | ||
| 833 | - hookEvent, errorEvent, eventResult -> | ||
| 834 | - { | ||
| 835 | - if (eventResult.type == SipSubscribe.EventResultType.response) { | ||
| 836 | - ResponseEvent responseEvent = (ResponseEvent) eventResult.event; | ||
| 837 | - String contentString = new String(responseEvent.getResponse().getRawContent()); | ||
| 838 | - // 获取ssrc | ||
| 839 | - int ssrcIndex = contentString.indexOf("y="); | ||
| 840 | - // 检查是否有y字段 | ||
| 841 | - if (ssrcIndex >= 0) { | ||
| 842 | - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容 | ||
| 843 | - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | ||
| 844 | - // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 | ||
| 845 | - if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { | ||
| 846 | - return; | ||
| 847 | - } | ||
| 848 | - logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); | ||
| 849 | - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | ||
| 850 | - logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | ||
| 851 | - | ||
| 852 | - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | ||
| 853 | - // ssrc 不可用 | 981 | + cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, |
| 982 | + hookEvent, errorEvent, eventResult ->{ | ||
| 983 | + inviteInfo.setStatus(InviteSessionStatus.ok); | ||
| 984 | + ResponseEvent responseEvent = (ResponseEvent) eventResult.event; | ||
| 985 | + String contentString = new String(responseEvent.getResponse().getRawContent()); | ||
| 986 | + // 获取ssrc | ||
| 987 | + int ssrcIndex = contentString.indexOf("y="); | ||
| 988 | + // 检查是否有y字段 | ||
| 989 | + if (ssrcIndex >= 0) { | ||
| 990 | + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容 | ||
| 991 | + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | ||
| 992 | + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 | ||
| 993 | + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { | ||
| 994 | + if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { | ||
| 995 | + String substring = contentString.substring(0, contentString.indexOf("y=")); | ||
| 996 | + try { | ||
| 997 | + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); | ||
| 998 | + int port = -1; | ||
| 999 | + Vector mediaDescriptions = sdp.getMediaDescriptions(true); | ||
| 1000 | + for (Object description : mediaDescriptions) { | ||
| 1001 | + MediaDescription mediaDescription = (MediaDescription) description; | ||
| 1002 | + Media media = mediaDescription.getMedia(); | ||
| 1003 | + | ||
| 1004 | + Vector mediaFormats = media.getMediaFormats(false); | ||
| 1005 | + if (mediaFormats.contains("96")) { | ||
| 1006 | + port = media.getMediaPort(); | ||
| 1007 | + break; | ||
| 1008 | + } | ||
| 1009 | + } | ||
| 1010 | + logger.info("[录像下载-TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); | ||
| 1011 | + JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); | ||
| 1012 | + logger.info("[录像下载-TCP主动连接对方] 结果: {}", jsonObject); | ||
| 1013 | + } catch (SdpException e) { | ||
| 1014 | + logger.error("[录像下载-TCP主动连接对方] deviceId: {}, channelId: {}, 解析200OK的SDP信息失败", device.getDeviceId(), channelId, e); | ||
| 1015 | + dynamicTask.stop(downLoadTimeOutTaskKey); | ||
| 1016 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | ||
| 854 | // 释放ssrc | 1017 | // 释放ssrc |
| 855 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 1018 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 1019 | + | ||
| 856 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | 1020 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 857 | - eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用"; | ||
| 858 | - eventResult.statusCode = 400; | ||
| 859 | - errorEvent.response(eventResult); | ||
| 860 | - return; | 1021 | + |
| 1022 | + callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), | ||
| 1023 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 1024 | + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, | ||
| 1025 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), | ||
| 1026 | + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); | ||
| 861 | } | 1027 | } |
| 1028 | + } | ||
| 1029 | + return; | ||
| 1030 | + } | ||
| 1031 | + logger.info("[录像下载] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); | ||
| 1032 | + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | ||
| 1033 | + logger.info("[录像下载] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | ||
| 1034 | + | ||
| 1035 | + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { | ||
| 1036 | + // ssrc 不可用 | ||
| 1037 | + // 释放ssrc | ||
| 1038 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 1039 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 1040 | + callback.run(InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getCode(), | ||
| 1041 | + InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getMsg(), null); | ||
| 1042 | + return; | ||
| 1043 | + } | ||
| 1044 | + | ||
| 1045 | + // 单端口模式streamId也有变化,需要重新设置监听 | ||
| 1046 | + if (!mediaServerItem.isRtpEnable()) { | ||
| 1047 | + // 添加订阅 | ||
| 1048 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | ||
| 1049 | + subscribe.removeSubscribe(hookSubscribe); | ||
| 1050 | + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); | ||
| 1051 | + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { | ||
| 1052 | + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); | ||
| 1053 | + dynamicTask.stop(downLoadTimeOutTaskKey); | ||
| 1054 | + hookEvent.response(mediaServerItemInUse, response); | ||
| 1055 | + }); | ||
| 1056 | + } | ||
| 862 | 1057 | ||
| 863 | - // 单端口模式streamId也有变化,需要重新设置监听 | ||
| 864 | - if (!mediaServerItem.isRtpEnable()) { | ||
| 865 | - // 添加订阅 | ||
| 866 | - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | ||
| 867 | - subscribe.removeSubscribe(hookSubscribe); | ||
| 868 | - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); | ||
| 869 | - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { | ||
| 870 | - logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); | ||
| 871 | - dynamicTask.stop(downLoadTimeOutTaskKey); | ||
| 872 | - // hook响应 | ||
| 873 | - onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, hookCallBack); | ||
| 874 | - hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream())); | ||
| 875 | - }); | 1058 | + // 更新ssrc |
| 1059 | + Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse); | ||
| 1060 | + if (!result) { | ||
| 1061 | + try { | ||
| 1062 | + logger.warn("[录像下载] 更新ssrc失败,停止录像回放 {}/{}", device.getDeviceId(), channelId); | ||
| 1063 | + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null); | ||
| 1064 | + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { | ||
| 1065 | + logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage()); | ||
| 876 | } | 1066 | } |
| 877 | - // 关闭rtp server | ||
| 878 | - mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | ||
| 879 | - // 重新开启ssrc server | ||
| 880 | - mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort(), false); | 1067 | + |
| 1068 | + dynamicTask.stop(downLoadTimeOutTaskKey); | ||
| 1069 | + // 释放ssrc | ||
| 1070 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 1071 | + | ||
| 1072 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 1073 | + | ||
| 1074 | + callback.run(InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), | ||
| 1075 | + "下级自定义了ssrc,重新设置收流信息失败", null); | ||
| 1076 | + | ||
| 1077 | + }else { | ||
| 1078 | + ssrcInfo.setSsrc(ssrcInResponse); | ||
| 1079 | + inviteInfo.setSsrcInfo(ssrcInfo); | ||
| 1080 | + inviteInfo.setStream(ssrcInfo.getStream()); | ||
| 881 | } | 1081 | } |
| 1082 | + }else { | ||
| 1083 | + logger.info("[录像下载] 收到invite 200, 下级自定义了ssrc, 但是当前模式无需修正"); | ||
| 882 | } | 1084 | } |
| 883 | } | 1085 | } |
| 884 | - | ||
| 885 | }); | 1086 | }); |
| 886 | } catch (InvalidArgumentException | SipException | ParseException e) { | 1087 | } catch (InvalidArgumentException | SipException | ParseException e) { |
| 887 | logger.error("[命令发送失败] 录像下载: {}", e.getMessage()); | 1088 | logger.error("[命令发送失败] 录像下载: {}", e.getMessage()); |
| 888 | 1089 | ||
| 889 | - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null)); | 1090 | + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(); |
| 1091 | + eventResult.type = SipSubscribe.EventResultType.cmdSendFailEvent; | ||
| 1092 | + eventResult.statusCode = -1; | ||
| 890 | eventResult.msg = "命令发送失败"; | 1093 | eventResult.msg = "命令发送失败"; |
| 891 | errorEvent.response(eventResult); | 1094 | errorEvent.response(eventResult); |
| 892 | } | 1095 | } |
| @@ -894,21 +1097,22 @@ public class PlayServiceImpl implements IPlayService { | @@ -894,21 +1097,22 @@ public class PlayServiceImpl implements IPlayService { | ||
| 894 | 1097 | ||
| 895 | @Override | 1098 | @Override |
| 896 | public StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream) { | 1099 | public StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream) { |
| 897 | - StreamInfo streamInfo = redisCatchStorage.queryDownload(deviceId, channelId, stream, null); | ||
| 898 | - if (streamInfo != null) { | ||
| 899 | - if (streamInfo.getProgress() == 1) { | ||
| 900 | - return streamInfo; | 1100 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, stream); |
| 1101 | + | ||
| 1102 | + if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { | ||
| 1103 | + if (inviteInfo.getStreamInfo().getProgress() == 1) { | ||
| 1104 | + return inviteInfo.getStreamInfo(); | ||
| 901 | } | 1105 | } |
| 902 | 1106 | ||
| 903 | // 获取当前已下载时长 | 1107 | // 获取当前已下载时长 |
| 904 | - String mediaServerId = streamInfo.getMediaServerId(); | 1108 | + String mediaServerId = inviteInfo.getStreamInfo().getMediaServerId(); |
| 905 | MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); | 1109 | MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); |
| 906 | if (mediaServerItem == null) { | 1110 | if (mediaServerItem == null) { |
| 907 | logger.warn("查询录像信息时发现节点已离线"); | 1111 | logger.warn("查询录像信息时发现节点已离线"); |
| 908 | return null; | 1112 | return null; |
| 909 | } | 1113 | } |
| 910 | if (mediaServerItem.getRecordAssistPort() > 0) { | 1114 | if (mediaServerItem.getRecordAssistPort() > 0) { |
| 911 | - JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, streamInfo.getApp(), streamInfo.getStream(), null); | 1115 | + JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, inviteInfo.getStreamInfo().getApp(), inviteInfo.getStreamInfo().getStream(), null); |
| 912 | if (jsonObject == null) { | 1116 | if (jsonObject == null) { |
| 913 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "连接Assist服务失败"); | 1117 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "连接Assist服务失败"); |
| 914 | } | 1118 | } |
| @@ -916,10 +1120,10 @@ public class PlayServiceImpl implements IPlayService { | @@ -916,10 +1120,10 @@ public class PlayServiceImpl implements IPlayService { | ||
| 916 | long duration = jsonObject.getLong("data"); | 1120 | long duration = jsonObject.getLong("data"); |
| 917 | 1121 | ||
| 918 | if (duration == 0) { | 1122 | if (duration == 0) { |
| 919 | - streamInfo.setProgress(0); | 1123 | + inviteInfo.getStreamInfo().setProgress(0); |
| 920 | } else { | 1124 | } else { |
| 921 | - String startTime = streamInfo.getStartTime(); | ||
| 922 | - String endTime = streamInfo.getEndTime(); | 1125 | + String startTime = inviteInfo.getStreamInfo().getStartTime(); |
| 1126 | + String endTime = inviteInfo.getStreamInfo().getEndTime(); | ||
| 923 | long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime); | 1127 | long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime); |
| 924 | long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime); | 1128 | long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime); |
| 925 | 1129 | ||
| @@ -927,29 +1131,31 @@ public class PlayServiceImpl implements IPlayService { | @@ -927,29 +1131,31 @@ public class PlayServiceImpl implements IPlayService { | ||
| 927 | BigDecimal totalCount = new BigDecimal(end - start); | 1131 | BigDecimal totalCount = new BigDecimal(end - start); |
| 928 | BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP); | 1132 | BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP); |
| 929 | double process = divide.doubleValue(); | 1133 | double process = divide.doubleValue(); |
| 930 | - streamInfo.setProgress(process); | 1134 | + inviteInfo.getStreamInfo().setProgress(process); |
| 931 | } | 1135 | } |
| 1136 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 932 | } | 1137 | } |
| 933 | } | 1138 | } |
| 1139 | + return inviteInfo.getStreamInfo(); | ||
| 934 | } | 1140 | } |
| 935 | - return streamInfo; | 1141 | + return null; |
| 936 | } | 1142 | } |
| 937 | 1143 | ||
| 938 | - @Override | ||
| 939 | - public void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String uuid) { | ||
| 940 | - RequestMessage msg = new RequestMessage(); | ||
| 941 | - msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId); | ||
| 942 | - msg.setId(uuid); | ||
| 943 | - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); | 1144 | + private StreamInfo onPublishHandlerForDownload(MediaServerItem mediaServerItemInuse, JSONObject response, String deviceId, String channelId, String startTime, String endTime) { |
| 1145 | + StreamInfo streamInfo = onPublishHandler(mediaServerItemInuse, response, deviceId, channelId); | ||
| 944 | if (streamInfo != null) { | 1146 | if (streamInfo != null) { |
| 945 | - redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); | ||
| 946 | - msg.setData(JSON.toJSONString(streamInfo)); | ||
| 947 | - resultHolder.invokeResult(msg); | ||
| 948 | - } else { | ||
| 949 | - logger.warn("设备预览API调用失败!"); | ||
| 950 | - msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "设备预览API调用失败!")); | ||
| 951 | - resultHolder.invokeResult(msg); | 1147 | + streamInfo.setProgress(0); |
| 1148 | + streamInfo.setStartTime(startTime); | ||
| 1149 | + streamInfo.setEndTime(endTime); | ||
| 1150 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, streamInfo.getStream()); | ||
| 1151 | + if (inviteInfo != null) { | ||
| 1152 | + logger.info("[录像下载] 更新invite消息中的stream信息"); | ||
| 1153 | + inviteInfo.setStatus(InviteSessionStatus.ok); | ||
| 1154 | + inviteInfo.setStreamInfo(streamInfo); | ||
| 1155 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 1156 | + } | ||
| 952 | } | 1157 | } |
| 1158 | + return streamInfo; | ||
| 953 | } | 1159 | } |
| 954 | 1160 | ||
| 955 | 1161 | ||
| @@ -1189,15 +1395,14 @@ public class PlayServiceImpl implements IPlayService { | @@ -1189,15 +1395,14 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1189 | 1395 | ||
| 1190 | @Override | 1396 | @Override |
| 1191 | public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { | 1397 | public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { |
| 1192 | - String key = redisCatchStorage.queryPlaybackForKey(null, null, streamId, null); | ||
| 1193 | - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); | ||
| 1194 | - if (null == streamInfo) { | 1398 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); |
| 1399 | + if (null == inviteInfo || inviteInfo.getStreamInfo() == null) { | ||
| 1195 | logger.warn("streamId不存在!"); | 1400 | logger.warn("streamId不存在!"); |
| 1196 | throw new ServiceException("streamId不存在"); | 1401 | throw new ServiceException("streamId不存在"); |
| 1197 | } | 1402 | } |
| 1198 | - streamInfo.setPause(true); | ||
| 1199 | - redisTemplate.opsForValue().set(key, streamInfo); | ||
| 1200 | - MediaServerItem mediaServerItem = mediaServerService.getOne(streamInfo.getMediaServerId()); | 1403 | + inviteInfo.getStreamInfo().setPause(true); |
| 1404 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 1405 | + MediaServerItem mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); | ||
| 1201 | if (null == mediaServerItem) { | 1406 | if (null == mediaServerItem) { |
| 1202 | logger.warn("mediaServer 不存在!"); | 1407 | logger.warn("mediaServer 不存在!"); |
| 1203 | throw new ServiceException("mediaServer不存在"); | 1408 | throw new ServiceException("mediaServer不存在"); |
| @@ -1207,21 +1412,20 @@ public class PlayServiceImpl implements IPlayService { | @@ -1207,21 +1412,20 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1207 | if (jsonObject == null || jsonObject.getInteger("code") != 0) { | 1412 | if (jsonObject == null || jsonObject.getInteger("code") != 0) { |
| 1208 | throw new ServiceException("暂停RTP接收失败"); | 1413 | throw new ServiceException("暂停RTP接收失败"); |
| 1209 | } | 1414 | } |
| 1210 | - Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); | ||
| 1211 | - cmder.playPauseCmd(device, streamInfo); | 1415 | + Device device = storager.queryVideoDevice(inviteInfo.getDeviceId()); |
| 1416 | + cmder.playPauseCmd(device, inviteInfo.getStreamInfo()); | ||
| 1212 | } | 1417 | } |
| 1213 | 1418 | ||
| 1214 | @Override | 1419 | @Override |
| 1215 | public void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { | 1420 | public void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { |
| 1216 | - String key = redisCatchStorage.queryPlaybackForKey(null, null, streamId, null); | ||
| 1217 | - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); | ||
| 1218 | - if (null == streamInfo) { | 1421 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); |
| 1422 | + if (null == inviteInfo || inviteInfo.getStreamInfo() == null) { | ||
| 1219 | logger.warn("streamId不存在!"); | 1423 | logger.warn("streamId不存在!"); |
| 1220 | throw new ServiceException("streamId不存在"); | 1424 | throw new ServiceException("streamId不存在"); |
| 1221 | } | 1425 | } |
| 1222 | - streamInfo.setPause(false); | ||
| 1223 | - redisTemplate.opsForValue().set(key, streamInfo); | ||
| 1224 | - MediaServerItem mediaServerItem = mediaServerService.getOne(streamInfo.getMediaServerId()); | 1426 | + inviteInfo.getStreamInfo().setPause(false); |
| 1427 | + inviteStreamService.updateInviteInfo(inviteInfo); | ||
| 1428 | + MediaServerItem mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); | ||
| 1225 | if (null == mediaServerItem) { | 1429 | if (null == mediaServerItem) { |
| 1226 | logger.warn("mediaServer 不存在!"); | 1430 | logger.warn("mediaServer 不存在!"); |
| 1227 | throw new ServiceException("mediaServer不存在"); | 1431 | throw new ServiceException("mediaServer不存在"); |
| @@ -1231,8 +1435,8 @@ public class PlayServiceImpl implements IPlayService { | @@ -1231,8 +1435,8 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1231 | if (jsonObject == null || jsonObject.getInteger("code") != 0) { | 1435 | if (jsonObject == null || jsonObject.getInteger("code") != 0) { |
| 1232 | throw new ServiceException("继续RTP接收失败"); | 1436 | throw new ServiceException("继续RTP接收失败"); |
| 1233 | } | 1437 | } |
| 1234 | - Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); | ||
| 1235 | - cmder.playResumeCmd(device, streamInfo); | 1438 | + Device device = storager.queryVideoDevice(inviteInfo.getDeviceId()); |
| 1439 | + cmder.playResumeCmd(device, inviteInfo.getStreamInfo()); | ||
| 1236 | } | 1440 | } |
| 1237 | 1441 | ||
| 1238 | @Override | 1442 | @Override |
| @@ -1308,7 +1512,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -1308,7 +1512,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1308 | logger.info("调用ZLM推流接口, 结果: {}", jsonObject); | 1512 | logger.info("调用ZLM推流接口, 结果: {}", jsonObject); |
| 1309 | logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, ", param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); | 1513 | logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, ", param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); |
| 1310 | } else { | 1514 | } else { |
| 1311 | - logger.error("RTP推流失败: {}, 参数:{}", jsonObject.getString("msg"), JSON.toJSONString(param)); | 1515 | + logger.error("RTP推流失败: {}, 参数:{}", jsonObject.getString("msg"), JSONObject.toJSONString(param)); |
| 1312 | if (sendRtpItem.isOnlyAudio()) { | 1516 | if (sendRtpItem.isOnlyAudio()) { |
| 1313 | Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); | 1517 | Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); |
| 1314 | AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | 1518 | AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); |
| @@ -1419,7 +1623,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -1419,7 +1623,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1419 | zlmrtpServerFactory.stopSendRtpStream(mediaServer, param); | 1623 | zlmrtpServerFactory.stopSendRtpStream(mediaServer, param); |
| 1420 | } | 1624 | } |
| 1421 | 1625 | ||
| 1422 | - mediaServer.getSsrcConfig().releaseSsrc(sendRtpItem.getSsrc()); | 1626 | + ssrcFactory.releaseSsrc(mediaServerId, sendRtpItem.getSsrc()); |
| 1423 | 1627 | ||
| 1424 | SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, null, sendRtpItem.getStream()); | 1628 | SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, null, sendRtpItem.getStream()); |
| 1425 | if (ssrcTransaction != null) { | 1629 | if (ssrcTransaction != null) { |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
| @@ -264,8 +264,8 @@ public class RedisGbPlayMsgListener implements MessageListener { | @@ -264,8 +264,8 @@ public class RedisGbPlayMsgListener implements MessageListener { | ||
| 264 | return; | 264 | return; |
| 265 | } | 265 | } |
| 266 | // 确定流是否在线 | 266 | // 确定流是否在线 |
| 267 | - boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, content.getApp(), content.getStream()); | ||
| 268 | - if (streamReady) { | 267 | + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, content.getApp(), content.getStream()); |
| 268 | + if (streamReady != null && streamReady) { | ||
| 269 | logger.info("[回复推流信息] {}/{}", content.getApp(), content.getStream()); | 269 | logger.info("[回复推流信息] {}/{}", content.getApp(), content.getStream()); |
| 270 | responseSendItem(mediaServerItem, content, toId, serial); | 270 | responseSendItem(mediaServerItem, content, toId, serial); |
| 271 | }else { | 271 | }else { |
| @@ -301,9 +301,6 @@ public class RedisGbPlayMsgListener implements MessageListener { | @@ -301,9 +301,6 @@ public class RedisGbPlayMsgListener implements MessageListener { | ||
| 301 | String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED; | 301 | String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED; |
| 302 | logger.info("[redis发送通知] 推流被请求 {}: {}/{}", key, messageForPushChannel.getApp(), messageForPushChannel.getStream()); | 302 | logger.info("[redis发送通知] 推流被请求 {}: {}/{}", key, messageForPushChannel.getApp(), messageForPushChannel.getStream()); |
| 303 | redisTemplate.convertAndSend(key, JSON.toJSON(messageForPushChannel)); | 303 | redisTemplate.convertAndSend(key, JSON.toJSON(messageForPushChannel)); |
| 304 | - | ||
| 305 | -// redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); | ||
| 306 | - | ||
| 307 | } | 304 | } |
| 308 | } | 305 | } |
| 309 | 306 |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java
| @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.service.redisMsg; | @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.service.redisMsg; | ||
| 3 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | import com.genersoft.iot.vmp.common.VideoManagerConstants; | 4 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 5 | import com.genersoft.iot.vmp.conf.DynamicTask; | 5 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 6 | +import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 6 | import com.genersoft.iot.vmp.service.IStreamPushService; | 7 | import com.genersoft.iot.vmp.service.IStreamPushService; |
| 7 | import com.genersoft.iot.vmp.service.bean.PushStreamStatusChangeFromRedisDto; | 8 | import com.genersoft.iot.vmp.service.bean.PushStreamStatusChangeFromRedisDto; |
| 8 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 9 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| @@ -38,6 +39,9 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic | @@ -38,6 +39,9 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic | ||
| 38 | @Autowired | 39 | @Autowired |
| 39 | private DynamicTask dynamicTask; | 40 | private DynamicTask dynamicTask; |
| 40 | 41 | ||
| 42 | + @Autowired | ||
| 43 | + private UserSetting userSetting; | ||
| 44 | + | ||
| 41 | 45 | ||
| 42 | 46 | ||
| 43 | private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); | 47 | private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); |
| @@ -89,13 +93,15 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic | @@ -89,13 +93,15 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic | ||
| 89 | 93 | ||
| 90 | @Override | 94 | @Override |
| 91 | public void run(ApplicationArguments args) throws Exception { | 95 | public void run(ApplicationArguments args) throws Exception { |
| 92 | - // 启动时设置所有推流通道离线,发起查询请求 | ||
| 93 | - redisCatchStorage.sendStreamPushRequestedMsgForStatus(); | ||
| 94 | - dynamicTask.startDelay(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED, ()->{ | ||
| 95 | - logger.info("[REDIS消息]未收到redis回复推流设备状态,执行推流设备离线"); | ||
| 96 | - // 五秒收不到请求就设置通道离线,然后通知上级离线 | ||
| 97 | - streamPushService.allStreamOffline(); | ||
| 98 | - }, 5000); | 96 | + if (!userSetting.isUsePushingAsStatus()) { |
| 97 | + // 启动时设置所有推流通道离线,发起查询请求 | ||
| 98 | + redisCatchStorage.sendStreamPushRequestedMsgForStatus(); | ||
| 99 | + dynamicTask.startDelay(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED, ()->{ | ||
| 100 | + logger.info("[REDIS消息]未收到redis回复推流设备状态,执行推流设备离线"); | ||
| 101 | + // 五秒收不到请求就设置通道离线,然后通知上级离线 | ||
| 102 | + streamPushService.allStreamOffline(); | ||
| 103 | + }, 5000); | ||
| 104 | + } | ||
| 99 | } | 105 | } |
| 100 | 106 | ||
| 101 | } | 107 | } |
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
| 1 | package com.genersoft.iot.vmp.storager; | 1 | package com.genersoft.iot.vmp.storager; |
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSONObject; | 3 | import com.alibaba.fastjson2.JSONObject; |
| 4 | -import com.genersoft.iot.vmp.common.StreamInfo; | ||
| 5 | import com.genersoft.iot.vmp.common.SystemAllInfo; | 4 | import com.genersoft.iot.vmp.common.SystemAllInfo; |
| 6 | -import com.genersoft.iot.vmp.gb28181.bean.*; | ||
| 7 | -import com.genersoft.iot.vmp.media.zlm.dto.*; | 5 | +import com.genersoft.iot.vmp.gb28181.bean.AlarmChannelMessage; |
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 7 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; | ||
| 8 | +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | ||
| 9 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | ||
| 10 | +import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; | ||
| 8 | import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; | 11 | import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; |
| 9 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | 12 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| 10 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | 13 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| 11 | -import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; | ||
| 12 | import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; | 14 | import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; |
| 13 | 15 | ||
| 14 | import java.util.List; | 16 | import java.util.List; |
| @@ -23,42 +25,6 @@ public interface IRedisCatchStorage { | @@ -23,42 +25,6 @@ public interface IRedisCatchStorage { | ||
| 23 | */ | 25 | */ |
| 24 | Long getCSEQ(); | 26 | Long getCSEQ(); |
| 25 | 27 | ||
| 26 | - /** | ||
| 27 | - * 开始播放时将流存入 | ||
| 28 | - * | ||
| 29 | - * @param stream 流信息 | ||
| 30 | - * @return | ||
| 31 | - */ | ||
| 32 | - boolean startPlay(StreamInfo stream); | ||
| 33 | - | ||
| 34 | - | ||
| 35 | - /** | ||
| 36 | - * 停止播放时删除 | ||
| 37 | - * | ||
| 38 | - * @return | ||
| 39 | - */ | ||
| 40 | - boolean stopPlay(StreamInfo streamInfo); | ||
| 41 | - | ||
| 42 | - /** | ||
| 43 | - * 查询播放列表 | ||
| 44 | - * @return | ||
| 45 | - */ | ||
| 46 | - StreamInfo queryPlay(StreamInfo streamInfo); | ||
| 47 | - | ||
| 48 | - StreamInfo queryPlayByStreamId(String steamId); | ||
| 49 | - | ||
| 50 | - StreamInfo queryPlayByDevice(String deviceId, String channelId); | ||
| 51 | - | ||
| 52 | - Map<String, StreamInfo> queryPlayByDeviceId(String deviceId); | ||
| 53 | - | ||
| 54 | - boolean startPlayback(StreamInfo stream, String callId); | ||
| 55 | - | ||
| 56 | - boolean stopPlayback(String deviceId, String channelId, String stream, String callId); | ||
| 57 | - | ||
| 58 | - StreamInfo queryPlayback(String deviceId, String channelID, String stream, String callId); | ||
| 59 | - | ||
| 60 | - String queryPlaybackForKey(String deviceId, String channelId, String stream, String callId); | ||
| 61 | - | ||
| 62 | void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch); | 28 | void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch); |
| 63 | 29 | ||
| 64 | ParentPlatformCatch queryPlatformCatchInfo(String platformGbId); | 30 | ParentPlatformCatch queryPlatformCatchInfo(String platformGbId); |
| @@ -75,8 +41,6 @@ public interface IRedisCatchStorage { | @@ -75,8 +41,6 @@ public interface IRedisCatchStorage { | ||
| 75 | 41 | ||
| 76 | void delPlatformRegisterInfo(String callId); | 42 | void delPlatformRegisterInfo(String callId); |
| 77 | 43 | ||
| 78 | - void cleanPlatformRegisterInfos(); | ||
| 79 | - | ||
| 80 | void updateSendRTPSever(SendRtpItem sendRtpItem); | 44 | void updateSendRTPSever(SendRtpItem sendRtpItem); |
| 81 | 45 | ||
| 82 | /** | 46 | /** |
| @@ -103,12 +67,6 @@ public interface IRedisCatchStorage { | @@ -103,12 +67,6 @@ public interface IRedisCatchStorage { | ||
| 103 | boolean isChannelSendingRTP(String channelId); | 67 | boolean isChannelSendingRTP(String channelId); |
| 104 | 68 | ||
| 105 | /** | 69 | /** |
| 106 | - * 清空某个设备的所有缓存 | ||
| 107 | - * @param deviceId 设备ID | ||
| 108 | - */ | ||
| 109 | - void clearCatchByDeviceId(String deviceId); | ||
| 110 | - | ||
| 111 | - /** | ||
| 112 | * 在redis添加wvp的信息 | 70 | * 在redis添加wvp的信息 |
| 113 | */ | 71 | */ |
| 114 | void updateWVPInfo(JSONObject jsonObject, int time); | 72 | void updateWVPInfo(JSONObject jsonObject, int time); |
| @@ -148,23 +106,6 @@ public interface IRedisCatchStorage { | @@ -148,23 +106,6 @@ public interface IRedisCatchStorage { | ||
| 148 | */ | 106 | */ |
| 149 | void removeStream(String mediaServerId, String type); | 107 | void removeStream(String mediaServerId, String type); |
| 150 | 108 | ||
| 151 | - /** | ||
| 152 | - * 开始下载录像时存入 | ||
| 153 | - * @param streamInfo | ||
| 154 | - */ | ||
| 155 | - boolean startDownload(StreamInfo streamInfo, String callId); | ||
| 156 | - | ||
| 157 | - StreamInfo queryDownload(String deviceId, String channelId, String stream, String callId); | ||
| 158 | - | ||
| 159 | - boolean stopDownload(String deviceId, String channelId, String stream, String callId); | ||
| 160 | - | ||
| 161 | - /** | ||
| 162 | - * 查找第三方系统留下的国标预设值 | ||
| 163 | - * @param queryKey | ||
| 164 | - * @return | ||
| 165 | - */ | ||
| 166 | - ThirdPartyGB queryMemberNoGBId(String queryKey); | ||
| 167 | - | ||
| 168 | List<OnStreamChangedHookParam> getStreams(String mediaServerId, String pull); | 109 | List<OnStreamChangedHookParam> getStreams(String mediaServerId, String pull); |
| 169 | 110 | ||
| 170 | /** | 111 | /** |
| @@ -261,4 +202,6 @@ public interface IRedisCatchStorage { | @@ -261,4 +202,6 @@ public interface IRedisCatchStorage { | ||
| 261 | List<Device> getAllDevices(); | 202 | List<Device> getAllDevices(); |
| 262 | 203 | ||
| 263 | void removeAllDevice(); | 204 | void removeAllDevice(); |
| 205 | + | ||
| 206 | + void sendDeviceOrChannelStatus(String deviceId, String channelId, boolean online); | ||
| 264 | } | 207 | } |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
| @@ -197,6 +197,81 @@ public interface DeviceChannelMapper { | @@ -197,6 +197,81 @@ public interface DeviceChannelMapper { | ||
| 197 | @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId}"}) | 197 | @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId}"}) |
| 198 | void offlineByDeviceId(String deviceId); | 198 | void offlineByDeviceId(String deviceId); |
| 199 | 199 | ||
| 200 | +// @Insert("<script> " + | ||
| 201 | +// "insert into device_channel " + | ||
| 202 | +// "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " + | ||
| 203 | +// " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + | ||
| 204 | +// " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " + | ||
| 205 | +// " longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " + | ||
| 206 | +// "values " + | ||
| 207 | +// "<foreach collection='addChannels' index='index' item='item' separator=','> " + | ||
| 208 | +// "(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " + | ||
| 209 | +// "#{item.owner}, #{item.civilCode}, #{item.block},#{item.subCount}," + | ||
| 210 | +// "#{item.address}, #{item.parental}, #{item.parentId}, #{item.safetyWay}, #{item.registerWay}, " + | ||
| 211 | +// "#{item.certNum}, #{item.certifiable}, #{item.errCode}, #{item.secrecy}, " + | ||
| 212 | +// "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " + | ||
| 213 | +// "#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " + | ||
| 214 | +// "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " + | ||
| 215 | +// "#{item.businessGroupId}, #{item.gpsTime}) " + | ||
| 216 | +// "</foreach> " + | ||
| 217 | +// "ON DUPLICATE KEY UPDATE " + | ||
| 218 | +// "updateTime=VALUES(updateTime), " + | ||
| 219 | +// "name=VALUES(name), " + | ||
| 220 | +// "manufacture=VALUES(manufacture), " + | ||
| 221 | +// "model=VALUES(model), " + | ||
| 222 | +// "owner=VALUES(owner), " + | ||
| 223 | +// "civilCode=VALUES(civilCode), " + | ||
| 224 | +// "block=VALUES(block), " + | ||
| 225 | +// "subCount=VALUES(subCount), " + | ||
| 226 | +// "address=VALUES(address), " + | ||
| 227 | +// "parental=VALUES(parental), " + | ||
| 228 | +// "parentId=VALUES(parentId), " + | ||
| 229 | +// "safetyWay=VALUES(safetyWay), " + | ||
| 230 | +// "registerWay=VALUES(registerWay), " + | ||
| 231 | +// "certNum=VALUES(certNum), " + | ||
| 232 | +// "certifiable=VALUES(certifiable), " + | ||
| 233 | +// "errCode=VALUES(errCode), " + | ||
| 234 | +// "secrecy=VALUES(secrecy), " + | ||
| 235 | +// "ipAddress=VALUES(ipAddress), " + | ||
| 236 | +// "port=VALUES(port), " + | ||
| 237 | +// "password=VALUES(password), " + | ||
| 238 | +// "PTZType=VALUES(PTZType), " + | ||
| 239 | +// "status=VALUES(status), " + | ||
| 240 | +// "streamId=VALUES(streamId), " + | ||
| 241 | +// "longitude=VALUES(longitude), " + | ||
| 242 | +// "latitude=VALUES(latitude), " + | ||
| 243 | +// "longitudeGcj02=VALUES(longitudeGcj02), " + | ||
| 244 | +// "latitudeGcj02=VALUES(latitudeGcj02), " + | ||
| 245 | +// "longitudeWgs84=VALUES(longitudeWgs84), " + | ||
| 246 | +// "latitudeWgs84=VALUES(latitudeWgs84), " + | ||
| 247 | +// "hasAudio=VALUES(hasAudio), " + | ||
| 248 | +// "businessGroupId=VALUES(businessGroupId), " + | ||
| 249 | +// "gpsTime=VALUES(gpsTime)" + | ||
| 250 | +// "</script>") | ||
| 251 | +// int batchAdd(List<DeviceChannel> addChannels); | ||
| 252 | + | ||
| 253 | + | ||
| 254 | + @Insert("<script> " + | ||
| 255 | + "insert into device_channel " + | ||
| 256 | + "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " + | ||
| 257 | + " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + | ||
| 258 | + " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " + | ||
| 259 | + " longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " + | ||
| 260 | + "values " + | ||
| 261 | + "<foreach collection='addChannels' index='index' item='item' separator=','> " + | ||
| 262 | + "(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " + | ||
| 263 | + "#{item.owner}, #{item.civilCode}, #{item.block},#{item.subCount}," + | ||
| 264 | + "#{item.address}, #{item.parental}, #{item.parentId}, #{item.safetyWay}, #{item.registerWay}, " + | ||
| 265 | + "#{item.certNum}, #{item.certifiable}, #{item.errCode}, #{item.secrecy}, " + | ||
| 266 | + "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " + | ||
| 267 | + "#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " + | ||
| 268 | + "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " + | ||
| 269 | + "#{item.businessGroupId}, #{item.gpsTime}) " + | ||
| 270 | + "</foreach> " + | ||
| 271 | + "</script>") | ||
| 272 | + int batchAdd(List<DeviceChannel> addChannels); | ||
| 273 | + | ||
| 274 | + | ||
| 200 | @Insert("<script> " + | 275 | @Insert("<script> " + |
| 201 | "insert into device_channel " + | 276 | "insert into device_channel " + |
| 202 | "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " + | 277 | "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " + |
| @@ -248,7 +323,7 @@ public interface DeviceChannelMapper { | @@ -248,7 +323,7 @@ public interface DeviceChannelMapper { | ||
| 248 | "businessGroupId=VALUES(businessGroupId), " + | 323 | "businessGroupId=VALUES(businessGroupId), " + |
| 249 | "gpsTime=VALUES(gpsTime)" + | 324 | "gpsTime=VALUES(gpsTime)" + |
| 250 | "</script>") | 325 | "</script>") |
| 251 | - int batchAdd(List<DeviceChannel> addChannels); | 326 | + int batchAddOrUpdate(List<DeviceChannel> addChannels); |
| 252 | 327 | ||
| 253 | @Update(value = {"UPDATE device_channel SET status=1 WHERE deviceId=#{deviceId} AND channelId=#{channelId}"}) | 328 | @Update(value = {"UPDATE device_channel SET status=1 WHERE deviceId=#{deviceId} AND channelId=#{channelId}"}) |
| 254 | void online(String deviceId, String channelId); | 329 | void online(String deviceId, String channelId); |
| @@ -264,7 +339,7 @@ public interface DeviceChannelMapper { | @@ -264,7 +339,7 @@ public interface DeviceChannelMapper { | ||
| 264 | "<if test='item.owner != null'>, owner=#{item.owner}</if>" + | 339 | "<if test='item.owner != null'>, owner=#{item.owner}</if>" + |
| 265 | "<if test='item.civilCode != null'>, civilCode=#{item.civilCode}</if>" + | 340 | "<if test='item.civilCode != null'>, civilCode=#{item.civilCode}</if>" + |
| 266 | "<if test='item.block != null'>, block=#{item.block}</if>" + | 341 | "<if test='item.block != null'>, block=#{item.block}</if>" + |
| 267 | - "<if test='item.subCount != null'>, block=#{item.subCount}</if>" + | 342 | + "<if test='item.subCount != null'>, subCount=#{item.subCount}</if>" + |
| 268 | "<if test='item.address != null'>, address=#{item.address}</if>" + | 343 | "<if test='item.address != null'>, address=#{item.address}</if>" + |
| 269 | "<if test='item.parental != null'>, parental=#{item.parental}</if>" + | 344 | "<if test='item.parental != null'>, parental=#{item.parental}</if>" + |
| 270 | "<if test='item.parentId != null'>, parentId=#{item.parentId}</if>" + | 345 | "<if test='item.parentId != null'>, parentId=#{item.parentId}</if>" + |
| @@ -289,7 +364,8 @@ public interface DeviceChannelMapper { | @@ -289,7 +364,8 @@ public interface DeviceChannelMapper { | ||
| 289 | "<if test='item.latitudeWgs84 != null'>, latitudeWgs84=#{item.latitudeWgs84}</if>" + | 364 | "<if test='item.latitudeWgs84 != null'>, latitudeWgs84=#{item.latitudeWgs84}</if>" + |
| 290 | "<if test='item.businessGroupId != null'>, businessGroupId=#{item.businessGroupId}</if>" + | 365 | "<if test='item.businessGroupId != null'>, businessGroupId=#{item.businessGroupId}</if>" + |
| 291 | "<if test='item.gpsTime != null'>, gpsTime=#{item.gpsTime}</if>" + | 366 | "<if test='item.gpsTime != null'>, gpsTime=#{item.gpsTime}</if>" + |
| 292 | - "WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}"+ | 367 | + "<if test='item.id > 0'>WHERE id=#{item.id}</if>" + |
| 368 | + "<if test='item.id == 0'>WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}</if>" + | ||
| 293 | "</foreach>" + | 369 | "</foreach>" + |
| 294 | "</script>"}) | 370 | "</script>"}) |
| 295 | int batchUpdate(List<DeviceChannel> updateChannels); | 371 | int batchUpdate(List<DeviceChannel> updateChannels); |
| @@ -403,4 +479,26 @@ public interface DeviceChannelMapper { | @@ -403,4 +479,26 @@ public interface DeviceChannelMapper { | ||
| 403 | 479 | ||
| 404 | @Select("select de.* from device de left join device_channel dc on de.deviceId = dc.deviceId where dc.channelId=#{channelId}") | 480 | @Select("select de.* from device de left join device_channel dc on de.deviceId = dc.deviceId where dc.channelId=#{channelId}") |
| 405 | List<Device> getDeviceByChannelId(String channelId); | 481 | List<Device> getDeviceByChannelId(String channelId); |
| 482 | + | ||
| 483 | + | ||
| 484 | + @Delete({"<script>" + | ||
| 485 | + "<foreach collection='deleteChannelList' item='item' separator=';'>" + | ||
| 486 | + "DELETE FROM device_channel WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}" + | ||
| 487 | + "</foreach>" + | ||
| 488 | + "</script>"}) | ||
| 489 | + int batchDel(List<DeviceChannel> deleteChannelList); | ||
| 490 | + | ||
| 491 | + @Update({"<script>" + | ||
| 492 | + "<foreach collection='channels' item='item' separator=';'>" + | ||
| 493 | + "UPDATE device_channel SET status=1 WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}" + | ||
| 494 | + "</foreach>" + | ||
| 495 | + "</script>"}) | ||
| 496 | + int batchOnline(List<DeviceChannel> channels); | ||
| 497 | + | ||
| 498 | + @Update({"<script>" + | ||
| 499 | + "<foreach collection='channels' item='item' separator=';'>" + | ||
| 500 | + "UPDATE device_channel SET status=0 WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}" + | ||
| 501 | + "</foreach>" + | ||
| 502 | + "</script>"}) | ||
| 503 | + int batchOffline(List<DeviceChannel> channels); | ||
| 406 | } | 504 | } |
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
| @@ -2,17 +2,18 @@ package com.genersoft.iot.vmp.storager.impl; | @@ -2,17 +2,18 @@ package com.genersoft.iot.vmp.storager.impl; | ||
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | import com.alibaba.fastjson2.JSONObject; | 4 | import com.alibaba.fastjson2.JSONObject; |
| 5 | -import com.genersoft.iot.vmp.common.StreamInfo; | ||
| 6 | import com.genersoft.iot.vmp.common.SystemAllInfo; | 5 | import com.genersoft.iot.vmp.common.SystemAllInfo; |
| 7 | import com.genersoft.iot.vmp.common.VideoManagerConstants; | 6 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 8 | import com.genersoft.iot.vmp.conf.UserSetting; | 7 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 9 | -import com.genersoft.iot.vmp.gb28181.bean.*; | ||
| 10 | -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; | 8 | +import com.genersoft.iot.vmp.gb28181.bean.AlarmChannelMessage; |
| 9 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 10 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; | ||
| 11 | +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | ||
| 11 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 12 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 12 | import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; | 13 | import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; |
| 14 | +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; | ||
| 13 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | 15 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| 14 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | 16 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| 15 | -import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; | ||
| 16 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 17 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 17 | import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; | 18 | import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; |
| 18 | import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; | 19 | import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; |
| @@ -24,8 +25,10 @@ import org.slf4j.Logger; | @@ -24,8 +25,10 @@ import org.slf4j.Logger; | ||
| 24 | import org.slf4j.LoggerFactory; | 25 | import org.slf4j.LoggerFactory; |
| 25 | import org.springframework.beans.factory.annotation.Autowired; | 26 | import org.springframework.beans.factory.annotation.Autowired; |
| 26 | import org.springframework.data.redis.core.RedisTemplate; | 27 | import org.springframework.data.redis.core.RedisTemplate; |
| 28 | +import org.springframework.data.redis.core.StringRedisTemplate; | ||
| 27 | import org.springframework.stereotype.Component; | 29 | import org.springframework.stereotype.Component; |
| 28 | 30 | ||
| 31 | +import java.time.Duration; | ||
| 29 | import java.util.*; | 32 | import java.util.*; |
| 30 | 33 | ||
| 31 | @SuppressWarnings("rawtypes") | 34 | @SuppressWarnings("rawtypes") |
| @@ -43,6 +46,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -43,6 +46,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 43 | @Autowired | 46 | @Autowired |
| 44 | private RedisTemplate<Object, Object> redisTemplate; | 47 | private RedisTemplate<Object, Object> redisTemplate; |
| 45 | 48 | ||
| 49 | + @Autowired | ||
| 50 | + private StringRedisTemplate stringRedisTemplate; | ||
| 51 | + | ||
| 46 | @Override | 52 | @Override |
| 47 | public Long getCSEQ() { | 53 | public Long getCSEQ() { |
| 48 | String key = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetting.getServerId(); | 54 | String key = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetting.getServerId(); |
| @@ -87,240 +93,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -87,240 +93,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 87 | } | 93 | } |
| 88 | } | 94 | } |
| 89 | 95 | ||
| 90 | - /** | ||
| 91 | - * 开始播放时将流存入redis | ||
| 92 | - */ | ||
| 93 | - @Override | ||
| 94 | - public boolean startPlay(StreamInfo stream) { | ||
| 95 | - | ||
| 96 | - redisTemplate.opsForValue().set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(), | ||
| 97 | - stream.getMediaServerId(), stream.getStream(), stream.getDeviceID(), stream.getChannelId()), | ||
| 98 | - stream); | ||
| 99 | - return true; | ||
| 100 | - } | ||
| 101 | - | ||
| 102 | - /** | ||
| 103 | - * 停止播放时从redis删除 | ||
| 104 | - */ | ||
| 105 | - @Override | ||
| 106 | - public boolean stopPlay(StreamInfo streamInfo) { | ||
| 107 | - if (streamInfo == null) { | ||
| 108 | - return false; | ||
| 109 | - } | ||
| 110 | - Boolean result = redisTemplate.delete(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, | ||
| 111 | - userSetting.getServerId(), | ||
| 112 | - streamInfo.getMediaServerId(), | ||
| 113 | - streamInfo.getStream(), | ||
| 114 | - streamInfo.getDeviceID(), | ||
| 115 | - streamInfo.getChannelId())); | ||
| 116 | - return result != null && result; | ||
| 117 | - } | ||
| 118 | - | ||
| 119 | - /** | ||
| 120 | - * 查询播放列表 | ||
| 121 | - */ | ||
| 122 | - @Override | ||
| 123 | - public StreamInfo queryPlay(StreamInfo streamInfo) { | ||
| 124 | - return (StreamInfo)redisTemplate.opsForValue().get(String.format("%S_%s_%s_%s_%s_%s", | ||
| 125 | - VideoManagerConstants.PLAYER_PREFIX, | ||
| 126 | - userSetting.getServerId(), | ||
| 127 | - streamInfo.getMediaServerId(), | ||
| 128 | - streamInfo.getStream(), | ||
| 129 | - streamInfo.getDeviceID(), | ||
| 130 | - streamInfo.getChannelId())); | ||
| 131 | - } | ||
| 132 | - @Override | ||
| 133 | - public StreamInfo queryPlayByStreamId(String streamId) { | ||
| 134 | - List<Object> playLeys = RedisUtil.scan(redisTemplate, String.format("%S_%s_*_%s_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(), streamId)); | ||
| 135 | - if (playLeys.size() == 0) { | ||
| 136 | - return null; | ||
| 137 | - } | ||
| 138 | - return (StreamInfo)redisTemplate.opsForValue().get(playLeys.get(0).toString()); | ||
| 139 | - } | ||
| 140 | - | ||
| 141 | - @Override | ||
| 142 | - public StreamInfo queryPlayByDevice(String deviceId, String channelId) { | ||
| 143 | - List<Object> playLeys = RedisUtil.scan(redisTemplate, String.format("%S_%s_*_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX, | ||
| 144 | - userSetting.getServerId(), | ||
| 145 | - deviceId, | ||
| 146 | - channelId)); | ||
| 147 | - if (playLeys.size() == 0) { | ||
| 148 | - return null; | ||
| 149 | - } | ||
| 150 | - return (StreamInfo)redisTemplate.opsForValue().get(playLeys.get(0).toString()); | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - @Override | ||
| 154 | - public Map<String, StreamInfo> queryPlayByDeviceId(String deviceId) { | ||
| 155 | - Map<String, StreamInfo> streamInfos = new HashMap<>(); | ||
| 156 | - List<Object> players = RedisUtil.scan(redisTemplate, String.format("%S_%s_*_*_%s_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(),deviceId)); | ||
| 157 | - if (players.size() == 0) { | ||
| 158 | - return streamInfos; | ||
| 159 | - } | ||
| 160 | - for (Object player : players) { | ||
| 161 | - String key = (String) player; | ||
| 162 | - StreamInfo streamInfo = JsonUtil.redisJsonToObject(redisTemplate, key, StreamInfo.class); | ||
| 163 | - if (Objects.isNull(streamInfo)) { | ||
| 164 | - continue; | ||
| 165 | - } | ||
| 166 | - streamInfos.put(streamInfo.getDeviceID() + "_" + streamInfo.getChannelId(), streamInfo); | ||
| 167 | - } | ||
| 168 | - return streamInfos; | ||
| 169 | - } | ||
| 170 | - | ||
| 171 | - | ||
| 172 | - @Override | ||
| 173 | - public boolean startPlayback(StreamInfo stream, String callId) { | ||
| 174 | - redisTemplate.opsForValue().set(String.format("%S_%s_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, | ||
| 175 | - userSetting.getServerId(), stream.getMediaServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream); | ||
| 176 | - return true; | ||
| 177 | - } | ||
| 178 | - | ||
| 179 | - @Override | ||
| 180 | - public boolean startDownload(StreamInfo stream, String callId) { | ||
| 181 | - String key=String.format("%S_%s_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, | ||
| 182 | - userSetting.getServerId(), stream.getMediaServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId); | ||
| 183 | - if (stream.getProgress() == 1) { | ||
| 184 | - logger.debug("添加下载缓存==已完成下载=》{}",key); | ||
| 185 | - redisTemplate.opsForValue().set(key, stream); | ||
| 186 | - }else { | ||
| 187 | - logger.debug("添加下载缓存==未完成下载=》{}",key); | ||
| 188 | - redisTemplate.opsForValue().set(key, stream, 60*60); | ||
| 189 | - } | ||
| 190 | - return true; | ||
| 191 | - } | ||
| 192 | - @Override | ||
| 193 | - public boolean stopDownload(String deviceId, String channelId, String stream, String callId) { | ||
| 194 | - DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); | ||
| 195 | - if (deviceChannel != null) { | ||
| 196 | - deviceChannel.setStreamId(null); | ||
| 197 | - deviceChannel.setDeviceId(deviceId); | ||
| 198 | - deviceChannelMapper.update(deviceChannel); | ||
| 199 | - } | ||
| 200 | - if (deviceId == null) { | ||
| 201 | - deviceId = "*"; | ||
| 202 | - } | ||
| 203 | - if (channelId == null) { | ||
| 204 | - channelId = "*"; | ||
| 205 | - } | ||
| 206 | - if (stream == null) { | ||
| 207 | - stream = "*"; | ||
| 208 | - } | ||
| 209 | - if (callId == null) { | ||
| 210 | - callId = "*"; | ||
| 211 | - } | ||
| 212 | - String key = String.format("%S_%s_*_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, | ||
| 213 | - userSetting.getServerId(), | ||
| 214 | - deviceId, | ||
| 215 | - channelId, | ||
| 216 | - stream, | ||
| 217 | - callId | ||
| 218 | - ); | ||
| 219 | - List<Object> scan = RedisUtil.scan(redisTemplate, key); | ||
| 220 | - if (scan.size() > 0) { | ||
| 221 | - for (Object keyObj : scan) { | ||
| 222 | - redisTemplate.delete(keyObj); | ||
| 223 | - } | ||
| 224 | - } | ||
| 225 | - return true; | ||
| 226 | - } | ||
| 227 | - | ||
| 228 | - @Override | ||
| 229 | - public boolean stopPlayback(String deviceId, String channelId, String stream, String callId) { | ||
| 230 | - DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); | ||
| 231 | - if (deviceChannel != null) { | ||
| 232 | - deviceChannel.setStreamId(null); | ||
| 233 | - deviceChannel.setDeviceId(deviceId); | ||
| 234 | - deviceChannelMapper.update(deviceChannel); | ||
| 235 | - } | ||
| 236 | - if (deviceId == null) { | ||
| 237 | - deviceId = "*"; | ||
| 238 | - } | ||
| 239 | - if (channelId == null) { | ||
| 240 | - channelId = "*"; | ||
| 241 | - } | ||
| 242 | - if (stream == null) { | ||
| 243 | - stream = "*"; | ||
| 244 | - } | ||
| 245 | - if (callId == null) { | ||
| 246 | - callId = "*"; | ||
| 247 | - } | ||
| 248 | - String key = String.format("%S_%s_*_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, | ||
| 249 | - userSetting.getServerId(), | ||
| 250 | - deviceId, | ||
| 251 | - channelId, | ||
| 252 | - stream, | ||
| 253 | - callId | ||
| 254 | - ); | ||
| 255 | - List<Object> scan = RedisUtil.scan(redisTemplate, key); | ||
| 256 | - if (scan.size() > 0) { | ||
| 257 | - for (Object keyObj : scan) { | ||
| 258 | - redisTemplate.delete(keyObj); | ||
| 259 | - } | ||
| 260 | - } | ||
| 261 | - return true; | ||
| 262 | - } | ||
| 263 | - | ||
| 264 | - @Override | ||
| 265 | - public StreamInfo queryPlayback(String deviceId, String channelId, String stream, String callId) { | ||
| 266 | - if (stream == null && callId == null) { | ||
| 267 | - return null; | ||
| 268 | - } | ||
| 269 | - if (deviceId == null) { | ||
| 270 | - deviceId = "*"; | ||
| 271 | - } | ||
| 272 | - if (channelId == null) { | ||
| 273 | - channelId = "*"; | ||
| 274 | - } | ||
| 275 | - if (stream == null) { | ||
| 276 | - stream = "*"; | ||
| 277 | - } | ||
| 278 | - if (callId == null) { | ||
| 279 | - callId = "*"; | ||
| 280 | - } | ||
| 281 | - String key = String.format("%S_%s_*_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, | ||
| 282 | - userSetting.getServerId(), | ||
| 283 | - deviceId, | ||
| 284 | - channelId, | ||
| 285 | - stream, | ||
| 286 | - callId | ||
| 287 | - ); | ||
| 288 | - List<Object> streamInfoScan = RedisUtil.scan(redisTemplate, key); | ||
| 289 | - if (streamInfoScan.size() > 0) { | ||
| 290 | - return (StreamInfo) redisTemplate.opsForValue().get(streamInfoScan.get(0)); | ||
| 291 | - }else { | ||
| 292 | - return null; | ||
| 293 | - } | ||
| 294 | - } | ||
| 295 | - | ||
| 296 | - @Override | ||
| 297 | - public String queryPlaybackForKey(String deviceId, String channelId, String stream, String callId) { | ||
| 298 | - if (stream == null && callId == null) { | ||
| 299 | - return null; | ||
| 300 | - } | ||
| 301 | - if (deviceId == null) { | ||
| 302 | - deviceId = "*"; | ||
| 303 | - } | ||
| 304 | - if (channelId == null) { | ||
| 305 | - channelId = "*"; | ||
| 306 | - } | ||
| 307 | - if (stream == null) { | ||
| 308 | - stream = "*"; | ||
| 309 | - } | ||
| 310 | - if (callId == null) { | ||
| 311 | - callId = "*"; | ||
| 312 | - } | ||
| 313 | - String key = String.format("%S_%s_*_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, | ||
| 314 | - userSetting.getServerId(), | ||
| 315 | - deviceId, | ||
| 316 | - channelId, | ||
| 317 | - stream, | ||
| 318 | - callId | ||
| 319 | - ); | ||
| 320 | - List<Object> streamInfoScan = RedisUtil.scan(redisTemplate, key); | ||
| 321 | - return (String) streamInfoScan.get(0); | ||
| 322 | - } | ||
| 323 | - | ||
| 324 | @Override | 96 | @Override |
| 325 | public void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch) { | 97 | public void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch) { |
| 326 | String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + parentPlatformCatch.getId(); | 98 | String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + parentPlatformCatch.getId(); |
| @@ -351,7 +123,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -351,7 +123,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 351 | @Override | 123 | @Override |
| 352 | public void updatePlatformRegisterInfo(String callId, PlatformRegisterInfo platformRegisterInfo) { | 124 | public void updatePlatformRegisterInfo(String callId, PlatformRegisterInfo platformRegisterInfo) { |
| 353 | String key = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId; | 125 | String key = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId; |
| 354 | - redisTemplate.opsForValue().set(key, platformRegisterInfo, 30); | 126 | + Duration duration = Duration.ofSeconds(30L); |
| 127 | + redisTemplate.opsForValue().set(key, platformRegisterInfo, duration); | ||
| 355 | } | 128 | } |
| 356 | 129 | ||
| 357 | 130 | ||
| @@ -366,14 +139,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -366,14 +139,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 366 | } | 139 | } |
| 367 | 140 | ||
| 368 | @Override | 141 | @Override |
| 369 | - public void cleanPlatformRegisterInfos() { | ||
| 370 | - List regInfos = RedisUtil.scan(redisTemplate, VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + "*"); | ||
| 371 | - for (Object key : regInfos) { | ||
| 372 | - redisTemplate.delete(key.toString()); | ||
| 373 | - } | ||
| 374 | - } | ||
| 375 | - | ||
| 376 | - @Override | ||
| 377 | public void updateSendRTPSever(SendRtpItem sendRtpItem) { | 142 | public void updateSendRTPSever(SendRtpItem sendRtpItem) { |
| 378 | 143 | ||
| 379 | String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + | 144 | String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + |
| @@ -530,39 +295,10 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -530,39 +295,10 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 530 | } | 295 | } |
| 531 | 296 | ||
| 532 | @Override | 297 | @Override |
| 533 | - public void clearCatchByDeviceId(String deviceId) { | ||
| 534 | - List<Object> playLeys = RedisUtil.scan(redisTemplate, String.format("%S_%s_*_%s_*", VideoManagerConstants.PLAYER_PREFIX, | ||
| 535 | - userSetting.getServerId(), | ||
| 536 | - deviceId)); | ||
| 537 | - if (playLeys.size() > 0) { | ||
| 538 | - for (Object key : playLeys) { | ||
| 539 | - redisTemplate.delete(key.toString()); | ||
| 540 | - } | ||
| 541 | - } | ||
| 542 | - | ||
| 543 | - List<Object> playBackers = RedisUtil.scan(redisTemplate, String.format("%S_%s_*_%s_*_*_*", VideoManagerConstants.PLAY_BLACK_PREFIX, | ||
| 544 | - userSetting.getServerId(), | ||
| 545 | - deviceId)); | ||
| 546 | - if (playBackers.size() > 0) { | ||
| 547 | - for (Object key : playBackers) { | ||
| 548 | - redisTemplate.delete(key.toString()); | ||
| 549 | - } | ||
| 550 | - } | ||
| 551 | - | ||
| 552 | - List<Object> deviceCache = RedisUtil.scan(redisTemplate, String.format("%S%s_%s", VideoManagerConstants.DEVICE_PREFIX, | ||
| 553 | - userSetting.getServerId(), | ||
| 554 | - deviceId)); | ||
| 555 | - if (deviceCache.size() > 0) { | ||
| 556 | - for (Object key : deviceCache) { | ||
| 557 | - redisTemplate.delete(key.toString()); | ||
| 558 | - } | ||
| 559 | - } | ||
| 560 | - } | ||
| 561 | - | ||
| 562 | - @Override | ||
| 563 | public void updateWVPInfo(JSONObject jsonObject, int time) { | 298 | public void updateWVPInfo(JSONObject jsonObject, int time) { |
| 564 | String key = VideoManagerConstants.WVP_SERVER_PREFIX + userSetting.getServerId(); | 299 | String key = VideoManagerConstants.WVP_SERVER_PREFIX + userSetting.getServerId(); |
| 565 | - redisTemplate.opsForValue().set(key, jsonObject, time); | 300 | + Duration duration = Duration.ofSeconds(time); |
| 301 | + redisTemplate.opsForValue().set(key, jsonObject, duration); | ||
| 566 | } | 302 | } |
| 567 | 303 | ||
| 568 | @Override | 304 | @Override |
| @@ -590,44 +326,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -590,44 +326,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 590 | } | 326 | } |
| 591 | 327 | ||
| 592 | @Override | 328 | @Override |
| 593 | - public StreamInfo queryDownload(String deviceId, String channelId, String stream, String callId) { | ||
| 594 | - if (stream == null && callId == null) { | ||
| 595 | - return null; | ||
| 596 | - } | ||
| 597 | - if (deviceId == null) { | ||
| 598 | - deviceId = "*"; | ||
| 599 | - } | ||
| 600 | - if (channelId == null) { | ||
| 601 | - channelId = "*"; | ||
| 602 | - } | ||
| 603 | - if (stream == null) { | ||
| 604 | - stream = "*"; | ||
| 605 | - } | ||
| 606 | - if (callId == null) { | ||
| 607 | - callId = "*"; | ||
| 608 | - } | ||
| 609 | - String key = String.format("%S_%s_*_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, | ||
| 610 | - userSetting.getServerId(), | ||
| 611 | - deviceId, | ||
| 612 | - channelId, | ||
| 613 | - stream, | ||
| 614 | - callId | ||
| 615 | - ); | ||
| 616 | - List<Object> streamInfoScan = RedisUtil.scan(redisTemplate, key); | ||
| 617 | - if (streamInfoScan.size() > 0) { | ||
| 618 | - return (StreamInfo) redisTemplate.opsForValue().get(streamInfoScan.get(0)); | ||
| 619 | - }else { | ||
| 620 | - return null; | ||
| 621 | - } | ||
| 622 | - } | ||
| 623 | - | ||
| 624 | - @Override | ||
| 625 | - public ThirdPartyGB queryMemberNoGBId(String queryKey) { | ||
| 626 | - String key = VideoManagerConstants.WVP_STREAM_GB_ID_PREFIX + queryKey; | ||
| 627 | - return JsonUtil.redisJsonToObject(redisTemplate, key, ThirdPartyGB.class); | ||
| 628 | - } | ||
| 629 | - | ||
| 630 | - @Override | ||
| 631 | public void removeStream(String mediaServerId, String type) { | 329 | public void removeStream(String mediaServerId, String type) { |
| 632 | String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_*_*_" + mediaServerId; | 330 | String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_*_*_" + mediaServerId; |
| 633 | List<Object> streams = RedisUtil.scan(redisTemplate, key); | 331 | List<Object> streams = RedisUtil.scan(redisTemplate, key); |
| @@ -694,7 +392,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -694,7 +392,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 694 | @Override | 392 | @Override |
| 695 | public void updateGpsMsgInfo(GPSMsgInfo gpsMsgInfo) { | 393 | public void updateGpsMsgInfo(GPSMsgInfo gpsMsgInfo) { |
| 696 | String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetting.getServerId() + "_" + gpsMsgInfo.getId(); | 394 | String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetting.getServerId() + "_" + gpsMsgInfo.getId(); |
| 697 | - redisTemplate.opsForValue().set(key, gpsMsgInfo, 60); // 默认GPS消息保存1分钟 | 395 | + Duration duration = Duration.ofSeconds(60L); |
| 396 | + redisTemplate.opsForValue().set(key, gpsMsgInfo, duration); // 默认GPS消息保存1分钟 | ||
| 698 | } | 397 | } |
| 699 | 398 | ||
| 700 | @Override | 399 | @Override |
| @@ -902,4 +601,23 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -902,4 +601,23 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 902 | + userSetting.getServerId() + "_*_" + id + "_*"; | 601 | + userSetting.getServerId() + "_*_" + id + "_*"; |
| 903 | return RedisUtil.scan(redisTemplate, key).size(); | 602 | return RedisUtil.scan(redisTemplate, key).size(); |
| 904 | } | 603 | } |
| 604 | + | ||
| 605 | + @Override | ||
| 606 | + public void sendDeviceOrChannelStatus(String deviceId, String channelId, boolean online) { | ||
| 607 | + String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_DEVICE_STATUS; | ||
| 608 | + if (channelId == null) { | ||
| 609 | + logger.info("[redis通知] 推送设备状态, {}-{}", deviceId, online); | ||
| 610 | + }else { | ||
| 611 | + logger.info("[redis通知] 推送通道状态, {}/{}-{}", deviceId, channelId, online); | ||
| 612 | + } | ||
| 613 | + | ||
| 614 | + StringBuilder msg = new StringBuilder(); | ||
| 615 | + msg.append(deviceId); | ||
| 616 | + if (channelId != null) { | ||
| 617 | + msg.append(":").append(channelId); | ||
| 618 | + } | ||
| 619 | + msg.append(" ").append(online? "ON":"OFF"); | ||
| 620 | + // 使用 RedisTemplate<Object, Object> 发送字符串消息会导致发送的消息多带了双引号 | ||
| 621 | + stringRedisTemplate.convertAndSend(key, msg.toString()); | ||
| 622 | + } | ||
| 905 | } | 623 | } |
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
| @@ -177,10 +177,10 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -177,10 +177,10 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 177 | if (i + limitCount > channels.size()) { | 177 | if (i + limitCount > channels.size()) { |
| 178 | toIndex = channels.size(); | 178 | toIndex = channels.size(); |
| 179 | } | 179 | } |
| 180 | - result = result || deviceChannelMapper.batchAdd(channels.subList(i, toIndex)) < 0; | 180 | + result = result || deviceChannelMapper.batchAddOrUpdate(channels.subList(i, toIndex)) < 0; |
| 181 | } | 181 | } |
| 182 | }else { | 182 | }else { |
| 183 | - result = result || deviceChannelMapper.batchAdd(channels) < 0; | 183 | + result = result || deviceChannelMapper.batchAddOrUpdate(channels) < 0; |
| 184 | } | 184 | } |
| 185 | } | 185 | } |
| 186 | if (result) { | 186 | if (result) { |
| @@ -278,10 +278,10 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -278,10 +278,10 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 278 | if (i + limitCount > addChannels.size()) { | 278 | if (i + limitCount > addChannels.size()) { |
| 279 | toIndex = addChannels.size(); | 279 | toIndex = addChannels.size(); |
| 280 | } | 280 | } |
| 281 | - result = result || deviceChannelMapper.batchAdd(addChannels.subList(i, toIndex)) < 0; | 281 | + result = result || deviceChannelMapper.batchAddOrUpdate(addChannels.subList(i, toIndex)) < 0; |
| 282 | } | 282 | } |
| 283 | }else { | 283 | }else { |
| 284 | - result = result || deviceChannelMapper.batchAdd(addChannels) < 0; | 284 | + result = result || deviceChannelMapper.batchAddOrUpdate(addChannels) < 0; |
| 285 | } | 285 | } |
| 286 | } | 286 | } |
| 287 | if (updateChannels.size() > 0) { | 287 | if (updateChannels.size() > 0) { |
| @@ -434,9 +434,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -434,9 +434,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 434 | */ | 434 | */ |
| 435 | @Override | 435 | @Override |
| 436 | public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) { | 436 | public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) { |
| 437 | - if (mobilePosition.getDeviceId().equals(mobilePosition.getChannelId())) { | ||
| 438 | - mobilePosition.setChannelId(null); | ||
| 439 | - } | ||
| 440 | return deviceMobilePositionMapper.insertNewPosition(mobilePosition) > 0; | 437 | return deviceMobilePositionMapper.insertNewPosition(mobilePosition) > 0; |
| 441 | } | 438 | } |
| 442 | 439 |
src/main/java/com/genersoft/iot/vmp/utils/ConfigConst.java deleted
100644 → 0
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
| @@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | @@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | ||
| 14 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 14 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 15 | import com.genersoft.iot.vmp.service.IDeviceChannelService; | 15 | import com.genersoft.iot.vmp.service.IDeviceChannelService; |
| 16 | import com.genersoft.iot.vmp.service.IDeviceService; | 16 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 17 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | ||
| 17 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 18 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 18 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 19 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 19 | import com.genersoft.iot.vmp.vmanager.bean.BaseTree; | 20 | import com.genersoft.iot.vmp.vmanager.bean.BaseTree; |
| @@ -62,6 +63,9 @@ public class DeviceQuery { | @@ -62,6 +63,9 @@ public class DeviceQuery { | ||
| 62 | 63 | ||
| 63 | @Autowired | 64 | @Autowired |
| 64 | private IRedisCatchStorage redisCatchStorage; | 65 | private IRedisCatchStorage redisCatchStorage; |
| 66 | + | ||
| 67 | + @Autowired | ||
| 68 | + private IInviteStreamService inviteStreamService; | ||
| 65 | 69 | ||
| 66 | @Autowired | 70 | @Autowired |
| 67 | private SIPCommander cmder; | 71 | private SIPCommander cmder; |
| @@ -184,7 +188,7 @@ public class DeviceQuery { | @@ -184,7 +188,7 @@ public class DeviceQuery { | ||
| 184 | // 清除redis记录 | 188 | // 清除redis记录 |
| 185 | boolean isSuccess = deviceService.delete(deviceId); | 189 | boolean isSuccess = deviceService.delete(deviceId); |
| 186 | if (isSuccess) { | 190 | if (isSuccess) { |
| 187 | - redisCatchStorage.clearCatchByDeviceId(deviceId); | 191 | + inviteStreamService.clearInviteInfo(deviceId); |
| 188 | // 停止此设备的订阅更新 | 192 | // 停止此设备的订阅更新 |
| 189 | Set<String> allKeys = dynamicTask.getAllKeys(); | 193 | Set<String> allKeys = dynamicTask.getAllKeys(); |
| 190 | for (String key : allKeys) { | 194 | for (String key : allKeys) { |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
| @@ -2,6 +2,9 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play; | @@ -2,6 +2,9 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play; | ||
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSONArray; | 3 | import com.alibaba.fastjson2.JSONArray; |
| 4 | import com.alibaba.fastjson2.JSONObject; | 4 | import com.alibaba.fastjson2.JSONObject; |
| 5 | +import com.genersoft.iot.vmp.common.InviteInfo; | ||
| 6 | +import com.genersoft.iot.vmp.common.InviteSessionStatus; | ||
| 7 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 5 | import com.genersoft.iot.vmp.common.StreamInfo; | 8 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 6 | import com.genersoft.iot.vmp.conf.UserSetting; | 9 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 7 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 10 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| @@ -14,12 +17,17 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | @@ -14,12 +17,17 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | ||
| 14 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 17 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 15 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | 18 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 16 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 19 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 20 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | ||
| 17 | import com.genersoft.iot.vmp.service.IMediaServerService; | 21 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 18 | import com.genersoft.iot.vmp.service.IMediaService; | 22 | import com.genersoft.iot.vmp.service.IMediaService; |
| 19 | import com.genersoft.iot.vmp.service.IPlayService; | 23 | import com.genersoft.iot.vmp.service.IPlayService; |
| 24 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCode; | ||
| 20 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 25 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 21 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 26 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 22 | import com.genersoft.iot.vmp.vmanager.bean.*; | 27 | import com.genersoft.iot.vmp.vmanager.bean.*; |
| 28 | +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | ||
| 29 | +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | ||
| 30 | +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | ||
| 23 | import io.swagger.v3.oas.annotations.Operation; | 31 | import io.swagger.v3.oas.annotations.Operation; |
| 24 | import io.swagger.v3.oas.annotations.Parameter; | 32 | import io.swagger.v3.oas.annotations.Parameter; |
| 25 | import io.swagger.v3.oas.annotations.tags.Tag; | 33 | import io.swagger.v3.oas.annotations.tags.Tag; |
| @@ -61,6 +69,9 @@ public class PlayController { | @@ -61,6 +69,9 @@ public class PlayController { | ||
| 61 | private IRedisCatchStorage redisCatchStorage; | 69 | private IRedisCatchStorage redisCatchStorage; |
| 62 | 70 | ||
| 63 | @Autowired | 71 | @Autowired |
| 72 | + private IInviteStreamService inviteStreamService; | ||
| 73 | + | ||
| 74 | + @Autowired | ||
| 64 | private ZLMRESTfulUtils zlmresTfulUtils; | 75 | private ZLMRESTfulUtils zlmresTfulUtils; |
| 65 | 76 | ||
| 66 | @Autowired | 77 | @Autowired |
| @@ -89,14 +100,12 @@ public class PlayController { | @@ -89,14 +100,12 @@ public class PlayController { | ||
| 89 | Device device = storager.queryVideoDevice(deviceId); | 100 | Device device = storager.queryVideoDevice(deviceId); |
| 90 | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); | 101 | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| 91 | 102 | ||
| 92 | - RequestMessage msg = new RequestMessage(); | 103 | + RequestMessage requestMessage = new RequestMessage(); |
| 93 | String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; | 104 | String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; |
| 94 | - boolean exist = resultHolder.exist(key, null); | ||
| 95 | - msg.setKey(key); | 105 | + requestMessage.setKey(key); |
| 96 | String uuid = UUID.randomUUID().toString(); | 106 | String uuid = UUID.randomUUID().toString(); |
| 97 | - msg.setId(uuid); | 107 | + requestMessage.setId(uuid); |
| 98 | DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); | 108 | DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); |
| 99 | - DeferredResultEx<WVPResult<StreamContent>> deferredResultEx = new DeferredResultEx<>(result); | ||
| 100 | 109 | ||
| 101 | result.onTimeout(()->{ | 110 | result.onTimeout(()->{ |
| 102 | logger.info("点播接口等待超时"); | 111 | logger.info("点播接口等待超时"); |
| @@ -104,32 +113,33 @@ public class PlayController { | @@ -104,32 +113,33 @@ public class PlayController { | ||
| 104 | WVPResult<StreamInfo> wvpResult = new WVPResult<>(); | 113 | WVPResult<StreamInfo> wvpResult = new WVPResult<>(); |
| 105 | wvpResult.setCode(ErrorCode.ERROR100.getCode()); | 114 | wvpResult.setCode(ErrorCode.ERROR100.getCode()); |
| 106 | wvpResult.setMsg("点播超时"); | 115 | wvpResult.setMsg("点播超时"); |
| 107 | - msg.setData(wvpResult); | ||
| 108 | - resultHolder.invokeResult(msg); | ||
| 109 | - }); | ||
| 110 | - // TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误 | ||
| 111 | - deferredResultEx.setFilter(result1 -> { | ||
| 112 | - WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>)result1; | ||
| 113 | - WVPResult<StreamContent> resultStream = new WVPResult<>(); | ||
| 114 | - resultStream.setCode(wvpResult1.getCode()); | ||
| 115 | - resultStream.setMsg(wvpResult1.getMsg()); | ||
| 116 | - if (wvpResult1.getCode() == ErrorCode.SUCCESS.getCode()) { | ||
| 117 | - StreamInfo data = wvpResult1.getData().clone(); | ||
| 118 | - if (userSetting.getUseSourceIpAsStreamIp()) { | ||
| 119 | - data.channgeStreamIp(request.getLocalName()); | ||
| 120 | - } | ||
| 121 | - resultStream.setData(new StreamContent(wvpResult1.getData())); | ||
| 122 | - } | ||
| 123 | - return resultStream; | 116 | + requestMessage.setData(wvpResult); |
| 117 | + resultHolder.invokeResult(requestMessage); | ||
| 124 | }); | 118 | }); |
| 125 | 119 | ||
| 126 | - | ||
| 127 | // 录像查询以channelId作为deviceId查询 | 120 | // 录像查询以channelId作为deviceId查询 |
| 128 | - resultHolder.put(key, uuid, deferredResultEx); | 121 | + resultHolder.put(key, uuid, result); |
| 129 | 122 | ||
| 130 | - if (!exist) { | ||
| 131 | - playService.play(newMediaServerItem, deviceId, channelId, null, null, null); | ||
| 132 | - } | 123 | + playService.play(newMediaServerItem, deviceId, channelId, (code, msg, data) -> { |
| 124 | + WVPResult<StreamContent> wvpResult = new WVPResult<>(); | ||
| 125 | + if (code == InviteErrorCode.SUCCESS.getCode()) { | ||
| 126 | + wvpResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 127 | + wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 128 | + | ||
| 129 | + if (data != null) { | ||
| 130 | + StreamInfo streamInfo = (StreamInfo)data; | ||
| 131 | + if (userSetting.getUseSourceIpAsStreamIp()) { | ||
| 132 | + streamInfo.channgeStreamIp(request.getLocalName()); | ||
| 133 | + } | ||
| 134 | + wvpResult.setData(new StreamContent(streamInfo)); | ||
| 135 | + } | ||
| 136 | + }else { | ||
| 137 | + wvpResult.setCode(code); | ||
| 138 | + wvpResult.setMsg(msg); | ||
| 139 | + } | ||
| 140 | + requestMessage.setData(wvpResult); | ||
| 141 | + resultHolder.invokeResult(requestMessage); | ||
| 142 | + }); | ||
| 133 | return result; | 143 | return result; |
| 134 | } | 144 | } |
| 135 | 145 | ||
| @@ -150,21 +160,22 @@ public class PlayController { | @@ -150,21 +160,22 @@ public class PlayController { | ||
| 150 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备[" + deviceId + "]不存在"); | 160 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备[" + deviceId + "]不存在"); |
| 151 | } | 161 | } |
| 152 | 162 | ||
| 153 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); | ||
| 154 | - if (streamInfo == null) { | 163 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| 164 | + if (inviteInfo == null) { | ||
| 155 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到"); | 165 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到"); |
| 156 | } | 166 | } |
| 157 | - | ||
| 158 | - try { | ||
| 159 | - logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId); | ||
| 160 | - cmder.streamByeCmd(device, channelId, streamInfo.getStream(), null, null); | ||
| 161 | - } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { | ||
| 162 | - logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage()); | ||
| 163 | - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | 167 | + if (InviteSessionStatus.ok == inviteInfo.getStatus()) { |
| 168 | + try { | ||
| 169 | + logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId); | ||
| 170 | + cmder.streamByeCmd(device, channelId, inviteInfo.getStream(), null, null); | ||
| 171 | + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { | ||
| 172 | + logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage()); | ||
| 173 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | ||
| 174 | + } | ||
| 164 | } | 175 | } |
| 165 | - redisCatchStorage.stopPlay(streamInfo); | 176 | + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| 166 | 177 | ||
| 167 | - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); | 178 | + storager.stopPlay(deviceId, channelId); |
| 168 | JSONObject json = new JSONObject(); | 179 | JSONObject json = new JSONObject(); |
| 169 | json.put("deviceId", deviceId); | 180 | json.put("deviceId", deviceId); |
| 170 | json.put("channelId", channelId); | 181 | json.put("channelId", channelId); |
| @@ -179,15 +190,14 @@ public class PlayController { | @@ -179,15 +190,14 @@ public class PlayController { | ||
| 179 | @Parameter(name = "streamId", description = "视频流ID", required = true) | 190 | @Parameter(name = "streamId", description = "视频流ID", required = true) |
| 180 | @PostMapping("/convert/{streamId}") | 191 | @PostMapping("/convert/{streamId}") |
| 181 | public JSONObject playConvert(@PathVariable String streamId) { | 192 | public JSONObject playConvert(@PathVariable String streamId) { |
| 182 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); | ||
| 183 | - if (streamInfo == null) { | ||
| 184 | - streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); | ||
| 185 | - } | ||
| 186 | - if (streamInfo == null) { | 193 | +// StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); |
| 194 | + | ||
| 195 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, streamId); | ||
| 196 | + if (inviteInfo == null || inviteInfo.getStreamInfo() == null) { | ||
| 187 | logger.warn("视频转码API调用失败!, 视频流已经停止!"); | 197 | logger.warn("视频转码API调用失败!, 视频流已经停止!"); |
| 188 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到视频流信息, 视频流可能已经停止"); | 198 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到视频流信息, 视频流可能已经停止"); |
| 189 | } | 199 | } |
| 190 | - MediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId()); | 200 | + MediaServerItem mediaInfo = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); |
| 191 | JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); | 201 | JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); |
| 192 | if (!rtpInfo.getBoolean("exist")) { | 202 | if (!rtpInfo.getBoolean("exist")) { |
| 193 | logger.warn("视频转码API调用失败!, 视频流已停止推流!"); | 203 | logger.warn("视频转码API调用失败!, 视频流已停止推流!"); |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
| 1 | package com.genersoft.iot.vmp.vmanager.gb28181.playback; | 1 | package com.genersoft.iot.vmp.vmanager.gb28181.playback; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.common.InviteInfo; | ||
| 4 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 3 | import com.genersoft.iot.vmp.common.StreamInfo; | 5 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | import com.genersoft.iot.vmp.conf.UserSetting; | 6 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 5 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 7 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 6 | import com.genersoft.iot.vmp.conf.exception.ServiceException; | 8 | import com.genersoft.iot.vmp.conf.exception.ServiceException; |
| 7 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 9 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 10 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 8 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | 11 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 9 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | 12 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| 13 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 10 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 14 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 11 | -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 15 | +import com.genersoft.iot.vmp.service.IInviteStreamService; |
| 12 | import com.genersoft.iot.vmp.service.IPlayService; | 16 | import com.genersoft.iot.vmp.service.IPlayService; |
| 17 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCode; | ||
| 18 | +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | ||
| 19 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | ||
| 13 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 20 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 14 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | 21 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; |
| 15 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | 22 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| @@ -20,17 +27,13 @@ import org.slf4j.Logger; | @@ -20,17 +27,13 @@ import org.slf4j.Logger; | ||
| 20 | import org.slf4j.LoggerFactory; | 27 | import org.slf4j.LoggerFactory; |
| 21 | import org.springframework.beans.factory.annotation.Autowired; | 28 | import org.springframework.beans.factory.annotation.Autowired; |
| 22 | import org.springframework.util.ObjectUtils; | 29 | import org.springframework.util.ObjectUtils; |
| 23 | -import org.springframework.web.bind.annotation.CrossOrigin; | ||
| 24 | import org.springframework.web.bind.annotation.GetMapping; | 30 | import org.springframework.web.bind.annotation.GetMapping; |
| 25 | import org.springframework.web.bind.annotation.PathVariable; | 31 | import org.springframework.web.bind.annotation.PathVariable; |
| 26 | import org.springframework.web.bind.annotation.RequestMapping; | 32 | import org.springframework.web.bind.annotation.RequestMapping; |
| 27 | import org.springframework.web.bind.annotation.RestController; | 33 | import org.springframework.web.bind.annotation.RestController; |
| 28 | - | ||
| 29 | -import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 30 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 31 | -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | ||
| 32 | import org.springframework.web.context.request.async.DeferredResult; | 34 | import org.springframework.web.context.request.async.DeferredResult; |
| 33 | 35 | ||
| 36 | +import javax.servlet.http.HttpServletRequest; | ||
| 34 | import javax.sip.InvalidArgumentException; | 37 | import javax.sip.InvalidArgumentException; |
| 35 | import javax.sip.SipException; | 38 | import javax.sip.SipException; |
| 36 | import java.text.ParseException; | 39 | import java.text.ParseException; |
| @@ -60,6 +63,9 @@ public class PlaybackController { | @@ -60,6 +63,9 @@ public class PlaybackController { | ||
| 60 | private IRedisCatchStorage redisCatchStorage; | 63 | private IRedisCatchStorage redisCatchStorage; |
| 61 | 64 | ||
| 62 | @Autowired | 65 | @Autowired |
| 66 | + private IInviteStreamService inviteStreamService; | ||
| 67 | + | ||
| 68 | + @Autowired | ||
| 63 | private IPlayService playService; | 69 | private IPlayService playService; |
| 64 | 70 | ||
| 65 | @Autowired | 71 | @Autowired |
| @@ -74,8 +80,8 @@ public class PlaybackController { | @@ -74,8 +80,8 @@ public class PlaybackController { | ||
| 74 | @Parameter(name = "startTime", description = "开始时间", required = true) | 80 | @Parameter(name = "startTime", description = "开始时间", required = true) |
| 75 | @Parameter(name = "endTime", description = "结束时间", required = true) | 81 | @Parameter(name = "endTime", description = "结束时间", required = true) |
| 76 | @GetMapping("/start/{deviceId}/{channelId}") | 82 | @GetMapping("/start/{deviceId}/{channelId}") |
| 77 | - public DeferredResult<WVPResult<StreamContent>> start(@PathVariable String deviceId, @PathVariable String channelId, | ||
| 78 | - String startTime, String endTime) { | 83 | + public DeferredResult<WVPResult<StreamContent>> start(HttpServletRequest request, @PathVariable String deviceId, @PathVariable String channelId, |
| 84 | + String startTime, String endTime) { | ||
| 79 | 85 | ||
| 80 | if (logger.isDebugEnabled()) { | 86 | if (logger.isDebugEnabled()) { |
| 81 | logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId)); | 87 | logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId)); |
| @@ -86,22 +92,31 @@ public class PlaybackController { | @@ -86,22 +92,31 @@ public class PlaybackController { | ||
| 86 | DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); | 92 | DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); |
| 87 | resultHolder.put(key, uuid, result); | 93 | resultHolder.put(key, uuid, result); |
| 88 | 94 | ||
| 89 | - WVPResult<StreamContent> wvpResult = new WVPResult<>(); | ||
| 90 | - | ||
| 91 | - RequestMessage msg = new RequestMessage(); | ||
| 92 | - msg.setKey(key); | ||
| 93 | - msg.setId(uuid); | ||
| 94 | - | ||
| 95 | - playService.playBack(deviceId, channelId, startTime, endTime, null, | ||
| 96 | - playBackResult->{ | ||
| 97 | - wvpResult.setCode(playBackResult.getCode()); | ||
| 98 | - wvpResult.setMsg(playBackResult.getMsg()); | ||
| 99 | - if (playBackResult.getCode() == ErrorCode.SUCCESS.getCode()) { | ||
| 100 | - StreamInfo streamInfo = (StreamInfo)playBackResult.getData(); | ||
| 101 | - wvpResult.setData(new StreamContent(streamInfo)); | 95 | + RequestMessage requestMessage = new RequestMessage(); |
| 96 | + requestMessage.setKey(key); | ||
| 97 | + requestMessage.setId(uuid); | ||
| 98 | + | ||
| 99 | + playService.playBack(deviceId, channelId, startTime, endTime, | ||
| 100 | + (code, msg, data)->{ | ||
| 101 | + | ||
| 102 | + WVPResult<StreamContent> wvpResult = new WVPResult<>(); | ||
| 103 | + if (code == InviteErrorCode.SUCCESS.getCode()) { | ||
| 104 | + wvpResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 105 | + wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 106 | + | ||
| 107 | + if (data != null) { | ||
| 108 | + StreamInfo streamInfo = (StreamInfo)data; | ||
| 109 | + if (userSetting.getUseSourceIpAsStreamIp()) { | ||
| 110 | + streamInfo.channgeStreamIp(request.getLocalName()); | ||
| 111 | + } | ||
| 112 | + wvpResult.setData(new StreamContent(streamInfo)); | ||
| 113 | + } | ||
| 114 | + }else { | ||
| 115 | + wvpResult.setCode(code); | ||
| 116 | + wvpResult.setMsg(msg); | ||
| 102 | } | 117 | } |
| 103 | - msg.setData(wvpResult); | ||
| 104 | - resultHolder.invokeResult(msg); | 118 | + requestMessage.setData(wvpResult); |
| 119 | + resultHolder.invokeResult(requestMessage); | ||
| 105 | }); | 120 | }); |
| 106 | 121 | ||
| 107 | return result; | 122 | return result; |
| @@ -169,14 +184,15 @@ public class PlaybackController { | @@ -169,14 +184,15 @@ public class PlaybackController { | ||
| 169 | @GetMapping("/seek/{streamId}/{seekTime}") | 184 | @GetMapping("/seek/{streamId}/{seekTime}") |
| 170 | public void playSeek(@PathVariable String streamId, @PathVariable long seekTime) { | 185 | public void playSeek(@PathVariable String streamId, @PathVariable long seekTime) { |
| 171 | logger.info("playSeek: "+streamId+", "+seekTime); | 186 | logger.info("playSeek: "+streamId+", "+seekTime); |
| 172 | - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); | ||
| 173 | - if (null == streamInfo) { | 187 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); |
| 188 | + | ||
| 189 | + if (null == inviteInfo || inviteInfo.getStreamInfo() == null) { | ||
| 174 | logger.warn("streamId不存在!"); | 190 | logger.warn("streamId不存在!"); |
| 175 | throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在"); | 191 | throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在"); |
| 176 | } | 192 | } |
| 177 | - Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); | 193 | + Device device = storager.queryVideoDevice(inviteInfo.getDeviceId()); |
| 178 | try { | 194 | try { |
| 179 | - cmder.playSeekCmd(device, streamInfo, seekTime); | 195 | + cmder.playSeekCmd(device, inviteInfo.getStreamInfo(), seekTime); |
| 180 | } catch (InvalidArgumentException | ParseException | SipException e) { | 196 | } catch (InvalidArgumentException | ParseException | SipException e) { |
| 181 | throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage()); | 197 | throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage()); |
| 182 | } | 198 | } |
| @@ -188,8 +204,9 @@ public class PlaybackController { | @@ -188,8 +204,9 @@ public class PlaybackController { | ||
| 188 | @GetMapping("/speed/{streamId}/{speed}") | 204 | @GetMapping("/speed/{streamId}/{speed}") |
| 189 | public void playSpeed(@PathVariable String streamId, @PathVariable Double speed) { | 205 | public void playSpeed(@PathVariable String streamId, @PathVariable Double speed) { |
| 190 | logger.info("playSpeed: "+streamId+", "+speed); | 206 | logger.info("playSpeed: "+streamId+", "+speed); |
| 191 | - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); | ||
| 192 | - if (null == streamInfo) { | 207 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); |
| 208 | + | ||
| 209 | + if (null == inviteInfo || inviteInfo.getStreamInfo() == null) { | ||
| 193 | logger.warn("streamId不存在!"); | 210 | logger.warn("streamId不存在!"); |
| 194 | throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在"); | 211 | throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在"); |
| 195 | } | 212 | } |
| @@ -197,9 +214,9 @@ public class PlaybackController { | @@ -197,9 +214,9 @@ public class PlaybackController { | ||
| 197 | logger.warn("不支持的speed: " + speed); | 214 | logger.warn("不支持的speed: " + speed); |
| 198 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed(0.25 0.5 1、2、4)"); | 215 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed(0.25 0.5 1、2、4)"); |
| 199 | } | 216 | } |
| 200 | - Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); | 217 | + Device device = storager.queryVideoDevice(inviteInfo.getDeviceId()); |
| 201 | try { | 218 | try { |
| 202 | - cmder.playSpeedCmd(device, streamInfo, speed); | 219 | + cmder.playSpeedCmd(device, inviteInfo.getStreamInfo(), speed); |
| 203 | } catch (InvalidArgumentException | ParseException | SipException e) { | 220 | } catch (InvalidArgumentException | ParseException | SipException e) { |
| 204 | throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage()); | 221 | throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage()); |
| 205 | } | 222 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
| 1 | package com.genersoft.iot.vmp.vmanager.gb28181.record; | 1 | package com.genersoft.iot.vmp.vmanager.gb28181.record; |
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.common.StreamInfo; | 3 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | +import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 4 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 5 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 5 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 6 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 6 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 7 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| @@ -10,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | @@ -10,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | ||
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 11 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 11 | import com.genersoft.iot.vmp.service.IDeviceService; | 12 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 12 | import com.genersoft.iot.vmp.service.IPlayService; | 13 | import com.genersoft.iot.vmp.service.IPlayService; |
| 14 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCode; | ||
| 13 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 15 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 14 | import com.genersoft.iot.vmp.utils.DateUtil; | 16 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 15 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 17 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| @@ -27,6 +29,7 @@ import org.springframework.web.bind.annotation.RequestMapping; | @@ -27,6 +29,7 @@ import org.springframework.web.bind.annotation.RequestMapping; | ||
| 27 | import org.springframework.web.bind.annotation.RestController; | 29 | import org.springframework.web.bind.annotation.RestController; |
| 28 | import org.springframework.web.context.request.async.DeferredResult; | 30 | import org.springframework.web.context.request.async.DeferredResult; |
| 29 | 31 | ||
| 32 | +import javax.servlet.http.HttpServletRequest; | ||
| 30 | import javax.sip.InvalidArgumentException; | 33 | import javax.sip.InvalidArgumentException; |
| 31 | import javax.sip.SipException; | 34 | import javax.sip.SipException; |
| 32 | import java.text.ParseException; | 35 | import java.text.ParseException; |
| @@ -55,8 +58,8 @@ public class GBRecordController { | @@ -55,8 +58,8 @@ public class GBRecordController { | ||
| 55 | @Autowired | 58 | @Autowired |
| 56 | private IDeviceService deviceService; | 59 | private IDeviceService deviceService; |
| 57 | 60 | ||
| 58 | - | ||
| 59 | - | 61 | + @Autowired |
| 62 | + private UserSetting userSetting; | ||
| 60 | 63 | ||
| 61 | @Operation(summary = "录像查询") | 64 | @Operation(summary = "录像查询") |
| 62 | @Parameter(name = "deviceId", description = "设备国标编号", required = true) | 65 | @Parameter(name = "deviceId", description = "设备国标编号", required = true) |
| @@ -119,8 +122,8 @@ public class GBRecordController { | @@ -119,8 +122,8 @@ public class GBRecordController { | ||
| 119 | @Parameter(name = "endTime", description = "结束时间", required = true) | 122 | @Parameter(name = "endTime", description = "结束时间", required = true) |
| 120 | @Parameter(name = "downloadSpeed", description = "下载倍速", required = true) | 123 | @Parameter(name = "downloadSpeed", description = "下载倍速", required = true) |
| 121 | @GetMapping("/download/start/{deviceId}/{channelId}") | 124 | @GetMapping("/download/start/{deviceId}/{channelId}") |
| 122 | - public DeferredResult<WVPResult<StreamContent>> download(@PathVariable String deviceId, @PathVariable String channelId, | ||
| 123 | - String startTime, String endTime, String downloadSpeed) { | 125 | + public DeferredResult<WVPResult<StreamContent>> download(HttpServletRequest request, @PathVariable String deviceId, @PathVariable String channelId, |
| 126 | + String startTime, String endTime, String downloadSpeed) { | ||
| 124 | 127 | ||
| 125 | if (logger.isDebugEnabled()) { | 128 | if (logger.isDebugEnabled()) { |
| 126 | logger.debug(String.format("历史媒体下载 API调用,deviceId:%s,channelId:%s,downloadSpeed:%s", deviceId, channelId, downloadSpeed)); | 129 | logger.debug(String.format("历史媒体下载 API调用,deviceId:%s,channelId:%s,downloadSpeed:%s", deviceId, channelId, downloadSpeed)); |
| @@ -130,22 +133,32 @@ public class GBRecordController { | @@ -130,22 +133,32 @@ public class GBRecordController { | ||
| 130 | String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId; | 133 | String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId; |
| 131 | DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(30000L); | 134 | DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(30000L); |
| 132 | resultHolder.put(key, uuid, result); | 135 | resultHolder.put(key, uuid, result); |
| 133 | - RequestMessage msg = new RequestMessage(); | ||
| 134 | - msg.setId(uuid); | ||
| 135 | - msg.setKey(key); | ||
| 136 | - | ||
| 137 | - WVPResult<StreamContent> wvpResult = new WVPResult<>(); | ||
| 138 | - | ||
| 139 | - playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed), null, playBackResult->{ | ||
| 140 | - | ||
| 141 | - wvpResult.setCode(playBackResult.getCode()); | ||
| 142 | - wvpResult.setMsg(playBackResult.getMsg()); | ||
| 143 | - if (playBackResult.getCode() == ErrorCode.SUCCESS.getCode()) { | ||
| 144 | - StreamInfo streamInfo = (StreamInfo)playBackResult.getData(); | ||
| 145 | - wvpResult.setData(new StreamContent(streamInfo)); | 136 | + RequestMessage requestMessage = new RequestMessage(); |
| 137 | + requestMessage.setId(uuid); | ||
| 138 | + requestMessage.setKey(key); | ||
| 139 | + | ||
| 140 | + | ||
| 141 | + playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed), | ||
| 142 | + (code, msg, data)->{ | ||
| 143 | + | ||
| 144 | + WVPResult<StreamContent> wvpResult = new WVPResult<>(); | ||
| 145 | + if (code == InviteErrorCode.SUCCESS.getCode()) { | ||
| 146 | + wvpResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 147 | + wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 148 | + | ||
| 149 | + if (data != null) { | ||
| 150 | + StreamInfo streamInfo = (StreamInfo)data; | ||
| 151 | + if (userSetting.getUseSourceIpAsStreamIp()) { | ||
| 152 | + streamInfo.channgeStreamIp(request.getLocalName()); | ||
| 153 | + } | ||
| 154 | + wvpResult.setData(new StreamContent(streamInfo)); | ||
| 155 | + } | ||
| 156 | + }else { | ||
| 157 | + wvpResult.setCode(code); | ||
| 158 | + wvpResult.setMsg(msg); | ||
| 146 | } | 159 | } |
| 147 | - msg.setData(wvpResult); | ||
| 148 | - resultHolder.invokeResult(msg); | 160 | + requestMessage.setData(wvpResult); |
| 161 | + resultHolder.invokeResult(requestMessage); | ||
| 149 | }); | 162 | }); |
| 150 | 163 | ||
| 151 | return result; | 164 | return result; |
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
| @@ -57,7 +57,7 @@ public class UserController { | @@ -57,7 +57,7 @@ public class UserController { | ||
| 57 | if (user == null) { | 57 | if (user == null) { |
| 58 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "用户名或密码错误"); | 58 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "用户名或密码错误"); |
| 59 | }else { | 59 | }else { |
| 60 | - String jwt = JwtUtils.createToken(username, password); | 60 | + String jwt = JwtUtils.createToken(username, password, user.getRole().getId()); |
| 61 | response.setHeader(JwtUtils.getHeader(), jwt); | 61 | response.setHeader(JwtUtils.getHeader(), jwt); |
| 62 | user.setAccessToken(jwt); | 62 | user.setAccessToken(jwt); |
| 63 | } | 63 | } |
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java
| 1 | package com.genersoft.iot.vmp.web.gb28181; | 1 | package com.genersoft.iot.vmp.web.gb28181; |
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSONObject; | 3 | import com.alibaba.fastjson2.JSONObject; |
| 4 | -import com.genersoft.iot.vmp.common.StreamInfo; | 4 | +import com.genersoft.iot.vmp.common.InviteInfo; |
| 5 | +import com.genersoft.iot.vmp.common.InviteSessionType; | ||
| 5 | import com.genersoft.iot.vmp.conf.UserSetting; | 6 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 6 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 7 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 7 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 8 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| @@ -9,13 +10,18 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | @@ -9,13 +10,18 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | ||
| 9 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 10 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 10 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 11 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 11 | import com.genersoft.iot.vmp.service.IDeviceService; | 12 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 13 | +import com.genersoft.iot.vmp.service.IInviteStreamService; | ||
| 12 | import com.genersoft.iot.vmp.service.IPlayService; | 14 | import com.genersoft.iot.vmp.service.IPlayService; |
| 15 | +import com.genersoft.iot.vmp.service.bean.InviteErrorCode; | ||
| 13 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 16 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 14 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 17 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 15 | import org.slf4j.Logger; | 18 | import org.slf4j.Logger; |
| 16 | import org.slf4j.LoggerFactory; | 19 | import org.slf4j.LoggerFactory; |
| 17 | import org.springframework.beans.factory.annotation.Autowired; | 20 | import org.springframework.beans.factory.annotation.Autowired; |
| 18 | -import org.springframework.web.bind.annotation.*; | 21 | +import org.springframework.web.bind.annotation.RequestMapping; |
| 22 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 23 | +import org.springframework.web.bind.annotation.ResponseBody; | ||
| 24 | +import org.springframework.web.bind.annotation.RestController; | ||
| 19 | import org.springframework.web.context.request.async.DeferredResult; | 25 | import org.springframework.web.context.request.async.DeferredResult; |
| 20 | 26 | ||
| 21 | import javax.sip.InvalidArgumentException; | 27 | import javax.sip.InvalidArgumentException; |
| @@ -46,6 +52,9 @@ public class ApiStreamController { | @@ -46,6 +52,9 @@ public class ApiStreamController { | ||
| 46 | private IRedisCatchStorage redisCatchStorage; | 52 | private IRedisCatchStorage redisCatchStorage; |
| 47 | 53 | ||
| 48 | @Autowired | 54 | @Autowired |
| 55 | + private IInviteStreamService inviteStreamService; | ||
| 56 | + | ||
| 57 | + @Autowired | ||
| 49 | private IDeviceService deviceService; | 58 | private IDeviceService deviceService; |
| 50 | 59 | ||
| 51 | @Autowired | 60 | @Autowired |
| @@ -111,46 +120,53 @@ public class ApiStreamController { | @@ -111,46 +120,53 @@ public class ApiStreamController { | ||
| 111 | return resultDeferredResult; | 120 | return resultDeferredResult; |
| 112 | } | 121 | } |
| 113 | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); | 122 | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| 114 | - playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{ | ||
| 115 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code); | ||
| 116 | - JSONObject result = new JSONObject(); | ||
| 117 | - result.put("StreamID", streamInfo.getStream()); | ||
| 118 | - result.put("DeviceID", device.getDeviceId()); | ||
| 119 | - result.put("ChannelID", code); | ||
| 120 | - result.put("ChannelName", deviceChannel.getName()); | ||
| 121 | - result.put("ChannelCustomName", ""); | ||
| 122 | - result.put("FLV", streamInfo.getFlv().getUrl()); | ||
| 123 | - result.put("WS_FLV", streamInfo.getWs_flv().getUrl()); | ||
| 124 | - result.put("RTMP", streamInfo.getRtmp().getUrl()); | ||
| 125 | - result.put("HLS", streamInfo.getHls().getUrl()); | ||
| 126 | - result.put("RTSP", streamInfo.getRtsp().getUrl()); | ||
| 127 | - result.put("WEBRTC", streamInfo.getRtc().getUrl()); | ||
| 128 | - result.put("CDN", ""); | ||
| 129 | - result.put("SnapURL", ""); | ||
| 130 | - result.put("Transport", device.getTransport()); | ||
| 131 | - result.put("StartAt", ""); | ||
| 132 | - result.put("Duration", ""); | ||
| 133 | - result.put("SourceVideoCodecName", ""); | ||
| 134 | - result.put("SourceVideoWidth", ""); | ||
| 135 | - result.put("SourceVideoHeight", ""); | ||
| 136 | - result.put("SourceVideoFrameRate", ""); | ||
| 137 | - result.put("SourceAudioCodecName", ""); | ||
| 138 | - result.put("SourceAudioSampleRate", ""); | ||
| 139 | - result.put("AudioEnable", ""); | ||
| 140 | - result.put("Ondemand", ""); | ||
| 141 | - result.put("InBytes", ""); | ||
| 142 | - result.put("InBitRate", ""); | ||
| 143 | - result.put("OutBytes", ""); | ||
| 144 | - result.put("NumOutputs", ""); | ||
| 145 | - result.put("CascadeSize", ""); | ||
| 146 | - result.put("RelaySize", ""); | ||
| 147 | - result.put("ChannelPTZType", "0"); | ||
| 148 | - resultDeferredResult.setResult(result); | ||
| 149 | - }, (eventResult) -> { | ||
| 150 | - JSONObject result = new JSONObject(); | ||
| 151 | - result.put("error", "channel[ " + code + " ] " + eventResult.msg); | ||
| 152 | - resultDeferredResult.setResult(result); | ||
| 153 | - }, null); | 123 | + |
| 124 | + | ||
| 125 | + playService.play(newMediaServerItem, serial, code, (errorCode, msg, data) -> { | ||
| 126 | + if (errorCode == InviteErrorCode.SUCCESS.getCode()) { | ||
| 127 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, serial, code); | ||
| 128 | + if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { | ||
| 129 | + JSONObject result = new JSONObject(); | ||
| 130 | + result.put("StreamID", inviteInfo.getStreamInfo().getStream()); | ||
| 131 | + result.put("DeviceID", device.getDeviceId()); | ||
| 132 | + result.put("ChannelID", code); | ||
| 133 | + result.put("ChannelName", deviceChannel.getName()); | ||
| 134 | + result.put("ChannelCustomName", ""); | ||
| 135 | + result.put("FLV", inviteInfo.getStreamInfo().getFlv().getUrl()); | ||
| 136 | + result.put("WS_FLV", inviteInfo.getStreamInfo().getWs_flv().getUrl()); | ||
| 137 | + result.put("RTMP", inviteInfo.getStreamInfo().getRtmp().getUrl()); | ||
| 138 | + result.put("HLS", inviteInfo.getStreamInfo().getHls().getUrl()); | ||
| 139 | + result.put("RTSP", inviteInfo.getStreamInfo().getRtsp().getUrl()); | ||
| 140 | + result.put("WEBRTC", inviteInfo.getStreamInfo().getRtc().getUrl()); | ||
| 141 | + result.put("CDN", ""); | ||
| 142 | + result.put("SnapURL", ""); | ||
| 143 | + result.put("Transport", device.getTransport()); | ||
| 144 | + result.put("StartAt", ""); | ||
| 145 | + result.put("Duration", ""); | ||
| 146 | + result.put("SourceVideoCodecName", ""); | ||
| 147 | + result.put("SourceVideoWidth", ""); | ||
| 148 | + result.put("SourceVideoHeight", ""); | ||
| 149 | + result.put("SourceVideoFrameRate", ""); | ||
| 150 | + result.put("SourceAudioCodecName", ""); | ||
| 151 | + result.put("SourceAudioSampleRate", ""); | ||
| 152 | + result.put("AudioEnable", ""); | ||
| 153 | + result.put("Ondemand", ""); | ||
| 154 | + result.put("InBytes", ""); | ||
| 155 | + result.put("InBitRate", ""); | ||
| 156 | + result.put("OutBytes", ""); | ||
| 157 | + result.put("NumOutputs", ""); | ||
| 158 | + result.put("CascadeSize", ""); | ||
| 159 | + result.put("RelaySize", ""); | ||
| 160 | + result.put("ChannelPTZType", "0"); | ||
| 161 | + resultDeferredResult.setResult(result); | ||
| 162 | + } | ||
| 163 | + }else { | ||
| 164 | + JSONObject result = new JSONObject(); | ||
| 165 | + result.put("error", "channel[ " + code + " ] " + msg); | ||
| 166 | + resultDeferredResult.setResult(result); | ||
| 167 | + } | ||
| 168 | + }); | ||
| 169 | + | ||
| 154 | return resultDeferredResult; | 170 | return resultDeferredResult; |
| 155 | } | 171 | } |
| 156 | 172 | ||
| @@ -171,8 +187,8 @@ public class ApiStreamController { | @@ -171,8 +187,8 @@ public class ApiStreamController { | ||
| 171 | 187 | ||
| 172 | ){ | 188 | ){ |
| 173 | 189 | ||
| 174 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code); | ||
| 175 | - if (streamInfo == null) { | 190 | + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, serial, code); |
| 191 | + if (inviteInfo == null) { | ||
| 176 | JSONObject result = new JSONObject(); | 192 | JSONObject result = new JSONObject(); |
| 177 | result.put("error","未找到流信息"); | 193 | result.put("error","未找到流信息"); |
| 178 | return result; | 194 | return result; |
| @@ -184,14 +200,14 @@ public class ApiStreamController { | @@ -184,14 +200,14 @@ public class ApiStreamController { | ||
| 184 | return result; | 200 | return result; |
| 185 | } | 201 | } |
| 186 | try { | 202 | try { |
| 187 | - cmder.streamByeCmd(device, code, streamInfo.getStream(), null); | ||
| 188 | - } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | 203 | + cmder.streamByeCmd(device, code, inviteInfo.getStream(), null); |
| 204 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | ||
| 189 | JSONObject result = new JSONObject(); | 205 | JSONObject result = new JSONObject(); |
| 190 | result.put("error","发送BYE失败:" + e.getMessage()); | 206 | result.put("error","发送BYE失败:" + e.getMessage()); |
| 191 | return result; | 207 | return result; |
| 192 | } | 208 | } |
| 193 | - redisCatchStorage.stopPlay(streamInfo); | ||
| 194 | - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); | 209 | + inviteStreamService.removeInviteInfo(inviteInfo); |
| 210 | + storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); | ||
| 195 | return null; | 211 | return null; |
| 196 | } | 212 | } |
| 197 | 213 |
src/main/resources/all-application.yml
| @@ -65,8 +65,11 @@ server: | @@ -65,8 +65,11 @@ server: | ||
| 65 | 65 | ||
| 66 | # 作为28181服务器的配置 | 66 | # 作为28181服务器的配置 |
| 67 | sip: | 67 | sip: |
| 68 | - # [必须修改] 本机的IP | ||
| 69 | - ip: 192.168.0.100 | 68 | + # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡, |
| 69 | + # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4 | ||
| 70 | + # 如果不明白,就使用0.0.0.0,大部分情况都是可以的 | ||
| 71 | + # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。 | ||
| 72 | + ip: 0.0.0.0 | ||
| 70 | # [可选] 没有任何业务需求,仅仅是在前端展示的时候用 | 73 | # [可选] 没有任何业务需求,仅仅是在前端展示的时候用 |
| 71 | show-ip: 192.168.0.100 | 74 | show-ip: 192.168.0.100 |
| 72 | # [可选] 28181服务监听的端口 | 75 | # [可选] 28181服务监听的端口 |
| @@ -89,6 +92,15 @@ sip: | @@ -89,6 +92,15 @@ sip: | ||
| 89 | # 是否存储alarm信息 | 92 | # 是否存储alarm信息 |
| 90 | alarm: false | 93 | alarm: false |
| 91 | 94 | ||
| 95 | +# 做为JT1078服务器的配置 | ||
| 96 | +jt1078: | ||
| 97 | + #[必须修改] 是否开启1078的服务 | ||
| 98 | + enable: true | ||
| 99 | + #[必修修改] 1708设备接入的端口 | ||
| 100 | + port: 21078 | ||
| 101 | + #[可选] 设备鉴权的密码 | ||
| 102 | + password: admin123 | ||
| 103 | + | ||
| 92 | #zlm 默认服务器配置 | 104 | #zlm 默认服务器配置 |
| 93 | media: | 105 | media: |
| 94 | # [必须修改] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId | 106 | # [必须修改] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId |
| @@ -182,6 +194,12 @@ user-settings: | @@ -182,6 +194,12 @@ user-settings: | ||
| 182 | send-to-platforms-when-id-lost: true | 194 | send-to-platforms-when-id-lost: true |
| 183 | # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息 | 195 | # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息 |
| 184 | refuse-channel-status-channel-form-notify: false | 196 | refuse-channel-status-channel-form-notify: false |
| 197 | + # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000 | ||
| 198 | + max-notify-count-queue: 10000 | ||
| 199 | + # 设备/通道状态变化时发送消息 | ||
| 200 | + device-status-notify: false | ||
| 201 | + # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式 | ||
| 202 | + use-custom-ssrc-for-parent-invite: true | ||
| 185 | # 跨域配置,配置你访问前端页面的地址即可, 可以配置多个 | 203 | # 跨域配置,配置你访问前端页面的地址即可, 可以配置多个 |
| 186 | allowed-origins: | 204 | allowed-origins: |
| 187 | - http://localhost:8008 | 205 | - http://localhost:8008 |
src/main/resources/application-dev.yml
| @@ -18,29 +18,19 @@ spring: | @@ -18,29 +18,19 @@ spring: | ||
| 18 | timeout: 10000 | 18 | timeout: 10000 |
| 19 | # mysql数据源 | 19 | # mysql数据源 |
| 20 | datasource: | 20 | datasource: |
| 21 | - type: com.alibaba.druid.pool.DruidDataSource | 21 | + type: com.zaxxer.hikari.HikariDataSource |
| 22 | driver-class-name: com.mysql.cj.jdbc.Driver | 22 | driver-class-name: com.mysql.cj.jdbc.Driver |
| 23 | url: jdbc:mysql://127.0.0.1:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true | 23 | url: jdbc:mysql://127.0.0.1:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true |
| 24 | username: root | 24 | username: root |
| 25 | password: 123456 | 25 | password: 123456 |
| 26 | - druid: | 26 | + hikari: |
| 27 | + connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数 | ||
| 27 | initialSize: 10 # 连接池初始化连接数 | 28 | initialSize: 10 # 连接池初始化连接数 |
| 28 | - maxActive: 200 # 连接池最大连接数 | ||
| 29 | - minIdle: 5 # 连接池最小空闲连接数 | ||
| 30 | - maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 | ||
| 31 | - keepAlive: true # 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。 | ||
| 32 | - validationQuery: select 1 # 检测连接是否有效sql,要求是查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 | ||
| 33 | - testWhileIdle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 | ||
| 34 | - testOnBorrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 | ||
| 35 | - testOnReturn: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 | ||
| 36 | - poolPreparedStatements: false # 是否開啟PSCache,並且指定每個連線上PSCache的大小 | ||
| 37 | - timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 | ||
| 38 | - minEvictableIdleTimeMillis: 300000 # 配置一個連線在池中最小生存的時間,單位是毫秒 | ||
| 39 | - filters: stat,slf4j # 配置监控统计拦截的filters,监控统计用的filter:sta, 日志用的filter:log4j | ||
| 40 | - useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据 | ||
| 41 | - # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 | ||
| 42 | - connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000 | ||
| 43 | - #stat-view-servlet.url-pattern: /admin/druid/* | 29 | + maximum-pool-size: 200 # 连接池最大连接数 |
| 30 | + minimum-idle: 5 # 连接池最小空闲连接数 | ||
| 31 | + idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位) | ||
| 32 | + max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位) | ||
| 33 | + | ||
| 44 | 34 | ||
| 45 | #[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 | 35 | #[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 |
| 46 | server: | 36 | server: |
| @@ -48,7 +38,10 @@ server: | @@ -48,7 +38,10 @@ server: | ||
| 48 | 38 | ||
| 49 | # 作为28181服务器的配置 | 39 | # 作为28181服务器的配置 |
| 50 | sip: | 40 | sip: |
| 51 | - # [必须修改] 本机的IP | 41 | + # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡, |
| 42 | + # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4 | ||
| 43 | + # 如果不明白,就使用0.0.0.0,大部分情况都是可以的 | ||
| 44 | + # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。 | ||
| 52 | ip: 192.168.41.16 | 45 | ip: 192.168.41.16 |
| 53 | # [可选] 28181服务监听的端口 | 46 | # [可选] 28181服务监听的端口 |
| 54 | port: 5060 | 47 | port: 5060 |
src/main/resources/application-docker.yml
| @@ -23,7 +23,7 @@ spring: | @@ -23,7 +23,7 @@ spring: | ||
| 23 | url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false&allowMultiQueries=true | 23 | url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false&allowMultiQueries=true |
| 24 | username: root | 24 | username: root |
| 25 | password: root | 25 | password: root |
| 26 | - type: com.alibaba.druid.pool.DruidDataSource | 26 | + type: com.zaxxer.hikari.HikariDataSource |
| 27 | driver-class-name: com.mysql.cj.jdbc.Driver | 27 | driver-class-name: com.mysql.cj.jdbc.Driver |
| 28 | 28 | ||
| 29 | # [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 | 29 | # [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 |
| @@ -32,7 +32,10 @@ server: | @@ -32,7 +32,10 @@ server: | ||
| 32 | 32 | ||
| 33 | # 作为28181服务器的配置 | 33 | # 作为28181服务器的配置 |
| 34 | sip: | 34 | sip: |
| 35 | - # [必须修改] 本机的IP | 35 | + # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡, |
| 36 | + # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4 | ||
| 37 | + # 如果不明白,就使用0.0.0.0,大部分情况都是可以的 | ||
| 38 | + # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。 | ||
| 36 | ip: ${WVP_HOST:127.0.0.1} | 39 | ip: ${WVP_HOST:127.0.0.1} |
| 37 | # [可选] 28181服务监听的端口 | 40 | # [可选] 28181服务监听的端口 |
| 38 | port: ${WVP_PORT:5060} | 41 | port: ${WVP_PORT:5060} |
src/main/resources/application.yml
| @@ -2,5 +2,4 @@ spring: | @@ -2,5 +2,4 @@ spring: | ||
| 2 | application: | 2 | application: |
| 3 | name: wvp | 3 | name: wvp |
| 4 | profiles: | 4 | profiles: |
| 5 | - active: local | ||
| 6 | - include: device-compatible | ||
| 7 | \ No newline at end of file | 5 | \ No newline at end of file |
| 6 | + active: local | ||
| 8 | \ No newline at end of file | 7 | \ No newline at end of file |
src/test/java/com/genersoft/iot/vmp/jt1078/JT1078ServerTest.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.jt1078; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.jt1078.cmd.JT1078Template; | ||
| 4 | +import com.genersoft.iot.vmp.jt1078.codec.netty.TcpServer; | ||
| 5 | +import com.genersoft.iot.vmp.jt1078.proc.response.J9102; | ||
| 6 | +import com.genersoft.iot.vmp.jt1078.proc.response.J9201; | ||
| 7 | +import com.genersoft.iot.vmp.jt1078.proc.response.J9202; | ||
| 8 | +import com.genersoft.iot.vmp.jt1078.proc.response.J9205; | ||
| 9 | + | ||
| 10 | +import java.util.Scanner; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * @author QingtaiJiang | ||
| 14 | + * @date 2023/4/28 14:22 | ||
| 15 | + * @email qingtaij@163.com | ||
| 16 | + */ | ||
| 17 | +public class JT1078ServerTest { | ||
| 18 | + | ||
| 19 | + private static final JT1078Template jt1078Template = new JT1078Template(); | ||
| 20 | + | ||
| 21 | + public static void main(String[] args) { | ||
| 22 | + System.out.println("Starting jt1078 server..."); | ||
| 23 | + TcpServer tcpServer = new TcpServer(21078); | ||
| 24 | + tcpServer.start(); | ||
| 25 | + System.out.println("Start jt1078 server success!"); | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + Scanner s = new Scanner(System.in); | ||
| 29 | + while (true) { | ||
| 30 | + String code = s.nextLine(); | ||
| 31 | + switch (code) { | ||
| 32 | + case "1": | ||
| 33 | + test9102(); | ||
| 34 | + break; | ||
| 35 | + case "2": | ||
| 36 | + test9201(); | ||
| 37 | + break; | ||
| 38 | + case "3": | ||
| 39 | + test9202(); | ||
| 40 | + break; | ||
| 41 | + case "4": | ||
| 42 | + test9205(); | ||
| 43 | + break; | ||
| 44 | + default: | ||
| 45 | + break; | ||
| 46 | + } | ||
| 47 | + } | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + private static void test9102() { | ||
| 51 | + J9102 j9102 = new J9102(); | ||
| 52 | + j9102.setChannel(1); | ||
| 53 | + j9102.setCommand(0); | ||
| 54 | + j9102.setCloseType(0); | ||
| 55 | + j9102.setStreamType(0); | ||
| 56 | + | ||
| 57 | + String s = jt1078Template.stopLive("18864197066", j9102, 6); | ||
| 58 | + System.out.println(s); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + private static void test9201() { | ||
| 62 | + J9201 j9201 = new J9201(); | ||
| 63 | + j9201.setIp("192.168.1.1"); | ||
| 64 | + j9201.setChannel(1); | ||
| 65 | + j9201.setTcpPort(7618); | ||
| 66 | + j9201.setUdpPort(7618); | ||
| 67 | + j9201.setType(0); | ||
| 68 | + j9201.setRate(0); | ||
| 69 | + j9201.setStorageType(0); | ||
| 70 | + j9201.setPlaybackType(0); | ||
| 71 | + j9201.setPlaybackSpeed(0); | ||
| 72 | + j9201.setStartTime("230428134100"); | ||
| 73 | + j9201.setEndTime("230428134200"); | ||
| 74 | + | ||
| 75 | + String s = jt1078Template.startBackLive("18864197066", j9201, 6); | ||
| 76 | + System.out.println(s); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + private static void test9202() { | ||
| 80 | + J9202 j9202 = new J9202(); | ||
| 81 | + | ||
| 82 | + j9202.setChannel(1); | ||
| 83 | + j9202.setPlaybackType(2); | ||
| 84 | + j9202.setPlaybackSpeed(0); | ||
| 85 | + j9202.setPlaybackTime("230428134100"); | ||
| 86 | + | ||
| 87 | + String s = jt1078Template.controlBackLive("18864197066", j9202, 6); | ||
| 88 | + System.out.println(s); | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + private static void test9205() { | ||
| 92 | + J9205 j9205 = new J9205(); | ||
| 93 | + j9205.setChannelId(1); | ||
| 94 | + j9205.setStartTime("230428134100"); | ||
| 95 | + j9205.setEndTime("230428134100"); | ||
| 96 | + j9205.setMediaType(0); | ||
| 97 | + j9205.setStreamType(0); | ||
| 98 | + j9205.setStorageType(0); | ||
| 99 | + | ||
| 100 | + String s = jt1078Template.queryBackTime("18864197066", j9205, 6); | ||
| 101 | + System.out.println(s); | ||
| 102 | + } | ||
| 103 | +} |
web_src/src/components/DeviceList.vue
| @@ -25,11 +25,13 @@ | @@ -25,11 +25,13 @@ | ||
| 25 | </el-table-column> | 25 | </el-table-column> |
| 26 | <el-table-column prop="manufacturer" label="厂家" min-width="120" > | 26 | <el-table-column prop="manufacturer" label="厂家" min-width="120" > |
| 27 | </el-table-column> | 27 | </el-table-column> |
| 28 | + <el-table-column prop="transport" label="信令传输模式" min-width="120" > | ||
| 29 | + </el-table-column> | ||
| 28 | <el-table-column label="流传输模式" min-width="160" > | 30 | <el-table-column label="流传输模式" min-width="160" > |
| 29 | <template slot-scope="scope"> | 31 | <template slot-scope="scope"> |
| 30 | <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择" style="width: 120px"> | 32 | <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择" style="width: 120px"> |
| 31 | <el-option key="UDP" label="UDP" value="UDP"></el-option> | 33 | <el-option key="UDP" label="UDP" value="UDP"></el-option> |
| 32 | - <el-option key="TCP-ACTIVE" label="TCP主动模式" :disabled="true" value="TCP-ACTIVE"></el-option> | 34 | + <el-option key="TCP-ACTIVE" label="TCP主动模式" value="TCP-ACTIVE"></el-option> |
| 33 | <el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option> | 35 | <el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option> |
| 34 | </el-select> | 36 | </el-select> |
| 35 | </template> | 37 | </template> |
web_src/src/components/GBRecordDetail.vue
| @@ -182,9 +182,11 @@ | @@ -182,9 +182,11 @@ | ||
| 182 | this.playerStyle["height"] = this.winHeight + "px"; | 182 | this.playerStyle["height"] = this.winHeight + "px"; |
| 183 | this.chooseDate = moment().format('YYYY-MM-DD') | 183 | this.chooseDate = moment().format('YYYY-MM-DD') |
| 184 | this.dateChange(); | 184 | this.dateChange(); |
| 185 | + window.addEventListener('beforeunload', this.stopPlayRecord) | ||
| 185 | }, | 186 | }, |
| 186 | destroyed() { | 187 | destroyed() { |
| 187 | this.$destroy('recordVideoPlayer'); | 188 | this.$destroy('recordVideoPlayer'); |
| 189 | + window.removeEventListener('beforeunload', this.stopPlayRecord) | ||
| 188 | }, | 190 | }, |
| 189 | methods: { | 191 | methods: { |
| 190 | dateChange(){ | 192 | dateChange(){ |
| @@ -338,14 +340,18 @@ | @@ -338,14 +340,18 @@ | ||
| 338 | }); | 340 | }); |
| 339 | }, | 341 | }, |
| 340 | stopPlayRecord: function (callback) { | 342 | stopPlayRecord: function (callback) { |
| 341 | - this.$refs["recordVideoPlayer"].pause(); | ||
| 342 | - this.videoUrl = ''; | ||
| 343 | - this.$axios({ | ||
| 344 | - method: 'get', | ||
| 345 | - url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId | ||
| 346 | - }).then(function (res) { | ||
| 347 | - if (callback) callback() | ||
| 348 | - }); | 343 | + console.log("停止录像回放") |
| 344 | + if (this.streamId !== "") { | ||
| 345 | + this.$refs["recordVideoPlayer"].pause(); | ||
| 346 | + this.videoUrl = ''; | ||
| 347 | + this.$axios({ | ||
| 348 | + method: 'get', | ||
| 349 | + url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId | ||
| 350 | + }).then(function (res) { | ||
| 351 | + if (callback) callback() | ||
| 352 | + }); | ||
| 353 | + } | ||
| 354 | + | ||
| 349 | }, | 355 | }, |
| 350 | getDataWidth(item){ | 356 | getDataWidth(item){ |
| 351 | let timeForFile = this.getTimeForFile(item); | 357 | let timeForFile = this.getTimeForFile(item); |
| @@ -423,8 +429,14 @@ | @@ -423,8 +429,14 @@ | ||
| 423 | return hStr + ":" + mStr + ":" + sStr | 429 | return hStr + ":" + mStr + ":" + sStr |
| 424 | }, | 430 | }, |
| 425 | goBack(){ | 431 | goBack(){ |
| 432 | + // 如果正在进行录像回放则,发送停止 | ||
| 433 | + if (this.streamId !== "") { | ||
| 434 | + this.stopPlayRecord(()=> { | ||
| 435 | + this.streamId = ""; | ||
| 436 | + }) | ||
| 437 | + } | ||
| 426 | window.history.go(-1); | 438 | window.history.go(-1); |
| 427 | - } | 439 | + }, |
| 428 | } | 440 | } |
| 429 | }; | 441 | }; |
| 430 | </script> | 442 | </script> |
web_src/src/components/channelList.vue
| @@ -123,7 +123,6 @@ | @@ -123,7 +123,6 @@ | ||
| 123 | <script> | 123 | <script> |
| 124 | import devicePlayer from './dialog/devicePlayer.vue' | 124 | import devicePlayer from './dialog/devicePlayer.vue' |
| 125 | import uiHeader from '../layout/UiHeader.vue' | 125 | import uiHeader from '../layout/UiHeader.vue' |
| 126 | -import moment from "moment"; | ||
| 127 | import DeviceService from "./service/DeviceService"; | 126 | import DeviceService from "./service/DeviceService"; |
| 128 | import DeviceTree from "./common/DeviceTree"; | 127 | import DeviceTree from "./common/DeviceTree"; |
| 129 | 128 | ||
| @@ -290,8 +289,8 @@ export default { | @@ -290,8 +289,8 @@ export default { | ||
| 290 | }); | 289 | }); |
| 291 | }, | 290 | }, |
| 292 | getSnap: function (row) { | 291 | getSnap: function (row) { |
| 293 | - let url = (process.env.NODE_ENV === 'development'? "debug": "") + '/api/device/query/snap/' + row.deviceId + '/' + row.channelId | ||
| 294 | - return url | 292 | + let baseUrl = window.baseUrl ? window.baseUrl : ""; |
| 293 | + return ((process.env.NODE_ENV === 'development') ? process.env.BASE_API : baseUrl) + '/api/device/query/snap/' + row.deviceId + '/' + row.channelId; | ||
| 295 | }, | 294 | }, |
| 296 | getBigSnap: function (row) { | 295 | getBigSnap: function (row) { |
| 297 | return [this.getSnap(row)] | 296 | return [this.getSnap(row)] |
web_src/src/components/dialog/recordDownload.vue
| @@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
| 7 | </el-col> | 7 | </el-col> |
| 8 | <el-col :span="6" > | 8 | <el-col :span="6" > |
| 9 | <el-button icon="el-icon-download" v-if="percentage < 100" size="mini" title="点击下载可将以缓存部分下载到本地" @click="download()">停止缓存并下载</el-button> | 9 | <el-button icon="el-icon-download" v-if="percentage < 100" size="mini" title="点击下载可将以缓存部分下载到本地" @click="download()">停止缓存并下载</el-button> |
| 10 | + <el-button icon="el-icon-download" v-if="downloadFile" size="mini" title="点击下载" @click="downloadFileClientEvent()">点击下载</el-button> | ||
| 10 | </el-col> | 11 | </el-col> |
| 11 | </el-row> | 12 | </el-row> |
| 12 | </el-dialog> | 13 | </el-dialog> |
| @@ -21,7 +22,7 @@ import moment from "moment"; | @@ -21,7 +22,7 @@ import moment from "moment"; | ||
| 21 | export default { | 22 | export default { |
| 22 | name: 'recordDownload', | 23 | name: 'recordDownload', |
| 23 | created() { | 24 | created() { |
| 24 | - | 25 | + window.addEventListener('beforeunload', this.stopDownloadRecord) |
| 25 | 26 | ||
| 26 | }, | 27 | }, |
| 27 | data() { | 28 | data() { |
| @@ -39,7 +40,8 @@ export default { | @@ -39,7 +40,8 @@ export default { | ||
| 39 | taskId: null, | 40 | taskId: null, |
| 40 | getProgressRun: false, | 41 | getProgressRun: false, |
| 41 | getProgressForFileRun: false, | 42 | getProgressForFileRun: false, |
| 42 | - timer: null | 43 | + timer: null, |
| 44 | + downloadFile: null, | ||
| 43 | 45 | ||
| 44 | }; | 46 | }; |
| 45 | }, | 47 | }, |
| @@ -96,7 +98,10 @@ export default { | @@ -96,7 +98,10 @@ export default { | ||
| 96 | }); | 98 | }); |
| 97 | }, | 99 | }, |
| 98 | close: function (){ | 100 | close: function (){ |
| 99 | - this.stopDownloadRecord(); | 101 | + if (this.streamInfo.progress < 1) { |
| 102 | + this.stopDownloadRecord(); | ||
| 103 | + } | ||
| 104 | + | ||
| 100 | if (this.timer !== null) { | 105 | if (this.timer !== null) { |
| 101 | window.clearTimeout(this.timer); | 106 | window.clearTimeout(this.timer); |
| 102 | this.timer = null; | 107 | this.timer = null; |
| @@ -158,7 +163,7 @@ export default { | @@ -158,7 +163,7 @@ export default { | ||
| 158 | } | 163 | } |
| 159 | setTimeout( ()=>{ | 164 | setTimeout( ()=>{ |
| 160 | if (!this.showDialog) return; | 165 | if (!this.showDialog) return; |
| 161 | - this.getProgressForFile(this.getProgressForFileTimer()) | 166 | + this.getProgressForFile(this.getProgressForFileTimer) |
| 162 | }, 1000) | 167 | }, 1000) |
| 163 | }, | 168 | }, |
| 164 | getProgressForFile: function (callback){ | 169 | getProgressForFile: function (callback){ |
| @@ -176,13 +181,17 @@ export default { | @@ -176,13 +181,17 @@ export default { | ||
| 176 | if (res.data.code === 0) { | 181 | if (res.data.code === 0) { |
| 177 | if (res.data.data.length === 0){ | 182 | if (res.data.data.length === 0){ |
| 178 | this.percentage = 0 | 183 | this.percentage = 0 |
| 184 | + // 往往在多次请求后(实验五分钟的视频是三次请求),才会返回数据,第一次请求通常是返回空数组 | ||
| 185 | + if (callback)callback() | ||
| 179 | return | 186 | return |
| 180 | } | 187 | } |
| 181 | - this.percentage = parseFloat(res.data.data.percentage)*100 | 188 | + // res.data.data应是数组类型 |
| 189 | + this.percentage = parseFloat(res.data.data[0].percentage)*100 | ||
| 182 | if (res.data.data[0].percentage === '1') { | 190 | if (res.data.data[0].percentage === '1') { |
| 183 | this.getProgressForFileRun = false; | 191 | this.getProgressForFileRun = false; |
| 184 | - window.open(res.data.data[0].downloadFile) | ||
| 185 | - this.close(); | 192 | + this.downloadFile = res.data.data[0].downloadFile |
| 193 | + this.title = "文件处理完成,点击按扭下载" | ||
| 194 | + // window.open(res.data.data[0].downloadFile) | ||
| 186 | }else { | 195 | }else { |
| 187 | if (callback)callback() | 196 | if (callback)callback() |
| 188 | } | 197 | } |
| @@ -190,7 +199,13 @@ export default { | @@ -190,7 +199,13 @@ export default { | ||
| 190 | }).catch(function (error) { | 199 | }).catch(function (error) { |
| 191 | console.log(error); | 200 | console.log(error); |
| 192 | }); | 201 | }); |
| 193 | - } | 202 | + }, |
| 203 | + downloadFileClientEvent: function (){ | ||
| 204 | + window.open(this.downloadFile ) | ||
| 205 | + } | ||
| 206 | + }, | ||
| 207 | + destroyed() { | ||
| 208 | + window.removeEventListener('beforeunload', this.stopDownloadRecord) | ||
| 194 | } | 209 | } |
| 195 | }; | 210 | }; |
| 196 | </script> | 211 | </script> |
web_src/src/layout/UiHeader.vue
| @@ -40,6 +40,7 @@ | @@ -40,6 +40,7 @@ | ||
| 40 | 40 | ||
| 41 | import changePasswordDialog from '../components/dialog/changePassword.vue' | 41 | import changePasswordDialog from '../components/dialog/changePassword.vue' |
| 42 | import userService from '../components/service/UserService' | 42 | import userService from '../components/service/UserService' |
| 43 | +import {Notification} from 'element-ui'; | ||
| 43 | 44 | ||
| 44 | export default { | 45 | export default { |
| 45 | name: "UiHeader", | 46 | name: "UiHeader", |