优化集群方案, 每个zlm一套ssrc;
优化集群下的docker接入逻辑; 更正sql脚本; 支持重启不设置设备离线。重启SIP事务不丢失
This commit is contained in:
parent
379830f7eb
commit
3469271ec2
7
pom.xml
7
pom.xml
@ -46,6 +46,7 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
|
<maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
|
||||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||||
|
<jedis-version>3.1.0</jedis-version>
|
||||||
|
|
||||||
<!-- 依赖版本 -->
|
<!-- 依赖版本 -->
|
||||||
<pagehelper.version>5.2.0</pagehelper.version>
|
<pagehelper.version>5.2.0</pagehelper.version>
|
||||||
@ -80,6 +81,12 @@
|
|||||||
<artifactId>spring-boot-starter-security</artifactId>
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>redis.clients</groupId>
|
||||||
|
<artifactId>jedis</artifactId>
|
||||||
|
<version>${jedis-version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- druid数据库连接池 -->
|
<!-- druid数据库连接池 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
|
204
sql/mysql.sql
204
sql/mysql.sql
@ -1,112 +1,145 @@
|
|||||||
-- auto-generated definition
|
-- auto-generated definition
|
||||||
create schema wvp collate utf8_bin;
|
|
||||||
|
|
||||||
|
CREATE DATABASE `wvp` /*!40100 DEFAULT CHARACTER SET utf8mb3 COLLATE utf8mb3_bin */;
|
||||||
|
|
||||||
|
use wvp;
|
||||||
|
|
||||||
create table device
|
create table device
|
||||||
(
|
(
|
||||||
deviceId varchar(50) not null
|
deviceId varchar(50) not null
|
||||||
primary key,
|
primary key,
|
||||||
name varchar(255) null,
|
name varchar(255) null,
|
||||||
manufacturer varchar(255) null,
|
manufacturer varchar(255) null,
|
||||||
model varchar(255) null,
|
model varchar(255) null,
|
||||||
firmware varchar(255) null,
|
firmware varchar(255) null,
|
||||||
transport varchar(50) null,
|
transport varchar(50) null,
|
||||||
streamMode varchar(50) null,
|
streamMode varchar(50) null,
|
||||||
online varchar(50) null,
|
online varchar(50) null,
|
||||||
registerTime varchar(50) null,
|
registerTime varchar(50) null,
|
||||||
keepaliveTime varchar(50) null,
|
keepaliveTime varchar(50) null,
|
||||||
ip varchar(50) not null,
|
ip varchar(50) not null,
|
||||||
createTime varchar(50) not null,
|
createTime varchar(50) not null,
|
||||||
updateTime varchar(50) not null,
|
updateTime varchar(50) not null,
|
||||||
port int not null,
|
port int not null,
|
||||||
expires int not null,
|
expires int not null,
|
||||||
hostAddress varchar(50) not null
|
hostAddress varchar(50) not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table device_channel
|
create table device_channel
|
||||||
(
|
(
|
||||||
channelId varchar(50) not null,
|
channelId varchar(50) not null,
|
||||||
name varchar(255) null,
|
name varchar(255) null,
|
||||||
manufacture varchar(50) null,
|
manufacture varchar(50) null,
|
||||||
model varchar(50) null,
|
model varchar(50) null,
|
||||||
owner varchar(50) null,
|
owner varchar(50) null,
|
||||||
civilCode varchar(50) null,
|
civilCode varchar(50) null,
|
||||||
block varchar(50) null,
|
block varchar(50) null,
|
||||||
address varchar(50) null,
|
address varchar(50) null,
|
||||||
parentId varchar(50) null,
|
parentId varchar(50) null,
|
||||||
safetyWay int null,
|
safetyWay int null,
|
||||||
registerWay int null,
|
registerWay int null,
|
||||||
certNum varchar(50) null,
|
certNum varchar(50) null,
|
||||||
certifiable int null,
|
certifiable int null,
|
||||||
errCode int null,
|
errCode int null,
|
||||||
endTime varchar(50) null,
|
endTime varchar(50) null,
|
||||||
secrecy varchar(50) null,
|
secrecy varchar(50) null,
|
||||||
ipAddress varchar(50) null,
|
ipAddress varchar(50) null,
|
||||||
port int null,
|
port int null,
|
||||||
password varchar(255) null,
|
password varchar(255) null,
|
||||||
PTZType int null,
|
PTZType int null,
|
||||||
status int null,
|
status int null,
|
||||||
longitude double null,
|
longitude double null,
|
||||||
latitude double null,
|
latitude double null,
|
||||||
streamId varchar(50) null,
|
streamId varchar(50) null,
|
||||||
deviceId varchar(50) not null,
|
deviceId varchar(50) not null,
|
||||||
parental varchar(50) null,
|
parental varchar(50) null,
|
||||||
hasAudio bit(1) null,
|
hasAudio bit null,
|
||||||
createTime varchar(50) not null,
|
createTime varchar(50) not null,
|
||||||
updateTime varchar(50) not null,
|
updateTime varchar(50) not null,
|
||||||
primary key (channelId, deviceId)
|
primary key (channelId, deviceId)
|
||||||
);
|
);
|
||||||
|
|
||||||
create table device_mobile_position
|
create table device_mobile_position
|
||||||
(
|
(
|
||||||
deviceId varchar(50) not null,
|
deviceId varchar(50) not null,
|
||||||
deviceName varchar(255) null,
|
deviceName varchar(255) null,
|
||||||
time varchar(50) not null,
|
time varchar(50) not null,
|
||||||
longitude double not null,
|
longitude double not null,
|
||||||
latitude double not null,
|
latitude double not null,
|
||||||
altitude double null,
|
altitude double null,
|
||||||
speed double null,
|
speed double null,
|
||||||
direction double null,
|
direction double null,
|
||||||
reportSource varchar(50) null,
|
reportSource varchar(50) null,
|
||||||
geodeticSystem varchar(50) null,
|
geodeticSystem varchar(50) null,
|
||||||
cnLng varchar(50) null,
|
cnLng varchar(50) null,
|
||||||
cnLat varchar(50) null,
|
cnLat varchar(50) null,
|
||||||
primary key (deviceId, time)
|
primary key (deviceId, time)
|
||||||
);
|
);
|
||||||
|
|
||||||
create table gb_stream
|
create table gb_stream
|
||||||
(
|
(
|
||||||
app varchar(255) not null,
|
app varchar(255) not null,
|
||||||
stream varchar(255) not null,
|
stream varchar(255) not null,
|
||||||
gbId varchar(50) not null,
|
gbId varchar(50) not null,
|
||||||
name varchar(255) null,
|
name varchar(255) null,
|
||||||
longitude double null,
|
longitude double null,
|
||||||
latitude double null,
|
latitude double null,
|
||||||
streamType varchar(50) null,
|
streamType varchar(50) null,
|
||||||
status int null,
|
mediaServerId varchar(50) null,
|
||||||
|
status int null,
|
||||||
primary key (app, stream, gbId)
|
primary key (app, stream, gbId)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create table media_server
|
||||||
|
(
|
||||||
|
id varchar(255) not null
|
||||||
|
primary key,
|
||||||
|
ip varchar(50) not null,
|
||||||
|
hookIp varchar(50) not null,
|
||||||
|
sdpIp varchar(50) not null,
|
||||||
|
streamIp varchar(50) not null,
|
||||||
|
httpPort int not null,
|
||||||
|
httpSSlPort int not null,
|
||||||
|
rtmpPort int not null,
|
||||||
|
rtmpSSlPort int not null,
|
||||||
|
rtpProxyPort int not null,
|
||||||
|
rtspPort int not null,
|
||||||
|
rtspSSLPort int not null,
|
||||||
|
autoConfig int not null,
|
||||||
|
secret varchar(50) not null,
|
||||||
|
streamNoneReaderDelayMS int not null,
|
||||||
|
rtpEnable int not null,
|
||||||
|
rtpPortRange varchar(50) not null,
|
||||||
|
recordAssistPort int not null,
|
||||||
|
defaultServer int not null,
|
||||||
|
createTime varchar(50) not null,
|
||||||
|
updateTime varchar(50) not null,
|
||||||
|
constraint media_server_i
|
||||||
|
unique (ip, httpPort)
|
||||||
|
);
|
||||||
|
|
||||||
create table parent_platform
|
create table parent_platform
|
||||||
(
|
(
|
||||||
id int auto_increment,
|
id int auto_increment,
|
||||||
enable int null,
|
enable int null,
|
||||||
name varchar(255) null,
|
name varchar(255) null,
|
||||||
serverGBId varchar(50) not null,
|
serverGBId varchar(50) not null,
|
||||||
serverGBDomain varchar(50) null,
|
serverGBDomain varchar(50) null,
|
||||||
serverIP varchar(50) null,
|
serverIP varchar(50) null,
|
||||||
serverPort int null,
|
serverPort int null,
|
||||||
deviceGBId varchar(50) not null,
|
deviceGBId varchar(50) not null,
|
||||||
deviceIp varchar(50) null,
|
deviceIp varchar(50) null,
|
||||||
devicePort varchar(50) null,
|
devicePort varchar(50) null,
|
||||||
username varchar(255) null,
|
username varchar(255) null,
|
||||||
password varchar(50) null,
|
password varchar(50) null,
|
||||||
expires varchar(50) null,
|
expires varchar(50) null,
|
||||||
keepTimeout varchar(50) null,
|
keepTimeout varchar(50) null,
|
||||||
transport varchar(50) null,
|
transport varchar(50) null,
|
||||||
characterSet varchar(50) null,
|
characterSet varchar(50) null,
|
||||||
ptz int null,
|
ptz int null,
|
||||||
rtcp int null,
|
rtcp int null,
|
||||||
status bit(1) null,
|
status bit null,
|
||||||
primary key (id, serverGBId)
|
primary key (id, serverGBId)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -121,7 +154,7 @@ create table platform_gb_channel
|
|||||||
|
|
||||||
create table platform_gb_stream
|
create table platform_gb_stream
|
||||||
(
|
(
|
||||||
platformId varchar(50) not null,
|
platformId varchar(50) not null,
|
||||||
app varchar(255) not null,
|
app varchar(255) not null,
|
||||||
stream varchar(255) not null,
|
stream varchar(255) not null,
|
||||||
primary key (platformId, app, stream)
|
primary key (platformId, app, stream)
|
||||||
@ -129,7 +162,7 @@ create table platform_gb_stream
|
|||||||
|
|
||||||
create table stream_proxy
|
create table stream_proxy
|
||||||
(
|
(
|
||||||
type varchar(50) not null,
|
type varchar(50) not null,
|
||||||
app varchar(255) not null,
|
app varchar(255) not null,
|
||||||
stream varchar(255) not null,
|
stream varchar(255) not null,
|
||||||
url varchar(255) null,
|
url varchar(255) null,
|
||||||
@ -137,11 +170,12 @@ create table stream_proxy
|
|||||||
dst_url varchar(255) null,
|
dst_url varchar(255) null,
|
||||||
timeout_ms int null,
|
timeout_ms int null,
|
||||||
ffmpeg_cmd_key varchar(255) null,
|
ffmpeg_cmd_key varchar(255) null,
|
||||||
rtp_type varchar(50) null,
|
rtp_type varchar(50) null,
|
||||||
mediaServerId varchar(50) null,
|
mediaServerId varchar(50) null,
|
||||||
enable_hls bit(1) null,
|
enable_hls bit null,
|
||||||
enable_mp4 bit(1) null,
|
enable_mp4 bit null,
|
||||||
enable bit(1) not null,
|
enable bit not null,
|
||||||
|
createTime varchar(50) not null,
|
||||||
primary key (app, stream)
|
primary key (app, stream)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -149,11 +183,12 @@ create table stream_push
|
|||||||
(
|
(
|
||||||
app varchar(255) not null,
|
app varchar(255) not null,
|
||||||
stream varchar(255) not null,
|
stream varchar(255) not null,
|
||||||
totalReaderCount varchar(50) null,
|
totalReaderCount varchar(50) null,
|
||||||
originType int null,
|
originType int null,
|
||||||
originTypeStr varchar(50) null,
|
originTypeStr varchar(50) null,
|
||||||
createStamp int null,
|
createStamp int null,
|
||||||
aliveSecond int null,
|
aliveSecond int null,
|
||||||
|
mediaServerId varchar(50) null,
|
||||||
primary key (app, stream)
|
primary key (app, stream)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -164,31 +199,6 @@ create table user
|
|||||||
username varchar(255) not null,
|
username varchar(255) not null,
|
||||||
password varchar(255) not null,
|
password varchar(255) not null,
|
||||||
roleId int not null,
|
roleId int not null,
|
||||||
create_time varchar(50) not null
|
create_time varchar(50) not null
|
||||||
);
|
);
|
||||||
|
|
||||||
insert into user (username, password, roleId, create_time) values ('admin', '21232f297a57a5a743894a0e4a801fc3', '0', '2021-04-13 14:14:57');
|
|
||||||
|
|
||||||
create table media_server (
|
|
||||||
id varchar(255)
|
|
||||||
primary key,
|
|
||||||
ip varchar(50) NOT NULL,
|
|
||||||
hookIp varchar(50) NOT NULL,
|
|
||||||
sdpIp varchar(50) NOT NULL,
|
|
||||||
streamIp varchar(50) NOT NULL,
|
|
||||||
httpPort int NOT NULL,
|
|
||||||
httpSSlPort int NOT NULL,
|
|
||||||
rtmpPort int NOT NULL,
|
|
||||||
rtmpSSlPort int NOT NULL,
|
|
||||||
rtpProxyPort int NOT NULL,
|
|
||||||
rtspPort int NOT NULL,
|
|
||||||
rtspSSLPort int NOT NULL,
|
|
||||||
autoConfig int NOT NULL,
|
|
||||||
secret varchar(50) NOT NULL,
|
|
||||||
streamNoneReaderDelayMS int NOT NULL,
|
|
||||||
rtpEnable int NOT NULL,
|
|
||||||
rtpPortRange varchar(50) NOT NULL,
|
|
||||||
recordAssistPort int NOT NULL,
|
|
||||||
createTime varchar(50) not null,
|
|
||||||
updateTime varchar(50) not null
|
|
||||||
);
|
|
@ -12,6 +12,8 @@ public class VideoManagerConstants {
|
|||||||
|
|
||||||
public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
|
public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
|
||||||
|
|
||||||
|
public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS";
|
||||||
|
|
||||||
public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM";
|
public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM";
|
||||||
|
|
||||||
public static final String DEVICE_PREFIX = "VMP_DEVICE_";
|
public static final String DEVICE_PREFIX = "VMP_DEVICE_";
|
||||||
@ -45,4 +47,8 @@ public class VideoManagerConstants {
|
|||||||
public static final String EVENT_OUTLINE_UNREGISTER = "1";
|
public static final String EVENT_OUTLINE_UNREGISTER = "1";
|
||||||
|
|
||||||
public static final String EVENT_OUTLINE_TIMEOUT = "2";
|
public static final String EVENT_OUTLINE_TIMEOUT = "2";
|
||||||
|
|
||||||
|
public static final String MEDIA_SSRC_USED_PREFIX = "VMP_media_used_ssrc_";
|
||||||
|
|
||||||
|
public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_media_transaction_";
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
package com.genersoft.iot.vmp.conf;
|
package com.genersoft.iot.vmp.conf;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
@Configuration("mediaConfig")
|
@Configuration("mediaConfig")
|
||||||
public class MediaConfig implements IMediaServerItem {
|
public class MediaConfig{
|
||||||
|
|
||||||
@Value("${media.id:}")
|
@Value("${media.id:}")
|
||||||
private String id;
|
private String id;
|
||||||
@ -21,6 +24,9 @@ public class MediaConfig implements IMediaServerItem {
|
|||||||
@Value("${sip.ip}")
|
@Value("${sip.ip}")
|
||||||
private String sipIp;
|
private String sipIp;
|
||||||
|
|
||||||
|
@Value("${sip.domain}")
|
||||||
|
private String sipDomain;
|
||||||
|
|
||||||
@Value("${media.sdp-ip:${media.ip}}")
|
@Value("${media.sdp-ip:${media.ip}}")
|
||||||
private String sdpIp;
|
private String sdpIp;
|
||||||
|
|
||||||
@ -66,31 +72,14 @@ public class MediaConfig implements IMediaServerItem {
|
|||||||
@Value("${media.record-assist-port:0}")
|
@Value("${media.record-assist-port:0}")
|
||||||
private Integer recordAssistPort = 0;
|
private Integer recordAssistPort = 0;
|
||||||
|
|
||||||
private String updateTime;
|
|
||||||
|
|
||||||
private String createTime;
|
|
||||||
|
|
||||||
private boolean docker = false;
|
|
||||||
|
|
||||||
private int count;
|
|
||||||
|
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIp() {
|
public String getIp() {
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIp(String ip) {
|
|
||||||
this.ip = ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHookIp() {
|
public String getHookIp() {
|
||||||
if (StringUtils.isEmpty(hookIp)){
|
if (StringUtils.isEmpty(hookIp)){
|
||||||
return sipIp;
|
return sipIp;
|
||||||
@ -100,78 +89,26 @@ public class MediaConfig implements IMediaServerItem {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHookIp(String hookIp) {
|
|
||||||
this.hookIp = hookIp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSipIp() {
|
public String getSipIp() {
|
||||||
return sipIp;
|
return sipIp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSipIp(String sipIp) {
|
|
||||||
this.sipIp = sipIp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSdpIp(String sdpIp) {
|
|
||||||
this.sdpIp = sdpIp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStreamIp(String streamIp) {
|
|
||||||
this.streamIp = streamIp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHttpPort() {
|
public int getHttpPort() {
|
||||||
return httpPort;
|
return httpPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setHttpPort(int httpPort) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHttpPort(Integer httpPort) {
|
|
||||||
this.httpPort = httpPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHttpSSlPort() {
|
public int getHttpSSlPort() {
|
||||||
return httpSSlPort;
|
return httpSSlPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setHttpSSlPort(int httpSSlPort) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHttpSSlPort(Integer httpSSlPort) {
|
|
||||||
this.httpSSlPort = httpSSlPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRtmpPort() {
|
public int getRtmpPort() {
|
||||||
return rtmpPort;
|
return rtmpPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRtmpPort(int rtmpPort) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRtmpPort(Integer rtmpPort) {
|
|
||||||
this.rtmpPort = rtmpPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRtmpSSlPort() {
|
public int getRtmpSSlPort() {
|
||||||
return rtmpSSlPort;
|
return rtmpSSlPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRtmpSSlPort(int rtmpSSlPort) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRtmpSSlPort(Integer rtmpSSlPort) {
|
|
||||||
this.rtmpSSlPort = rtmpSSlPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRtpProxyPort() {
|
public int getRtpProxyPort() {
|
||||||
if (rtpProxyPort == null) {
|
if (rtpProxyPort == null) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -181,104 +118,38 @@ public class MediaConfig implements IMediaServerItem {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRtpProxyPort(int rtpProxyPort) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRtpProxyPort(Integer rtpProxyPort) {
|
|
||||||
this.rtpProxyPort = rtpProxyPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRtspPort() {
|
public int getRtspPort() {
|
||||||
return rtspPort;
|
return rtspPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRtspPort(int rtspPort) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRtspPort(Integer rtspPort) {
|
|
||||||
this.rtspPort = rtspPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRtspSSLPort() {
|
public int getRtspSSLPort() {
|
||||||
return rtspSSLPort;
|
return rtspSSLPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRtspSSLPort(int rtspSSLPort) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRtspSSLPort(Integer rtspSSLPort) {
|
|
||||||
this.rtspSSLPort = rtspSSLPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAutoConfig() {
|
public boolean isAutoConfig() {
|
||||||
return autoConfig;
|
return autoConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAutoConfig(boolean autoConfig) {
|
|
||||||
this.autoConfig = autoConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSecret() {
|
public String getSecret() {
|
||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSecret(String secret) {
|
|
||||||
this.secret = secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStreamNoneReaderDelayMS() {
|
public String getStreamNoneReaderDelayMS() {
|
||||||
return streamNoneReaderDelayMS;
|
return streamNoneReaderDelayMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS) {
|
|
||||||
this.streamNoneReaderDelayMS = streamNoneReaderDelayMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRtpEnable() {
|
public boolean isRtpEnable() {
|
||||||
return rtpEnable;
|
return rtpEnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRtpEnable(boolean rtpEnable) {
|
|
||||||
this.rtpEnable = rtpEnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRtpPortRange() {
|
public String getRtpPortRange() {
|
||||||
return rtpPortRange;
|
return rtpPortRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRtpPortRange(String rtpPortRange) {
|
|
||||||
this.rtpPortRange = rtpPortRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRecordAssistPort() {
|
public int getRecordAssistPort() {
|
||||||
return recordAssistPort;
|
return recordAssistPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRecordAssistPort(int recordAssistPort) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRecordAssistPort(Integer recordAssistPort) {
|
|
||||||
this.recordAssistPort = recordAssistPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDocker() {
|
|
||||||
return docker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDocker(boolean docker) {
|
|
||||||
this.docker = docker;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSdpIp() {
|
public String getSdpIp() {
|
||||||
if (StringUtils.isEmpty(sdpIp)){
|
if (StringUtils.isEmpty(sdpIp)){
|
||||||
return ip;
|
return ip;
|
||||||
@ -295,13 +166,11 @@ public class MediaConfig implements IMediaServerItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public MediaServerItem getMediaSerItem(){
|
public MediaServerItem getMediaSerItem(){
|
||||||
MediaServerItem mediaServerItem = new MediaServerItem();
|
MediaServerItem mediaServerItem = new MediaServerItem();
|
||||||
mediaServerItem.setId(id);
|
mediaServerItem.setId(id);
|
||||||
mediaServerItem.setIp(ip);
|
mediaServerItem.setIp(ip);
|
||||||
mediaServerItem.setDocker(true);
|
mediaServerItem.setDefaultServer(true);
|
||||||
mediaServerItem.setHookIp(hookIp);
|
mediaServerItem.setHookIp(hookIp);
|
||||||
mediaServerItem.setSdpIp(sdpIp);
|
mediaServerItem.setSdpIp(sdpIp);
|
||||||
mediaServerItem.setStreamIp(streamIp);
|
mediaServerItem.setStreamIp(streamIp);
|
||||||
@ -318,39 +187,12 @@ public class MediaConfig implements IMediaServerItem {
|
|||||||
mediaServerItem.setRtpEnable(rtpEnable);
|
mediaServerItem.setRtpEnable(rtpEnable);
|
||||||
mediaServerItem.setRtpPortRange(rtpPortRange);
|
mediaServerItem.setRtpPortRange(rtpPortRange);
|
||||||
mediaServerItem.setRecordAssistPort(recordAssistPort);
|
mediaServerItem.setRecordAssistPort(recordAssistPort);
|
||||||
mediaServerItem.setCreateTime(createTime);
|
|
||||||
mediaServerItem.setUpdateTime(updateTime);
|
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
mediaServerItem.setCount(count);
|
mediaServerItem.setCreateTime(format.format(new Date(System.currentTimeMillis())));
|
||||||
|
mediaServerItem.setUpdateTime(format.format(new Date(System.currentTimeMillis())));
|
||||||
|
|
||||||
return mediaServerItem;
|
return mediaServerItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUpdateTime() {
|
|
||||||
return updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUpdateTime(String updateTime) {
|
|
||||||
this.updateTime = updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getCreateTime() {
|
|
||||||
return createTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCreateTime(String createTime) {
|
|
||||||
this.createTime = createTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCount(int count) {
|
|
||||||
this.count = count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.conf;
|
package com.genersoft.iot.vmp.conf;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import org.apache.catalina.connector.ClientAbortException;
|
import org.apache.catalina.connector.ClientAbortException;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
@ -49,7 +49,7 @@ public class ProxyServletConfig {
|
|||||||
@Override
|
@Override
|
||||||
protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
|
protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
|
||||||
String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
|
String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
|
||||||
IMediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
|
MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
|
||||||
if (mediaInfo != null) {
|
if (mediaInfo != null) {
|
||||||
if (!StringUtils.isEmpty(queryStr)) {
|
if (!StringUtils.isEmpty(queryStr)) {
|
||||||
queryStr += "&secret=" + mediaInfo.getSecret();
|
queryStr += "&secret=" + mediaInfo.getSecret();
|
||||||
@ -88,7 +88,7 @@ public class ProxyServletConfig {
|
|||||||
@Override
|
@Override
|
||||||
protected String getTargetUri(HttpServletRequest servletRequest) {
|
protected String getTargetUri(HttpServletRequest servletRequest) {
|
||||||
String requestURI = servletRequest.getRequestURI();
|
String requestURI = servletRequest.getRequestURI();
|
||||||
IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
||||||
|
|
||||||
String uri = null;
|
String uri = null;
|
||||||
if (mediaInfo != null) {
|
if (mediaInfo != null) {
|
||||||
@ -106,7 +106,7 @@ public class ProxyServletConfig {
|
|||||||
@Override
|
@Override
|
||||||
protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
|
protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
|
||||||
String requestURI = servletRequest.getRequestURI();
|
String requestURI = servletRequest.getRequestURI();
|
||||||
IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
||||||
HttpHost host;
|
HttpHost host;
|
||||||
if (mediaInfo != null) {
|
if (mediaInfo != null) {
|
||||||
host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort());
|
host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort());
|
||||||
@ -120,7 +120,7 @@ public class ProxyServletConfig {
|
|||||||
/**
|
/**
|
||||||
* 根据uri获取流媒体信息
|
* 根据uri获取流媒体信息
|
||||||
*/
|
*/
|
||||||
IMediaServerItem getMediaInfoByUri(String uri){
|
MediaServerItem getMediaInfoByUri(String uri){
|
||||||
String[] split = uri.split("/");
|
String[] split = uri.split("/");
|
||||||
String mediaServerId = split[2];
|
String mediaServerId = split[2];
|
||||||
return mediaServerService.getOne(mediaServerId);
|
return mediaServerService.getOne(mediaServerId);
|
||||||
@ -132,7 +132,7 @@ public class ProxyServletConfig {
|
|||||||
@Override
|
@Override
|
||||||
protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
|
protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
|
||||||
String requestURI = servletRequest.getRequestURI();
|
String requestURI = servletRequest.getRequestURI();
|
||||||
IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
||||||
String url = super.rewriteUrlFromRequest(servletRequest);
|
String url = super.rewriteUrlFromRequest(servletRequest);
|
||||||
if (mediaInfo == null) {
|
if (mediaInfo == null) {
|
||||||
return url;
|
return url;
|
||||||
@ -186,7 +186,7 @@ public class ProxyServletConfig {
|
|||||||
@Override
|
@Override
|
||||||
protected String getTargetUri(HttpServletRequest servletRequest) {
|
protected String getTargetUri(HttpServletRequest servletRequest) {
|
||||||
String requestURI = servletRequest.getRequestURI();
|
String requestURI = servletRequest.getRequestURI();
|
||||||
IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
||||||
|
|
||||||
String uri = null;
|
String uri = null;
|
||||||
if (mediaInfo != null) {
|
if (mediaInfo != null) {
|
||||||
@ -204,7 +204,7 @@ public class ProxyServletConfig {
|
|||||||
@Override
|
@Override
|
||||||
protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
|
protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
|
||||||
String requestURI = servletRequest.getRequestURI();
|
String requestURI = servletRequest.getRequestURI();
|
||||||
IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
||||||
HttpHost host;
|
HttpHost host;
|
||||||
if (mediaInfo != null) {
|
if (mediaInfo != null) {
|
||||||
host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
|
host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
|
||||||
@ -218,7 +218,7 @@ public class ProxyServletConfig {
|
|||||||
/**
|
/**
|
||||||
* 根据uri获取流媒体信息
|
* 根据uri获取流媒体信息
|
||||||
*/
|
*/
|
||||||
IMediaServerItem getMediaInfoByUri(String uri){
|
MediaServerItem getMediaInfoByUri(String uri){
|
||||||
String[] split = uri.split("/");
|
String[] split = uri.split("/");
|
||||||
String mediaServerId = split[2];
|
String mediaServerId = split[2];
|
||||||
return mediaServerService.getOne(mediaServerId);
|
return mediaServerService.getOne(mediaServerId);
|
||||||
@ -230,7 +230,7 @@ public class ProxyServletConfig {
|
|||||||
@Override
|
@Override
|
||||||
protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
|
protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
|
||||||
String requestURI = servletRequest.getRequestURI();
|
String requestURI = servletRequest.getRequestURI();
|
||||||
IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
|
||||||
String url = super.rewriteUrlFromRequest(servletRequest);
|
String url = super.rewriteUrlFromRequest(servletRequest);
|
||||||
if (mediaInfo == null) {
|
if (mediaInfo == null) {
|
||||||
return url;
|
return url;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.genersoft.iot.vmp.conf;
|
package com.genersoft.iot.vmp.conf;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -10,6 +12,8 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.parser.ParserConfig;
|
import com.alibaba.fastjson.parser.ParserConfig;
|
||||||
import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
|
import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
import redis.clients.jedis.JedisPoolConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
* @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
||||||
@ -20,6 +24,37 @@ import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
|
|||||||
@Configuration
|
@Configuration
|
||||||
public class RedisConfig extends CachingConfigurerSupport {
|
public class RedisConfig extends CachingConfigurerSupport {
|
||||||
|
|
||||||
|
@Value("${spring.redis.host}")
|
||||||
|
private String host;
|
||||||
|
@Value("${spring.redis.port}")
|
||||||
|
private int port;
|
||||||
|
@Value("${spring.redis.database}")
|
||||||
|
private int database;
|
||||||
|
@Value("${spring.redis.password}")
|
||||||
|
private String password;
|
||||||
|
@Value("${spring.redis.timeout}")
|
||||||
|
private int timeout;
|
||||||
|
@Value("${spring.redis.poolMaxTotal:1000}")
|
||||||
|
private int poolMaxTotal;
|
||||||
|
@Value("${spring.redis.poolMaxIdle:500}")
|
||||||
|
private int poolMaxIdle;
|
||||||
|
@Value("${spring.redis.poolMaxWait:5}")
|
||||||
|
private int poolMaxWait;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JedisPool jedisPool() {
|
||||||
|
if (StringUtils.isBlank(password)) {
|
||||||
|
password = null;
|
||||||
|
}
|
||||||
|
JedisPoolConfig poolConfig = new JedisPoolConfig();
|
||||||
|
poolConfig.setMaxIdle(poolMaxIdle);
|
||||||
|
poolConfig.setMaxTotal(poolMaxTotal);
|
||||||
|
// 秒转毫秒
|
||||||
|
poolConfig.setMaxWaitMillis(poolMaxWait * 1000L);
|
||||||
|
JedisPool jp = new JedisPool(poolConfig, host, port, timeout * 1000, password, database);
|
||||||
|
return jp;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean("redisTemplate")
|
@Bean("redisTemplate")
|
||||||
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||||
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
||||||
@ -34,7 +69,7 @@ public class RedisConfig extends CachingConfigurerSupport {
|
|||||||
template.setHashKeySerializer(new StringRedisSerializer());
|
template.setHashKeySerializer(new StringRedisSerializer());
|
||||||
template.setConnectionFactory(redisConnectionFactory);
|
template.setConnectionFactory(redisConnectionFactory);
|
||||||
// 使用fastjson时需设置此项,否则会报异常not support type
|
// 使用fastjson时需设置此项,否则会报异常not support type
|
||||||
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
|
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.conf;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.CommandLineRunner;
|
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 系统启动时控制设备离线
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
@Order(value=4)
|
|
||||||
public class SipDeviceRunner implements CommandLineRunner {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IVideoManagerStorager storager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(String... args) throws Exception {
|
|
||||||
// 设置所有设备离线
|
|
||||||
storager.outlineForAll();
|
|
||||||
// 设置所有设备离线
|
|
||||||
redisCatchStorage.outlineForAll();
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,6 +12,7 @@ import javax.sip.header.CallIdHeader;
|
|||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import gov.nist.javax.sip.SipProviderImpl;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -39,7 +40,7 @@ public class SipLayer implements SipListener {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SipSubscribe sipSubscribe;
|
private SipSubscribe sipSubscribe;
|
||||||
|
|
||||||
private SipStack sipStack;
|
private SipStackImpl sipStack;
|
||||||
|
|
||||||
private SipFactory sipFactory;
|
private SipFactory sipFactory;
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ public class SipLayer implements SipListener {
|
|||||||
private ThreadPoolExecutor initSipServer() {
|
private ThreadPoolExecutor initSipServer() {
|
||||||
|
|
||||||
int processThreadNum = Runtime.getRuntime().availableProcessors() * 10;
|
int processThreadNum = Runtime.getRuntime().availableProcessors() * 10;
|
||||||
LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<Runnable>(10000);
|
LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<>(10000);
|
||||||
processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum,
|
processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum,
|
||||||
0L,TimeUnit.MILLISECONDS,processQueue,
|
0L,TimeUnit.MILLISECONDS,processQueue,
|
||||||
new ThreadPoolExecutor.CallerRunsPolicy());
|
new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
@ -88,17 +89,14 @@ public class SipLayer implements SipListener {
|
|||||||
|
|
||||||
@Bean("tcpSipProvider")
|
@Bean("tcpSipProvider")
|
||||||
@DependsOn("sipStack")
|
@DependsOn("sipStack")
|
||||||
private SipProvider startTcpListener() {
|
private SipProviderImpl startTcpListener() {
|
||||||
ListeningPoint tcpListeningPoint = null;
|
ListeningPoint tcpListeningPoint = null;
|
||||||
SipProvider tcpSipProvider = null;
|
SipProviderImpl tcpSipProvider = null;
|
||||||
try {
|
try {
|
||||||
tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "TCP");
|
tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "TCP");
|
||||||
tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint);
|
tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
|
||||||
tcpSipProvider.addSipListener(this);
|
tcpSipProvider.addSipListener(this);
|
||||||
logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getSipPort() + "}");
|
logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getSipPort() + "}");
|
||||||
// } catch (TransportNotSupportedException | InvalidArgumentException | TooManyListenersException | ObjectInUseException e) {
|
|
||||||
// logger.error(String.format("创建SIP服务失败: %s", e.getMessage()));
|
|
||||||
// }
|
|
||||||
} catch (TransportNotSupportedException e) {
|
} catch (TransportNotSupportedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InvalidArgumentException e) {
|
} catch (InvalidArgumentException e) {
|
||||||
@ -114,13 +112,14 @@ public class SipLayer implements SipListener {
|
|||||||
|
|
||||||
@Bean("udpSipProvider")
|
@Bean("udpSipProvider")
|
||||||
@DependsOn("sipStack")
|
@DependsOn("sipStack")
|
||||||
private SipProvider startUdpListener() {
|
private SipProviderImpl startUdpListener() {
|
||||||
ListeningPoint udpListeningPoint = null;
|
ListeningPoint udpListeningPoint = null;
|
||||||
SipProvider udpSipProvider = null;
|
SipProviderImpl udpSipProvider = null;
|
||||||
try {
|
try {
|
||||||
udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP");
|
udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP");
|
||||||
udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
|
udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
||||||
udpSipProvider.addSipListener(this);
|
udpSipProvider.addSipListener(this);
|
||||||
|
// udpSipProvider.setAutomaticDialogSupportEnabled(false);
|
||||||
} catch (TransportNotSupportedException e) {
|
} catch (TransportNotSupportedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InvalidArgumentException e) {
|
} catch (InvalidArgumentException e) {
|
||||||
@ -141,7 +140,7 @@ public class SipLayer implements SipListener {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void processRequest(RequestEvent evt) {
|
public void processRequest(RequestEvent evt) {
|
||||||
// logger.debug(evt.getRequest().toString());
|
logger.debug(evt.getRequest().toString());
|
||||||
// 由于jainsip是单线程程序,为提高性能并发处理
|
// 由于jainsip是单线程程序,为提高性能并发处理
|
||||||
processThreadPool.execute(() -> {
|
processThreadPool.execute(() -> {
|
||||||
if (processorFactory != null) {
|
if (processorFactory != null) {
|
||||||
@ -153,7 +152,7 @@ public class SipLayer implements SipListener {
|
|||||||
@Override
|
@Override
|
||||||
public void processResponse(ResponseEvent evt) {
|
public void processResponse(ResponseEvent evt) {
|
||||||
Response response = evt.getResponse();
|
Response response = evt.getResponse();
|
||||||
// logger.debug(evt.getResponse().toString());
|
logger.debug(evt.getResponse().toString());
|
||||||
int status = response.getStatusCode();
|
int status = response.getStatusCode();
|
||||||
if (((status >= 200) && (status < 300)) || status == 401) { // Success!
|
if (((status >= 200) && (status < 300)) || status == 401) { // Success!
|
||||||
ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
|
ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
|
||||||
@ -163,6 +162,7 @@ public class SipLayer implements SipListener {
|
|||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
|
if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
|
||||||
CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
|
CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
|
||||||
if (callIdHeader != null) {
|
if (callIdHeader != null) {
|
||||||
@ -220,7 +220,6 @@ public class SipLayer implements SipListener {
|
|||||||
@Override
|
@Override
|
||||||
public void processIOException(IOExceptionEvent exceptionEvent) {
|
public void processIOException(IOExceptionEvent exceptionEvent) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -236,7 +235,6 @@ public class SipLayer implements SipListener {
|
|||||||
@Override
|
@Override
|
||||||
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
|
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
import javax.sip.message.Request;
|
||||||
|
|
||||||
|
public class SsrcTransaction {
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
private String channelId;
|
||||||
|
private String ssrc;
|
||||||
|
private String streamId;
|
||||||
|
private byte[] transaction;
|
||||||
|
private byte[] dialog;
|
||||||
|
private String mediaServerId;
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChannelId() {
|
||||||
|
return channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChannelId(String channelId) {
|
||||||
|
this.channelId = channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSsrc() {
|
||||||
|
return ssrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSsrc(String ssrc) {
|
||||||
|
this.ssrc = ssrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStreamId() {
|
||||||
|
return streamId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStreamId(String streamId) {
|
||||||
|
this.streamId = streamId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getTransaction() {
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransaction(byte[] transaction) {
|
||||||
|
this.transaction = transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getDialog() {
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDialog(byte[] dialog) {
|
||||||
|
this.dialog = dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMediaServerId() {
|
||||||
|
return mediaServerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMediaServerId(String mediaServerId) {
|
||||||
|
this.mediaServerId = mediaServerId;
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,6 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
|||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
@ -77,7 +76,7 @@ public class PlatformNotRegisterEventLister implements ApplicationListener<Platf
|
|||||||
}
|
}
|
||||||
stream.append(sendRtpItem.getStreamId());
|
stream.append(sendRtpItem.getStreamId());
|
||||||
redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId());
|
redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId());
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
param.put("vhost", "__defaultVhost__");
|
param.put("vhost", "__defaultVhost__");
|
||||||
param.put("app", app.toString());
|
param.put("app", app.toString());
|
||||||
|
@ -0,0 +1,140 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.session;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.utils.ConfigConst;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class SsrcConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zlm流媒体服务器Id
|
||||||
|
*/
|
||||||
|
private String mediaServerId;
|
||||||
|
|
||||||
|
private String ssrcPrefix;
|
||||||
|
/**
|
||||||
|
* zlm流媒体服务器已用会话句柄
|
||||||
|
*/
|
||||||
|
private List<String> isUsed;
|
||||||
|
/**
|
||||||
|
* zlm流媒体服务器可用会话句柄
|
||||||
|
*/
|
||||||
|
private List<String> notUsed;
|
||||||
|
|
||||||
|
public SsrcConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SsrcConfig(String mediaServerId, Set<String> usedSet, String sipDomain) {
|
||||||
|
this.mediaServerId = mediaServerId;
|
||||||
|
this.isUsed = new ArrayList<>();
|
||||||
|
this.ssrcPrefix = sipDomain.substring(3, 8);
|
||||||
|
this.notUsed = new ArrayList<>();
|
||||||
|
for (int i = 1; i < ConfigConst.MAX_STRTEAM_COUNT; i++) {
|
||||||
|
String ssrc;
|
||||||
|
if (i < 10) {
|
||||||
|
ssrc = "000" + i;
|
||||||
|
} else if (i < 100) {
|
||||||
|
ssrc = "00" + i;
|
||||||
|
} else if (i < 1000) {
|
||||||
|
ssrc = "0" + i;
|
||||||
|
} else {
|
||||||
|
ssrc = String.valueOf(i);
|
||||||
|
}
|
||||||
|
if (null == usedSet || !usedSet.contains(ssrc)) {
|
||||||
|
this.notUsed.add(ssrc);
|
||||||
|
} else {
|
||||||
|
this.isUsed.add(ssrc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取视频预览的SSRC值,第一位固定为0
|
||||||
|
* @return ssrc
|
||||||
|
*/
|
||||||
|
public String getPlaySsrc() {
|
||||||
|
return "0" + getSsrcPrefix() + getSN();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取录像回放的SSRC值,第一位固定为1
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public String getPlayBackSsrc() {
|
||||||
|
return "1" + getSsrcPrefix() + getSN();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
|
||||||
|
* @param ssrc 需要重置的ssrc
|
||||||
|
*/
|
||||||
|
public void releaseSsrc(String ssrc) {
|
||||||
|
if (ssrc == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String sn = ssrc.substring(6);
|
||||||
|
try {
|
||||||
|
isUsed.remove(sn);
|
||||||
|
notUsed.add(sn);
|
||||||
|
}catch (NullPointerException e){
|
||||||
|
System.out.printf("11111");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取后四位数SN,随机数
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private String getSN() {
|
||||||
|
String sn = null;
|
||||||
|
int index = 0;
|
||||||
|
if (notUsed.size() == 0) {
|
||||||
|
throw new RuntimeException("ssrc已经用完");
|
||||||
|
} else if (notUsed.size() == 1) {
|
||||||
|
sn = notUsed.get(0);
|
||||||
|
} else {
|
||||||
|
index = new Random().nextInt(notUsed.size() - 1);
|
||||||
|
sn = notUsed.get(index);
|
||||||
|
}
|
||||||
|
notUsed.remove(index);
|
||||||
|
isUsed.add(sn);
|
||||||
|
return sn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSsrcPrefix() {
|
||||||
|
return ssrcPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMediaServerId() {
|
||||||
|
return mediaServerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMediaServerId(String mediaServerId) {
|
||||||
|
this.mediaServerId = mediaServerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSsrcPrefix(String ssrcPrefix) {
|
||||||
|
this.ssrcPrefix = ssrcPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getIsUsed() {
|
||||||
|
return isUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsUsed(List<String> isUsed) {
|
||||||
|
this.isUsed = isUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getNotUsed() {
|
||||||
|
return notUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotUsed(List<String> notUsed) {
|
||||||
|
this.notUsed = notUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,101 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.session;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:SIP信令中的SSRC工具类。SSRC值由10位十进制整数组成的字符串,第一位为0代表实况,为1则代表回放;第二位至第六位由监控域ID的第4位到第8位组成;最后4位为不重复的4个整数
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月10日 上午11:57:57
|
|
||||||
*/
|
|
||||||
public class SsrcUtil {
|
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(SsrcUtil.class);
|
|
||||||
|
|
||||||
private static String ssrcPrefix;
|
|
||||||
|
|
||||||
private static List<String> isUsed;
|
|
||||||
|
|
||||||
private static List<String> notUsed;
|
|
||||||
|
|
||||||
private static void init() {
|
|
||||||
SipConfig sipConfig = (SipConfig) SpringBeanFactory.getBean("sipConfig");
|
|
||||||
ssrcPrefix = sipConfig.getSipDomain().substring(3, 8);
|
|
||||||
isUsed = new ArrayList<String>();
|
|
||||||
notUsed = new ArrayList<String>();
|
|
||||||
for (int i = 1; i < 10000; i++) {
|
|
||||||
if (i < 10) {
|
|
||||||
notUsed.add("000" + i);
|
|
||||||
} else if (i < 100) {
|
|
||||||
notUsed.add("00" + i);
|
|
||||||
} else if (i < 1000) {
|
|
||||||
notUsed.add("0" + i);
|
|
||||||
} else {
|
|
||||||
notUsed.add(String.valueOf(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取视频预览的SSRC值,第一位固定为0
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static String getPlaySsrc() {
|
|
||||||
return "0" + getSsrcPrefix() + getSN();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取录像回放的SSRC值,第一位固定为1
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static String getPlayBackSsrc() {
|
|
||||||
return "1" + getSsrcPrefix() + getSN();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static void releaseSsrc(String ssrc) {
|
|
||||||
if (ssrc == null) {
|
|
||||||
logger.error("要释放ssrc为null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String sn = ssrc.substring(6);
|
|
||||||
isUsed.remove(sn);
|
|
||||||
notUsed.add(sn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取后四位数SN,随机数
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static String getSN() {
|
|
||||||
String sn = null;
|
|
||||||
int index = 0;
|
|
||||||
if (notUsed.size() == 0) {
|
|
||||||
throw new RuntimeException("ssrc已经用完");
|
|
||||||
} else if (notUsed.size() == 1) {
|
|
||||||
sn = notUsed.get(0);
|
|
||||||
} else {
|
|
||||||
index = new Random().nextInt(notUsed.size() - 1);
|
|
||||||
sn = notUsed.get(index);
|
|
||||||
}
|
|
||||||
notUsed.remove(index);
|
|
||||||
isUsed.add(sn);
|
|
||||||
return sn;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getSsrcPrefix() {
|
|
||||||
if (ssrcPrefix == null) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
return ssrcPrefix;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,23 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.session;
|
package com.genersoft.iot.vmp.gb28181.session;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import javax.sip.ClientTransaction;
|
import javax.sip.ClientTransaction;
|
||||||
|
import javax.sip.Dialog;
|
||||||
|
import javax.sip.message.Request;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||||
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
|
import com.genersoft.iot.vmp.utils.SerializeUtils;
|
||||||
|
import com.genersoft.iot.vmp.utils.redis.JedisUtil;
|
||||||
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
import gov.nist.javax.sip.stack.SIPDialog;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,50 +28,85 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
public class VideoStreamSessionManager {
|
public class VideoStreamSessionManager {
|
||||||
|
|
||||||
private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>();
|
@Autowired
|
||||||
private ConcurrentHashMap<String, String> ssrcMap = new ConcurrentHashMap<>();
|
private RedisUtil redisUtil;
|
||||||
private ConcurrentHashMap<String, String> streamIdMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public String createPlaySsrc(){
|
public void put(String deviceId, String channelId ,String ssrc, String streamId, String mediaServerId, ClientTransaction transaction){
|
||||||
return SsrcUtil.getPlaySsrc();
|
SsrcTransaction ssrcTransaction = new SsrcTransaction();
|
||||||
|
ssrcTransaction.setDeviceId(deviceId);
|
||||||
|
ssrcTransaction.setChannelId(channelId);
|
||||||
|
ssrcTransaction.setStreamId(streamId);
|
||||||
|
byte[] transactionByteArray = SerializeUtils.serialize(transaction);
|
||||||
|
ssrcTransaction.setTransaction(transactionByteArray);
|
||||||
|
ssrcTransaction.setSsrc(ssrc);
|
||||||
|
ssrcTransaction.setMediaServerId(mediaServerId);
|
||||||
|
|
||||||
|
redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId, ssrcTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createPlayBackSsrc(){
|
public void put(String deviceId, String channelId , Dialog dialog){
|
||||||
return SsrcUtil.getPlayBackSsrc();
|
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||||
}
|
if (ssrcTransaction != null) {
|
||||||
|
byte[] dialogByteArray = SerializeUtils.serialize(dialog);
|
||||||
public void put(String deviceId, String channelId ,String ssrc, String streamId, ClientTransaction transaction){
|
ssrcTransaction.setDialog(dialogByteArray);
|
||||||
sessionMap.put(deviceId + "_" + channelId, transaction);
|
}
|
||||||
ssrcMap.put(deviceId + "_" + channelId, ssrc);
|
redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId, ssrcTransaction);
|
||||||
streamIdMap.put(deviceId + "_" + channelId, streamId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ClientTransaction getTransaction(String deviceId, String channelId){
|
public ClientTransaction getTransaction(String deviceId, String channelId){
|
||||||
return sessionMap.get(deviceId + "_" + channelId);
|
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||||
|
if (ssrcTransaction == null) return null;
|
||||||
|
byte[] transactionByteArray = ssrcTransaction.getTransaction();
|
||||||
|
ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
|
||||||
|
return clientTransaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SIPDialog getDialog(String deviceId, String channelId){
|
||||||
|
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||||
|
if (ssrcTransaction == null) return null;
|
||||||
|
byte[] dialogByteArray = ssrcTransaction.getDialog();
|
||||||
|
if (dialogByteArray == null) return null;
|
||||||
|
SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SsrcTransaction getSsrcTransaction(String deviceId, String channelId){
|
||||||
|
SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId);
|
||||||
|
return ssrcTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStreamId(String deviceId, String channelId){
|
public String getStreamId(String deviceId, String channelId){
|
||||||
return streamIdMap.get(deviceId + "_" + channelId);
|
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||||
|
if (ssrcTransaction == null) return null;
|
||||||
|
return ssrcTransaction.getStreamId();
|
||||||
|
}
|
||||||
|
public String getMediaServerId(String deviceId, String channelId){
|
||||||
|
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||||
|
if (ssrcTransaction == null) return null;
|
||||||
|
return ssrcTransaction.getMediaServerId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSSRC(String deviceId, String channelId){
|
||||||
|
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||||
|
if (ssrcTransaction == null) return null;
|
||||||
|
return ssrcTransaction.getSsrc();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(String deviceId, String channelId) {
|
public void remove(String deviceId, String channelId) {
|
||||||
sessionMap.remove(deviceId + "_" + channelId);
|
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||||
if (ssrcMap.get(deviceId + "_" + channelId) != null) {
|
if (ssrcTransaction == null) return;
|
||||||
SsrcUtil.releaseSsrc(ssrcMap.get(deviceId + "_" + channelId));
|
redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SsrcTransaction> getAllSsrc() {
|
||||||
|
List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX));
|
||||||
|
List<SsrcTransaction> result= new ArrayList<>();
|
||||||
|
for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
|
||||||
|
String key = (String)ssrcTransactionKeys.get(i);
|
||||||
|
SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(key);
|
||||||
|
result.add(ssrcTransaction);
|
||||||
}
|
}
|
||||||
ssrcMap.remove(deviceId + "_" + channelId);
|
return result;
|
||||||
streamIdMap.remove(deviceId + "_" + channelId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConcurrentHashMap<String, ClientTransaction> getSessionMap() {
|
|
||||||
return sessionMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConcurrentHashMap<String, String> getSsrcMap() {
|
|
||||||
return ssrcMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConcurrentHashMap<String, String> getStreamIdMap() {
|
|
||||||
return streamIdMap;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import javax.sip.header.CSeqHeader;
|
|||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
@ -108,7 +109,6 @@ public class SIPProcessorFactory {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IMediaServerService mediaServerService;
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
|
|
||||||
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
||||||
private SipProvider tcpSipProvider;
|
private SipProvider tcpSipProvider;
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
||||||
@ -92,7 +92,7 @@ public interface ISIPCommander {
|
|||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channelId 预览通道
|
* @param channelId 预览通道
|
||||||
*/
|
*/
|
||||||
void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求回放视频流
|
* 请求回放视频流
|
||||||
@ -102,7 +102,7 @@ public interface ISIPCommander {
|
|||||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
*/
|
*/
|
||||||
void playbackStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求历史媒体下载
|
* 请求历史媒体下载
|
||||||
@ -113,12 +113,10 @@ public interface ISIPCommander {
|
|||||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
* @param downloadSpeed 下载倍速参数
|
* @param downloadSpeed 下载倍速参数
|
||||||
*/
|
*/
|
||||||
void downloadStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视频流停止
|
* 视频流停止
|
||||||
*
|
|
||||||
* @param ssrc ssrc
|
|
||||||
*/
|
*/
|
||||||
void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);
|
void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);
|
||||||
void streamByeCmd(String deviceId, String channelId);
|
void streamByeCmd(String deviceId, String channelId);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
import javax.sip.*;
|
import javax.sip.*;
|
||||||
import javax.sip.address.SipURI;
|
import javax.sip.address.SipURI;
|
||||||
@ -8,18 +10,21 @@ import javax.sip.header.CallIdHeader;
|
|||||||
import javax.sip.header.ViaHeader;
|
import javax.sip.header.ViaHeader;
|
||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
|
||||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
|
||||||
import com.genersoft.iot.vmp.conf.UserSetup;
|
import com.genersoft.iot.vmp.conf.UserSetup;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||||
import com.genersoft.iot.vmp.media.zlm.*;
|
import com.genersoft.iot.vmp.media.zlm.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import gov.nist.javax.sip.SipProviderImpl;
|
||||||
|
import gov.nist.javax.sip.SipStackImpl;
|
||||||
import gov.nist.javax.sip.message.SIPRequest;
|
import gov.nist.javax.sip.message.SIPRequest;
|
||||||
|
import gov.nist.javax.sip.stack.SIPDialog;
|
||||||
|
import gov.nist.javax.sip.stack.SIPTransaction;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -35,7 +40,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
|||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,12 +59,12 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
@Lazy
|
@Lazy
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(value="tcpSipProvider")
|
@Qualifier(value="tcpSipProvider")
|
||||||
private SipProvider tcpSipProvider;
|
private SipProviderImpl tcpSipProvider;
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(value="udpSipProvider")
|
@Qualifier(value="udpSipProvider")
|
||||||
private SipProvider udpSipProvider;
|
private SipProviderImpl udpSipProvider;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SIPRequestHeaderProvider headerProvider;
|
private SIPRequestHeaderProvider headerProvider;
|
||||||
@ -74,9 +78,6 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserSetup userSetup;
|
private UserSetup userSetup;
|
||||||
|
|
||||||
@ -86,6 +87,11 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SipSubscribe sipSubscribe;
|
private SipSubscribe sipSubscribe;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
|
private SIPDialog dialog;
|
||||||
|
|
||||||
public SipConfig getSipConfig() {
|
public SipConfig getSipConfig() {
|
||||||
return sipConfig;
|
return sipConfig;
|
||||||
}
|
}
|
||||||
@ -334,26 +340,13 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
* @param errorEvent sip错误订阅
|
* @param errorEvent sip错误订阅
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
|
public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
|
||||||
String streamId = null;
|
String streamId = ssrcInfo.getStreamId();
|
||||||
try {
|
try {
|
||||||
if (device == null) return;
|
if (device == null) return;
|
||||||
String streamMode = device.getStreamMode().toUpperCase();
|
String streamMode = device.getStreamMode().toUpperCase();
|
||||||
|
|
||||||
String ssrc = streamSession.createPlaySsrc();
|
logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
|
||||||
if (mediaServerItem.isRtpEnable()) {
|
|
||||||
streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
|
||||||
}else {
|
|
||||||
streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
|
||||||
}
|
|
||||||
Integer mediaPort = null;
|
|
||||||
// 使用动态udp端口
|
|
||||||
if (mediaServerItem.isRtpEnable()) {
|
|
||||||
mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
|
|
||||||
}else {
|
|
||||||
mediaPort = mediaServerItem.getRtpProxyPort();
|
|
||||||
}
|
|
||||||
logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
|
|
||||||
// 添加订阅
|
// 添加订阅
|
||||||
JSONObject subscribeKey = new JSONObject();
|
JSONObject subscribeKey = new JSONObject();
|
||||||
subscribeKey.put("app", "rtp");
|
subscribeKey.put("app", "rtp");
|
||||||
@ -361,7 +354,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
subscribeKey.put("regist", true);
|
subscribeKey.put("regist", true);
|
||||||
subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
||||||
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
||||||
(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
|
(MediaServerItem mediaServerItemInUse, JSONObject json)->{
|
||||||
if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
||||||
event.response(mediaServerItemInUse, json);
|
event.response(mediaServerItemInUse, json);
|
||||||
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
||||||
@ -369,7 +362,6 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
//
|
//
|
||||||
StringBuffer content = new StringBuffer(200);
|
StringBuffer content = new StringBuffer(200);
|
||||||
content.append("v=0\r\n");
|
content.append("v=0\r\n");
|
||||||
// content.append("o=" + sipConfig.getSipId() + " 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
|
|
||||||
content.append("o="+"00000"+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
content.append("o="+"00000"+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
||||||
content.append("s=Play\r\n");
|
content.append("s=Play\r\n");
|
||||||
content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
||||||
@ -377,11 +369,11 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
|
|
||||||
if (userSetup.isSeniorSdp()) {
|
if (userSetup.isSeniorSdp()) {
|
||||||
if("TCP-PASSIVE".equals(streamMode)) {
|
if("TCP-PASSIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
||||||
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
||||||
}else if("UDP".equals(streamMode)) {
|
}else if("UDP".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" RTP/AVP 96 126 125 99 34 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
|
||||||
}
|
}
|
||||||
content.append("a=recvonly\r\n");
|
content.append("a=recvonly\r\n");
|
||||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
content.append("a=rtpmap:96 PS/90000\r\n");
|
||||||
@ -402,11 +394,11 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
if("TCP-PASSIVE".equals(streamMode)) {
|
if("TCP-PASSIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
|
||||||
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
|
||||||
}else if("UDP".equals(streamMode)) {
|
}else if("UDP".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n");
|
||||||
}
|
}
|
||||||
content.append("a=recvonly\r\n");
|
content.append("a=recvonly\r\n");
|
||||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
content.append("a=rtpmap:96 PS/90000\r\n");
|
||||||
@ -421,20 +413,25 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
content.append("y="+ssrc+"\r\n");//ssrc
|
content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc
|
||||||
|
|
||||||
String tm = Long.toString(System.currentTimeMillis());
|
String tm = Long.toString(System.currentTimeMillis());
|
||||||
|
|
||||||
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
|
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
|
||||||
: udpSipProvider.getNewCallId();
|
: udpSipProvider.getNewCallId();
|
||||||
|
|
||||||
Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrc, callIdHeader);
|
Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrcInfo.getSsrc(), callIdHeader);
|
||||||
|
|
||||||
ClientTransaction transaction = transmitRequest(device, request, (e -> {
|
String finalStreamId = streamId;
|
||||||
|
transmitRequest(device, request, (e -> {
|
||||||
streamSession.remove(device.getDeviceId(), channelId);
|
streamSession.remove(device.getDeviceId(), channelId);
|
||||||
|
mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
|
||||||
errorEvent.response(e);
|
errorEvent.response(e);
|
||||||
}));
|
}), e ->{
|
||||||
streamSession.put(device.getDeviceId(), channelId ,ssrc,streamId, transaction);
|
streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(),e.getClientTransaction());
|
||||||
|
streamSession.put(device.getDeviceId(), channelId , e.getDialog());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -450,30 +447,21 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void playbackStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
|
public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
|
||||||
, SipSubscribe.Event errorEvent) {
|
, SipSubscribe.Event errorEvent) {
|
||||||
try {
|
try {
|
||||||
String ssrc = streamSession.createPlayBackSsrc();
|
|
||||||
String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
|
||||||
|
|
||||||
Integer mediaPort = null;
|
logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
|
||||||
// 使用动态udp端口
|
|
||||||
if (mediaServerItem.isRtpEnable()) {
|
|
||||||
mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
|
|
||||||
}else {
|
|
||||||
mediaPort = mediaServerItem.getRtpProxyPort();
|
|
||||||
}
|
|
||||||
logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
|
|
||||||
|
|
||||||
// 添加订阅
|
// 添加订阅
|
||||||
JSONObject subscribeKey = new JSONObject();
|
JSONObject subscribeKey = new JSONObject();
|
||||||
subscribeKey.put("app", "rtp");
|
subscribeKey.put("app", "rtp");
|
||||||
subscribeKey.put("stream", streamId);
|
subscribeKey.put("stream", ssrcInfo.getStreamId());
|
||||||
subscribeKey.put("regist", true);
|
subscribeKey.put("regist", true);
|
||||||
subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
||||||
logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
|
logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
|
||||||
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
||||||
(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
|
(MediaServerItem mediaServerItemInUse, JSONObject json)->{
|
||||||
if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
||||||
event.response(mediaServerItemInUse, json);
|
event.response(mediaServerItemInUse, json);
|
||||||
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
||||||
@ -494,11 +482,11 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
|
|
||||||
if (userSetup.isSeniorSdp()) {
|
if (userSetup.isSeniorSdp()) {
|
||||||
if("TCP-PASSIVE".equals(streamMode)) {
|
if("TCP-PASSIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
||||||
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
||||||
}else if("UDP".equals(streamMode)) {
|
}else if("UDP".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" RTP/AVP 96 126 125 99 34 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
|
||||||
}
|
}
|
||||||
content.append("a=recvonly\r\n");
|
content.append("a=recvonly\r\n");
|
||||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
content.append("a=rtpmap:96 PS/90000\r\n");
|
||||||
@ -519,11 +507,11 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
if("TCP-PASSIVE".equals(streamMode)) {
|
if("TCP-PASSIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
|
||||||
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
|
||||||
}else if("UDP".equals(streamMode)) {
|
}else if("UDP".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n");
|
||||||
}
|
}
|
||||||
content.append("a=recvonly\r\n");
|
content.append("a=recvonly\r\n");
|
||||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
content.append("a=rtpmap:96 PS/90000\r\n");
|
||||||
@ -538,7 +526,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
content.append("y="+ssrc+"\r\n");//ssrc
|
content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
|
||||||
|
|
||||||
String tm = Long.toString(System.currentTimeMillis());
|
String tm = Long.toString(System.currentTimeMillis());
|
||||||
|
|
||||||
@ -547,9 +535,11 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
|
|
||||||
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
|
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
|
||||||
|
|
||||||
ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
transmitRequest(device, request, errorEvent, okEvent -> {
|
||||||
streamSession.put(device.getDeviceId(), channelId, ssrc, streamId, transaction);
|
Dialog dialog = okEvent.getClientTransaction().getDialog();
|
||||||
|
streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), okEvent.getClientTransaction());
|
||||||
|
streamSession.put(device.getDeviceId(), channelId, dialog);
|
||||||
|
});
|
||||||
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -565,30 +555,20 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
* @param downloadSpeed 下载倍速参数
|
* @param downloadSpeed 下载倍速参数
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void downloadStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event
|
public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event
|
||||||
, SipSubscribe.Event errorEvent) {
|
, SipSubscribe.Event errorEvent) {
|
||||||
try {
|
try {
|
||||||
String ssrc = streamSession.createPlayBackSsrc();
|
logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
|
||||||
String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
|
||||||
|
|
||||||
Integer mediaPort = null;
|
|
||||||
// 使用动态udp端口
|
|
||||||
if (mediaServerItem.isRtpEnable()) {
|
|
||||||
mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
|
|
||||||
}else {
|
|
||||||
mediaPort = mediaServerItem.getRtpProxyPort();
|
|
||||||
}
|
|
||||||
logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
|
|
||||||
|
|
||||||
// 添加订阅
|
// 添加订阅
|
||||||
JSONObject subscribeKey = new JSONObject();
|
JSONObject subscribeKey = new JSONObject();
|
||||||
subscribeKey.put("app", "rtp");
|
subscribeKey.put("app", "rtp");
|
||||||
subscribeKey.put("stream", streamId);
|
subscribeKey.put("stream", ssrcInfo.getStreamId());
|
||||||
subscribeKey.put("regist", true);
|
subscribeKey.put("regist", true);
|
||||||
subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
||||||
logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
|
logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
|
||||||
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
||||||
(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
|
(MediaServerItem mediaServerItemInUse, JSONObject json)->{
|
||||||
if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
||||||
event.response(mediaServerItemInUse, json);
|
event.response(mediaServerItemInUse, json);
|
||||||
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
||||||
@ -609,11 +589,11 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
|
|
||||||
if (userSetup.isSeniorSdp()) {
|
if (userSetup.isSeniorSdp()) {
|
||||||
if("TCP-PASSIVE".equals(streamMode)) {
|
if("TCP-PASSIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
||||||
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
|
||||||
}else if("UDP".equals(streamMode)) {
|
}else if("UDP".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" RTP/AVP 96 126 125 99 34 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
|
||||||
}
|
}
|
||||||
content.append("a=recvonly\r\n");
|
content.append("a=recvonly\r\n");
|
||||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
content.append("a=rtpmap:96 PS/90000\r\n");
|
||||||
@ -634,11 +614,11 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
if("TCP-PASSIVE".equals(streamMode)) {
|
if("TCP-PASSIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
|
||||||
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
|
||||||
}else if("UDP".equals(streamMode)) {
|
}else if("UDP".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n");
|
content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n");
|
||||||
}
|
}
|
||||||
content.append("a=recvonly\r\n");
|
content.append("a=recvonly\r\n");
|
||||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
content.append("a=rtpmap:96 PS/90000\r\n");
|
||||||
@ -654,7 +634,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
content.append("a=downloadspeed:" + downloadSpeed + "\r\n");
|
content.append("a=downloadspeed:" + downloadSpeed + "\r\n");
|
||||||
|
|
||||||
content.append("y="+ssrc+"\r\n");//ssrc
|
content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
|
||||||
|
|
||||||
String tm = Long.toString(System.currentTimeMillis());
|
String tm = Long.toString(System.currentTimeMillis());
|
||||||
|
|
||||||
@ -664,7 +644,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
|
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
|
||||||
|
|
||||||
ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
||||||
streamSession.put(device.getDeviceId(), channelId, ssrc, streamId, transaction);
|
streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), transaction);
|
||||||
|
|
||||||
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -684,53 +664,35 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
|
public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
|
||||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
|
||||||
try {
|
try {
|
||||||
ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
|
ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
|
||||||
// 服务重启后, 无法直接发送bye, 通过手动构建发送
|
|
||||||
// if (transaction == null) {
|
|
||||||
//
|
|
||||||
// if (streamInfo != null) {
|
|
||||||
// MediaServerItem mediaServerItem = redisCatchStorage.getMediaInfo(streamInfo.getMediaServerId());
|
|
||||||
// JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaServerItem,streamInfo.getApp(), streamInfo.getStreamId());
|
|
||||||
// if (mediaList != null) { // 仍在推流才发送
|
|
||||||
// if (mediaList.getInteger("code") == 0) {
|
|
||||||
// JSONArray data = mediaList.getJSONArray("data");
|
|
||||||
// if (data != null && data.size() > 0) {
|
|
||||||
// Device device = storager.queryVideoDevice(deviceId);
|
|
||||||
// if (device != null) {
|
|
||||||
// StreamInfo.TransactionInfo transactionInfo = streamInfo.getTransactionInfo();
|
|
||||||
// try {
|
|
||||||
// Request byteRequest = headerProvider.createByteRequest(device, channelId,
|
|
||||||
// transactionInfo.branch,
|
|
||||||
// transactionInfo.localTag,
|
|
||||||
// transactionInfo.remoteTag,
|
|
||||||
// transactionInfo.callId);
|
|
||||||
// transmitRequest(device, byteRequest);
|
|
||||||
// } catch (InvalidArgumentException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// redisCatchStorage.stopPlay(streamInfo);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (okEvent != null) {
|
|
||||||
// okEvent.response(null);
|
|
||||||
// }
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
if (transaction == null) {
|
if (transaction == null) {
|
||||||
logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
|
logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Dialog dialog = transaction.getDialog();
|
SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
|
||||||
if (dialog == null) {
|
if (dialog == null) {
|
||||||
logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
|
logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SipStack sipStack = udpSipProvider.getSipStack();
|
||||||
|
SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
|
||||||
|
if (dialog != sipDialog) {
|
||||||
|
dialog = sipDialog;
|
||||||
|
}else {
|
||||||
|
dialog.setSipProvider(udpSipProvider);
|
||||||
|
try {
|
||||||
|
Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");
|
||||||
|
sipStackField.setAccessible(true);
|
||||||
|
sipStackField.set(dialog, sipStack);
|
||||||
|
Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");
|
||||||
|
eventListenersField.setAccessible(true);
|
||||||
|
eventListenersField.set(dialog, new HashSet<>());
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Request byeRequest = dialog.createRequest(Request.BYE);
|
Request byeRequest = dialog.createRequest(Request.BYE);
|
||||||
SipURI byeURI = (SipURI) byeRequest.getRequestURI();
|
SipURI byeURI = (SipURI) byeRequest.getRequestURI();
|
||||||
SIPRequest request = (SIPRequest)transaction.getRequest();
|
SIPRequest request = (SIPRequest)transaction.getRequest();
|
||||||
@ -752,7 +714,12 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
|
|
||||||
dialog.sendRequest(clientTransaction);
|
dialog.sendRequest(clientTransaction);
|
||||||
|
|
||||||
streamSession.remove(deviceId, channelId);
|
SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId);
|
||||||
|
if (ssrcTransaction != null) {
|
||||||
|
MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
|
||||||
|
mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc());
|
||||||
|
streamSession.remove(deviceId, channelId);
|
||||||
|
}
|
||||||
} catch (SipException | ParseException e) {
|
} catch (SipException | ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import com.genersoft.iot.vmp.common.StreamInfo;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
@ -81,7 +80,7 @@ public class AckRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
while (!rtpPushed) {
|
while (!rtpPushed) {
|
||||||
try {
|
try {
|
||||||
if (System.currentTimeMillis() - startTime < 30 * 1000) {
|
if (System.currentTimeMillis() - startTime < 30 * 1000) {
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||||
if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) {
|
if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) {
|
||||||
rtpPushed = true;
|
rtpPushed = true;
|
||||||
logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]",
|
logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]",
|
||||||
|
@ -15,7 +15,6 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
|||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
@ -65,7 +64,7 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
param.put("stream",streamId);
|
param.put("stream",streamId);
|
||||||
param.put("ssrc",sendRtpItem.getSsrc());
|
param.put("ssrc",sendRtpItem.getSsrc());
|
||||||
logger.info("停止向上级推流:" + streamId);
|
logger.info("停止向上级推流:" + streamId);
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||||
zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
|
zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
|
||||||
redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
|
redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
|
||||||
if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {
|
if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {
|
||||||
|
@ -11,14 +11,11 @@ import javax.sip.header.*;
|
|||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
@ -97,7 +94,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
// 查询平台下是否有该通道
|
// 查询平台下是否有该通道
|
||||||
DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
|
DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
|
||||||
GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
|
GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
|
||||||
IMediaServerItem mediaServerItem = null;
|
MediaServerItem mediaServerItem = null;
|
||||||
// 不是通道可能是直播流
|
// 不是通道可能是直播流
|
||||||
if (channel != null && gbStream == null ) {
|
if (channel != null && gbStream == null ) {
|
||||||
if (channel.getStatus() == 0) {
|
if (channel.getStatus() == 0) {
|
||||||
|
@ -3,14 +3,18 @@ package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
|
|||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
|
||||||
import javax.sip.*;
|
import javax.sip.*;
|
||||||
|
import javax.sip.address.Address;
|
||||||
import javax.sip.address.SipURI;
|
import javax.sip.address.SipURI;
|
||||||
import javax.sip.header.CSeqHeader;
|
import javax.sip.header.CSeqHeader;
|
||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
import gov.nist.javax.sip.ResponseEventExt;
|
import gov.nist.javax.sip.ResponseEventExt;
|
||||||
|
import gov.nist.javax.sip.stack.SIPDialog;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
@ -28,6 +32,9 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
|
|||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
|
private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VideoStreamSessionManager streamSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理invite响应
|
* 处理invite响应
|
||||||
*
|
*
|
||||||
@ -46,7 +53,7 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
|
|||||||
// 下发ack
|
// 下发ack
|
||||||
if (statusCode == Response.OK) {
|
if (statusCode == Response.OK) {
|
||||||
ResponseEventExt event = (ResponseEventExt)evt;
|
ResponseEventExt event = (ResponseEventExt)evt;
|
||||||
Dialog dialog = evt.getDialog();
|
SIPDialog dialog = (SIPDialog)evt.getDialog();
|
||||||
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
||||||
Request reqAck = dialog.createAck(cseq.getSeqNumber());
|
Request reqAck = dialog.createAck(cseq.getSeqNumber());
|
||||||
SipURI requestURI = (SipURI) reqAck.getRequestURI();
|
SipURI requestURI = (SipURI) reqAck.getRequestURI();
|
||||||
@ -54,7 +61,12 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
|
|||||||
requestURI.setPort(event.getRemotePort());
|
requestURI.setPort(event.getRemotePort());
|
||||||
reqAck.setRequestURI(requestURI);
|
reqAck.setRequestURI(requestURI);
|
||||||
logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
|
logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
|
||||||
|
SipURI sipURI = (SipURI)dialog.getRemoteParty().getURI();
|
||||||
|
String deviceId = requestURI.getUser();
|
||||||
|
String channelId = sipURI.getUser();
|
||||||
|
|
||||||
dialog.sendAck(reqAck);
|
dialog.sendAck(reqAck);
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (InvalidArgumentException | SipException e) {
|
} catch (InvalidArgumentException | SipException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -3,15 +3,14 @@ package com.genersoft.iot.vmp.media.zlm;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
import com.genersoft.iot.vmp.conf.MediaConfig;
|
||||||
import com.genersoft.iot.vmp.conf.UserSetup;
|
import com.genersoft.iot.vmp.conf.UserSetup;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.service.IPlayService;
|
import com.genersoft.iot.vmp.service.IPlayService;
|
||||||
@ -42,7 +41,6 @@ public class ZLMHttpHookListener {
|
|||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
|
private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SIPCommander cmder;
|
private SIPCommander cmder;
|
||||||
|
|
||||||
@ -125,7 +123,7 @@ public class ZLMHttpHookListener {
|
|||||||
String mediaServerId = json.getString("mediaServerId");
|
String mediaServerId = json.getString("mediaServerId");
|
||||||
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json);
|
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json);
|
||||||
if (subscribe != null ) {
|
if (subscribe != null ) {
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
||||||
if (mediaInfo != null) {
|
if (mediaInfo != null) {
|
||||||
subscribe.response(mediaInfo, json);
|
subscribe.response(mediaInfo, json);
|
||||||
}
|
}
|
||||||
@ -150,7 +148,7 @@ public class ZLMHttpHookListener {
|
|||||||
String mediaServerId = json.getString("mediaServerId");
|
String mediaServerId = json.getString("mediaServerId");
|
||||||
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
|
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
|
||||||
if (subscribe != null) {
|
if (subscribe != null) {
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
||||||
if (mediaInfo != null) {
|
if (mediaInfo != null) {
|
||||||
subscribe.response(mediaInfo, json);
|
subscribe.response(mediaInfo, json);
|
||||||
}
|
}
|
||||||
@ -237,7 +235,7 @@ public class ZLMHttpHookListener {
|
|||||||
String mediaServerId = json.getString("mediaServerId");
|
String mediaServerId = json.getString("mediaServerId");
|
||||||
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json);
|
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json);
|
||||||
if (subscribe != null ) {
|
if (subscribe != null ) {
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
||||||
if (mediaInfo != null) {
|
if (mediaInfo != null) {
|
||||||
subscribe.response(mediaInfo, json);
|
subscribe.response(mediaInfo, json);
|
||||||
}
|
}
|
||||||
@ -264,7 +262,7 @@ public class ZLMHttpHookListener {
|
|||||||
String mediaServerId = json.getString("mediaServerId");
|
String mediaServerId = json.getString("mediaServerId");
|
||||||
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
|
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
|
||||||
if (subscribe != null ) {
|
if (subscribe != null ) {
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
||||||
if (mediaInfo != null) {
|
if (mediaInfo != null) {
|
||||||
subscribe.response(mediaInfo, json);
|
subscribe.response(mediaInfo, json);
|
||||||
}
|
}
|
||||||
@ -297,7 +295,7 @@ public class ZLMHttpHookListener {
|
|||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
if (!"rtp".equals(app) ){
|
if (!"rtp".equals(app) ){
|
||||||
IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||||
if (regist) {
|
if (regist) {
|
||||||
zlmMediaListManager.addMedia(mediaServerItem, app, streamId);
|
zlmMediaListManager.addMedia(mediaServerItem, app, streamId);
|
||||||
}else {
|
}else {
|
||||||
@ -369,7 +367,7 @@ public class ZLMHttpHookListener {
|
|||||||
logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString());
|
logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString());
|
||||||
}
|
}
|
||||||
String mediaServerId = json.getString("mediaServerId");
|
String mediaServerId = json.getString("mediaServerId");
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
||||||
if (userSetup.isAutoApplyPlay() && mediaInfo != null) {
|
if (userSetup.isAutoApplyPlay() && mediaInfo != null) {
|
||||||
String app = json.getString("app");
|
String app = json.getString("app");
|
||||||
String streamId = json.getString("stream");
|
String streamId = json.getString("stream");
|
||||||
@ -381,7 +379,13 @@ public class ZLMHttpHookListener {
|
|||||||
Device device = storager.queryVideoDevice(deviceId);
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
if (device != null) {
|
if (device != null) {
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
cmder.playStreamCmd(mediaInfo, device, channelId, (IMediaServerItem mediaServerItemInuse, JSONObject response) -> {
|
SSRCInfo ssrcInfo;
|
||||||
|
String streamId2 = null;
|
||||||
|
if (mediaInfo.isRtpEnable()) {
|
||||||
|
streamId2 = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
||||||
|
}
|
||||||
|
ssrcInfo = mediaServerService.openRTPServer(mediaInfo, streamId2);
|
||||||
|
cmder.playStreamCmd(mediaInfo, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
|
||||||
logger.info("收到订阅消息: " + response.toJSONString());
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
playService.onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
|
playService.onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
|
||||||
}, null);
|
}, null);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.media.zlm;
|
package com.genersoft.iot.vmp.media.zlm;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@ -32,7 +31,7 @@ public class ZLMHttpHookSubscribe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface Event{
|
public interface Event{
|
||||||
void response(IMediaServerItem mediaServerItem, JSONObject response);
|
void response(MediaServerItem mediaServerItem, JSONObject response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<HookType, Map<JSONObject, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
|
private Map<HookType, Map<JSONObject, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
|
||||||
@ -58,6 +57,9 @@ public class ZLMHttpHookSubscribe {
|
|||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = key.getString(s).equals(hookResponse.getString(s));
|
result = key.getString(s).equals(hookResponse.getString(s));
|
||||||
}else {
|
}else {
|
||||||
|
if (key.getString(s) == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
result = result && key.getString(s).equals(hookResponse.getString(s));
|
result = result && key.getString(s).equals(hookResponse.getString(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,9 +85,9 @@ public class ZLMHttpHookSubscribe {
|
|||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = key.getString(s).equals(hookResponse.getString(s));
|
result = key.getString(s).equals(hookResponse.getString(s));
|
||||||
}else {
|
}else {
|
||||||
|
if (key.getString(s) == null) continue;
|
||||||
result = result && key.getString(s).equals(hookResponse.getString(s));
|
result = result && key.getString(s).equals(hookResponse.getString(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (null != result && result){
|
if (null != result && result){
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
package com.genersoft.iot.vmp.media.zlm;
|
package com.genersoft.iot.vmp.media.zlm;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
|
||||||
import com.genersoft.iot.vmp.service.IStreamPushService;
|
import com.genersoft.iot.vmp.service.IStreamPushService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
@ -76,7 +73,7 @@ public class ZLMMediaListManager {
|
|||||||
jsonObject.put("stream", streamPushItem.getStream());
|
jsonObject.put("stream", streamPushItem.getStream());
|
||||||
jsonObject.put("mediaServerId", mediaServerItem.getId());
|
jsonObject.put("mediaServerId", mediaServerItem.getId());
|
||||||
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject,
|
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject,
|
||||||
(IMediaServerItem mediaServerItemInuse, JSONObject response)->{
|
(MediaServerItem mediaServerItemInuse, JSONObject response)->{
|
||||||
updateMedia(mediaServerItem, response.getString("app"), response.getString("stream"));
|
updateMedia(mediaServerItem, response.getString("app"), response.getString("stream"));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -86,13 +83,13 @@ public class ZLMMediaListManager {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMedia(IMediaServerItem mediaServerItem, String app, String streamId) {
|
public void addMedia(MediaServerItem mediaServerItem, String app, String streamId) {
|
||||||
//使用异步更新推流
|
//使用异步更新推流
|
||||||
updateMedia(mediaServerItem, app, streamId);
|
updateMedia(mediaServerItem, app, streamId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void updateMedia(IMediaServerItem mediaServerItem, String app, String streamId) {
|
public void updateMedia(MediaServerItem mediaServerItem, String app, String streamId) {
|
||||||
//使用异步更新推流
|
//使用异步更新推流
|
||||||
zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId, "rtmp", json->{
|
zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId, "rtmp", json->{
|
||||||
|
|
||||||
|
@ -2,14 +2,11 @@ package com.genersoft.iot.vmp.media.zlm;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import okhttp3.*;
|
import okhttp3.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -27,7 +24,7 @@ public class ZLMRESTfulUtils {
|
|||||||
void run(JSONObject response);
|
void run(JSONObject response);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject sendPost(IMediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
|
public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
|
||||||
OkHttpClient client = new OkHttpClient();
|
OkHttpClient client = new OkHttpClient();
|
||||||
String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
|
String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
|
||||||
JSONObject responseJSON = null;
|
JSONObject responseJSON = null;
|
||||||
@ -93,7 +90,7 @@ public class ZLMRESTfulUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void sendPostForImg(IMediaServerItem mediaServerItem, String api, Map<String, Object> param, String targetPath, String fileName) {
|
public void sendPostForImg(MediaServerItem mediaServerItem, String api, Map<String, Object> param, String targetPath, String fileName) {
|
||||||
OkHttpClient client = new OkHttpClient();
|
OkHttpClient client = new OkHttpClient();
|
||||||
String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
|
String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
|
||||||
JSONObject responseJSON = null;
|
JSONObject responseJSON = null;
|
||||||
@ -139,7 +136,7 @@ public class ZLMRESTfulUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public JSONObject getMediaList(IMediaServerItem mediaServerItem,String app, String stream, String schema, RequestCallback callback){
|
public JSONObject getMediaList(MediaServerItem mediaServerItem, String app, String stream, String schema, RequestCallback callback){
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
if (app != null) param.put("app",app);
|
if (app != null) param.put("app",app);
|
||||||
if (stream != null) param.put("stream",stream);
|
if (stream != null) param.put("stream",stream);
|
||||||
@ -148,15 +145,15 @@ public class ZLMRESTfulUtils {
|
|||||||
return sendPost(mediaServerItem, "getMediaList",param, callback);
|
return sendPost(mediaServerItem, "getMediaList",param, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject getMediaList(IMediaServerItem mediaServerItem,String app, String stream){
|
public JSONObject getMediaList(MediaServerItem mediaServerItem, String app, String stream){
|
||||||
return getMediaList(mediaServerItem, app, stream,null, null);
|
return getMediaList(mediaServerItem, app, stream,null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject getMediaList(IMediaServerItem mediaServerItem,RequestCallback callback){
|
public JSONObject getMediaList(MediaServerItem mediaServerItem, RequestCallback callback){
|
||||||
return sendPost(mediaServerItem, "getMediaList",null, callback);
|
return sendPost(mediaServerItem, "getMediaList",null, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject getMediaInfo(IMediaServerItem mediaServerItem,String app, String schema, String stream){
|
public JSONObject getMediaInfo(MediaServerItem mediaServerItem, String app, String schema, String stream){
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
param.put("app",app);
|
param.put("app",app);
|
||||||
param.put("schema",schema);
|
param.put("schema",schema);
|
||||||
@ -165,13 +162,13 @@ public class ZLMRESTfulUtils {
|
|||||||
return sendPost(mediaServerItem, "getMediaInfo",param, null);
|
return sendPost(mediaServerItem, "getMediaInfo",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject getRtpInfo(IMediaServerItem mediaServerItem,String stream_id){
|
public JSONObject getRtpInfo(MediaServerItem mediaServerItem, String stream_id){
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
param.put("stream_id",stream_id);
|
param.put("stream_id",stream_id);
|
||||||
return sendPost(mediaServerItem, "getRtpInfo",param, null);
|
return sendPost(mediaServerItem, "getRtpInfo",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject addFFmpegSource(IMediaServerItem mediaServerItem,String src_url, String dst_url, String timeout_ms,
|
public JSONObject addFFmpegSource(MediaServerItem mediaServerItem, String src_url, String dst_url, String timeout_ms,
|
||||||
boolean enable_hls, boolean enable_mp4, String ffmpeg_cmd_key){
|
boolean enable_hls, boolean enable_mp4, String ffmpeg_cmd_key){
|
||||||
logger.info(src_url);
|
logger.info(src_url);
|
||||||
logger.info(dst_url);
|
logger.info(dst_url);
|
||||||
@ -185,41 +182,41 @@ public class ZLMRESTfulUtils {
|
|||||||
return sendPost(mediaServerItem, "addFFmpegSource",param, null);
|
return sendPost(mediaServerItem, "addFFmpegSource",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject delFFmpegSource(IMediaServerItem mediaServerItem,String key){
|
public JSONObject delFFmpegSource(MediaServerItem mediaServerItem, String key){
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
param.put("key", key);
|
param.put("key", key);
|
||||||
return sendPost(mediaServerItem, "delFFmpegSource",param, null);
|
return sendPost(mediaServerItem, "delFFmpegSource",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject getMediaServerConfig(IMediaServerItem mediaServerItem){
|
public JSONObject getMediaServerConfig(MediaServerItem mediaServerItem){
|
||||||
return sendPost(mediaServerItem, "getServerConfig",null, null);
|
return sendPost(mediaServerItem, "getServerConfig",null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject setServerConfig(IMediaServerItem mediaServerItem, Map<String, Object> param){
|
public JSONObject setServerConfig(MediaServerItem mediaServerItem, Map<String, Object> param){
|
||||||
return sendPost(mediaServerItem,"setServerConfig",param, null);
|
return sendPost(mediaServerItem,"setServerConfig",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject openRtpServer(IMediaServerItem mediaServerItem,Map<String, Object> param){
|
public JSONObject openRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param){
|
||||||
return sendPost(mediaServerItem, "openRtpServer",param, null);
|
return sendPost(mediaServerItem, "openRtpServer",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject closeRtpServer(IMediaServerItem mediaServerItem,Map<String, Object> param) {
|
public JSONObject closeRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param) {
|
||||||
return sendPost(mediaServerItem, "closeRtpServer",param, null);
|
return sendPost(mediaServerItem, "closeRtpServer",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject listRtpServer(IMediaServerItem mediaServerItem) {
|
public JSONObject listRtpServer(MediaServerItem mediaServerItem) {
|
||||||
return sendPost(mediaServerItem, "listRtpServer",null, null);
|
return sendPost(mediaServerItem, "listRtpServer",null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject startSendRtp(IMediaServerItem mediaServerItem,Map<String, Object> param) {
|
public JSONObject startSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) {
|
||||||
return sendPost(mediaServerItem, "startSendRtp",param, null);
|
return sendPost(mediaServerItem, "startSendRtp",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject stopSendRtp(IMediaServerItem mediaServerItem,Map<String, Object> param) {
|
public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) {
|
||||||
return sendPost(mediaServerItem, "stopSendRtp",param, null);
|
return sendPost(mediaServerItem, "stopSendRtp",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject addStreamProxy(IMediaServerItem mediaServerItem,String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) {
|
public JSONObject addStreamProxy(MediaServerItem mediaServerItem, String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) {
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
param.put("vhost", "__defaultVhost__");
|
param.put("vhost", "__defaultVhost__");
|
||||||
param.put("app", app);
|
param.put("app", app);
|
||||||
@ -231,7 +228,7 @@ public class ZLMRESTfulUtils {
|
|||||||
return sendPost(mediaServerItem, "addStreamProxy",param, null);
|
return sendPost(mediaServerItem, "addStreamProxy",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject closeStreams(IMediaServerItem mediaServerItem,String app, String stream) {
|
public JSONObject closeStreams(MediaServerItem mediaServerItem, String app, String stream) {
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
param.put("vhost", "__defaultVhost__");
|
param.put("vhost", "__defaultVhost__");
|
||||||
param.put("app", app);
|
param.put("app", app);
|
||||||
@ -240,17 +237,17 @@ public class ZLMRESTfulUtils {
|
|||||||
return sendPost(mediaServerItem, "close_streams",param, null);
|
return sendPost(mediaServerItem, "close_streams",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject getAllSession(IMediaServerItem mediaServerItem) {
|
public JSONObject getAllSession(MediaServerItem mediaServerItem) {
|
||||||
return sendPost(mediaServerItem, "getAllSession",null, null);
|
return sendPost(mediaServerItem, "getAllSession",null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void kickSessions(IMediaServerItem mediaServerItem, String localPortSStr) {
|
public void kickSessions(MediaServerItem mediaServerItem, String localPortSStr) {
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
param.put("local_port", localPortSStr);
|
param.put("local_port", localPortSStr);
|
||||||
sendPost(mediaServerItem, "kick_sessions",param, null);
|
sendPost(mediaServerItem, "kick_sessions",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getSnap(IMediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
|
public void getSnap(MediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
param.put("url", flvUrl);
|
param.put("url", flvUrl);
|
||||||
param.put("timeout_sec", timeout_sec);
|
param.put("timeout_sec", timeout_sec);
|
||||||
|
@ -2,10 +2,7 @@ package com.genersoft.iot.vmp.media.zlm;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.SsrcUtil;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -20,29 +17,20 @@ public class ZLMRTPServerFactory {
|
|||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory");
|
private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory");
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MediaConfig mediaConfig;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||||
|
|
||||||
private int[] portRangeArray = new int[2];
|
private int[] portRangeArray = new int[2];
|
||||||
|
|
||||||
private int currentPort = 0;
|
public int createRTPServer(MediaServerItem mediaServerItem, String streamId) {
|
||||||
|
Map<String, Integer> currentStreams = new HashMap<>();
|
||||||
private Map<String, Integer> currentStreams = null;
|
JSONObject listRtpServerJsonResult = zlmresTfulUtils.listRtpServer(mediaServerItem);
|
||||||
|
if (listRtpServerJsonResult != null) {
|
||||||
public int createRTPServer(IMediaServerItem mediaServerItem, String streamId) {
|
JSONArray data = listRtpServerJsonResult.getJSONArray("data");
|
||||||
if (currentStreams == null) {
|
if (data != null) {
|
||||||
currentStreams = new HashMap<>();
|
for (int i = 0; i < data.size(); i++) {
|
||||||
JSONObject jsonObject = zlmresTfulUtils.listRtpServer(mediaServerItem);
|
JSONObject dataItem = data.getJSONObject(i);
|
||||||
if (jsonObject != null) {
|
currentStreams.put(dataItem.getString("stream_id"), dataItem.getInteger("port"));
|
||||||
JSONArray data = jsonObject.getJSONArray("data");
|
|
||||||
if (data != null) {
|
|
||||||
for (int i = 0; i < data.size(); i++) {
|
|
||||||
JSONObject dataItem = data.getJSONObject(i);
|
|
||||||
currentStreams.put(dataItem.getString("stream_id"), dataItem.getInteger("port"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,18 +44,18 @@ public class ZLMRTPServerFactory {
|
|||||||
|
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
int result = -1;
|
int result = -1;
|
||||||
int newPort = getPortFromportRange();
|
int newPort = getPortFromportRange(mediaServerItem);
|
||||||
param.put("port", newPort);
|
param.put("port", newPort);
|
||||||
param.put("enable_tcp", 1);
|
param.put("enable_tcp", 1);
|
||||||
param.put("stream_id", streamId);
|
param.put("stream_id", streamId);
|
||||||
JSONObject jsonObject = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
|
JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
|
||||||
|
|
||||||
if (jsonObject != null) {
|
if (openRtpServerResultJson != null) {
|
||||||
switch (jsonObject.getInteger("code")){
|
switch (openRtpServerResultJson.getInteger("code")){
|
||||||
case 0:
|
case 0:
|
||||||
result= newPort;
|
result= newPort;
|
||||||
break;
|
break;
|
||||||
case -300: // id已经存在, 可能已经在其他端口推流
|
case -300: // id已经存在, 可能已经在其他端口推流, TODO 也可能是设备不等ack就直接推流了, 需要查询与设置的推流ip端口是否一致
|
||||||
Map<String, Object> closeRtpServerParam = new HashMap<>();
|
Map<String, Object> closeRtpServerParam = new HashMap<>();
|
||||||
closeRtpServerParam.put("stream_id", streamId);
|
closeRtpServerParam.put("stream_id", streamId);
|
||||||
zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam);
|
zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam);
|
||||||
@ -77,7 +65,7 @@ public class ZLMRTPServerFactory {
|
|||||||
result= createRTPServer(mediaServerItem, streamId);
|
result= createRTPServer(mediaServerItem, streamId);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.error("创建RTP Server 失败 {}: " + jsonObject.getString("msg"), newPort);
|
logger.error("创建RTP Server 失败 {}: " + openRtpServerResultJson.getString("msg"), newPort);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
@ -87,7 +75,7 @@ public class ZLMRTPServerFactory {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean closeRTPServer(IMediaServerItem serverItem, String streamId) {
|
public boolean closeRTPServer(MediaServerItem serverItem, String streamId) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
if (serverItem !=null){
|
if (serverItem !=null){
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
@ -107,21 +95,25 @@ public class ZLMRTPServerFactory {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPortFromportRange() {
|
private int getPortFromportRange(MediaServerItem mediaServerItem) {
|
||||||
|
int currentPort = mediaServerItem.getCurrentPort();
|
||||||
if (currentPort == 0) {
|
if (currentPort == 0) {
|
||||||
String[] portRangeStrArray = mediaConfig.getRtpPortRange().split(",");
|
String[] portRangeStrArray = mediaServerItem.getRtpPortRange().split(",");
|
||||||
portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]);
|
portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]);
|
||||||
portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]);
|
portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPort == 0 || currentPort++ > portRangeArray[1]) {
|
if (currentPort == 0 || currentPort++ > portRangeArray[1]) {
|
||||||
currentPort = portRangeArray[0];
|
currentPort = portRangeArray[0];
|
||||||
|
mediaServerItem.setCurrentPort(currentPort);
|
||||||
return portRangeArray[0];
|
return portRangeArray[0];
|
||||||
} else {
|
} else {
|
||||||
if (currentPort % 2 == 1) {
|
if (currentPort % 2 == 1) {
|
||||||
currentPort++;
|
currentPort++;
|
||||||
}
|
}
|
||||||
return currentPort++;
|
currentPort++;
|
||||||
|
mediaServerItem.setCurrentPort(currentPort);
|
||||||
|
return currentPort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,10 +127,14 @@ public class ZLMRTPServerFactory {
|
|||||||
* @param tcp 是否为tcp
|
* @param tcp 是否为tcp
|
||||||
* @return SendRtpItem
|
* @return SendRtpItem
|
||||||
*/
|
*/
|
||||||
public SendRtpItem createSendRtpItem(IMediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){
|
public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){
|
||||||
String playSsrc = SsrcUtil.getPlaySsrc();
|
|
||||||
int localPort = createRTPServer(serverItem, SsrcUtil.getPlaySsrc());
|
// 使用RTPServer 功能找一个可用的端口
|
||||||
|
String playSsrc = serverItem.getSsrcConfig().getPlaySsrc();
|
||||||
|
int localPort = createRTPServer(serverItem, playSsrc);
|
||||||
if (localPort != -1) {
|
if (localPort != -1) {
|
||||||
|
// TODO 高并发时可能因为未放入缓存而ssrc冲突
|
||||||
|
serverItem.getSsrcConfig().releaseSsrc(playSsrc);
|
||||||
closeRTPServer(serverItem, playSsrc);
|
closeRTPServer(serverItem, playSsrc);
|
||||||
}else {
|
}else {
|
||||||
logger.error("没有可用的端口");
|
logger.error("没有可用的端口");
|
||||||
@ -168,10 +164,12 @@ public class ZLMRTPServerFactory {
|
|||||||
* @param tcp 是否为tcp
|
* @param tcp 是否为tcp
|
||||||
* @return SendRtpItem
|
* @return SendRtpItem
|
||||||
*/
|
*/
|
||||||
public SendRtpItem createSendRtpItem(IMediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){
|
public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){
|
||||||
String playSsrc = SsrcUtil.getPlaySsrc();
|
String playSsrc = serverItem.getSsrcConfig().getPlaySsrc();
|
||||||
int localPort = createRTPServer(serverItem, SsrcUtil.getPlaySsrc());
|
int localPort = createRTPServer(serverItem, playSsrc);
|
||||||
if (localPort != -1) {
|
if (localPort != -1) {
|
||||||
|
// TODO 高并发时可能因为未放入缓存而ssrc冲突
|
||||||
|
serverItem.getSsrcConfig().releaseSsrc(ssrc);
|
||||||
closeRTPServer(serverItem, playSsrc);
|
closeRTPServer(serverItem, playSsrc);
|
||||||
}else {
|
}else {
|
||||||
logger.error("没有可用的端口");
|
logger.error("没有可用的端口");
|
||||||
@ -194,7 +192,7 @@ public class ZLMRTPServerFactory {
|
|||||||
/**
|
/**
|
||||||
* 调用zlm RESTful API —— startSendRtp
|
* 调用zlm RESTful API —— startSendRtp
|
||||||
*/
|
*/
|
||||||
public Boolean startSendRtpStream(IMediaServerItem mediaServerItem, Map<String, Object>param) {
|
public Boolean startSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) {
|
||||||
Boolean result = false;
|
Boolean result = false;
|
||||||
JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param);
|
JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param);
|
||||||
if (jsonObject == null) {
|
if (jsonObject == null) {
|
||||||
@ -219,7 +217,7 @@ public class ZLMRTPServerFactory {
|
|||||||
/**
|
/**
|
||||||
* 查询待转推的流是否就绪
|
* 查询待转推的流是否就绪
|
||||||
*/
|
*/
|
||||||
public Boolean isStreamReady(IMediaServerItem mediaServerItem, String app, String streamId) {
|
public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) {
|
||||||
JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
|
JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
|
||||||
return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"));
|
return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"));
|
||||||
}
|
}
|
||||||
@ -229,7 +227,7 @@ public class ZLMRTPServerFactory {
|
|||||||
* @param streamId
|
* @param streamId
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public int totalReaderCount(IMediaServerItem mediaServerItem, String app, String streamId) {
|
public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) {
|
||||||
JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
|
JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
|
||||||
return mediaInfo.getInteger("totalReaderCount");
|
return mediaInfo.getInteger("totalReaderCount");
|
||||||
}
|
}
|
||||||
@ -237,7 +235,7 @@ public class ZLMRTPServerFactory {
|
|||||||
/**
|
/**
|
||||||
* 调用zlm RESTful API —— stopSendRtp
|
* 调用zlm RESTful API —— stopSendRtp
|
||||||
*/
|
*/
|
||||||
public Boolean stopSendRtpStream(IMediaServerItem mediaServerItem,Map<String, Object>param) {
|
public Boolean stopSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) {
|
||||||
Boolean result = false;
|
Boolean result = false;
|
||||||
JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
|
JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
|
||||||
if (jsonObject == null) {
|
if (jsonObject == null) {
|
||||||
|
@ -4,22 +4,16 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
import com.genersoft.iot.vmp.conf.MediaConfig;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
import com.genersoft.iot.vmp.service.IStreamProxyService;
|
import com.genersoft.iot.vmp.service.IStreamProxyService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import javax.print.attribute.standard.Media;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@ -47,16 +41,26 @@ public class ZLMRunner implements CommandLineRunner {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(String... strings) throws Exception {
|
public void run(String... strings) throws Exception {
|
||||||
IMediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort(
|
// 清楚redis缓存的在线zlm信息
|
||||||
|
mediaServerService.clearMediaServerForOnline();
|
||||||
|
|
||||||
|
// 将配置文件的meida配置写入数据库
|
||||||
|
MediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort(
|
||||||
mediaConfig.getIp(), mediaConfig.getHttpPort());
|
mediaConfig.getIp(), mediaConfig.getHttpPort());
|
||||||
if (presetMediaServer != null) {
|
if (presetMediaServer != null) {
|
||||||
mediaConfig.setId(presetMediaServer.getId());
|
MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem();
|
||||||
mediaServerService.update(mediaConfig);
|
mediaSerItem.setId(presetMediaServer.getId());
|
||||||
|
mediaServerService.update(mediaSerItem);
|
||||||
|
}else {
|
||||||
|
if (mediaConfig.getId() != null) {
|
||||||
|
MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem();
|
||||||
|
mediaServerService.add(mediaSerItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 订阅 zlm启动事件, 新的zlm也会从这里进入系统
|
// 订阅 zlm启动事件, 新的zlm也会从这里进入系统
|
||||||
hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null,
|
hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null,
|
||||||
(IMediaServerItem mediaServerItem, JSONObject response)->{
|
(MediaServerItem mediaServerItem, JSONObject response)->{
|
||||||
ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class);
|
ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class);
|
||||||
if (zlmServerConfig !=null ) {
|
if (zlmServerConfig !=null ) {
|
||||||
startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());
|
startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());
|
||||||
@ -69,23 +73,25 @@ public class ZLMRunner implements CommandLineRunner {
|
|||||||
logger.info("等待默认zlm接入...");
|
logger.info("等待默认zlm接入...");
|
||||||
|
|
||||||
// 获取所有的zlm, 并开启主动连接
|
// 获取所有的zlm, 并开启主动连接
|
||||||
List<IMediaServerItem> all = mediaServerService.getAll();
|
List<MediaServerItem> all = mediaServerService.getAll();
|
||||||
if (presetMediaServer == null) {
|
if (presetMediaServer == null) {
|
||||||
all.add(mediaConfig.getMediaSerItem());
|
all.add(mediaConfig.getMediaSerItem());
|
||||||
}
|
}
|
||||||
for (IMediaServerItem mediaServerItem : all) {
|
for (MediaServerItem mediaServerItem : all) {
|
||||||
if (startGetMedia == null) startGetMedia = new HashMap<>();
|
if (startGetMedia == null) startGetMedia = new HashMap<>();
|
||||||
startGetMedia.put(mediaServerItem.getId(), true);
|
startGetMedia.put(mediaServerItem.getId(), true);
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem);
|
ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem);
|
||||||
if (zlmServerConfig != null) {
|
if (zlmServerConfig != null) {
|
||||||
|
zlmServerConfig.setIp(mediaServerItem.getIp());
|
||||||
|
zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort());
|
||||||
startGetMedia.remove(mediaServerItem.getId());
|
startGetMedia.remove(mediaServerItem.getId());
|
||||||
mediaServerService.handLeZLMServerConfig(zlmServerConfig);
|
mediaServerService.handLeZLMServerConfig(zlmServerConfig);
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
Timer timer = new Timer();
|
Timer timer = new Timer();
|
||||||
// 1分钟后未连接到则不再去主动连接
|
// 2分钟后未连接到则不再去主动连接, TODO 并对重启前使用此在zlm的通道发送bye
|
||||||
timer.schedule(new TimerTask() {
|
timer.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -100,7 +106,7 @@ public class ZLMRunner implements CommandLineRunner {
|
|||||||
}, 60 * 1000 * 2);
|
}, 60 * 1000 * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ZLMServerConfig getMediaServerConfig(IMediaServerItem mediaServerItem) {
|
public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem) {
|
||||||
if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) return null;
|
if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) return null;
|
||||||
JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
|
JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
|
||||||
ZLMServerConfig ZLMServerConfig = null;
|
ZLMServerConfig ZLMServerConfig = null;
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.media.zlm.dto;
|
|
||||||
|
|
||||||
public interface IMediaServerItem {
|
|
||||||
|
|
||||||
String getId();
|
|
||||||
|
|
||||||
void setId(String id);
|
|
||||||
|
|
||||||
String getIp();
|
|
||||||
|
|
||||||
void setIp(String ip);
|
|
||||||
|
|
||||||
String getHookIp();
|
|
||||||
|
|
||||||
void setHookIp(String hookIp);
|
|
||||||
|
|
||||||
String getSdpIp();
|
|
||||||
|
|
||||||
void setSdpIp(String sdpIp);
|
|
||||||
|
|
||||||
String getStreamIp();
|
|
||||||
|
|
||||||
void setStreamIp(String streamIp);
|
|
||||||
|
|
||||||
int getHttpPort();
|
|
||||||
|
|
||||||
void setHttpPort(int httpPort);
|
|
||||||
|
|
||||||
int getHttpSSlPort();
|
|
||||||
|
|
||||||
void setHttpSSlPort(int httpSSlPort);
|
|
||||||
|
|
||||||
int getRtmpPort();
|
|
||||||
|
|
||||||
void setRtmpPort(int rtmpPort);
|
|
||||||
|
|
||||||
int getRtmpSSlPort();
|
|
||||||
|
|
||||||
void setRtmpSSlPort(int rtmpSSlPort);
|
|
||||||
|
|
||||||
int getRtpProxyPort();
|
|
||||||
|
|
||||||
void setRtpProxyPort(int rtpProxyPort);
|
|
||||||
|
|
||||||
int getRtspPort();
|
|
||||||
|
|
||||||
void setRtspPort(int rtspPort);
|
|
||||||
|
|
||||||
int getRtspSSLPort();
|
|
||||||
|
|
||||||
void setRtspSSLPort(int rtspSSLPort);
|
|
||||||
|
|
||||||
boolean isAutoConfig();
|
|
||||||
|
|
||||||
void setAutoConfig(boolean autoConfig);
|
|
||||||
|
|
||||||
String getSecret();
|
|
||||||
|
|
||||||
void setSecret(String secret);
|
|
||||||
|
|
||||||
String getStreamNoneReaderDelayMS();
|
|
||||||
|
|
||||||
void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS);
|
|
||||||
|
|
||||||
boolean isRtpEnable();
|
|
||||||
|
|
||||||
void setRtpEnable(boolean rtpEnable);
|
|
||||||
|
|
||||||
String getRtpPortRange();
|
|
||||||
|
|
||||||
void setRtpPortRange(String rtpPortRange);
|
|
||||||
|
|
||||||
int getRecordAssistPort();
|
|
||||||
|
|
||||||
void setRecordAssistPort(int recordAssistPort);
|
|
||||||
|
|
||||||
boolean isDocker();
|
|
||||||
|
|
||||||
void setDocker(boolean docker);
|
|
||||||
|
|
||||||
String getUpdateTime();
|
|
||||||
|
|
||||||
void setUpdateTime(String updateTime);
|
|
||||||
|
|
||||||
String getCreateTime();
|
|
||||||
|
|
||||||
void setCreateTime(String createTime);
|
|
||||||
|
|
||||||
int getCount();
|
|
||||||
|
|
||||||
void setCount(int count);
|
|
||||||
}
|
|
@ -1,10 +1,13 @@
|
|||||||
package com.genersoft.iot.vmp.media.zlm.dto;
|
package com.genersoft.iot.vmp.media.zlm.dto;
|
||||||
|
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
public class MediaServerItem implements IMediaServerItem{
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class MediaServerItem{
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@ -46,9 +49,18 @@ public class MediaServerItem implements IMediaServerItem{
|
|||||||
|
|
||||||
private String updateTime;
|
private String updateTime;
|
||||||
|
|
||||||
private boolean docker;
|
private boolean defaultServer;
|
||||||
|
|
||||||
private int count;
|
private SsrcConfig ssrcConfig;
|
||||||
|
|
||||||
|
private int currentPort;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每一台ZLM都有一套独立的SSRC列表
|
||||||
|
* 在ApplicationCheckRunner里对mediaServerSsrcMap进行初始化
|
||||||
|
*/
|
||||||
|
private HashMap<String, SsrcConfig> mediaServerSsrcMap;
|
||||||
|
|
||||||
public MediaServerItem() {
|
public MediaServerItem() {
|
||||||
}
|
}
|
||||||
@ -218,14 +230,12 @@ public class MediaServerItem implements IMediaServerItem{
|
|||||||
this.recordAssistPort = recordAssistPort;
|
this.recordAssistPort = recordAssistPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public boolean isDefaultServer() {
|
||||||
public boolean isDocker() {
|
return defaultServer;
|
||||||
return docker;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setDefaultServer(boolean defaultServer) {
|
||||||
public void setDocker(boolean docker) {
|
this.defaultServer = defaultServer;
|
||||||
this.docker = docker;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCreateTime() {
|
public String getCreateTime() {
|
||||||
@ -244,11 +254,29 @@ public class MediaServerItem implements IMediaServerItem{
|
|||||||
this.updateTime = updateTime;
|
this.updateTime = updateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCount() {
|
public HashMap<String, SsrcConfig> getMediaServerSsrcMap() {
|
||||||
return count;
|
return mediaServerSsrcMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCount(int count) {
|
public void setMediaServerSsrcMap(HashMap<String, SsrcConfig> mediaServerSsrcMap) {
|
||||||
this.count = count;
|
this.mediaServerSsrcMap = mediaServerSsrcMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SsrcConfig getSsrcConfig() {
|
||||||
|
return ssrcConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSsrcConfig(SsrcConfig ssrcConfig) {
|
||||||
|
this.ssrcConfig = ssrcConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCurrentPort() {
|
||||||
|
return currentPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentPort(int currentPort) {
|
||||||
|
this.currentPort = currentPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package com.genersoft.iot.vmp.service;
|
|||||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
import com.genersoft.iot.vmp.conf.MediaConfig;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -13,11 +13,13 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface IMediaServerService {
|
public interface IMediaServerService {
|
||||||
|
|
||||||
List<IMediaServerItem> getAll();
|
List<MediaServerItem> getAll();
|
||||||
|
|
||||||
IMediaServerItem getOne(String generalMediaServerId);
|
List<MediaServerItem> getAllOnline();
|
||||||
|
|
||||||
IMediaServerItem getOneByHostAndPort(String host, int port);
|
MediaServerItem getOne(String generalMediaServerId);
|
||||||
|
|
||||||
|
MediaServerItem getOneByHostAndPort(String host, int port);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新的节点加入
|
* 新的节点加入
|
||||||
@ -26,19 +28,27 @@ public interface IMediaServerService {
|
|||||||
*/
|
*/
|
||||||
void handLeZLMServerConfig(ZLMServerConfig zlmServerConfig);
|
void handLeZLMServerConfig(ZLMServerConfig zlmServerConfig);
|
||||||
|
|
||||||
void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean b);
|
MediaServerItem getMediaServerForMinimumLoad();
|
||||||
|
|
||||||
IMediaServerItem getMediaServerForMinimumLoad();
|
void setZLMConfig(MediaServerItem mediaServerItem);
|
||||||
|
|
||||||
void setZLMConfig(IMediaServerItem mediaServerItem);
|
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId);
|
||||||
|
|
||||||
void init();
|
|
||||||
|
|
||||||
void closeRTPServer(Device device, String channelId);
|
void closeRTPServer(Device device, String channelId);
|
||||||
|
|
||||||
void update(MediaConfig mediaConfig);
|
void clearRTPServer(MediaServerItem mediaServerItem);
|
||||||
|
|
||||||
|
void update(MediaServerItem mediaSerItem);
|
||||||
|
|
||||||
void addCount(String mediaServerId);
|
void addCount(String mediaServerId);
|
||||||
|
|
||||||
void removeCount(String mediaServerId);
|
void removeCount(String mediaServerId);
|
||||||
|
|
||||||
|
void releaseSsrc(MediaServerItem mediaServerItem, String ssrc);
|
||||||
|
|
||||||
|
void clearMediaServerForOnline();
|
||||||
|
|
||||||
|
void add(MediaServerItem mediaSerItem);
|
||||||
|
|
||||||
|
void resetOnlineServerItem(MediaServerItem serverItem);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.service;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,7 +32,7 @@ public interface IMediaService {
|
|||||||
* @param stream
|
* @param stream
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaServerItem, String app, String stream, JSONArray tracks);
|
StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, JSONArray tracks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据应用名和流ID获取播放地址, 只是地址拼接,返回的ip使用远程访问ip,适用与zlm与wvp在一台主机的情况
|
* 根据应用名和流ID获取播放地址, 只是地址拼接,返回的ip使用远程访问ip,适用与zlm与wvp在一台主机的情况
|
||||||
@ -41,5 +40,5 @@ public interface IMediaService {
|
|||||||
* @param stream
|
* @param stream
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr);
|
StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
|
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
|
||||||
|
|
||||||
@ -13,10 +12,10 @@ import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
|
|||||||
*/
|
*/
|
||||||
public interface IPlayService {
|
public interface IPlayService {
|
||||||
|
|
||||||
void onPublishHandlerForPlayBack(IMediaServerItem mediaServerItem,JSONObject resonse, String deviceId, String channelId, String uuid);
|
void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
|
||||||
void onPublishHandlerForPlay(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
|
void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
|
||||||
|
|
||||||
PlayResult play(IMediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||||
|
|
||||||
IMediaServerItem getNewMediaServerItem(Device device);
|
MediaServerItem getNewMediaServerItem(Device device);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.service;
|
package com.genersoft.iot.vmp.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
@ -63,5 +62,5 @@ public interface IStreamProxyService {
|
|||||||
* 获取ffmpeg.cmd模板
|
* 获取ffmpeg.cmd模板
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem);
|
JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.genersoft.iot.vmp.service;
|
package com.genersoft.iot.vmp.service;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public interface IStreamPushService {
|
public interface IStreamPushService {
|
||||||
|
|
||||||
List<StreamPushItem> handleJSON(String json, IMediaServerItem mediaServerItem);
|
List<StreamPushItem> handleJSON(String json, MediaServerItem mediaServerItem);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将应用名和流ID加入国标关联
|
* 将应用名和流ID加入国标关联
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.genersoft.iot.vmp.service.bean;
|
||||||
|
|
||||||
|
public class SSRCInfo {
|
||||||
|
|
||||||
|
private int port;
|
||||||
|
private String ssrc;
|
||||||
|
private String StreamId;
|
||||||
|
|
||||||
|
public SSRCInfo(int port, String ssrc, String streamId) {
|
||||||
|
this.port = port;
|
||||||
|
this.ssrc = ssrc;
|
||||||
|
StreamId = streamId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSsrc() {
|
||||||
|
return ssrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSsrc(String ssrc) {
|
||||||
|
this.ssrc = ssrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStreamId() {
|
||||||
|
return StreamId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStreamId(String streamId) {
|
||||||
|
StreamId = streamId;
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +1,32 @@
|
|||||||
package com.genersoft.iot.vmp.service.impl;
|
package com.genersoft.iot.vmp.service.impl;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
import com.genersoft.iot.vmp.conf.MediaConfig;
|
||||||
import com.genersoft.iot.vmp.conf.ProxyServletConfig;
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.ZLMRunInfo;
|
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
|
import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
|
||||||
import org.mitre.dsmiley.httpproxy.ProxyServlet;
|
import com.genersoft.iot.vmp.utils.redis.JedisUtil;
|
||||||
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.sql.Array;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -31,15 +34,13 @@ import java.util.*;
|
|||||||
* 媒体服务器节点管理
|
* 媒体服务器节点管理
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class MediaServerServiceImpl implements IMediaServerService {
|
@Order(value=2)
|
||||||
|
public class MediaServerServiceImpl implements IMediaServerService, CommandLineRunner {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class);
|
private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class);
|
||||||
|
|
||||||
private Map<String, IMediaServerItem> zlmServers = new HashMap<>(); // 所有数据库的zlm的缓存
|
@Autowired
|
||||||
private Map<String, Integer> zlmServerStatus = new LinkedHashMap<>(); // 所有上线的zlm的缓存以及负载
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
@Value("${sip.ip}")
|
|
||||||
private String sipIp;
|
|
||||||
|
|
||||||
@Value("${server.ssl.enabled:false}")
|
@Value("${server.ssl.enabled:false}")
|
||||||
private boolean sslEnabled;
|
private boolean sslEnabled;
|
||||||
@ -56,7 +57,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private MediaServerMapper mediaServerMapper;
|
private MediaServerMapper mediaServerMapper;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@ -66,53 +66,134 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
private ZLMRTPServerFactory zlmrtpServerFactory;
|
||||||
|
|
||||||
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
@Autowired
|
||||||
|
private RedisUtil redisUtil;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
JedisUtil jedisUtil;
|
||||||
|
|
||||||
|
private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化
|
* 初始化
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void run(String... args) throws Exception {
|
||||||
zlmServers.clear();
|
logger.info("Media Server 缓存初始化");
|
||||||
zlmServerStatus.clear();
|
|
||||||
List<MediaServerItem> mediaServerItemList = mediaServerMapper.queryAll();
|
List<MediaServerItem> mediaServerItemList = mediaServerMapper.queryAll();
|
||||||
for (IMediaServerItem mediaServerItem : mediaServerItemList) {
|
for (MediaServerItem mediaServerItem : mediaServerItemList) {
|
||||||
zlmServers.put(mediaServerItem.getId(), mediaServerItem);
|
// 更新
|
||||||
|
if (mediaServerItem.getSsrcConfig() == null) {
|
||||||
|
SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getSipDomain());
|
||||||
|
mediaServerItem.setSsrcConfig(ssrcConfig);
|
||||||
|
redisUtil.set(VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId(), mediaServerItem);
|
||||||
|
}
|
||||||
|
// 查询redis是否存在此mediaServer
|
||||||
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId();
|
||||||
|
if (!redisUtil.hasKey(key)) {
|
||||||
|
redisUtil.set(key, mediaServerItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId) {
|
||||||
|
if (mediaServerItem == null || mediaServerItem.getId() == null) return null;
|
||||||
|
// 获取mediaServer可用的ssrc
|
||||||
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId();
|
||||||
|
|
||||||
|
SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
|
||||||
|
if (ssrcConfig == null) {
|
||||||
|
logger.info("media server [ {} ] ssrcConfig is null", mediaServerItem.getId());
|
||||||
|
return null;
|
||||||
|
}else {
|
||||||
|
String ssrc = ssrcConfig.getPlaySsrc();
|
||||||
|
if (streamId == null) streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
||||||
|
int rtpServerPort = mediaServerItem.getRtpProxyPort();
|
||||||
|
if (mediaServerItem.isRtpEnable()) {
|
||||||
|
rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
|
||||||
|
}
|
||||||
|
redisUtil.set(key, mediaServerItem);
|
||||||
|
return new SSRCInfo(rtpServerPort, ssrc, streamId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeRTPServer(Device device, String channelId) {
|
public void closeRTPServer(Device device, String channelId) {
|
||||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
|
String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId);
|
||||||
IMediaServerItem mediaServerItem = null;
|
MediaServerItem mediaServerItem = this.getOne(mediaServerId);
|
||||||
if (streamInfo != null) {
|
if (mediaServerItem != null) {
|
||||||
mediaServerItem = this.getOne (streamInfo.getMediaServerId());
|
String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
||||||
|
zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId);
|
||||||
|
releaseSsrc(mediaServerItem, streamSession.getSSRC(device.getDeviceId(), channelId));
|
||||||
}
|
}
|
||||||
String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
|
||||||
zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId);
|
|
||||||
streamSession.remove(device.getDeviceId(), channelId);
|
streamSession.remove(device.getDeviceId(), channelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(MediaConfig mediaConfig) {
|
public void releaseSsrc(MediaServerItem mediaServerItem, String ssrc) {
|
||||||
|
if (mediaServerItem == null || ssrc == null) return;
|
||||||
|
SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
|
||||||
|
ssrcConfig.releaseSsrc(ssrc);
|
||||||
|
mediaServerItem.setSsrcConfig(ssrcConfig);
|
||||||
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId();
|
||||||
|
redisUtil.set(key, mediaServerItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zlm 重启后重置他的推流信息, TODO 给正在使用的设备发送停止命令
|
||||||
|
* @param mediaServerItem
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void clearRTPServer(MediaServerItem mediaServerItem) {
|
||||||
|
mediaServerItem.setSsrcConfig(new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getSipDomain()));
|
||||||
|
redisUtil.zAdd(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX, mediaServerItem.getId(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(MediaServerItem mediaSerItem) {
|
||||||
|
mediaServerMapper.update(mediaSerItem);
|
||||||
|
MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId());
|
||||||
|
MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId());
|
||||||
|
if (mediaServerItemInRedis != null && mediaServerItemInRedis.getSsrcConfig() != null) {
|
||||||
|
mediaServerItemInDataBase.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
|
||||||
|
}else {
|
||||||
|
mediaServerItemInDataBase.setSsrcConfig(
|
||||||
|
new SsrcConfig(
|
||||||
|
mediaServerItemInDataBase.getId(),
|
||||||
|
null,
|
||||||
|
sipConfig.getSipDomain()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItemInDataBase.getId();
|
||||||
|
redisUtil.set(key, mediaServerItemInDataBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<IMediaServerItem> getAll() {
|
public List<MediaServerItem> getAll() {
|
||||||
if (zlmServers.size() == 0) {
|
List<MediaServerItem> result = new ArrayList<>();
|
||||||
init();
|
List<Object> mediaServerKeys = redisUtil.scan(String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX));
|
||||||
}
|
for (int i = 0; i < mediaServerKeys.size(); i++) {
|
||||||
List<IMediaServerItem> result = new ArrayList<>();
|
String key = (String) mediaServerKeys.get(i);
|
||||||
for (String id : zlmServers.keySet()) {
|
result.add((MediaServerItem)redisUtil.get(key));
|
||||||
IMediaServerItem mediaServerItem = zlmServers.get(id);
|
|
||||||
mediaServerItem.setCount(zlmServerStatus.get(id) == null ? 0 : zlmServerStatus.get(id));
|
|
||||||
result.add(mediaServerItem);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
// return mediaServerMapper.queryAll();
|
public List<MediaServerItem> getAllOnline() {
|
||||||
|
String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
|
||||||
|
Set<String> mediaServerIdSet = redisUtil.zRevRange(key, 0, -1);
|
||||||
|
List<MediaServerItem> result = new ArrayList<>();
|
||||||
|
if (mediaServerIdSet != null && mediaServerIdSet.size() > 0) {
|
||||||
|
for (String mediaServerId : mediaServerIdSet) {
|
||||||
|
String serverKey = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerId;
|
||||||
|
result.add((MediaServerItem) redisUtil.get(serverKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,26 +202,28 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
|||||||
* @return MediaServerItem
|
* @return MediaServerItem
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public IMediaServerItem getOne(String mediaServerId) {
|
public MediaServerItem getOne(String mediaServerId) {
|
||||||
if (mediaServerId ==null) return null;
|
if (mediaServerId == null) return null;
|
||||||
IMediaServerItem mediaServerItem = zlmServers.get(mediaServerId);
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerId;
|
||||||
if (mediaServerItem != null) {
|
return (MediaServerItem)redisUtil.get(key);
|
||||||
mediaServerItem.setCount(zlmServerStatus.get(mediaServerId) == null ? 0 : zlmServerStatus.get(mediaServerId));
|
|
||||||
return mediaServerItem;
|
|
||||||
}else {
|
|
||||||
IMediaServerItem item = mediaServerMapper.queryOne(mediaServerId);
|
|
||||||
if (item != null) {
|
|
||||||
zlmServers.put(item.getId(), item);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IMediaServerItem getOneByHostAndPort(String host, int port) {
|
public MediaServerItem getOneByHostAndPort(String host, int port) {
|
||||||
return mediaServerMapper.queryOneByHostAndPort(host, port);
|
return mediaServerMapper.queryOneByHostAndPort(host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearMediaServerForOnline() {
|
||||||
|
String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
|
||||||
|
redisUtil.del(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(MediaServerItem mediaSerItem) {
|
||||||
|
mediaServerMapper.add(mediaSerItem);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理zlm上线
|
* 处理zlm上线
|
||||||
* @param zlmServerConfig zlm上线携带的参数
|
* @param zlmServerConfig zlm上线携带的参数
|
||||||
@ -150,111 +233,100 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
|||||||
logger.info("[ {} ]-[ {}:{} ]已连接",
|
logger.info("[ {} ]-[ {}:{} ]已连接",
|
||||||
zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
|
zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
|
||||||
|
|
||||||
IMediaServerItem serverItem = getOne(zlmServerConfig.getGeneralMediaServerId());
|
MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId());
|
||||||
String now = this.format.format(new Date(System.currentTimeMillis()));
|
if (serverItem == null) {
|
||||||
if (serverItem != null) {
|
serverItem = mediaServerMapper.queryOneByHostAndPort(zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
|
||||||
serverItem.setSecret(zlmServerConfig.getApiSecret());
|
}
|
||||||
serverItem.setIp(zlmServerConfig.getIp());
|
if (zlmServerConfig.getGeneralMediaServerId().equals(mediaConfig.getId())
|
||||||
|
|| (zlmServerConfig.getIp().equals(mediaConfig.getIp()) && zlmServerConfig.getHttpPort() == mediaConfig.getHttpPort())) {
|
||||||
|
// 配置文件的zlm
|
||||||
// 如果是配置文件中的zlm。 也就是默认zlm。 一切以配置文件内容为准
|
// 如果是配置文件中的zlm。 也就是默认zlm。 一切以配置文件内容为准
|
||||||
// docker部署不会使用zlm配置的端口号;
|
// docker部署不会使用zlm配置的端口号不是默认的则不做更新, 配置修改需要自行修改server配置;
|
||||||
// 直接编译部署的使用配置文件的端口号,如果zlm修改配改了配置,wvp自动修改
|
MediaServerItem serverItemFromConfig = mediaConfig.getMediaSerItem();
|
||||||
|
serverItemFromConfig.setId(zlmServerConfig.getGeneralMediaServerId());
|
||||||
if (serverItem.getId().equals(mediaConfig.getId())
|
if (mediaConfig.getHttpPort() == 0) serverItemFromConfig.setHttpPort(zlmServerConfig.getHttpPort());
|
||||||
|| (serverItem.getIp().equals(mediaConfig.getIp()) && serverItem.getHttpPort() == mediaConfig.getHttpPort())) {
|
if (mediaConfig.getHttpSSlPort() == 0) serverItemFromConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
|
||||||
// 配置文件的zlm
|
if (mediaConfig.getRtmpPort() == 0) serverItemFromConfig.setRtmpPort(zlmServerConfig.getRtmpPort());
|
||||||
mediaConfig.setId(zlmServerConfig.getGeneralMediaServerId());
|
if (mediaConfig.getRtmpSSlPort() == 0) serverItemFromConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
|
||||||
mediaConfig.setUpdateTime(now);
|
if (mediaConfig.getRtspPort() == 0) serverItemFromConfig.setRtspPort(zlmServerConfig.getRtspPort());
|
||||||
if (mediaConfig.getHttpPort() == 0) mediaConfig.setHttpPort(zlmServerConfig.getHttpPort());
|
if (mediaConfig.getRtspSSLPort() == 0) serverItemFromConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
|
||||||
if (mediaConfig.getHttpSSlPort() == 0) mediaConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
|
if (mediaConfig.getRtpProxyPort() == 0) serverItemFromConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
|
||||||
if (mediaConfig.getRtmpPort() == 0) mediaConfig.setRtmpPort(zlmServerConfig.getRtmpPort());
|
if (serverItem != null){
|
||||||
if (mediaConfig.getRtmpSSlPort() == 0) mediaConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
|
// 可能是同一个zlm但id发生了变化
|
||||||
if (mediaConfig.getRtspPort() == 0) mediaConfig.setRtspPort(zlmServerConfig.getRtspPort());
|
if (!serverItem.getId().equals(zlmServerConfig.getGeneralMediaServerId())) {
|
||||||
if (mediaConfig.getRtspSSLPort() == 0) mediaConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
|
mediaServerMapper.delOne(serverItem.getId());
|
||||||
if (mediaConfig.getRtpProxyPort() == 0) mediaConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
|
redisUtil.del(VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItem.getId());
|
||||||
mediaServerMapper.update(mediaConfig);
|
|
||||||
serverItem = mediaConfig.getMediaSerItem();
|
|
||||||
setZLMConfig(mediaConfig);
|
|
||||||
}else {
|
|
||||||
if (!serverItem.isDocker()) {
|
|
||||||
serverItem.setHttpPort(zlmServerConfig.getHttpPort());
|
|
||||||
serverItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
|
|
||||||
serverItem.setRtmpPort(zlmServerConfig.getRtmpPort());
|
|
||||||
serverItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
|
|
||||||
serverItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
|
|
||||||
serverItem.setRtspPort(zlmServerConfig.getRtspPort());
|
|
||||||
|
|
||||||
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItemFromConfig.getId();
|
||||||
|
serverItemFromConfig.setSsrcConfig(new SsrcConfig(serverItemFromConfig.getId(), null, sipConfig.getSipDomain()));
|
||||||
|
redisUtil.set(key, serverItemFromConfig);
|
||||||
|
mediaServerMapper.add(serverItemFromConfig);
|
||||||
|
}else {
|
||||||
|
mediaServerMapper.update(serverItemFromConfig);
|
||||||
}
|
}
|
||||||
serverItem.setUpdateTime(now);
|
}else {
|
||||||
mediaServerMapper.update(serverItem);
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItemFromConfig.getId();
|
||||||
|
serverItemFromConfig.setSsrcConfig(new SsrcConfig(serverItemFromConfig.getId(), null, sipConfig.getSipDomain()));
|
||||||
|
redisUtil.set(key, serverItemFromConfig);
|
||||||
|
mediaServerMapper.add(serverItemFromConfig);
|
||||||
|
}
|
||||||
|
resetOnlineServerItem(serverItemFromConfig);
|
||||||
|
setZLMConfig(serverItemFromConfig);
|
||||||
|
}else {
|
||||||
|
String now = this.format.format(new Date(System.currentTimeMillis()));
|
||||||
|
if (serverItem == null){
|
||||||
|
// 一个新的zlm接入wvp
|
||||||
|
serverItem = new MediaServerItem(zlmServerConfig, sipConfig.getSipIp());
|
||||||
|
serverItem.setCreateTime(now);
|
||||||
|
serverItem.setUpdateTime(now);
|
||||||
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItem.getId();
|
||||||
|
serverItem.setSsrcConfig(new SsrcConfig(serverItem.getId(), null, sipConfig.getSipDomain()));
|
||||||
|
redisUtil.set(key, serverItem);
|
||||||
|
// 存入数据库
|
||||||
|
mediaServerMapper.add(serverItem);
|
||||||
setZLMConfig(serverItem);
|
setZLMConfig(serverItem);
|
||||||
}
|
}
|
||||||
}else {
|
resetOnlineServerItem(serverItem);
|
||||||
if (zlmServerConfig.getGeneralMediaServerId().equals(mediaConfig.getId())
|
|
||||||
|| (zlmServerConfig.getIp().equals(mediaConfig.getIp()) && zlmServerConfig.getHttpPort() == mediaConfig.getHttpPort())) {
|
|
||||||
mediaConfig.setId(zlmServerConfig.getGeneralMediaServerId());
|
|
||||||
mediaConfig.setCreateTime(now);
|
|
||||||
mediaConfig.setUpdateTime(now);
|
|
||||||
serverItem = mediaConfig.getMediaSerItem();
|
|
||||||
mediaServerMapper.add(mediaConfig);
|
|
||||||
}else {
|
|
||||||
// 一个新的zlm接入wvp
|
|
||||||
serverItem = new MediaServerItem(zlmServerConfig, sipIp);
|
|
||||||
serverItem.setCreateTime(now);
|
|
||||||
serverItem.setUpdateTime(now);
|
|
||||||
mediaServerMapper.add(serverItem);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 更新缓存
|
|
||||||
if (zlmServerStatus.get(serverItem.getId()) == null) {
|
|
||||||
zlmServers.put(serverItem.getId(), serverItem);
|
|
||||||
zlmServerStatus.put(serverItem.getId(),0);
|
|
||||||
}
|
|
||||||
// 查询服务流数量
|
|
||||||
IMediaServerItem finalServerItem = serverItem;
|
|
||||||
zlmresTfulUtils.getMediaList(serverItem, null, null, "rtmp",(mediaList ->{
|
|
||||||
Integer code = mediaList.getInteger("code");
|
|
||||||
if (code == 0) {
|
|
||||||
JSONArray data = mediaList.getJSONArray("data");
|
|
||||||
if (data != null) {
|
|
||||||
zlmServerStatus.put(finalServerItem.getId(),data.size());
|
|
||||||
}else {
|
|
||||||
zlmServerStatus.put(finalServerItem.getId(),0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新缓存
|
|
||||||
* @param mediaServerItem zlm服务
|
|
||||||
* @param count 在线数
|
|
||||||
* @param online 在线状态
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean online) {
|
public void resetOnlineServerItem(MediaServerItem serverItem) {
|
||||||
if (mediaServerItem != null) {
|
// 更新缓存
|
||||||
zlmServers.put(mediaServerItem.getId(), mediaServerItem);
|
String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
|
||||||
Collection<Integer> values = zlmServerStatus.values();
|
// 使用zset的分数作为当前并发量, 默认值设置为0
|
||||||
if (online != null && count != null) {
|
if (redisUtil.zScore(key, serverItem.getId()) == null) { // 不存在则设置默认值 已存在则重置
|
||||||
zlmServerStatus.put(mediaServerItem.getId(), count);
|
redisUtil.zAdd(key, serverItem.getId(), 0L);
|
||||||
}
|
// 查询服务流数量
|
||||||
|
zlmresTfulUtils.getMediaList(serverItem, null, null, "rtmp",(mediaList ->{
|
||||||
|
Integer code = mediaList.getInteger("code");
|
||||||
|
if (code == 0) {
|
||||||
|
JSONArray data = mediaList.getJSONArray("data");
|
||||||
|
if (data != null) {
|
||||||
|
redisUtil.zAdd(key, serverItem.getId(), data.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}else {
|
||||||
|
clearRTPServer(serverItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addCount(String mediaServerId) {
|
public void addCount(String mediaServerId) {
|
||||||
if (zlmServerStatus.get(mediaServerId) != null) {
|
if (mediaServerId == null) return;
|
||||||
zlmServerStatus.put(mediaServerId, zlmServerStatus.get(mediaServerId) + 1);
|
String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
|
||||||
}
|
Double aDouble = redisUtil.zScore(key, mediaServerId);
|
||||||
|
redisUtil.zIncrScore(key, mediaServerId, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeCount(String mediaServerId) {
|
public void removeCount(String mediaServerId) {
|
||||||
if (zlmServerStatus.get(mediaServerId) != null) {
|
String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
|
||||||
zlmServerStatus.put(mediaServerId, zlmServerStatus.get(mediaServerId) - 1);
|
redisUtil.zIncrScore(key, mediaServerId, - 1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,35 +334,18 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
|||||||
* @return MediaServerItem
|
* @return MediaServerItem
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public IMediaServerItem getMediaServerForMinimumLoad() {
|
public MediaServerItem getMediaServerForMinimumLoad() {
|
||||||
int mediaCount = -1;
|
String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
|
||||||
String key = null;
|
|
||||||
System.out.println(JSON.toJSONString(zlmServerStatus));
|
if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) {
|
||||||
if (zlmServerStatus.size() == 1) {
|
logger.info("获取负载最低的节点时无在线节点");
|
||||||
Map.Entry entry = zlmServerStatus.entrySet().iterator().next();
|
|
||||||
key= (String) entry.getKey();
|
|
||||||
}else {
|
|
||||||
for (String id : zlmServerStatus.keySet()) {
|
|
||||||
if (key == null) {
|
|
||||||
key = id;
|
|
||||||
mediaCount = zlmServerStatus.get(id);
|
|
||||||
}
|
|
||||||
if (zlmServerStatus.get(id) == 0) {
|
|
||||||
key = id;
|
|
||||||
break;
|
|
||||||
}else if (mediaCount >= zlmServerStatus.get(id)){
|
|
||||||
mediaCount = zlmServerStatus.get(id);
|
|
||||||
key = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == null) {
|
// 获取分数最低的,及并发最低的
|
||||||
logger.info("获取负载最低的节点时无在线节点");
|
Set<Object> objects = redisUtil.ZRange(key, 0, -1);
|
||||||
return null;
|
ArrayList<Object> MediaServerObjectS = new ArrayList<>(objects);
|
||||||
}else{
|
String mediaServerId = (String)MediaServerObjectS.get(0);
|
||||||
return zlmServers.get(key);
|
return getOne(mediaServerId);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -298,7 +353,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
|||||||
* @param mediaServerItem 服务ID
|
* @param mediaServerItem 服务ID
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setZLMConfig(IMediaServerItem mediaServerItem) {
|
public void setZLMConfig(MediaServerItem mediaServerItem) {
|
||||||
logger.info("[ {} ]-[ {}:{} ]设置zlm",
|
logger.info("[ {} ]-[ {}:{} ]设置zlm",
|
||||||
mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
|
mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
|
||||||
String protocol = sslEnabled ? "https" : "http";
|
String protocol = sslEnabled ? "https" : "http";
|
||||||
@ -333,8 +388,10 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
|||||||
logger.info("[ {} ]-[ {}:{} ]设置zlm成功",
|
logger.info("[ {} ]-[ {}:{} ]设置zlm成功",
|
||||||
mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
|
mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
|
||||||
}else {
|
}else {
|
||||||
logger.info("[ {} ]-[ {}:{} ]设置zlm失败" + responseJSON.getString("msg"),
|
logger.info("[ {} ]-[ {}:{} ]设置zlm失败",
|
||||||
mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
|
mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,7 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
@ -33,14 +31,14 @@ public class MediaServiceImpl implements IMediaService {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks) {
|
public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, JSONArray tracks) {
|
||||||
return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
|
return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) {
|
public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) {
|
||||||
StreamInfo streamInfo = null;
|
StreamInfo streamInfo = null;
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
||||||
if (mediaInfo == null) {
|
if (mediaInfo == null) {
|
||||||
return streamInfo;
|
return streamInfo;
|
||||||
}
|
}
|
||||||
@ -63,7 +61,7 @@ public class MediaServiceImpl implements IMediaService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr) {
|
public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr) {
|
||||||
StreamInfo streamInfoResult = new StreamInfo();
|
StreamInfo streamInfoResult = new StreamInfo();
|
||||||
streamInfoResult.setStreamId(stream);
|
streamInfoResult.setStreamId(stream);
|
||||||
streamInfoResult.setApp(app);
|
streamInfoResult.setApp(app);
|
||||||
|
@ -14,11 +14,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
|||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||||
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
|
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
|
||||||
import com.genersoft.iot.vmp.service.IMediaService;
|
import com.genersoft.iot.vmp.service.IMediaService;
|
||||||
@ -53,6 +54,9 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisUtil redis;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeferredResultHolder resultHolder;
|
private DeferredResultHolder resultHolder;
|
||||||
|
|
||||||
@ -73,7 +77,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlayResult play(IMediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
|
public PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
|
||||||
PlayResult playResult = new PlayResult();
|
PlayResult playResult = new PlayResult();
|
||||||
if (mediaServerItem == null) {
|
if (mediaServerItem == null) {
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
@ -97,14 +101,21 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
// 超时处理
|
// 超时处理
|
||||||
result.onTimeout(()->{
|
result.onTimeout(()->{
|
||||||
logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
||||||
// 释放rtpserver
|
|
||||||
mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
|
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());
|
||||||
WVPResult wvpResult = new WVPResult();
|
WVPResult wvpResult = new WVPResult();
|
||||||
wvpResult.setCode(-1);
|
wvpResult.setCode(-1);
|
||||||
wvpResult.setMsg("Timeout");
|
SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
|
||||||
|
if (dialog != null) {
|
||||||
|
wvpResult.setMsg("收流超时,请稍候重试");
|
||||||
|
}else {
|
||||||
|
wvpResult.setMsg("点播超时,请稍候重试");
|
||||||
|
}
|
||||||
msg.setData(wvpResult);
|
msg.setData(wvpResult);
|
||||||
|
// 点播超时回复BYE
|
||||||
|
cmder.streamByeCmd(device.getDeviceId(), channelId);
|
||||||
|
// 释放rtpserver
|
||||||
|
mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
|
||||||
resultHolder.invokeResult(msg);
|
resultHolder.invokeResult(msg);
|
||||||
});
|
});
|
||||||
result.onCompletion(()->{
|
result.onCompletion(()->{
|
||||||
@ -131,7 +142,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
WVPResult wvpResult = (WVPResult)responseEntity.getBody();
|
WVPResult wvpResult = (WVPResult)responseEntity.getBody();
|
||||||
if (wvpResult.getCode() == 0) {
|
if (wvpResult.getCode() == 0) {
|
||||||
StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
|
StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
|
MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
|
||||||
String streamUrl = streamInfoForSuccess.getFmp4();
|
String streamUrl = streamInfoForSuccess.getFmp4();
|
||||||
// 请求截图
|
// 请求截图
|
||||||
zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
|
zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
|
||||||
@ -142,14 +153,23 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (streamInfo == null) {
|
if (streamInfo == null) {
|
||||||
|
SSRCInfo ssrcInfo;
|
||||||
|
String streamId = null;
|
||||||
|
if (mediaServerItem.isRtpEnable()) {
|
||||||
|
streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId);
|
||||||
|
|
||||||
// 发送点播消息
|
// 发送点播消息
|
||||||
cmder.playStreamCmd(mediaServerItem, device, channelId, (IMediaServerItem mediaServerItemInUse, JSONObject response) -> {
|
cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {
|
||||||
logger.info("收到订阅消息: " + response.toJSONString());
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
onPublishHandlerForPlay(mediaServerItemInUse, response, deviceId, channelId, uuid.toString());
|
onPublishHandlerForPlay(mediaServerItemInUse, response, deviceId, channelId, uuid.toString());
|
||||||
if (hookEvent != null) {
|
if (hookEvent != null) {
|
||||||
hookEvent.response(mediaServerItem, response);
|
hookEvent.response(mediaServerItem, response);
|
||||||
}
|
}
|
||||||
}, (event) -> {
|
}, (event) -> {
|
||||||
|
// 点播返回sip错误
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
Response response = event.getResponse();
|
Response response = event.getResponse();
|
||||||
@ -162,6 +182,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
if (errorEvent != null) {
|
if (errorEvent != null) {
|
||||||
errorEvent.response(event);
|
errorEvent.response(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
String streamId = streamInfo.getStreamId();
|
String streamId = streamInfo.getStreamId();
|
||||||
@ -176,7 +197,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
return playResult;
|
return playResult;
|
||||||
}
|
}
|
||||||
String mediaServerId = streamInfo.getMediaServerId();
|
String mediaServerId = streamInfo.getMediaServerId();
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
||||||
|
|
||||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
|
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
|
||||||
if (rtpInfo != null && rtpInfo.getBoolean("exist")) {
|
if (rtpInfo != null && rtpInfo.getBoolean("exist")) {
|
||||||
@ -194,9 +215,17 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo)));
|
hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// TODO 点播前是否重置状态
|
||||||
redisCatchStorage.stopPlay(streamInfo);
|
redisCatchStorage.stopPlay(streamInfo);
|
||||||
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
||||||
cmder.playStreamCmd(mediaServerItem, device, channelId, (IMediaServerItem mediaServerItemInuse, JSONObject response) -> {
|
SSRCInfo ssrcInfo;
|
||||||
|
String streamId2 = null;
|
||||||
|
if (mediaServerItem.isRtpEnable()) {
|
||||||
|
streamId2 = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
||||||
|
}
|
||||||
|
ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2);
|
||||||
|
|
||||||
|
cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
|
||||||
logger.info("收到订阅消息: " + response.toJSONString());
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
|
onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
|
||||||
}, (event) -> {
|
}, (event) -> {
|
||||||
@ -218,7 +247,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPublishHandlerForPlay(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
|
public void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
|
StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
|
||||||
@ -228,14 +257,6 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
deviceChannel.setStreamId(streamInfo.getStreamId());
|
deviceChannel.setStreamId(streamInfo.getStreamId());
|
||||||
storager.startPlay(deviceId, channelId, streamInfo.getStreamId());
|
storager.startPlay(deviceId, channelId, streamInfo.getStreamId());
|
||||||
}
|
}
|
||||||
ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
|
|
||||||
SIPDialog dialog = (SIPDialog)transaction.getDialog();
|
|
||||||
StreamInfo.TransactionInfo transactionInfo = new StreamInfo.TransactionInfo();
|
|
||||||
transactionInfo.callId = dialog.getCallId().getCallId();
|
|
||||||
transactionInfo.localTag = dialog.getLocalTag();
|
|
||||||
transactionInfo.remoteTag = dialog.getRemoteTag();
|
|
||||||
transactionInfo.branch = dialog.getFirstTransactionInt().getBranchId();
|
|
||||||
streamInfo.setTransactionInfo(transactionInfo);
|
|
||||||
redisCatchStorage.startPlay(streamInfo);
|
redisCatchStorage.startPlay(streamInfo);
|
||||||
msg.setData(JSON.toJSONString(streamInfo));
|
msg.setData(JSON.toJSONString(streamInfo));
|
||||||
|
|
||||||
@ -254,10 +275,10 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IMediaServerItem getNewMediaServerItem(Device device) {
|
public MediaServerItem getNewMediaServerItem(Device device) {
|
||||||
if (device == null) return null;
|
if (device == null) return null;
|
||||||
String mediaServerId = device.getMediaServerId();
|
String mediaServerId = device.getMediaServerId();
|
||||||
IMediaServerItem mediaServerItem = null;
|
MediaServerItem mediaServerItem = null;
|
||||||
if (mediaServerId == null) {
|
if (mediaServerId == null) {
|
||||||
mediaServerItem = mediaServerService.getMediaServerForMinimumLoad();
|
mediaServerItem = mediaServerService.getMediaServerForMinimumLoad();
|
||||||
}else {
|
}else {
|
||||||
@ -270,7 +291,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPublishHandlerForPlayBack(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
|
public void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
|
StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
|
||||||
@ -285,7 +306,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public StreamInfo onPublishHandler(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
|
public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
|
||||||
String streamId = resonse.getString("stream");
|
String streamId = resonse.getString("stream");
|
||||||
JSONArray tracks = resonse.getJSONArray("tracks");
|
JSONArray tracks = resonse.getJSONArray("tracks");
|
||||||
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);
|
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);
|
||||||
|
@ -3,7 +3,6 @@ package com.genersoft.iot.vmp.service.impl;
|
|||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
||||||
import com.genersoft.iot.vmp.service.IGbStreamService;
|
import com.genersoft.iot.vmp.service.IGbStreamService;
|
||||||
@ -58,7 +57,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String save(StreamProxyItem param) {
|
public String save(StreamProxyItem param) {
|
||||||
IMediaServerItem mediaInfo;
|
MediaServerItem mediaInfo;
|
||||||
if ("auto".equals(param.getMediaServerId())){
|
if ("auto".equals(param.getMediaServerId())){
|
||||||
mediaInfo = mediaServerService.getMediaServerForMinimumLoad();
|
mediaInfo = mediaServerService.getMediaServerForMinimumLoad();
|
||||||
}else {
|
}else {
|
||||||
@ -120,7 +119,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
|||||||
@Override
|
@Override
|
||||||
public JSONObject addStreamProxyToZlm(StreamProxyItem param) {
|
public JSONObject addStreamProxyToZlm(StreamProxyItem param) {
|
||||||
JSONObject result = null;
|
JSONObject result = null;
|
||||||
IMediaServerItem mediaServerItem = null;
|
MediaServerItem mediaServerItem = null;
|
||||||
if (param.getMediaServerId() == null) {
|
if (param.getMediaServerId() == null) {
|
||||||
logger.warn("添加代理时MediaServerId 为null");
|
logger.warn("添加代理时MediaServerId 为null");
|
||||||
return null;
|
return null;
|
||||||
@ -141,7 +140,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
|||||||
@Override
|
@Override
|
||||||
public JSONObject removeStreamProxyFromZlm(StreamProxyItem param) {
|
public JSONObject removeStreamProxyFromZlm(StreamProxyItem param) {
|
||||||
if (param ==null) return null;
|
if (param ==null) return null;
|
||||||
IMediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
|
MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
|
||||||
JSONObject result = zlmresTfulUtils.closeStreams(mediaServerItem, param.getApp(), param.getStream());
|
JSONObject result = zlmresTfulUtils.closeStreams(mediaServerItem, param.getApp(), param.getStream());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -198,7 +197,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem) {
|
public JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem) {
|
||||||
JSONObject result = new JSONObject();
|
JSONObject result = new JSONObject();
|
||||||
JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
|
JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
|
||||||
if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0
|
if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0
|
||||||
|
@ -5,7 +5,6 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
import com.alibaba.fastjson.TypeReference;
|
import com.alibaba.fastjson.TypeReference;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
||||||
@ -43,7 +42,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
|||||||
private IMediaServerService mediaServerService;
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<StreamPushItem> handleJSON(String jsonData, IMediaServerItem mediaServerItem) {
|
public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) {
|
||||||
if (jsonData == null) return null;
|
if (jsonData == null) return null;
|
||||||
|
|
||||||
Map<String, StreamPushItem> result = new HashMap<>();
|
Map<String, StreamPushItem> result = new HashMap<>();
|
||||||
@ -98,7 +97,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
|||||||
@Override
|
@Override
|
||||||
public boolean removeFromGB(GbStream stream) {
|
public boolean removeFromGB(GbStream stream) {
|
||||||
int del = gbStreamMapper.del(stream.getApp(), stream.getStream());
|
int del = gbStreamMapper.del(stream.getApp(), stream.getStream());
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId());
|
MediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId());
|
||||||
JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream());
|
JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream());
|
||||||
if (mediaList == null) {
|
if (mediaList == null) {
|
||||||
streamPushMapper.del(stream.getApp(), stream.getStream());
|
streamPushMapper.del(stream.getApp(), stream.getStream());
|
||||||
|
@ -5,8 +5,6 @@ import com.genersoft.iot.vmp.common.StreamInfo;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -3,7 +3,6 @@ package com.genersoft.iot.vmp.storager;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package com.genersoft.iot.vmp.storager.dao;
|
package com.genersoft.iot.vmp.storager.dao;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import org.apache.ibatis.annotations.Insert;
|
import org.apache.ibatis.annotations.Insert;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
@ -35,6 +33,7 @@ public interface MediaServerMapper {
|
|||||||
"rtpEnable, " +
|
"rtpEnable, " +
|
||||||
"rtpPortRange, " +
|
"rtpPortRange, " +
|
||||||
"recordAssistPort, " +
|
"recordAssistPort, " +
|
||||||
|
"defaultServer, " +
|
||||||
"createTime, " +
|
"createTime, " +
|
||||||
"updateTime" +
|
"updateTime" +
|
||||||
") VALUES " +
|
") VALUES " +
|
||||||
@ -57,9 +56,10 @@ public interface MediaServerMapper {
|
|||||||
"${rtpEnable}, " +
|
"${rtpEnable}, " +
|
||||||
"'${rtpPortRange}', " +
|
"'${rtpPortRange}', " +
|
||||||
"${recordAssistPort}, " +
|
"${recordAssistPort}, " +
|
||||||
|
"${defaultServer}, " +
|
||||||
"'${createTime}', " +
|
"'${createTime}', " +
|
||||||
"'${updateTime}')")
|
"'${updateTime}')")
|
||||||
int add(IMediaServerItem mediaServerItem);
|
int add(MediaServerItem mediaServerItem);
|
||||||
|
|
||||||
@Update(value = {" <script>" +
|
@Update(value = {" <script>" +
|
||||||
"UPDATE media_server " +
|
"UPDATE media_server " +
|
||||||
@ -83,7 +83,7 @@ public interface MediaServerMapper {
|
|||||||
"<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" +
|
"<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" +
|
||||||
"WHERE id='${id}'"+
|
"WHERE id='${id}'"+
|
||||||
" </script>"})
|
" </script>"})
|
||||||
int update(IMediaServerItem mediaServerItem);
|
int update(MediaServerItem mediaServerItem);
|
||||||
|
|
||||||
@Select("SELECT * FROM media_server WHERE id='${id}'")
|
@Select("SELECT * FROM media_server WHERE id='${id}'")
|
||||||
MediaServerItem queryOne(String id);
|
MediaServerItem queryOne(String id);
|
||||||
@ -92,7 +92,7 @@ public interface MediaServerMapper {
|
|||||||
List<MediaServerItem> queryAll();
|
List<MediaServerItem> queryAll();
|
||||||
|
|
||||||
@Select("DELETE FROM media_server WHERE id='${id}'")
|
@Select("DELETE FROM media_server WHERE id='${id}'")
|
||||||
int delOne(String secret);
|
void delOne(String id);
|
||||||
|
|
||||||
@Select("SELECT * FROM media_server WHERE ip='${host}' and httpPort=${port}")
|
@Select("SELECT * FROM media_server WHERE ip='${host}' and httpPort=${port}")
|
||||||
MediaServerItem queryOneByHostAndPort(String host, int port);
|
MediaServerItem queryOneByHostAndPort(String host, int port);
|
||||||
|
@ -3,10 +3,7 @@ package com.genersoft.iot.vmp.storager.impl;
|
|||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
|
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
|
||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.genersoft.iot.vmp.utils;
|
||||||
|
|
||||||
|
public class ConfigConst {
|
||||||
|
/**
|
||||||
|
* 播流最大并发个数
|
||||||
|
*/
|
||||||
|
public static final Integer MAX_STRTEAM_COUNT = 10000;
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.genersoft.iot.vmp.utils;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class SerializeUtils {
|
||||||
|
public static byte[] serialize(Object obj){
|
||||||
|
byte[] bytes = null;
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream baos=new ByteArrayOutputStream();;
|
||||||
|
ObjectOutputStream oos=new ObjectOutputStream(baos);
|
||||||
|
oos.writeObject(obj);
|
||||||
|
bytes=baos.toByteArray();
|
||||||
|
baos.close();
|
||||||
|
oos.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
public static Object deSerialize(byte[] bytes){
|
||||||
|
Object obj=null;
|
||||||
|
try {
|
||||||
|
ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
|
||||||
|
ObjectInputStream ois=new ObjectInputStream(bais);
|
||||||
|
obj=ois.readObject();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
package com.genersoft.iot.vmp.utils.redis;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description:Jedis工具类
|
||||||
|
* @author: wangshaopeng@sunnybs.com
|
||||||
|
* @date: 2021年03月22日 下午8:27:29
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class JedisUtil {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JedisPool jedisPool;
|
||||||
|
|
||||||
|
// ============================== Key ==============================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查给定 key 是否存在。
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Boolean exists(String key) {
|
||||||
|
Jedis jedis = null;
|
||||||
|
try {
|
||||||
|
jedis = jedisPool.getResource();
|
||||||
|
Boolean exists = jedis.exists(key);
|
||||||
|
return exists;
|
||||||
|
} finally {
|
||||||
|
returnToPool(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================== Set ==============================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SADD key member [member ...]
|
||||||
|
* 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。
|
||||||
|
* 假如 key 不存在,则创建一个只包含 member 元素作成员的集合。
|
||||||
|
* 当 key 不是集合类型时,返回一个错误。
|
||||||
|
*/
|
||||||
|
public Long sadd(String key, String... members) {
|
||||||
|
Jedis jedis = null;
|
||||||
|
try {
|
||||||
|
jedis = jedisPool.getResource();
|
||||||
|
Long smove = jedis.sadd(key, members);
|
||||||
|
return smove;
|
||||||
|
} finally {
|
||||||
|
returnToPool(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMEMBERS key
|
||||||
|
* 返回集合 key 中的所有成员。
|
||||||
|
* 不存在的 key 被视为空集合。
|
||||||
|
*/
|
||||||
|
public Set<String> smembers(String key) {
|
||||||
|
Jedis jedis = null;
|
||||||
|
try {
|
||||||
|
jedis = jedisPool.getResource();
|
||||||
|
Set<String> smembers = jedis.smembers(key);
|
||||||
|
return smembers;
|
||||||
|
} finally {
|
||||||
|
returnToPool(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SREM key member1 [member2]
|
||||||
|
* 移除集合中一个或多个成员
|
||||||
|
*/
|
||||||
|
public Long srem(String key, String... member) {
|
||||||
|
Jedis jedis = null;
|
||||||
|
try {
|
||||||
|
jedis = jedisPool.getResource();
|
||||||
|
Long srem = jedis.srem(key, member);
|
||||||
|
return srem;
|
||||||
|
} finally {
|
||||||
|
returnToPool(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void returnToPool(Jedis jedis) {
|
||||||
|
if (jedis != null) {
|
||||||
|
jedis.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -415,10 +415,10 @@ public class RedisUtil {
|
|||||||
*
|
*
|
||||||
* @param key
|
* @param key
|
||||||
* @param value
|
* @param value
|
||||||
* @param score
|
* @param delta -1 表示减 1 表示加1
|
||||||
*/
|
*/
|
||||||
public Double zIncrScore(Object key, Object value, double score) {
|
public Double zIncrScore(Object key, Object value, double delta) {
|
||||||
return redisTemplate.opsForZSet().incrementScore(key, value, score);
|
return redisTemplate.opsForZSet().incrementScore(key, value, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,13 +2,12 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
@ -37,7 +36,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
|||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import org.springframework.web.context.request.async.DeferredResult;
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
import java.util.Enumeration;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -89,7 +88,7 @@ public class PlayController {
|
|||||||
|
|
||||||
// 获取可用的zlm
|
// 获取可用的zlm
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
|
MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
|
||||||
PlayResult playResult = playService.play(newMediaServerItem, deviceId, channelId, null, null);
|
PlayResult playResult = playService.play(newMediaServerItem, deviceId, channelId, null, null);
|
||||||
|
|
||||||
return playResult.getResult();
|
return playResult.getResult();
|
||||||
@ -174,7 +173,7 @@ public class PlayController {
|
|||||||
logger.warn("视频转码API调用失败!, 视频流已经停止!");
|
logger.warn("视频转码API调用失败!, 视频流已经停止!");
|
||||||
return new ResponseEntity<String>("未找到视频流信息, 视频流可能已经停止", HttpStatus.OK);
|
return new ResponseEntity<String>("未找到视频流信息, 视频流可能已经停止", HttpStatus.OK);
|
||||||
}
|
}
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
|
MediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
|
||||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
|
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
|
||||||
if (!rtpInfo.getBoolean("exist")) {
|
if (!rtpInfo.getBoolean("exist")) {
|
||||||
logger.warn("视频转码API调用失败!, 视频流已停止推流!");
|
logger.warn("视频转码API调用失败!, 视频流已停止推流!");
|
||||||
@ -219,7 +218,7 @@ public class PlayController {
|
|||||||
result.put("msg", "mediaServerId is null");
|
result.put("msg", "mediaServerId is null");
|
||||||
return new ResponseEntity<String>( result.toJSONString(), HttpStatus.BAD_REQUEST);
|
return new ResponseEntity<String>( result.toJSONString(), HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
||||||
if (mediaInfo == null) {
|
if (mediaInfo == null) {
|
||||||
result.put("code", 0);
|
result.put("code", 0);
|
||||||
result.put("msg", "使用的流媒体已经停止运行");
|
result.put("msg", "使用的流媒体已经停止运行");
|
||||||
@ -307,16 +306,16 @@ public class PlayController {
|
|||||||
logger.debug("获取所有的ssrc");
|
logger.debug("获取所有的ssrc");
|
||||||
}
|
}
|
||||||
JSONArray objects = new JSONArray();
|
JSONArray objects = new JSONArray();
|
||||||
for(Map.Entry<String, String> entry: streamSession.getSsrcMap().entrySet()) {
|
List<SsrcTransaction> allSsrc = streamSession.getAllSsrc();
|
||||||
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
|
for (SsrcTransaction transaction : allSsrc) {
|
||||||
JSONObject jsonObject = new JSONObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
String[] keyArray = entry.getKey().split("_");
|
jsonObject.put("deviceId", transaction.getDeviceId());
|
||||||
jsonObject.put("deviceId", keyArray[0]);
|
jsonObject.put("channelId", transaction.getChannelId());
|
||||||
jsonObject.put("channelId", keyArray[1]);
|
jsonObject.put("ssrc", transaction.getSsrc());
|
||||||
jsonObject.put("ssrc", entry.getValue());
|
jsonObject.put("streamId", transaction.getStreamId());
|
||||||
jsonObject.put("streamId", streamSession.getStreamIdMap().get(entry.getKey()));
|
|
||||||
objects.add(jsonObject);
|
objects.add(jsonObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
WVPResult<JSONObject> result = new WVPResult<>();
|
WVPResult<JSONObject> result = new WVPResult<>();
|
||||||
result.setCode(0);
|
result.setCode(0);
|
||||||
result.setMsg("success");
|
result.setMsg("success");
|
||||||
|
@ -3,9 +3,9 @@ package com.genersoft.iot.vmp.vmanager.gb28181.playback;
|
|||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
//import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.service.IPlayService;
|
import com.genersoft.iot.vmp.service.IPlayService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
@ -58,6 +58,9 @@ public class DownloadController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DeferredResultHolder resultHolder;
|
private DeferredResultHolder resultHolder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
@ApiOperation("开始历史媒体下载")
|
@ApiOperation("开始历史媒体下载")
|
||||||
@ApiImplicitParams({
|
@ApiImplicitParams({
|
||||||
@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
|
@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
|
||||||
@ -90,7 +93,7 @@ public class DownloadController {
|
|||||||
cmder.streamByeCmd(deviceId, channelId);
|
cmder.streamByeCmd(deviceId, channelId);
|
||||||
}
|
}
|
||||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
|
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
|
||||||
IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
|
MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
|
||||||
if (newMediaServerItem == null) {
|
if (newMediaServerItem == null) {
|
||||||
logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
@ -99,7 +102,10 @@ public class DownloadController {
|
|||||||
resultHolder.invokeResult(msg);
|
resultHolder.invokeResult(msg);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
cmder.downloadStreamCmd(newMediaServerItem, device, channelId, startTime, endTime, downloadSpeed, (IMediaServerItem mediaServerItem, JSONObject response) -> {
|
|
||||||
|
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null);
|
||||||
|
|
||||||
|
cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> {
|
||||||
logger.info("收到订阅消息: " + response.toJSONString());
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
|
playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
|
||||||
}, event -> {
|
}, event -> {
|
||||||
|
@ -4,8 +4,9 @@ import com.genersoft.iot.vmp.common.StreamInfo;
|
|||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
//import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
//import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.service.IPlayService;
|
import com.genersoft.iot.vmp.service.IPlayService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
@ -58,6 +59,9 @@ public class PlaybackController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DeferredResultHolder resultHolder;
|
private DeferredResultHolder resultHolder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
@ApiOperation("开始视频回放")
|
@ApiOperation("开始视频回放")
|
||||||
@ApiImplicitParams({
|
@ApiImplicitParams({
|
||||||
@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
|
@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
|
||||||
@ -74,6 +78,15 @@ public class PlaybackController {
|
|||||||
}
|
}
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
|
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
|
||||||
|
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
|
||||||
|
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null);
|
||||||
|
|
||||||
// 超时处理
|
// 超时处理
|
||||||
result.onTimeout(()->{
|
result.onTimeout(()->{
|
||||||
logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
||||||
@ -82,14 +95,14 @@ public class PlaybackController {
|
|||||||
msg.setData("Timeout");
|
msg.setData("Timeout");
|
||||||
resultHolder.invokeResult(msg);
|
resultHolder.invokeResult(msg);
|
||||||
});
|
});
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
|
||||||
StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
|
StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
|
||||||
if (streamInfo != null) {
|
if (streamInfo != null) {
|
||||||
// 停止之前的回放
|
// 停止之前的回放
|
||||||
cmder.streamByeCmd(deviceId, channelId);
|
cmder.streamByeCmd(deviceId, channelId);
|
||||||
}
|
}
|
||||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
|
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
|
||||||
IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
|
|
||||||
if (newMediaServerItem == null) {
|
if (newMediaServerItem == null) {
|
||||||
logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
@ -98,7 +111,8 @@ public class PlaybackController {
|
|||||||
resultHolder.invokeResult(msg);
|
resultHolder.invokeResult(msg);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
cmder.playbackStreamCmd(newMediaServerItem, device, channelId, startTime, endTime, (IMediaServerItem mediaServerItem, JSONObject response) -> {
|
|
||||||
|
cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> {
|
||||||
logger.info("收到订阅消息: " + response.toJSONString());
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
|
playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
|
||||||
}, event -> {
|
}, event -> {
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.genersoft.iot.vmp.vmanager.gb28181.session;
|
||||||
|
|
||||||
|
public enum PlayTypeEnum {
|
||||||
|
|
||||||
|
PLAY("0", "直播"),
|
||||||
|
PLAY_BACK("1", "回放");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
PlayTypeEnum(String value, String name) {
|
||||||
|
this.value = value;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,8 @@
|
|||||||
package com.genersoft.iot.vmp.vmanager.server;
|
package com.genersoft.iot.vmp.vmanager.server;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.VManageBootstrap;
|
import com.genersoft.iot.vmp.VManageBootstrap;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||||
import gov.nist.javax.sip.SipStackImpl;
|
import gov.nist.javax.sip.SipStackImpl;
|
||||||
@ -17,7 +15,6 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import javax.sip.ListeningPoint;
|
import javax.sip.ListeningPoint;
|
||||||
import javax.sip.ObjectInUseException;
|
import javax.sip.ObjectInUseException;
|
||||||
import javax.sip.SipProvider;
|
import javax.sip.SipProvider;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -38,19 +35,30 @@ public class ServerController {
|
|||||||
@ApiOperation("流媒体服务列表")
|
@ApiOperation("流媒体服务列表")
|
||||||
@GetMapping(value = "/media_server/list")
|
@GetMapping(value = "/media_server/list")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public WVPResult<List<IMediaServerItem>> getMediaServerList(){
|
public WVPResult<List<MediaServerItem>> getMediaServerList(){
|
||||||
WVPResult<List<IMediaServerItem>> result = new WVPResult<>();
|
WVPResult<List<MediaServerItem>> result = new WVPResult<>();
|
||||||
result.setCode(0);
|
result.setCode(0);
|
||||||
result.setMsg("success");
|
result.setMsg("success");
|
||||||
result.setData(mediaServerService.getAll());
|
result.setData(mediaServerService.getAll());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation("在线流媒体服务列表")
|
||||||
|
@GetMapping(value = "/media_server/online/list")
|
||||||
|
@ResponseBody
|
||||||
|
public WVPResult<List<MediaServerItem>> getOnlineMediaServerList(){
|
||||||
|
WVPResult<List<MediaServerItem>> result = new WVPResult<>();
|
||||||
|
result.setCode(0);
|
||||||
|
result.setMsg("success");
|
||||||
|
result.setData(mediaServerService.getAllOnline());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@ApiOperation("获取流媒体服务")
|
@ApiOperation("获取流媒体服务")
|
||||||
@GetMapping(value = "/media_server/one/{id}")
|
@GetMapping(value = "/media_server/one/{id}")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public WVPResult<IMediaServerItem> getMediaServer(@PathVariable String id){
|
public WVPResult<MediaServerItem> getMediaServer(@PathVariable String id){
|
||||||
WVPResult<IMediaServerItem> result = new WVPResult<>();
|
WVPResult<MediaServerItem> result = new WVPResult<>();
|
||||||
result.setCode(0);
|
result.setCode(0);
|
||||||
result.setMsg("success");
|
result.setMsg("success");
|
||||||
result.setData(mediaServerService.getOne(id));
|
result.setData(mediaServerService.getOne(id));
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.vmanager.streamProxy;
|
package com.genersoft.iot.vmp.vmanager.streamProxy;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
@ -9,7 +8,6 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|||||||
import com.genersoft.iot.vmp.service.IStreamProxyService;
|
import com.genersoft.iot.vmp.service.IStreamProxyService;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
import io.netty.util.internal.StringUtil;
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
import io.swagger.annotations.ApiImplicitParams;
|
import io.swagger.annotations.ApiImplicitParams;
|
||||||
@ -86,7 +84,7 @@ public class StreamProxyController {
|
|||||||
public WVPResult getFFmpegCMDs(@RequestParam String mediaServerId){
|
public WVPResult getFFmpegCMDs(@RequestParam String mediaServerId){
|
||||||
logger.debug("获取节点[ {} ]ffmpeg.cmd模板", mediaServerId );
|
logger.debug("获取节点[ {} ]ffmpeg.cmd模板", mediaServerId );
|
||||||
|
|
||||||
IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||||
JSONObject data = streamProxyService.getFFmpegCMDs(mediaServerItem);
|
JSONObject data = streamProxyService.getFFmpegCMDs(mediaServerItem);
|
||||||
WVPResult<JSONObject> result = new WVPResult<>();
|
WVPResult<JSONObject> result = new WVPResult<>();
|
||||||
result.setCode(0);
|
result.setCode(0);
|
||||||
|
@ -17,6 +17,12 @@ spring:
|
|||||||
password:
|
password:
|
||||||
# [可选] 超时时间
|
# [可选] 超时时间
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
# [可选] 一个pool最多可分配多少个jedis实例
|
||||||
|
poolMaxTotal: 1000
|
||||||
|
# [可选] 一个pool最多有多少个状态为idle(空闲)的jedis实例
|
||||||
|
poolMaxIdle: 500
|
||||||
|
# [可选] 最大的等待时间(秒)
|
||||||
|
poolMaxWait: 5
|
||||||
# [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置
|
# [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置
|
||||||
datasource:
|
datasource:
|
||||||
# 使用mysql 打开23-28行注释, 删除29-36行
|
# 使用mysql 打开23-28行注释, 删除29-36行
|
||||||
@ -124,6 +130,7 @@ logging:
|
|||||||
level:
|
level:
|
||||||
com.genersoft.iot: debug
|
com.genersoft.iot: debug
|
||||||
com.genersoft.iot.vmp.storager.dao: info
|
com.genersoft.iot.vmp.storager.dao: info
|
||||||
|
com.genersoft.iot.vmp.gb28181: info
|
||||||
# [根据业务需求配置]
|
# [根据业务需求配置]
|
||||||
user-settings:
|
user-settings:
|
||||||
# [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
|
# [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
|
||||||
|
@ -76,6 +76,8 @@ logging:
|
|||||||
level:
|
level:
|
||||||
com.genersoft.iot: debug
|
com.genersoft.iot: debug
|
||||||
com.genersoft.iot.vmp.storager.dao: info
|
com.genersoft.iot.vmp.storager.dao: info
|
||||||
|
com.genersoft.iot.vmp.gb28181: info
|
||||||
|
|
||||||
# [根据业务需求配置]
|
# [根据业务需求配置]
|
||||||
user-settings:
|
user-settings:
|
||||||
# 推流直播是否录制
|
# 推流直播是否录制
|
||||||
|
Binary file not shown.
@ -9,7 +9,7 @@ class MediaServer{
|
|||||||
getMediaServerList(callback){
|
getMediaServerList(callback){
|
||||||
this.$axios({
|
this.$axios({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url:`/api/server/media_server/list`,
|
url:`/api/server/media_server/online/list`,
|
||||||
}).then(function (res) {
|
}).then(function (res) {
|
||||||
if (typeof (callback) == "function") callback(res.data)
|
if (typeof (callback) == "function") callback(res.data)
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user