优化集群方案, 每个zlm一套ssrc;
优化集群下的docker接入逻辑;
更正sql脚本;
支持重启不设置设备离线。重启SIP事务不丢失
| | |
| | | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| | | <maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format> |
| | | <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> |
| | |
| | | <artifactId>spring-boot-starter-security</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>redis.clients</groupId> |
| | | <artifactId>jedis</artifactId> |
| | | <version>${jedis-version}</version> |
| | | </dependency> |
| | | |
| | | <!-- druid数据库连接池 --> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | |
| | | -- 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 |
| | | ( |
| | | deviceId varchar(50) not null |
| | | deviceId varchar(50) not null |
| | | primary key, |
| | | name varchar(255) null, |
| | | manufacturer varchar(255) null, |
| | | model varchar(255) null, |
| | | firmware varchar(255) null, |
| | | transport varchar(50) null, |
| | | streamMode varchar(50) null, |
| | | online varchar(50) null, |
| | | registerTime varchar(50) null, |
| | | keepaliveTime varchar(50) null, |
| | | ip varchar(50) not null, |
| | | createTime varchar(50) not null, |
| | | updateTime varchar(50) not null, |
| | | port int not null, |
| | | expires int not null, |
| | | hostAddress varchar(50) not null |
| | | name varchar(255) null, |
| | | manufacturer varchar(255) null, |
| | | model varchar(255) null, |
| | | firmware varchar(255) null, |
| | | transport varchar(50) null, |
| | | streamMode varchar(50) null, |
| | | online varchar(50) null, |
| | | registerTime varchar(50) null, |
| | | keepaliveTime varchar(50) null, |
| | | ip varchar(50) not null, |
| | | createTime varchar(50) not null, |
| | | updateTime varchar(50) not null, |
| | | port int not null, |
| | | expires int not null, |
| | | hostAddress varchar(50) not null |
| | | ); |
| | | |
| | | create table device_channel |
| | | ( |
| | | channelId varchar(50) not null, |
| | | channelId varchar(50) not null, |
| | | name varchar(255) null, |
| | | manufacture varchar(50) null, |
| | | model varchar(50) null, |
| | | owner varchar(50) null, |
| | | civilCode varchar(50) null, |
| | | block varchar(50) null, |
| | | address varchar(50) null, |
| | | parentId varchar(50) null, |
| | | manufacture varchar(50) null, |
| | | model varchar(50) null, |
| | | owner varchar(50) null, |
| | | civilCode varchar(50) null, |
| | | block varchar(50) null, |
| | | address varchar(50) null, |
| | | parentId varchar(50) null, |
| | | safetyWay int null, |
| | | registerWay int null, |
| | | certNum varchar(50) null, |
| | | certNum varchar(50) null, |
| | | certifiable int null, |
| | | errCode int null, |
| | | endTime varchar(50) null, |
| | | secrecy varchar(50) null, |
| | | ipAddress varchar(50) null, |
| | | endTime varchar(50) null, |
| | | secrecy varchar(50) null, |
| | | ipAddress varchar(50) null, |
| | | port int null, |
| | | password varchar(255) null, |
| | | PTZType int null, |
| | | status int null, |
| | | longitude double null, |
| | | latitude double null, |
| | | streamId varchar(50) null, |
| | | deviceId varchar(50) not null, |
| | | parental varchar(50) null, |
| | | hasAudio bit(1) null, |
| | | createTime varchar(50) not null, |
| | | updateTime varchar(50) not null, |
| | | streamId varchar(50) null, |
| | | deviceId varchar(50) not null, |
| | | parental varchar(50) null, |
| | | hasAudio bit null, |
| | | createTime varchar(50) not null, |
| | | updateTime varchar(50) not null, |
| | | primary key (channelId, deviceId) |
| | | ); |
| | | |
| | | create table device_mobile_position |
| | | ( |
| | | deviceId varchar(50) not null, |
| | | deviceId varchar(50) not null, |
| | | deviceName varchar(255) null, |
| | | time varchar(50) not null, |
| | | time varchar(50) not null, |
| | | longitude double not null, |
| | | latitude double not null, |
| | | altitude double null, |
| | | speed double null, |
| | | direction double null, |
| | | reportSource varchar(50) null, |
| | | geodeticSystem varchar(50) null, |
| | | cnLng varchar(50) null, |
| | | cnLat varchar(50) null, |
| | | reportSource varchar(50) null, |
| | | geodeticSystem varchar(50) null, |
| | | cnLng varchar(50) null, |
| | | cnLat varchar(50) null, |
| | | primary key (deviceId, time) |
| | | ); |
| | | |
| | | create table gb_stream |
| | | ( |
| | | app varchar(255) not null, |
| | | stream varchar(255) not null, |
| | | gbId varchar(50) not null, |
| | | name varchar(255) null, |
| | | longitude double null, |
| | | latitude double null, |
| | | streamType varchar(50) null, |
| | | status int null, |
| | | app varchar(255) not null, |
| | | stream varchar(255) not null, |
| | | gbId varchar(50) not null, |
| | | name varchar(255) null, |
| | | longitude double null, |
| | | latitude double null, |
| | | streamType varchar(50) null, |
| | | mediaServerId varchar(50) null, |
| | | status int null, |
| | | 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 |
| | | ( |
| | | id int auto_increment, |
| | | id int auto_increment, |
| | | enable int null, |
| | | name varchar(255) null, |
| | | serverGBId varchar(50) not null, |
| | | serverGBDomain varchar(50) null, |
| | | serverIP varchar(50) null, |
| | | serverGBId varchar(50) not null, |
| | | serverGBDomain varchar(50) null, |
| | | serverIP varchar(50) null, |
| | | serverPort int null, |
| | | deviceGBId varchar(50) not null, |
| | | deviceIp varchar(50) null, |
| | | devicePort varchar(50) null, |
| | | deviceGBId varchar(50) not null, |
| | | deviceIp varchar(50) null, |
| | | devicePort varchar(50) null, |
| | | username varchar(255) null, |
| | | password varchar(50) null, |
| | | expires varchar(50) null, |
| | | keepTimeout varchar(50) null, |
| | | transport varchar(50) null, |
| | | characterSet varchar(50) null, |
| | | password varchar(50) null, |
| | | expires varchar(50) null, |
| | | keepTimeout varchar(50) null, |
| | | transport varchar(50) null, |
| | | characterSet varchar(50) null, |
| | | ptz int null, |
| | | rtcp int null, |
| | | status bit(1) null, |
| | | status bit null, |
| | | primary key (id, serverGBId) |
| | | ); |
| | | |
| | |
| | | |
| | | create table platform_gb_stream |
| | | ( |
| | | platformId varchar(50) not null, |
| | | platformId varchar(50) not null, |
| | | app varchar(255) not null, |
| | | stream varchar(255) not null, |
| | | primary key (platformId, app, stream) |
| | |
| | | |
| | | create table stream_proxy |
| | | ( |
| | | type varchar(50) not null, |
| | | type varchar(50) not null, |
| | | app varchar(255) not null, |
| | | stream varchar(255) not null, |
| | | url varchar(255) null, |
| | |
| | | dst_url varchar(255) null, |
| | | timeout_ms int null, |
| | | ffmpeg_cmd_key varchar(255) null, |
| | | rtp_type varchar(50) null, |
| | | mediaServerId varchar(50) null, |
| | | enable_hls bit(1) null, |
| | | enable_mp4 bit(1) null, |
| | | enable bit(1) not null, |
| | | rtp_type varchar(50) null, |
| | | mediaServerId varchar(50) null, |
| | | enable_hls bit null, |
| | | enable_mp4 bit null, |
| | | enable bit not null, |
| | | createTime varchar(50) not null, |
| | | primary key (app, stream) |
| | | ); |
| | | |
| | |
| | | ( |
| | | app varchar(255) not null, |
| | | stream varchar(255) not null, |
| | | totalReaderCount varchar(50) null, |
| | | totalReaderCount varchar(50) null, |
| | | originType int null, |
| | | originTypeStr varchar(50) null, |
| | | originTypeStr varchar(50) null, |
| | | createStamp int null, |
| | | aliveSecond int null, |
| | | mediaServerId varchar(50) null, |
| | | primary key (app, stream) |
| | | ); |
| | | |
| | |
| | | username varchar(255) not null, |
| | | password varchar(255) 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 |
| | | ); |
| | |
| | |
|
| | | 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 DEVICE_PREFIX = "VMP_DEVICE_";
|
| | |
| | | public static final String EVENT_OUTLINE_UNREGISTER = "1";
|
| | |
|
| | | 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_";
|
| | | }
|
| | |
| | | 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 org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | |
| | | @Configuration("mediaConfig") |
| | | public class MediaConfig implements IMediaServerItem { |
| | | public class MediaConfig{ |
| | | |
| | | @Value("${media.id:}") |
| | | private String id; |
| | |
| | | |
| | | @Value("${sip.ip}") |
| | | private String sipIp; |
| | | |
| | | @Value("${sip.domain}") |
| | | private String sipDomain; |
| | | |
| | | @Value("${media.sdp-ip:${media.ip}}") |
| | | private String sdpIp; |
| | |
| | | @Value("${media.record-assist-port:0}") |
| | | private Integer recordAssistPort = 0; |
| | | |
| | | private String updateTime; |
| | | |
| | | private String createTime; |
| | | |
| | | private boolean docker = false; |
| | | |
| | | private int count; |
| | | |
| | | |
| | | public String getId() { |
| | | return id; |
| | | } |
| | | |
| | | public void setId(String id) { |
| | | this.id = id; |
| | | } |
| | | |
| | | public String getIp() { |
| | | return ip; |
| | | } |
| | | |
| | | public void setIp(String ip) { |
| | | this.ip = ip; |
| | | } |
| | | |
| | | public String getHookIp() { |
| | |
| | | |
| | | } |
| | | |
| | | public void setHookIp(String hookIp) { |
| | | this.hookIp = hookIp; |
| | | } |
| | | |
| | | public String getSipIp() { |
| | | 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() { |
| | | return httpPort; |
| | | } |
| | | |
| | | @Override |
| | | public void setHttpPort(int httpPort) { |
| | | |
| | | } |
| | | |
| | | public void setHttpPort(Integer httpPort) { |
| | | this.httpPort = httpPort; |
| | | } |
| | | |
| | | public int getHttpSSlPort() { |
| | | return httpSSlPort; |
| | | } |
| | | |
| | | @Override |
| | | public void setHttpSSlPort(int httpSSlPort) { |
| | | |
| | | } |
| | | |
| | | public void setHttpSSlPort(Integer httpSSlPort) { |
| | | this.httpSSlPort = httpSSlPort; |
| | | } |
| | | |
| | | public int getRtmpPort() { |
| | | return rtmpPort; |
| | | } |
| | | |
| | | @Override |
| | | public void setRtmpPort(int rtmpPort) { |
| | | |
| | | } |
| | | |
| | | public void setRtmpPort(Integer rtmpPort) { |
| | | this.rtmpPort = rtmpPort; |
| | | } |
| | | |
| | | |
| | | public int getRtmpSSlPort() { |
| | | return rtmpSSlPort; |
| | | } |
| | | |
| | | @Override |
| | | public void setRtmpSSlPort(int rtmpSSlPort) { |
| | | |
| | | } |
| | | |
| | | public void setRtmpSSlPort(Integer rtmpSSlPort) { |
| | | this.rtmpSSlPort = rtmpSSlPort; |
| | | } |
| | | |
| | | public int getRtpProxyPort() { |
| | |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void setRtpProxyPort(int rtpProxyPort) { |
| | | |
| | | } |
| | | |
| | | public void setRtpProxyPort(Integer rtpProxyPort) { |
| | | this.rtpProxyPort = rtpProxyPort; |
| | | } |
| | | |
| | | public int getRtspPort() { |
| | | return rtspPort; |
| | | } |
| | | |
| | | @Override |
| | | public void setRtspPort(int rtspPort) { |
| | | |
| | | } |
| | | |
| | | public void setRtspPort(Integer rtspPort) { |
| | | this.rtspPort = rtspPort; |
| | | } |
| | | |
| | | public int getRtspSSLPort() { |
| | | return rtspSSLPort; |
| | | } |
| | | |
| | | @Override |
| | | public void setRtspSSLPort(int rtspSSLPort) { |
| | | |
| | | } |
| | | |
| | | public void setRtspSSLPort(Integer rtspSSLPort) { |
| | | this.rtspSSLPort = rtspSSLPort; |
| | | } |
| | | |
| | | public boolean isAutoConfig() { |
| | | return autoConfig; |
| | | } |
| | | |
| | | public void setAutoConfig(boolean autoConfig) { |
| | | this.autoConfig = autoConfig; |
| | | } |
| | | |
| | | public String getSecret() { |
| | | return secret; |
| | | } |
| | | |
| | | public void setSecret(String secret) { |
| | | this.secret = secret; |
| | | } |
| | | |
| | | public String getStreamNoneReaderDelayMS() { |
| | | return streamNoneReaderDelayMS; |
| | | } |
| | | |
| | | public void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS) { |
| | | this.streamNoneReaderDelayMS = streamNoneReaderDelayMS; |
| | | } |
| | | |
| | | public boolean isRtpEnable() { |
| | | return rtpEnable; |
| | | } |
| | | |
| | | public void setRtpEnable(boolean rtpEnable) { |
| | | this.rtpEnable = rtpEnable; |
| | | } |
| | | |
| | | public String getRtpPortRange() { |
| | | return rtpPortRange; |
| | | } |
| | | |
| | | public void setRtpPortRange(String rtpPortRange) { |
| | | this.rtpPortRange = rtpPortRange; |
| | | } |
| | | |
| | | |
| | | public int getRecordAssistPort() { |
| | | 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 MediaServerItem getMediaSerItem(){ |
| | | MediaServerItem mediaServerItem = new MediaServerItem(); |
| | | mediaServerItem.setId(id); |
| | | mediaServerItem.setIp(ip); |
| | | mediaServerItem.setDocker(true); |
| | | mediaServerItem.setDefaultServer(true); |
| | | mediaServerItem.setHookIp(hookIp); |
| | | mediaServerItem.setSdpIp(sdpIp); |
| | | mediaServerItem.setStreamIp(streamIp); |
| | |
| | | mediaServerItem.setRtpEnable(rtpEnable); |
| | | mediaServerItem.setRtpPortRange(rtpPortRange); |
| | | mediaServerItem.setRecordAssistPort(recordAssistPort); |
| | | mediaServerItem.setCreateTime(createTime); |
| | | mediaServerItem.setUpdateTime(updateTime); |
| | | mediaServerItem.setCount(count); |
| | | |
| | | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | mediaServerItem.setCreateTime(format.format(new Date(System.currentTimeMillis()))); |
| | | mediaServerItem.setUpdateTime(format.format(new Date(System.currentTimeMillis()))); |
| | | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | 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 org.apache.catalina.connector.ClientAbortException; |
| | | import org.apache.http.HttpHost; |
| | |
| | | @Override |
| | | protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) { |
| | | String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString); |
| | | IMediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI()); |
| | | MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI()); |
| | | if (mediaInfo != null) { |
| | | if (!StringUtils.isEmpty(queryStr)) { |
| | | queryStr += "&secret=" + mediaInfo.getSecret(); |
| | |
| | | @Override |
| | | protected String getTargetUri(HttpServletRequest servletRequest) { |
| | | String requestURI = servletRequest.getRequestURI(); |
| | | IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | |
| | | String uri = null; |
| | | if (mediaInfo != null) { |
| | |
| | | @Override |
| | | protected HttpHost getTargetHost(HttpServletRequest servletRequest) { |
| | | String requestURI = servletRequest.getRequestURI(); |
| | | IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | HttpHost host; |
| | | if (mediaInfo != null) { |
| | | host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort()); |
| | |
| | | /** |
| | | * 根据uri获取流媒体信息 |
| | | */ |
| | | IMediaServerItem getMediaInfoByUri(String uri){ |
| | | MediaServerItem getMediaInfoByUri(String uri){ |
| | | String[] split = uri.split("/"); |
| | | String mediaServerId = split[2]; |
| | | return mediaServerService.getOne(mediaServerId); |
| | |
| | | @Override |
| | | protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) { |
| | | String requestURI = servletRequest.getRequestURI(); |
| | | IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | String url = super.rewriteUrlFromRequest(servletRequest); |
| | | if (mediaInfo == null) { |
| | | return url; |
| | |
| | | @Override |
| | | protected String getTargetUri(HttpServletRequest servletRequest) { |
| | | String requestURI = servletRequest.getRequestURI(); |
| | | IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | |
| | | String uri = null; |
| | | if (mediaInfo != null) { |
| | |
| | | @Override |
| | | protected HttpHost getTargetHost(HttpServletRequest servletRequest) { |
| | | String requestURI = servletRequest.getRequestURI(); |
| | | IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | HttpHost host; |
| | | if (mediaInfo != null) { |
| | | host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort()); |
| | |
| | | /** |
| | | * 根据uri获取流媒体信息 |
| | | */ |
| | | IMediaServerItem getMediaInfoByUri(String uri){ |
| | | MediaServerItem getMediaInfoByUri(String uri){ |
| | | String[] split = uri.split("/"); |
| | | String mediaServerId = split[2]; |
| | | return mediaServerService.getOne(mediaServerId); |
| | |
| | | @Override |
| | | protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) { |
| | | String requestURI = servletRequest.getRequestURI(); |
| | | IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); |
| | | String url = super.rewriteUrlFromRequest(servletRequest); |
| | | if (mediaInfo == null) { |
| | | return url; |
| | |
| | | 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.context.annotation.Bean;
|
| | | import org.springframework.context.annotation.Configuration;
|
| | |
| | |
|
| | | import com.alibaba.fastjson.parser.ParserConfig;
|
| | | 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配置
|
| | |
| | | */
|
| | | @Configuration
|
| | | 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")
|
| | | public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
| | |
| | | template.setHashKeySerializer(new StringRedisSerializer());
|
| | | template.setConnectionFactory(redisConnectionFactory);
|
| | | // 使用fastjson时需设置此项,否则会报异常not support type
|
| | | ParserConfig.getGlobalInstance().setAutoTypeSupport(true); |
| | | ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
|
| | | return template;
|
| | | }
|
| | |
|
| | |
| | | import javax.sip.message.Response;
|
| | |
|
| | | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
| | | import gov.nist.javax.sip.SipProviderImpl;
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | | import org.springframework.beans.factory.annotation.Autowired;
|
| | |
| | | @Autowired
|
| | | private SipSubscribe sipSubscribe;
|
| | |
|
| | | private SipStack sipStack;
|
| | | private SipStackImpl sipStack;
|
| | |
|
| | | private SipFactory sipFactory;
|
| | |
|
| | |
| | | private ThreadPoolExecutor initSipServer() {
|
| | |
|
| | | int processThreadNum = Runtime.getRuntime().availableProcessors() * 10;
|
| | | LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<Runnable>(10000);
|
| | | LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<>(10000);
|
| | | processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum,
|
| | | 0L,TimeUnit.MILLISECONDS,processQueue,
|
| | | new ThreadPoolExecutor.CallerRunsPolicy());
|
| | |
| | |
|
| | | @Bean("tcpSipProvider")
|
| | | @DependsOn("sipStack")
|
| | | private SipProvider startTcpListener() {
|
| | | private SipProviderImpl startTcpListener() {
|
| | | ListeningPoint tcpListeningPoint = null;
|
| | | SipProvider tcpSipProvider = null;
|
| | | SipProviderImpl tcpSipProvider = null;
|
| | | try {
|
| | | tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "TCP");
|
| | | tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint);
|
| | | tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
|
| | | tcpSipProvider.addSipListener(this);
|
| | | 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) {
|
| | | e.printStackTrace();
|
| | | } catch (InvalidArgumentException e) {
|
| | |
| | |
|
| | | @Bean("udpSipProvider")
|
| | | @DependsOn("sipStack")
|
| | | private SipProvider startUdpListener() {
|
| | | private SipProviderImpl startUdpListener() {
|
| | | ListeningPoint udpListeningPoint = null;
|
| | | SipProvider udpSipProvider = null;
|
| | | SipProviderImpl udpSipProvider = null;
|
| | | try {
|
| | | udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP");
|
| | | udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
|
| | | udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
| | | udpSipProvider.addSipListener(this);
|
| | | // udpSipProvider.setAutomaticDialogSupportEnabled(false);
|
| | | } catch (TransportNotSupportedException e) {
|
| | | e.printStackTrace();
|
| | | } catch (InvalidArgumentException e) {
|
| | |
| | | */
|
| | | @Override
|
| | | public void processRequest(RequestEvent evt) {
|
| | | // logger.debug(evt.getRequest().toString());
|
| | | logger.debug(evt.getRequest().toString());
|
| | | // 由于jainsip是单线程程序,为提高性能并发处理
|
| | | processThreadPool.execute(() -> {
|
| | | if (processorFactory != null) {
|
| | |
| | | @Override
|
| | | public void processResponse(ResponseEvent evt) {
|
| | | Response response = evt.getResponse();
|
| | | // logger.debug(evt.getResponse().toString());
|
| | | logger.debug(evt.getResponse().toString());
|
| | | int status = response.getStatusCode();
|
| | | if (((status >= 200) && (status < 300)) || status == 401) { // Success!
|
| | | ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
|
| | |
| | | // TODO Auto-generated catch block
|
| | | e.printStackTrace();
|
| | | }
|
| | |
|
| | | if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
|
| | | CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
|
| | | if (callIdHeader != null) {
|
| | |
| | | @Override
|
| | | public void processIOException(IOExceptionEvent exceptionEvent) {
|
| | | // TODO Auto-generated method stub
|
| | |
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | @Override
|
| | | public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
|
| | | // TODO Auto-generated method stub
|
| | |
|
| | | }
|
| | |
|
| | | /**
|
New file |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| | | 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.dto.IMediaServerItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import com.genersoft.iot.vmp.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | |
| | | } |
| | | stream.append(sendRtpItem.getStreamId()); |
| | | redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId()); |
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| | | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| | | Map<String, Object> param = new HashMap<>(); |
| | | param.put("vhost", "__defaultVhost__"); |
| | | param.put("app", app.toString()); |
New file |
| | |
| | | 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; |
| | | } |
| | | |
| | | } |
| | |
| | | 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 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;
|
| | |
|
| | | /**
|
| | |
| | | @Component
|
| | | public class VideoStreamSessionManager {
|
| | |
|
| | | private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>();
|
| | | private ConcurrentHashMap<String, String> ssrcMap = new ConcurrentHashMap<>();
|
| | | private ConcurrentHashMap<String, String> streamIdMap = new ConcurrentHashMap<>();
|
| | | @Autowired
|
| | | private RedisUtil redisUtil;
|
| | |
|
| | | public String createPlaySsrc(){
|
| | | return SsrcUtil.getPlaySsrc();
|
| | | public void put(String deviceId, String channelId ,String ssrc, String streamId, String mediaServerId, ClientTransaction transaction){
|
| | | 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(){
|
| | | return SsrcUtil.getPlayBackSsrc();
|
| | |
|
| | | public void put(String deviceId, String channelId , Dialog dialog){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
| | | if (ssrcTransaction != null) {
|
| | | byte[] dialogByteArray = SerializeUtils.serialize(dialog);
|
| | | ssrcTransaction.setDialog(dialogByteArray);
|
| | | }
|
| | | redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId, ssrcTransaction);
|
| | | }
|
| | | |
| | | public void put(String deviceId, String channelId ,String ssrc, String streamId, ClientTransaction transaction){
|
| | | sessionMap.put(deviceId + "_" + channelId, transaction);
|
| | | ssrcMap.put(deviceId + "_" + channelId, ssrc);
|
| | | streamIdMap.put(deviceId + "_" + channelId, streamId);
|
| | | }
|
| | |
|
| | |
|
| | | 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){
|
| | | 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) {
|
| | | sessionMap.remove(deviceId + "_" + channelId);
|
| | | if (ssrcMap.get(deviceId + "_" + channelId) != null) {
|
| | | SsrcUtil.releaseSsrc(ssrcMap.get(deviceId + "_" + channelId));
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
| | | if (ssrcTransaction == null) return;
|
| | | 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);
|
| | | 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;
|
| | | return result;
|
| | | }
|
| | | }
|
| | |
| | | import javax.sip.message.Request;
|
| | | 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.media.zlm.ZLMRTPServerFactory;
|
| | | import com.genersoft.iot.vmp.service.IMediaServerService;
|
| | |
| | |
|
| | | @Autowired
|
| | | private IMediaServerService mediaServerService;
|
| | |
|
| | |
|
| | | // 注:这里使用注解会导致循环依赖注入,暂用springBean
|
| | | private SipProvider tcpSipProvider;
|
| | |
| | | import com.genersoft.iot.vmp.gb28181.bean.Device;
|
| | | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
| | | 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.service.bean.SSRCInfo;
|
| | |
|
| | | /**
|
| | | * @Description:设备能力接口,用于定义设备的控制、查询能力
|
| | |
| | | * @param device 视频设备
|
| | | * @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);
|
| | |
|
| | | /**
|
| | | * 请求回放视频流
|
| | |
| | | * @param startTime 开始时间,格式要求: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);
|
| | |
|
| | | /**
|
| | | * 请求历史媒体下载
|
| | |
| | | * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
| | | * @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);
|
| | |
| | | package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
| | |
|
| | | import java.lang.reflect.Field;
|
| | | import java.text.ParseException;
|
| | | import java.util.HashSet;
|
| | |
|
| | | import javax.sip.*;
|
| | | import javax.sip.address.SipURI;
|
| | |
| | | import javax.sip.header.ViaHeader;
|
| | | import javax.sip.message.Request;
|
| | |
|
| | | import com.alibaba.fastjson.JSONArray;
|
| | | 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.gb28181.bean.SsrcTransaction;
|
| | | import com.genersoft.iot.vmp.media.zlm.*;
|
| | | 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.service.IMediaServerService;
|
| | | import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
| | | 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.stack.SIPDialog;
|
| | | import gov.nist.javax.sip.stack.SIPTransaction;
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | | import org.springframework.beans.factory.annotation.Autowired;
|
| | |
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
| | | import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
| | | import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
| | | import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
| | | import org.springframework.util.StringUtils;
|
| | |
|
| | | /**
|
| | |
| | | @Lazy
|
| | | @Autowired
|
| | | @Qualifier(value="tcpSipProvider")
|
| | | private SipProvider tcpSipProvider;
|
| | | private SipProviderImpl tcpSipProvider;
|
| | |
|
| | | @Lazy
|
| | | @Autowired
|
| | | @Qualifier(value="udpSipProvider")
|
| | | private SipProvider udpSipProvider;
|
| | | private SipProviderImpl udpSipProvider;
|
| | |
|
| | | @Autowired
|
| | | private SIPRequestHeaderProvider headerProvider;
|
| | |
| | | private IRedisCatchStorage redisCatchStorage;
|
| | |
|
| | | @Autowired
|
| | | private ZLMRTPServerFactory zlmrtpServerFactory;
|
| | |
|
| | | @Autowired
|
| | | private UserSetup userSetup;
|
| | |
|
| | | @Autowired
|
| | |
| | |
|
| | | @Autowired
|
| | | private SipSubscribe sipSubscribe;
|
| | |
|
| | | @Autowired
|
| | | private IMediaServerService mediaServerService;
|
| | |
|
| | | private SIPDialog dialog;
|
| | |
|
| | | public SipConfig getSipConfig() {
|
| | | return sipConfig;
|
| | |
| | | * @param errorEvent sip错误订阅
|
| | | */
|
| | | @Override
|
| | | public void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
|
| | | String streamId = null;
|
| | | public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
|
| | | String streamId = ssrcInfo.getStreamId();
|
| | | try {
|
| | | if (device == null) return;
|
| | | String streamMode = device.getStreamMode().toUpperCase();
|
| | |
|
| | | String ssrc = streamSession.createPlaySsrc();
|
| | | 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);
|
| | | logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
|
| | | // 添加订阅
|
| | | JSONObject subscribeKey = new JSONObject();
|
| | | subscribeKey.put("app", "rtp");
|
| | |
| | | subscribeKey.put("regist", true);
|
| | | subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
| | | subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
| | | (IMediaServerItem mediaServerItemInUse, JSONObject json)->{
|
| | | (MediaServerItem mediaServerItemInUse, JSONObject json)->{
|
| | | if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
| | | event.response(mediaServerItemInUse, json);
|
| | | subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
| | |
| | | //
|
| | | StringBuffer content = new StringBuffer(200);
|
| | | 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("s=Play\r\n");
|
| | | content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
| | |
| | |
|
| | | if (userSetup.isSeniorSdp()) {
|
| | | 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)) {
|
| | | 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)) {
|
| | | 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=rtpmap:96 PS/90000\r\n");
|
| | |
| | | }
|
| | | }else {
|
| | | 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)) {
|
| | | 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)) {
|
| | | 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=rtpmap:96 PS/90000\r\n");
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | content.append("y="+ssrc+"\r\n");//ssrc
|
| | | content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc
|
| | |
|
| | | String tm = Long.toString(System.currentTimeMillis());
|
| | |
|
| | | CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.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);
|
| | | mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
|
| | | errorEvent.response(e);
|
| | | }));
|
| | | streamSession.put(device.getDeviceId(), channelId ,ssrc,streamId, transaction);
|
| | | }), e ->{
|
| | | streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(),e.getClientTransaction());
|
| | | streamSession.put(device.getDeviceId(), channelId , e.getDialog());
|
| | | });
|
| | |
|
| | |
|
| | | } catch ( SipException | ParseException | InvalidArgumentException e) {
|
| | | e.printStackTrace();
|
| | |
| | | * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
| | | */
|
| | | @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) {
|
| | | try {
|
| | | String ssrc = streamSession.createPlayBackSsrc();
|
| | | 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);
|
| | | logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
|
| | |
|
| | | // 添加订阅
|
| | | JSONObject subscribeKey = new JSONObject();
|
| | | subscribeKey.put("app", "rtp");
|
| | | subscribeKey.put("stream", streamId);
|
| | | subscribeKey.put("stream", ssrcInfo.getStreamId());
|
| | | subscribeKey.put("regist", true);
|
| | | subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
| | | logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
|
| | | subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
| | | (IMediaServerItem mediaServerItemInUse, JSONObject json)->{
|
| | | (MediaServerItem mediaServerItemInUse, JSONObject json)->{
|
| | | if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
| | | event.response(mediaServerItemInUse, json);
|
| | | subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
| | |
| | |
|
| | | if (userSetup.isSeniorSdp()) {
|
| | | 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)) {
|
| | | 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)) {
|
| | | 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=rtpmap:96 PS/90000\r\n");
|
| | |
| | | }
|
| | | }else {
|
| | | 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)) {
|
| | | 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)) {
|
| | | 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=rtpmap:96 PS/90000\r\n");
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | content.append("y="+ssrc+"\r\n");//ssrc
|
| | | content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
|
| | |
|
| | | String tm = Long.toString(System.currentTimeMillis());
|
| | |
|
| | |
| | |
|
| | | Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
|
| | |
|
| | | ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
| | | streamSession.put(device.getDeviceId(), channelId, ssrc, streamId, transaction);
|
| | |
|
| | | transmitRequest(device, request, errorEvent, okEvent -> {
|
| | | 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) {
|
| | | e.printStackTrace();
|
| | | }
|
| | |
| | | * @param downloadSpeed 下载倍速参数
|
| | | */
|
| | | @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) {
|
| | | try {
|
| | | String ssrc = streamSession.createPlayBackSsrc();
|
| | | 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);
|
| | | logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
|
| | |
|
| | | // 添加订阅
|
| | | JSONObject subscribeKey = new JSONObject();
|
| | | subscribeKey.put("app", "rtp");
|
| | | subscribeKey.put("stream", streamId);
|
| | | subscribeKey.put("stream", ssrcInfo.getStreamId());
|
| | | subscribeKey.put("regist", true);
|
| | | subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
| | | logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
|
| | | subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
| | | (IMediaServerItem mediaServerItemInUse, JSONObject json)->{
|
| | | (MediaServerItem mediaServerItemInUse, JSONObject json)->{
|
| | | if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
| | | event.response(mediaServerItemInUse, json);
|
| | | subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
| | |
| | |
|
| | | if (userSetup.isSeniorSdp()) {
|
| | | 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)) {
|
| | | 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)) {
|
| | | 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=rtpmap:96 PS/90000\r\n");
|
| | |
| | | }
|
| | | }else {
|
| | | 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)) {
|
| | | 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)) {
|
| | | 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=rtpmap:96 PS/90000\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());
|
| | |
|
| | |
| | | Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
|
| | |
|
| | | 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) {
|
| | | e.printStackTrace();
|
| | |
| | | */
|
| | | @Override
|
| | | public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
|
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
| | | try {
|
| | | 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) {
|
| | | logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
|
| | | return;
|
| | | }
|
| | | Dialog dialog = transaction.getDialog();
|
| | | SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
|
| | | if (dialog == null) {
|
| | | logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
|
| | | 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);
|
| | | SipURI byeURI = (SipURI) byeRequest.getRequestURI();
|
| | | SIPRequest request = (SIPRequest)transaction.getRequest();
|
| | |
| | |
|
| | | 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) {
|
| | | e.printStackTrace();
|
| | | }
|
| | |
| | | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
| | | import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
| | | 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.service.IMediaServerService;
|
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
| | |
| | | while (!rtpPushed) {
|
| | | try {
|
| | | 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())) {
|
| | | rtpPushed = true;
|
| | | logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]",
|
| | |
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
| | | import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
| | | 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.service.IMediaServerService;
|
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
| | |
| | | param.put("stream",streamId);
|
| | | param.put("ssrc",sendRtpItem.getSsrc());
|
| | | logger.info("停止向上级推流:" + streamId);
|
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
| | | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
| | | zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
|
| | | redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
|
| | | if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {
|
| | |
| | | import javax.sip.message.Request;
|
| | | 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.transmit.cmd.impl.SIPCommander;
|
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
| | | import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
| | | 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.service.IMediaServerService;
|
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
| | |
| | | // 查询平台下是否有该通道
|
| | | DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
|
| | | GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
|
| | | IMediaServerItem mediaServerItem = null;
|
| | | MediaServerItem mediaServerItem = null;
|
| | | // 不是通道可能是直播流
|
| | | if (channel != null && gbStream == null ) {
|
| | | if (channel.getStatus() == 0) {
|
| | |
| | | import java.text.ParseException;
|
| | |
|
| | | import javax.sip.*;
|
| | | import javax.sip.address.Address;
|
| | | import javax.sip.address.SipURI;
|
| | | import javax.sip.header.CSeqHeader;
|
| | | import javax.sip.message.Request;
|
| | | import javax.sip.message.Response;
|
| | |
|
| | | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
| | | import gov.nist.javax.sip.ResponseEventExt;
|
| | | import gov.nist.javax.sip.stack.SIPDialog;
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | | import org.springframework.beans.factory.annotation.Autowired;
|
| | | import org.springframework.stereotype.Component;
|
| | |
|
| | | import com.genersoft.iot.vmp.conf.SipConfig;
|
| | |
| | | public class InviteResponseProcessor implements ISIPResponseProcessor {
|
| | |
|
| | | private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
|
| | |
|
| | | @Autowired
|
| | | private VideoStreamSessionManager streamSession;
|
| | |
|
| | | /**
|
| | | * 处理invite响应
|
| | |
| | | // 下发ack
|
| | | if (statusCode == Response.OK) {
|
| | | ResponseEventExt event = (ResponseEventExt)evt;
|
| | | Dialog dialog = evt.getDialog();
|
| | | SIPDialog dialog = (SIPDialog)evt.getDialog();
|
| | | CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
| | | Request reqAck = dialog.createAck(cseq.getSeqNumber());
|
| | | SipURI requestURI = (SipURI) reqAck.getRequestURI();
|
| | |
| | | requestURI.setPort(event.getRemotePort());
|
| | | reqAck.setRequestURI(requestURI);
|
| | | logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
|
| | | SipURI sipURI = (SipURI)dialog.getRemoteParty().getURI();
|
| | | String deviceId = requestURI.getUser();
|
| | | String channelId = sipURI.getUser();
|
| | |
|
| | | dialog.sendAck(reqAck);
|
| | |
|
| | | }
|
| | | } catch (InvalidArgumentException | SipException e) {
|
| | | e.printStackTrace();
|
| | |
| | | import java.util.List;
|
| | | import java.util.UUID;
|
| | |
|
| | | import com.alibaba.fastjson.JSON;
|
| | | import com.alibaba.fastjson.JSONArray;
|
| | | 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.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.service.IMediaServerService;
|
| | | import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
| | | import com.genersoft.iot.vmp.service.IPlayService;
|
| | |
| | | public class ZLMHttpHookListener {
|
| | |
|
| | | private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
|
| | |
|
| | |
|
| | | @Autowired
|
| | | private SIPCommander cmder;
|
| | |
| | | String mediaServerId = json.getString("mediaServerId");
|
| | | ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json);
|
| | | if (subscribe != null ) {
|
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
| | | MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
| | | if (mediaInfo != null) {
|
| | | subscribe.response(mediaInfo, json);
|
| | | }
|
| | |
| | | String mediaServerId = json.getString("mediaServerId");
|
| | | ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
|
| | | if (subscribe != null) {
|
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
| | | MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
| | | if (mediaInfo != null) {
|
| | | subscribe.response(mediaInfo, json);
|
| | | }
|
| | |
| | | String mediaServerId = json.getString("mediaServerId");
|
| | | ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json);
|
| | | if (subscribe != null ) {
|
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
| | | MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
| | | if (mediaInfo != null) {
|
| | | subscribe.response(mediaInfo, json);
|
| | | }
|
| | |
| | | String mediaServerId = json.getString("mediaServerId");
|
| | | ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
|
| | | if (subscribe != null ) {
|
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
| | | MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
| | | if (mediaInfo != null) {
|
| | | subscribe.response(mediaInfo, json);
|
| | | }
|
| | |
| | | }
|
| | | }else {
|
| | | if (!"rtp".equals(app) ){
|
| | | IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
| | | MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
| | | if (regist) {
|
| | | zlmMediaListManager.addMedia(mediaServerItem, app, streamId);
|
| | | }else {
|
| | |
| | | logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString());
|
| | | }
|
| | | String mediaServerId = json.getString("mediaServerId");
|
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
| | | MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
| | | if (userSetup.isAutoApplyPlay() && mediaInfo != null) {
|
| | | String app = json.getString("app");
|
| | | String streamId = json.getString("stream");
|
| | |
| | | Device device = storager.queryVideoDevice(deviceId);
|
| | | if (device != null) {
|
| | | 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());
|
| | | playService.onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
|
| | | }, null);
|
| | |
| | | package com.genersoft.iot.vmp.media.zlm; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | |
| | | } |
| | | |
| | | 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<>(); |
| | |
| | | if (result == null) { |
| | | result = key.getString(s).equals(hookResponse.getString(s)); |
| | | }else { |
| | | if (key.getString(s) == null) { |
| | | continue; |
| | | } |
| | | result = result && key.getString(s).equals(hookResponse.getString(s)); |
| | | } |
| | | |
| | |
| | | if (result == null) { |
| | | result = key.getString(s).equals(hookResponse.getString(s)); |
| | | }else { |
| | | if (key.getString(s) == null) continue; |
| | | result = result && key.getString(s).equals(hookResponse.getString(s)); |
| | | } |
| | | |
| | | } |
| | | if (null != result && result){ |
| | | iterator.remove(); |
| | |
| | | package com.genersoft.iot.vmp.media.zlm; |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | 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.StreamProxyItem; |
| | | 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.storager.IRedisCatchStorage; |
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| | |
| | | jsonObject.put("stream", streamPushItem.getStream()); |
| | | jsonObject.put("mediaServerId", mediaServerItem.getId()); |
| | | subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject, |
| | | (IMediaServerItem mediaServerItemInuse, JSONObject response)->{ |
| | | (MediaServerItem mediaServerItemInuse, JSONObject response)->{ |
| | | updateMedia(mediaServerItem, response.getString("app"), response.getString("stream")); |
| | | } |
| | | ); |
| | |
| | | |
| | | } |
| | | |
| | | public void addMedia(IMediaServerItem mediaServerItem, String app, String streamId) { |
| | | public void addMedia(MediaServerItem mediaServerItem, String app, String 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->{ |
| | | |
| | |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | 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 okhttp3.*; |
| | | import org.jetbrains.annotations.NotNull; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.io.*; |
| | |
| | | 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(); |
| | | String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api); |
| | | JSONObject responseJSON = null; |
| | |
| | | } |
| | | |
| | | |
| | | 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(); |
| | | String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api); |
| | | JSONObject responseJSON = null; |
| | |
| | | } |
| | | |
| | | |
| | | 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<>(); |
| | | if (app != null) param.put("app",app); |
| | | if (stream != null) param.put("stream",stream); |
| | |
| | | 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); |
| | | } |
| | | |
| | | public JSONObject getMediaList(IMediaServerItem mediaServerItem,RequestCallback callback){ |
| | | public JSONObject getMediaList(MediaServerItem mediaServerItem, RequestCallback 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<>(); |
| | | param.put("app",app); |
| | | param.put("schema",schema); |
| | |
| | | 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<>(); |
| | | param.put("stream_id",stream_id); |
| | | 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){ |
| | | logger.info(src_url); |
| | | logger.info(dst_url); |
| | |
| | | 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<>(); |
| | | param.put("key", key); |
| | | return sendPost(mediaServerItem, "delFFmpegSource",param, null); |
| | | } |
| | | |
| | | public JSONObject getMediaServerConfig(IMediaServerItem mediaServerItem){ |
| | | public JSONObject getMediaServerConfig(MediaServerItem mediaServerItem){ |
| | | 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); |
| | | } |
| | | |
| | | public JSONObject openRtpServer(IMediaServerItem mediaServerItem,Map<String, Object> param){ |
| | | public JSONObject openRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param){ |
| | | 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); |
| | | } |
| | | |
| | | public JSONObject listRtpServer(IMediaServerItem mediaServerItem) { |
| | | public JSONObject listRtpServer(MediaServerItem mediaServerItem) { |
| | | 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); |
| | | } |
| | | |
| | | public JSONObject stopSendRtp(IMediaServerItem mediaServerItem,Map<String, Object> param) { |
| | | public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) { |
| | | 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<>(); |
| | | param.put("vhost", "__defaultVhost__"); |
| | | param.put("app", app); |
| | |
| | | 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<>(); |
| | | param.put("vhost", "__defaultVhost__"); |
| | | param.put("app", app); |
| | |
| | | return sendPost(mediaServerItem, "close_streams",param, null); |
| | | } |
| | | |
| | | public JSONObject getAllSession(IMediaServerItem mediaServerItem) { |
| | | public JSONObject getAllSession(MediaServerItem mediaServerItem) { |
| | | 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<>(); |
| | | param.put("local_port", localPortSStr); |
| | | 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<>(); |
| | | param.put("url", flvUrl); |
| | | param.put("timeout_sec", timeout_sec); |
| | |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | 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.session.SsrcUtil; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | |
| | | private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory"); |
| | | |
| | | @Autowired |
| | | private MediaConfig mediaConfig; |
| | | |
| | | @Autowired |
| | | private ZLMRESTfulUtils zlmresTfulUtils; |
| | | |
| | | private int[] portRangeArray = new int[2]; |
| | | |
| | | private int currentPort = 0; |
| | | |
| | | private Map<String, Integer> currentStreams = null; |
| | | |
| | | public int createRTPServer(IMediaServerItem mediaServerItem, String streamId) { |
| | | if (currentStreams == null) { |
| | | currentStreams = new HashMap<>(); |
| | | JSONObject jsonObject = zlmresTfulUtils.listRtpServer(mediaServerItem); |
| | | if (jsonObject != null) { |
| | | 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")); |
| | | } |
| | | public int createRTPServer(MediaServerItem mediaServerItem, String streamId) { |
| | | Map<String, Integer> currentStreams = new HashMap<>(); |
| | | JSONObject listRtpServerJsonResult = zlmresTfulUtils.listRtpServer(mediaServerItem); |
| | | if (listRtpServerJsonResult != null) { |
| | | JSONArray data = listRtpServerJsonResult.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")); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | Map<String, Object> param = new HashMap<>(); |
| | | int result = -1; |
| | | int newPort = getPortFromportRange(); |
| | | int newPort = getPortFromportRange(mediaServerItem); |
| | | param.put("port", newPort); |
| | | param.put("enable_tcp", 1); |
| | | param.put("stream_id", streamId); |
| | | JSONObject jsonObject = zlmresTfulUtils.openRtpServer(mediaServerItem, param); |
| | | JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); |
| | | |
| | | if (jsonObject != null) { |
| | | switch (jsonObject.getInteger("code")){ |
| | | if (openRtpServerResultJson != null) { |
| | | switch (openRtpServerResultJson.getInteger("code")){ |
| | | case 0: |
| | | result= newPort; |
| | | break; |
| | | case -300: // id已经存在, 可能已经在其他端口推流 |
| | | case -300: // id已经存在, 可能已经在其他端口推流, TODO 也可能是设备不等ack就直接推流了, 需要查询与设置的推流ip端口是否一致 |
| | | Map<String, Object> closeRtpServerParam = new HashMap<>(); |
| | | closeRtpServerParam.put("stream_id", streamId); |
| | | zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam); |
| | |
| | | result= createRTPServer(mediaServerItem, streamId); |
| | | break; |
| | | default: |
| | | logger.error("创建RTP Server 失败 {}: " + jsonObject.getString("msg"), newPort); |
| | | logger.error("创建RTP Server 失败 {}: " + openRtpServerResultJson.getString("msg"), newPort); |
| | | break; |
| | | } |
| | | }else { |
| | |
| | | return result; |
| | | } |
| | | |
| | | public boolean closeRTPServer(IMediaServerItem serverItem, String streamId) { |
| | | public boolean closeRTPServer(MediaServerItem serverItem, String streamId) { |
| | | boolean result = false; |
| | | if (serverItem !=null){ |
| | | Map<String, Object> param = new HashMap<>(); |
| | |
| | | return result; |
| | | } |
| | | |
| | | private int getPortFromportRange() { |
| | | private int getPortFromportRange(MediaServerItem mediaServerItem) { |
| | | int currentPort = mediaServerItem.getCurrentPort(); |
| | | if (currentPort == 0) { |
| | | String[] portRangeStrArray = mediaConfig.getRtpPortRange().split(","); |
| | | String[] portRangeStrArray = mediaServerItem.getRtpPortRange().split(","); |
| | | portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]); |
| | | portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]); |
| | | } |
| | | |
| | | if (currentPort == 0 || currentPort++ > portRangeArray[1]) { |
| | | currentPort = portRangeArray[0]; |
| | | mediaServerItem.setCurrentPort(currentPort); |
| | | return portRangeArray[0]; |
| | | } else { |
| | | if (currentPort % 2 == 1) { |
| | | currentPort++; |
| | | } |
| | | return currentPort++; |
| | | currentPort++; |
| | | mediaServerItem.setCurrentPort(currentPort); |
| | | return currentPort; |
| | | } |
| | | } |
| | | |
| | |
| | | * @param tcp 是否为tcp |
| | | * @return SendRtpItem |
| | | */ |
| | | public SendRtpItem createSendRtpItem(IMediaServerItem 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()); |
| | | public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){ |
| | | |
| | | // 使用RTPServer 功能找一个可用的端口 |
| | | String playSsrc = serverItem.getSsrcConfig().getPlaySsrc(); |
| | | int localPort = createRTPServer(serverItem, playSsrc); |
| | | if (localPort != -1) { |
| | | // TODO 高并发时可能因为未放入缓存而ssrc冲突 |
| | | serverItem.getSsrcConfig().releaseSsrc(playSsrc); |
| | | closeRTPServer(serverItem, playSsrc); |
| | | }else { |
| | | logger.error("没有可用的端口"); |
| | |
| | | * @param tcp 是否为tcp |
| | | * @return SendRtpItem |
| | | */ |
| | | public SendRtpItem createSendRtpItem(IMediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){ |
| | | String playSsrc = SsrcUtil.getPlaySsrc(); |
| | | int localPort = createRTPServer(serverItem, SsrcUtil.getPlaySsrc()); |
| | | public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){ |
| | | String playSsrc = serverItem.getSsrcConfig().getPlaySsrc(); |
| | | int localPort = createRTPServer(serverItem, playSsrc); |
| | | if (localPort != -1) { |
| | | // TODO 高并发时可能因为未放入缓存而ssrc冲突 |
| | | serverItem.getSsrcConfig().releaseSsrc(ssrc); |
| | | closeRTPServer(serverItem, playSsrc); |
| | | }else { |
| | | logger.error("没有可用的端口"); |
| | |
| | | /** |
| | | * 调用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; |
| | | JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param); |
| | | if (jsonObject == null) { |
| | |
| | | /** |
| | | * 查询待转推的流是否就绪 |
| | | */ |
| | | 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); |
| | | return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")); |
| | | } |
| | |
| | | * @param streamId |
| | | * @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); |
| | | return mediaInfo.getInteger("totalReaderCount"); |
| | | } |
| | |
| | | /** |
| | | * 调用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; |
| | | JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param); |
| | | if (jsonObject == null) { |
| | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | 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.StreamProxyItem; |
| | | import com.genersoft.iot.vmp.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| | | import com.genersoft.iot.vmp.service.IStreamProxyService; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.boot.CommandLineRunner; |
| | | import org.springframework.core.annotation.Order; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import javax.print.attribute.standard.Media; |
| | | import java.util.*; |
| | | |
| | | @Component |
| | |
| | | |
| | | @Override |
| | | public void run(String... strings) throws Exception { |
| | | IMediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort( |
| | | // 清楚redis缓存的在线zlm信息 |
| | | mediaServerService.clearMediaServerForOnline(); |
| | | |
| | | // 将配置文件的meida配置写入数据库 |
| | | MediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort( |
| | | mediaConfig.getIp(), mediaConfig.getHttpPort()); |
| | | if (presetMediaServer != null) { |
| | | mediaConfig.setId(presetMediaServer.getId()); |
| | | mediaServerService.update(mediaConfig); |
| | | MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem(); |
| | | mediaSerItem.setId(presetMediaServer.getId()); |
| | | mediaServerService.update(mediaSerItem); |
| | | }else { |
| | | if (mediaConfig.getId() != null) { |
| | | MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem(); |
| | | mediaServerService.add(mediaSerItem); |
| | | } |
| | | } |
| | | |
| | | // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 |
| | | hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null, |
| | | (IMediaServerItem mediaServerItem, JSONObject response)->{ |
| | | (MediaServerItem mediaServerItem, JSONObject response)->{ |
| | | ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class); |
| | | if (zlmServerConfig !=null ) { |
| | | startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId()); |
| | |
| | | logger.info("等待默认zlm接入..."); |
| | | |
| | | // 获取所有的zlm, 并开启主动连接 |
| | | List<IMediaServerItem> all = mediaServerService.getAll(); |
| | | List<MediaServerItem> all = mediaServerService.getAll(); |
| | | if (presetMediaServer == null) { |
| | | all.add(mediaConfig.getMediaSerItem()); |
| | | } |
| | | for (IMediaServerItem mediaServerItem : all) { |
| | | for (MediaServerItem mediaServerItem : all) { |
| | | if (startGetMedia == null) startGetMedia = new HashMap<>(); |
| | | startGetMedia.put(mediaServerItem.getId(), true); |
| | | new Thread(() -> { |
| | | ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem); |
| | | if (zlmServerConfig != null) { |
| | | zlmServerConfig.setIp(mediaServerItem.getIp()); |
| | | zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort()); |
| | | startGetMedia.remove(mediaServerItem.getId()); |
| | | mediaServerService.handLeZLMServerConfig(zlmServerConfig); |
| | | } |
| | | }).start(); |
| | | } |
| | | Timer timer = new Timer(); |
| | | // 1分钟后未连接到则不再去主动连接 |
| | | // 2分钟后未连接到则不再去主动连接, TODO 并对重启前使用此在zlm的通道发送bye |
| | | timer.schedule(new TimerTask() { |
| | | @Override |
| | | public void run() { |
| | |
| | | }, 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; |
| | | JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); |
| | | ZLMServerConfig ZLMServerConfig = null; |
| | |
| | | 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 org.springframework.util.StringUtils; |
| | | |
| | | public class MediaServerItem implements IMediaServerItem{ |
| | | import java.util.HashMap; |
| | | |
| | | public class MediaServerItem{ |
| | | |
| | | private String id; |
| | | |
| | |
| | | |
| | | 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() { |
| | | } |
| | |
| | | this.recordAssistPort = recordAssistPort; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isDocker() { |
| | | return docker; |
| | | public boolean isDefaultServer() { |
| | | return defaultServer; |
| | | } |
| | | |
| | | @Override |
| | | public void setDocker(boolean docker) { |
| | | this.docker = docker; |
| | | public void setDefaultServer(boolean defaultServer) { |
| | | this.defaultServer = defaultServer; |
| | | } |
| | | |
| | | public String getCreateTime() { |
| | |
| | | this.updateTime = updateTime; |
| | | } |
| | | |
| | | public int getCount() { |
| | | return count; |
| | | public HashMap<String, SsrcConfig> getMediaServerSsrcMap() { |
| | | return mediaServerSsrcMap; |
| | | } |
| | | |
| | | public void setCount(int count) { |
| | | this.count = count; |
| | | public void setMediaServerSsrcMap(HashMap<String, SsrcConfig> mediaServerSsrcMap) { |
| | | 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; |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | import com.genersoft.iot.vmp.conf.MediaConfig; |
| | | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| | | 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.service.bean.SSRCInfo; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | */ |
| | | 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); |
| | | |
| | | /** |
| | | * 新的节点加入 |
| | |
| | | */ |
| | | void handLeZLMServerConfig(ZLMServerConfig zlmServerConfig); |
| | | |
| | | void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean b); |
| | | MediaServerItem getMediaServerForMinimumLoad(); |
| | | |
| | | IMediaServerItem getMediaServerForMinimumLoad(); |
| | | void setZLMConfig(MediaServerItem mediaServerItem); |
| | | |
| | | void setZLMConfig(IMediaServerItem mediaServerItem); |
| | | |
| | | void init(); |
| | | SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId); |
| | | |
| | | void closeRTPServer(Device device, String channelId); |
| | | |
| | | void update(MediaConfig mediaConfig); |
| | | void clearRTPServer(MediaServerItem mediaServerItem); |
| | | |
| | | void update(MediaServerItem mediaSerItem); |
| | | |
| | | void addCount(String mediaServerId); |
| | | |
| | | void removeCount(String mediaServerId); |
| | | |
| | | void releaseSsrc(MediaServerItem mediaServerItem, String ssrc); |
| | | |
| | | void clearMediaServerForOnline(); |
| | | |
| | | void add(MediaServerItem mediaSerItem); |
| | | |
| | | void resetOnlineServerItem(MediaServerItem serverItem); |
| | | } |
| | |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | 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; |
| | | |
| | | /** |
| | |
| | | * @param stream |
| | | * @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在一台主机的情况 |
| | |
| | | * @param stream |
| | | * @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); |
| | | } |
| | |
| | | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| | | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| | | 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.vmanager.gb28181.play.bean.PlayResult; |
| | | |
| | |
| | | */ |
| | | public interface IPlayService { |
| | | |
| | | void onPublishHandlerForPlayBack(IMediaServerItem mediaServerItem,JSONObject resonse, String deviceId, String channelId, String uuid); |
| | | void onPublishHandlerForPlay(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid); |
| | | void onPublishHandlerForPlayBack(MediaServerItem 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); |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.service; |
| | | |
| | | 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.StreamProxyItem; |
| | | import com.github.pagehelper.PageInfo; |
| | |
| | | * 获取ffmpeg.cmd模板 |
| | | * @return |
| | | */ |
| | | JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem); |
| | | JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem); |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.service; |
| | | |
| | | 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.github.pagehelper.PageInfo; |
| | | |
| | |
| | | |
| | | public interface IStreamPushService { |
| | | |
| | | List<StreamPushItem> handleJSON(String json, IMediaServerItem mediaServerItem); |
| | | List<StreamPushItem> handleJSON(String json, MediaServerItem mediaServerItem); |
| | | |
| | | /** |
| | | * 将应用名和流ID加入国标关联 |
New file |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.service.impl; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONArray; |
| | | 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.ProxyServletConfig; |
| | | import com.genersoft.iot.vmp.conf.SipConfig; |
| | | 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.media.zlm.ZLMRESTfulUtils; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| | | 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.ZLMRunInfo; |
| | | 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.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.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.boot.CommandLineRunner; |
| | | import org.springframework.core.annotation.Order; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.sql.Array; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | |
| | |
| | | * 媒体服务器节点管理 |
| | | */ |
| | | @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 Map<String, IMediaServerItem> zlmServers = new HashMap<>(); // 所有数据库的zlm的缓存 |
| | | private Map<String, Integer> zlmServerStatus = new LinkedHashMap<>(); // 所有上线的zlm的缓存以及负载 |
| | | |
| | | @Value("${sip.ip}") |
| | | private String sipIp; |
| | | @Autowired |
| | | private SipConfig sipConfig; |
| | | |
| | | @Value("${server.ssl.enabled:false}") |
| | | private boolean sslEnabled; |
| | |
| | | @Autowired |
| | | private MediaServerMapper mediaServerMapper; |
| | | |
| | | |
| | | @Autowired |
| | | private IRedisCatchStorage redisCatchStorage; |
| | | |
| | |
| | | @Autowired |
| | | 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 |
| | | public void init() { |
| | | zlmServers.clear(); |
| | | zlmServerStatus.clear(); |
| | | public void run(String... args) throws Exception { |
| | | logger.info("Media Server 缓存初始化"); |
| | | List<MediaServerItem> mediaServerItemList = mediaServerMapper.queryAll(); |
| | | for (IMediaServerItem mediaServerItem : mediaServerItemList) { |
| | | zlmServers.put(mediaServerItem.getId(), mediaServerItem); |
| | | for (MediaServerItem mediaServerItem : mediaServerItemList) { |
| | | // 更新 |
| | | 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 |
| | | public void closeRTPServer(Device device, String channelId) { |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); |
| | | IMediaServerItem mediaServerItem = null; |
| | | if (streamInfo != null) { |
| | | mediaServerItem = this.getOne (streamInfo.getMediaServerId()); |
| | | String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId); |
| | | MediaServerItem mediaServerItem = this.getOne(mediaServerId); |
| | | if (mediaServerItem != null) { |
| | | 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); |
| | | } |
| | | |
| | | @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 |
| | | public List<IMediaServerItem> getAll() { |
| | | if (zlmServers.size() == 0) { |
| | | init(); |
| | | } |
| | | List<IMediaServerItem> result = new ArrayList<>(); |
| | | for (String id : zlmServers.keySet()) { |
| | | IMediaServerItem mediaServerItem = zlmServers.get(id); |
| | | mediaServerItem.setCount(zlmServerStatus.get(id) == null ? 0 : zlmServerStatus.get(id)); |
| | | result.add(mediaServerItem); |
| | | public List<MediaServerItem> getAll() { |
| | | List<MediaServerItem> result = new ArrayList<>(); |
| | | List<Object> mediaServerKeys = redisUtil.scan(String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX)); |
| | | for (int i = 0; i < mediaServerKeys.size(); i++) { |
| | | String key = (String) mediaServerKeys.get(i); |
| | | result.add((MediaServerItem)redisUtil.get(key)); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | // return mediaServerMapper.queryAll(); |
| | | @Override |
| | | 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; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return MediaServerItem |
| | | */ |
| | | @Override |
| | | public IMediaServerItem getOne(String mediaServerId) { |
| | | if (mediaServerId ==null) return null; |
| | | IMediaServerItem mediaServerItem = zlmServers.get(mediaServerId); |
| | | if (mediaServerItem != null) { |
| | | 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; |
| | | } |
| | | public MediaServerItem getOne(String mediaServerId) { |
| | | if (mediaServerId == null) return null; |
| | | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerId; |
| | | return (MediaServerItem)redisUtil.get(key); |
| | | } |
| | | |
| | | @Override |
| | | public IMediaServerItem getOneByHostAndPort(String host, int port) { |
| | | public MediaServerItem getOneByHostAndPort(String host, int 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | logger.info("[ {} ]-[ {}:{} ]已连接", |
| | | zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); |
| | | |
| | | IMediaServerItem serverItem = getOne(zlmServerConfig.getGeneralMediaServerId()); |
| | | String now = this.format.format(new Date(System.currentTimeMillis())); |
| | | if (serverItem != null) { |
| | | serverItem.setSecret(zlmServerConfig.getApiSecret()); |
| | | serverItem.setIp(zlmServerConfig.getIp()); |
| | | MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()); |
| | | if (serverItem == null) { |
| | | serverItem = mediaServerMapper.queryOneByHostAndPort(zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); |
| | | } |
| | | if (zlmServerConfig.getGeneralMediaServerId().equals(mediaConfig.getId()) |
| | | || (zlmServerConfig.getIp().equals(mediaConfig.getIp()) && zlmServerConfig.getHttpPort() == mediaConfig.getHttpPort())) { |
| | | // 配置文件的zlm |
| | | // 如果是配置文件中的zlm。 也就是默认zlm。 一切以配置文件内容为准 |
| | | // docker部署不会使用zlm配置的端口号; |
| | | // 直接编译部署的使用配置文件的端口号,如果zlm修改配改了配置,wvp自动修改 |
| | | // docker部署不会使用zlm配置的端口号不是默认的则不做更新, 配置修改需要自行修改server配置; |
| | | MediaServerItem serverItemFromConfig = mediaConfig.getMediaSerItem(); |
| | | serverItemFromConfig.setId(zlmServerConfig.getGeneralMediaServerId()); |
| | | if (mediaConfig.getHttpPort() == 0) serverItemFromConfig.setHttpPort(zlmServerConfig.getHttpPort()); |
| | | if (mediaConfig.getHttpSSlPort() == 0) serverItemFromConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport()); |
| | | if (mediaConfig.getRtmpPort() == 0) serverItemFromConfig.setRtmpPort(zlmServerConfig.getRtmpPort()); |
| | | if (mediaConfig.getRtmpSSlPort() == 0) serverItemFromConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); |
| | | if (mediaConfig.getRtspPort() == 0) serverItemFromConfig.setRtspPort(zlmServerConfig.getRtspPort()); |
| | | if (mediaConfig.getRtspSSLPort() == 0) serverItemFromConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); |
| | | if (mediaConfig.getRtpProxyPort() == 0) serverItemFromConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); |
| | | if (serverItem != null){ |
| | | // 可能是同一个zlm但id发生了变化 |
| | | if (!serverItem.getId().equals(zlmServerConfig.getGeneralMediaServerId())) { |
| | | mediaServerMapper.delOne(serverItem.getId()); |
| | | redisUtil.del(VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItem.getId()); |
| | | |
| | | if (serverItem.getId().equals(mediaConfig.getId()) |
| | | || (serverItem.getIp().equals(mediaConfig.getIp()) && serverItem.getHttpPort() == mediaConfig.getHttpPort())) { |
| | | // 配置文件的zlm |
| | | mediaConfig.setId(zlmServerConfig.getGeneralMediaServerId()); |
| | | mediaConfig.setUpdateTime(now); |
| | | if (mediaConfig.getHttpPort() == 0) mediaConfig.setHttpPort(zlmServerConfig.getHttpPort()); |
| | | if (mediaConfig.getHttpSSlPort() == 0) mediaConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport()); |
| | | if (mediaConfig.getRtmpPort() == 0) mediaConfig.setRtmpPort(zlmServerConfig.getRtmpPort()); |
| | | if (mediaConfig.getRtmpSSlPort() == 0) mediaConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); |
| | | if (mediaConfig.getRtspPort() == 0) mediaConfig.setRtspPort(zlmServerConfig.getRtspPort()); |
| | | if (mediaConfig.getRtspSSLPort() == 0) mediaConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); |
| | | if (mediaConfig.getRtpProxyPort() == 0) mediaConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); |
| | | 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); |
| | | mediaServerMapper.update(serverItem); |
| | | }else { |
| | | 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); |
| | | } |
| | | }else { |
| | | 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); |
| | | } |
| | | resetOnlineServerItem(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 |
| | | public void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean online) { |
| | | if (mediaServerItem != null) { |
| | | zlmServers.put(mediaServerItem.getId(), mediaServerItem); |
| | | Collection<Integer> values = zlmServerStatus.values(); |
| | | if (online != null && count != null) { |
| | | zlmServerStatus.put(mediaServerItem.getId(), count); |
| | | } |
| | | public void resetOnlineServerItem(MediaServerItem serverItem) { |
| | | // 更新缓存 |
| | | String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX; |
| | | // 使用zset的分数作为当前并发量, 默认值设置为0 |
| | | if (redisUtil.zScore(key, serverItem.getId()) == null) { // 不存在则设置默认值 已存在则重置 |
| | | 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 |
| | | public void addCount(String mediaServerId) { |
| | | if (zlmServerStatus.get(mediaServerId) != null) { |
| | | zlmServerStatus.put(mediaServerId, zlmServerStatus.get(mediaServerId) + 1); |
| | | } |
| | | if (mediaServerId == null) return; |
| | | String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX; |
| | | Double aDouble = redisUtil.zScore(key, mediaServerId); |
| | | redisUtil.zIncrScore(key, mediaServerId, 1); |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void removeCount(String mediaServerId) { |
| | | if (zlmServerStatus.get(mediaServerId) != null) { |
| | | zlmServerStatus.put(mediaServerId, zlmServerStatus.get(mediaServerId) - 1); |
| | | } |
| | | String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX; |
| | | redisUtil.zIncrScore(key, mediaServerId, - 1); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return MediaServerItem |
| | | */ |
| | | @Override |
| | | public IMediaServerItem getMediaServerForMinimumLoad() { |
| | | int mediaCount = -1; |
| | | String key = null; |
| | | System.out.println(JSON.toJSONString(zlmServerStatus)); |
| | | if (zlmServerStatus.size() == 1) { |
| | | 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; |
| | | } |
| | | } |
| | | public MediaServerItem getMediaServerForMinimumLoad() { |
| | | String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX; |
| | | |
| | | if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) { |
| | | logger.info("获取负载最低的节点时无在线节点"); |
| | | } |
| | | |
| | | if (key == null) { |
| | | logger.info("获取负载最低的节点时无在线节点"); |
| | | return null; |
| | | }else{ |
| | | return zlmServers.get(key); |
| | | } |
| | | // 获取分数最低的,及并发最低的 |
| | | Set<Object> objects = redisUtil.ZRange(key, 0, -1); |
| | | ArrayList<Object> MediaServerObjectS = new ArrayList<>(objects); |
| | | String mediaServerId = (String)MediaServerObjectS.get(0); |
| | | return getOne(mediaServerId); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @param mediaServerItem 服务ID |
| | | */ |
| | | @Override |
| | | public void setZLMConfig(IMediaServerItem mediaServerItem) { |
| | | public void setZLMConfig(MediaServerItem mediaServerItem) { |
| | | logger.info("[ {} ]-[ {}:{} ]设置zlm", |
| | | mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); |
| | | String protocol = sslEnabled ? "https" : "http"; |
| | |
| | | logger.info("[ {} ]-[ {}:{} ]设置zlm成功", |
| | | mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); |
| | | }else { |
| | | logger.info("[ {} ]-[ {}:{} ]设置zlm失败" + responseJSON.getString("msg"), |
| | | logger.info("[ {} ]-[ {}:{} ]设置zlm失败", |
| | | mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | 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.dto.IMediaServerItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import com.genersoft.iot.vmp.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | |
| | | |
| | | |
| | | @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); |
| | | } |
| | | |
| | | @Override |
| | | public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) { |
| | | StreamInfo streamInfo = null; |
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); |
| | | MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); |
| | | if (mediaInfo == null) { |
| | | return streamInfo; |
| | | } |
| | |
| | | } |
| | | |
| | | @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(); |
| | | streamInfoResult.setStreamId(stream); |
| | | streamInfoResult.setApp(app); |
| | |
| | | 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.ZLMRESTfulUtils; |
| | | 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.bean.SSRCInfo; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | 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.gb28181.play.bean.PlayResult; |
| | | import com.genersoft.iot.vmp.service.IMediaService; |
| | |
| | | private IRedisCatchStorage redisCatchStorage; |
| | | |
| | | @Autowired |
| | | private RedisUtil redis; |
| | | |
| | | @Autowired |
| | | private DeferredResultHolder resultHolder; |
| | | |
| | | @Autowired |
| | |
| | | |
| | | |
| | | @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(); |
| | | if (mediaServerItem == null) { |
| | | RequestMessage msg = new RequestMessage(); |
| | |
| | | // 超时处理 |
| | | result.onTimeout(()->{ |
| | | logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId)); |
| | | // 释放rtpserver |
| | | mediaServerService.closeRTPServer(playResult.getDevice(), channelId); |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid()); |
| | | WVPResult wvpResult = new WVPResult(); |
| | | wvpResult.setCode(-1); |
| | | wvpResult.setMsg("Timeout"); |
| | | SIPDialog dialog = streamSession.getDialog(deviceId, channelId); |
| | | if (dialog != null) { |
| | | wvpResult.setMsg("收流超时,请稍候重试"); |
| | | }else { |
| | | wvpResult.setMsg("点播超时,请稍候重试"); |
| | | } |
| | | msg.setData(wvpResult); |
| | | // 点播超时回复BYE |
| | | cmder.streamByeCmd(device.getDeviceId(), channelId); |
| | | // 释放rtpserver |
| | | mediaServerService.closeRTPServer(playResult.getDevice(), channelId); |
| | | resultHolder.invokeResult(msg); |
| | | }); |
| | | result.onCompletion(()->{ |
| | |
| | | WVPResult wvpResult = (WVPResult)responseEntity.getBody(); |
| | | if (wvpResult.getCode() == 0) { |
| | | StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData(); |
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId()); |
| | | MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId()); |
| | | String streamUrl = streamInfoForSuccess.getFmp4(); |
| | | // 请求截图 |
| | | zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName); |
| | |
| | | } |
| | | }); |
| | | 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()); |
| | | onPublishHandlerForPlay(mediaServerItemInUse, response, deviceId, channelId, uuid.toString()); |
| | | if (hookEvent != null) { |
| | | hookEvent.response(mediaServerItem, response); |
| | | } |
| | | }, (event) -> { |
| | | // 点播返回sip错误 |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); |
| | | Response response = event.getResponse(); |
| | |
| | | if (errorEvent != null) { |
| | | errorEvent.response(event); |
| | | } |
| | | |
| | | }); |
| | | } else { |
| | | String streamId = streamInfo.getStreamId(); |
| | |
| | | return playResult; |
| | | } |
| | | String mediaServerId = streamInfo.getMediaServerId(); |
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); |
| | | MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); |
| | | |
| | | JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); |
| | | if (rtpInfo != null && rtpInfo.getBoolean("exist")) { |
| | |
| | | hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo))); |
| | | } |
| | | } else { |
| | | // TODO 点播前是否重置状态 |
| | | redisCatchStorage.stopPlay(streamInfo); |
| | | 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()); |
| | | onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString()); |
| | | }, (event) -> { |
| | |
| | | } |
| | | |
| | | @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(); |
| | | msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); |
| | | StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid); |
| | |
| | | deviceChannel.setStreamId(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); |
| | | msg.setData(JSON.toJSONString(streamInfo)); |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | public IMediaServerItem getNewMediaServerItem(Device device) { |
| | | public MediaServerItem getNewMediaServerItem(Device device) { |
| | | if (device == null) return null; |
| | | String mediaServerId = device.getMediaServerId(); |
| | | IMediaServerItem mediaServerItem = null; |
| | | MediaServerItem mediaServerItem = null; |
| | | if (mediaServerId == null) { |
| | | mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(); |
| | | }else { |
| | |
| | | } |
| | | |
| | | @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(); |
| | | msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); |
| | | StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid); |
| | |
| | | } |
| | | } |
| | | |
| | | 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"); |
| | | JSONArray tracks = resonse.getJSONArray("tracks"); |
| | | StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks); |
| | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.genersoft.iot.vmp.gb28181.bean.GbStream; |
| | | 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.StreamProxyItem; |
| | | import com.genersoft.iot.vmp.service.IGbStreamService; |
| | |
| | | |
| | | @Override |
| | | public String save(StreamProxyItem param) { |
| | | IMediaServerItem mediaInfo; |
| | | MediaServerItem mediaInfo; |
| | | if ("auto".equals(param.getMediaServerId())){ |
| | | mediaInfo = mediaServerService.getMediaServerForMinimumLoad(); |
| | | }else { |
| | |
| | | @Override |
| | | public JSONObject addStreamProxyToZlm(StreamProxyItem param) { |
| | | JSONObject result = null; |
| | | IMediaServerItem mediaServerItem = null; |
| | | MediaServerItem mediaServerItem = null; |
| | | if (param.getMediaServerId() == null) { |
| | | logger.warn("添加代理时MediaServerId 为null"); |
| | | return null; |
| | |
| | | @Override |
| | | public JSONObject removeStreamProxyFromZlm(StreamProxyItem param) { |
| | | 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()); |
| | | return result; |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem) { |
| | | public JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem) { |
| | | JSONObject result = new JSONObject(); |
| | | JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); |
| | | if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0 |
| | |
| | | import com.alibaba.fastjson.TypeReference; |
| | | import com.genersoft.iot.vmp.gb28181.bean.GbStream; |
| | | 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.MediaServerItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| | |
| | | private IMediaServerService mediaServerService; |
| | | |
| | | @Override |
| | | public List<StreamPushItem> handleJSON(String jsonData, IMediaServerItem mediaServerItem) { |
| | | public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) { |
| | | if (jsonData == null) return null; |
| | | |
| | | Map<String, StreamPushItem> result = new HashMap<>(); |
| | |
| | | @Override |
| | | public boolean removeFromGB(GbStream stream) { |
| | | 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()); |
| | | if (mediaList == null) { |
| | | streamPushMapper.del(stream.getApp(), stream.getStream()); |
| | |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; |
| | | 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.Map; |
| | |
| | | import java.util.List;
|
| | |
|
| | | 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.StreamProxyItem;
|
| | | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
| | |
| | | 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 org.apache.ibatis.annotations.Insert; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | |
| | | "rtpEnable, " + |
| | | "rtpPortRange, " + |
| | | "recordAssistPort, " + |
| | | "defaultServer, " + |
| | | "createTime, " + |
| | | "updateTime" + |
| | | ") VALUES " + |
| | |
| | | "${rtpEnable}, " + |
| | | "'${rtpPortRange}', " + |
| | | "${recordAssistPort}, " + |
| | | "${defaultServer}, " + |
| | | "'${createTime}', " + |
| | | "'${updateTime}')") |
| | | int add(IMediaServerItem mediaServerItem); |
| | | int add(MediaServerItem mediaServerItem); |
| | | |
| | | @Update(value = {" <script>" + |
| | | "UPDATE media_server " + |
| | |
| | | "<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" + |
| | | "WHERE id='${id}'"+ |
| | | " </script>"}) |
| | | int update(IMediaServerItem mediaServerItem); |
| | | int update(MediaServerItem mediaServerItem); |
| | | |
| | | @Select("SELECT * FROM media_server WHERE id='${id}'") |
| | | MediaServerItem queryOne(String id); |
| | |
| | | List<MediaServerItem> queryAll(); |
| | | |
| | | @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}") |
| | | MediaServerItem queryOneByHostAndPort(String host, int port); |
| | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.genersoft.iot.vmp.common.StreamInfo; |
| | | 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.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.dao.DeviceChannelMapper; |
| | | import com.genersoft.iot.vmp.utils.redis.RedisUtil; |
New file |
| | |
| | | package com.genersoft.iot.vmp.utils; |
| | | |
| | | public class ConfigConst { |
| | | /** |
| | | * 播流最大并发个数 |
| | | */ |
| | | public static final Integer MAX_STRTEAM_COUNT = 10000; |
| | | } |
New file |
| | |
| | | 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; |
| | | } |
| | | } |
New file |
| | |
| | | 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(); |
| | | } |
| | | } |
| | | } |
| | |
| | | *
|
| | | * @param key
|
| | | * @param value
|
| | | * @param score
|
| | | * @param delta -1 表示减 1 表示加1
|
| | | */
|
| | | public Double zIncrScore(Object key, Object value, double score) {
|
| | | return redisTemplate.opsForZSet().incrementScore(key, value, score);
|
| | | public Double zIncrScore(Object key, Object value, double delta) {
|
| | | return redisTemplate.opsForZSet().incrementScore(key, value, delta);
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | 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.media.zlm.ZLMServerConfig; |
| | | 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.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.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | |
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| | | import org.springframework.web.context.request.async.DeferredResult; |
| | | |
| | | import java.util.Enumeration; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.UUID; |
| | | |
| | |
| | | |
| | | // 获取可用的zlm |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | | PlayResult playResult = playService.play(newMediaServerItem, deviceId, channelId, null, null); |
| | | |
| | | return playResult.getResult(); |
| | |
| | | logger.warn("视频转码API调用失败!, 视频流已经停止!"); |
| | | return new ResponseEntity<String>("未找到视频流信息, 视频流可能已经停止", HttpStatus.OK); |
| | | } |
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId()); |
| | | MediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId()); |
| | | JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); |
| | | if (!rtpInfo.getBoolean("exist")) { |
| | | logger.warn("视频转码API调用失败!, 视频流已停止推流!"); |
| | |
| | | result.put("msg", "mediaServerId is null"); |
| | | return new ResponseEntity<String>( result.toJSONString(), HttpStatus.BAD_REQUEST); |
| | | } |
| | | IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); |
| | | MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); |
| | | if (mediaInfo == null) { |
| | | result.put("code", 0); |
| | | result.put("msg", "使用的流媒体已经停止运行"); |
| | |
| | | logger.debug("获取所有的ssrc"); |
| | | } |
| | | JSONArray objects = new JSONArray(); |
| | | for(Map.Entry<String, String> entry: streamSession.getSsrcMap().entrySet()) { |
| | | System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); |
| | | List<SsrcTransaction> allSsrc = streamSession.getAllSsrc(); |
| | | for (SsrcTransaction transaction : allSsrc) { |
| | | JSONObject jsonObject = new JSONObject(); |
| | | String[] keyArray = entry.getKey().split("_"); |
| | | jsonObject.put("deviceId", keyArray[0]); |
| | | jsonObject.put("channelId", keyArray[1]); |
| | | jsonObject.put("ssrc", entry.getValue()); |
| | | jsonObject.put("streamId", streamSession.getStreamIdMap().get(entry.getKey())); |
| | | jsonObject.put("deviceId", transaction.getDeviceId()); |
| | | jsonObject.put("channelId", transaction.getChannelId()); |
| | | jsonObject.put("ssrc", transaction.getSsrc()); |
| | | jsonObject.put("streamId", transaction.getStreamId()); |
| | | objects.add(jsonObject); |
| | | } |
| | | |
| | | WVPResult<JSONObject> result = new WVPResult<>(); |
| | | result.setCode(0); |
| | | result.setMsg("success"); |
| | |
| | | import com.genersoft.iot.vmp.common.StreamInfo; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| | | 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.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | import com.genersoft.iot.vmp.service.IPlayService; |
| | | import io.swagger.annotations.Api; |
| | |
| | | @Autowired |
| | | private DeferredResultHolder resultHolder; |
| | | |
| | | @Autowired |
| | | private IMediaServerService mediaServerService; |
| | | |
| | | @ApiOperation("开始历史媒体下载") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), |
| | |
| | | cmder.streamByeCmd(deviceId, channelId); |
| | | } |
| | | resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result); |
| | | IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | | if (newMediaServerItem == null) { |
| | | logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId)); |
| | | RequestMessage msg = new RequestMessage(); |
| | |
| | | resultHolder.invokeResult(msg); |
| | | 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()); |
| | | playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString()); |
| | | }, event -> { |
| | |
| | | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| | | 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.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | import com.genersoft.iot.vmp.service.IPlayService; |
| | | import io.swagger.annotations.Api; |
| | |
| | | @Autowired |
| | | private DeferredResultHolder resultHolder; |
| | | |
| | | @Autowired |
| | | private IMediaServerService mediaServerService; |
| | | |
| | | @ApiOperation("开始视频回放") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), |
| | |
| | | } |
| | | UUID uuid = UUID.randomUUID(); |
| | | 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(()->{ |
| | | logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId)); |
| | |
| | | msg.setData("Timeout"); |
| | | resultHolder.invokeResult(msg); |
| | | }); |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId); |
| | | if (streamInfo != null) { |
| | | // 停止之前的回放 |
| | | cmder.streamByeCmd(deviceId, channelId); |
| | | } |
| | | resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result); |
| | | IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | | |
| | | if (newMediaServerItem == null) { |
| | | logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId)); |
| | | RequestMessage msg = new RequestMessage(); |
| | |
| | | resultHolder.invokeResult(msg); |
| | | 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()); |
| | | playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString()); |
| | | }, event -> { |
New file |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.vmanager.server; |
| | | |
| | | import com.genersoft.iot.vmp.VManageBootstrap; |
| | | 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.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | import com.genersoft.iot.vmp.utils.SpringBeanFactory; |
| | | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| | | import gov.nist.javax.sip.SipStackImpl; |
| | |
| | | import javax.sip.ListeningPoint; |
| | | import javax.sip.ObjectInUseException; |
| | | import javax.sip.SipProvider; |
| | | import java.util.ArrayList; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | |
| | |
| | | @ApiOperation("流媒体服务列表") |
| | | @GetMapping(value = "/media_server/list") |
| | | @ResponseBody |
| | | public WVPResult<List<IMediaServerItem>> getMediaServerList(){ |
| | | WVPResult<List<IMediaServerItem>> result = new WVPResult<>(); |
| | | public WVPResult<List<MediaServerItem>> getMediaServerList(){ |
| | | WVPResult<List<MediaServerItem>> result = new WVPResult<>(); |
| | | result.setCode(0); |
| | | result.setMsg("success"); |
| | | result.setData(mediaServerService.getAll()); |
| | | 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("获取流媒体服务") |
| | | @GetMapping(value = "/media_server/one/{id}") |
| | | @ResponseBody |
| | | public WVPResult<IMediaServerItem> getMediaServer(@PathVariable String id){ |
| | | WVPResult<IMediaServerItem> result = new WVPResult<>(); |
| | | public WVPResult<MediaServerItem> getMediaServer(@PathVariable String id){ |
| | | WVPResult<MediaServerItem> result = new WVPResult<>(); |
| | | result.setCode(0); |
| | | result.setMsg("success"); |
| | | result.setData(mediaServerService.getOne(id)); |
| | |
| | | package com.genersoft.iot.vmp.vmanager.streamProxy; |
| | | |
| | | 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.StreamProxyItem; |
| | | import com.genersoft.iot.vmp.service.IMediaServerService; |
| | |
| | | import com.genersoft.iot.vmp.service.IStreamProxyService; |
| | | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| | | import com.github.pagehelper.PageInfo; |
| | | import io.netty.util.internal.StringUtil; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | |
| | | public WVPResult getFFmpegCMDs(@RequestParam String mediaServerId){ |
| | | logger.debug("获取节点[ {} ]ffmpeg.cmd模板", mediaServerId ); |
| | | |
| | | IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); |
| | | MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); |
| | | JSONObject data = streamProxyService.getFFmpegCMDs(mediaServerItem); |
| | | WVPResult<JSONObject> result = new WVPResult<>(); |
| | | result.setCode(0); |
| | |
| | | password: |
| | | # [可选] 超时时间 |
| | | timeout: 10000 |
| | | # [可选] 一个pool最多可分配多少个jedis实例 |
| | | poolMaxTotal: 1000 |
| | | # [可选] 一个pool最多有多少个状态为idle(空闲)的jedis实例 |
| | | poolMaxIdle: 500 |
| | | # [可选] 最大的等待时间(秒) |
| | | poolMaxWait: 5 |
| | | # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 |
| | | datasource: |
| | | # 使用mysql 打开23-28行注释, 删除29-36行 |
| | |
| | | level: |
| | | com.genersoft.iot: debug |
| | | com.genersoft.iot.vmp.storager.dao: info |
| | | com.genersoft.iot.vmp.gb28181: info |
| | | # [根据业务需求配置] |
| | | user-settings: |
| | | # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true |
| | |
| | | level: |
| | | com.genersoft.iot: debug |
| | | com.genersoft.iot.vmp.storager.dao: info |
| | | com.genersoft.iot.vmp.gb28181: info |
| | | |
| | | # [根据业务需求配置] |
| | | user-settings: |
| | | # 推流直播是否录制 |
| | |
| | | getMediaServerList(callback){ |
| | | this.$axios({ |
| | | method: 'get', |
| | | url:`/api/server/media_server/list`, |
| | | url:`/api/server/media_server/online/list`, |
| | | }).then(function (res) { |
| | | if (typeof (callback) == "function") callback(res.data) |
| | | }).catch(function (error) { |