Merge pull request #893 from sxh-netizen/wvp-28181-2.0
新增设备主子码流开关选择,默认为不开启
| | |
| | | alter table device |
| | | add mediaServerId varchar(50) default null; |
| | | |
| | | |
| | | ALTER TABLE device |
| | | ADD COLUMN `switchPrimarySubStream` bit(1) NOT NULL DEFAULT b'0' COMMENT 'å¼å¯ä¸»åç æµåæ¢çå¼å
³ï¼0-ä¸å¼å¯ï¼1-å¼å¯ï¼ç°å¨å·²ç¥æ¯æè®¾å¤ä¸º 大åãTPââLINKå
¨ç³»è®¾å¤' AFTER `keepalive_interval_time` |
| | | |
| | | |
| | |
| | | package com.genersoft.iot.vmp.common; |
| | | |
| | | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | |
| | | /** |
| | | * è®°å½æ¯æ¬¡åéinviteæ¶æ¯çç¶æ |
| | |
| | | public void setStreamMode(String streamMode) { |
| | | this.streamMode = streamMode; |
| | | } |
| | | |
| | | |
| | | /*=========================设å¤ä¸»åç æµé»è¾START====================*/ |
| | | @Schema(description = "æ¯å¦ä¸ºåç æµ(true-æ¯ï¼false-ä¸»ç æµ)") |
| | | private boolean subStream; |
| | | |
| | | public boolean isSubStream() { |
| | | return subStream; |
| | | } |
| | | |
| | | public void setSubStream(boolean subStream) { |
| | | this.subStream = subStream; |
| | | } |
| | | |
| | | public static InviteInfo getInviteInfo(String deviceId, String channelId,Boolean isSubStream, String stream, SSRCInfo ssrcInfo, |
| | | String receiveIp, Integer receivePort, String streamMode, |
| | | InviteSessionType type, InviteSessionStatus status) { |
| | | InviteInfo inviteInfo = new InviteInfo(); |
| | | inviteInfo.setDeviceId(deviceId); |
| | | inviteInfo.setChannelId(channelId); |
| | | inviteInfo.setStream(stream); |
| | | inviteInfo.setSsrcInfo(ssrcInfo); |
| | | inviteInfo.setReceiveIp(receiveIp); |
| | | inviteInfo.setReceivePort(receivePort); |
| | | inviteInfo.setStreamMode(streamMode); |
| | | inviteInfo.setType(type); |
| | | inviteInfo.setStatus(status); |
| | | if(isSubStream != null){ |
| | | inviteInfo.setSubStream(isSubStream); |
| | | } |
| | | return inviteInfo; |
| | | } |
| | | /*=========================设å¤ä¸»åç æµé»è¾END====================*/ |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | } |
| | | return instance; |
| | | } |
| | | |
| | | |
| | | /*=========================设å¤ä¸»åç æµé»è¾START====================*/ |
| | | @Schema(description = "æ¯å¦ä¸ºåç æµ(true-æ¯ï¼false-ä¸»ç æµ)") |
| | | private boolean subStream; |
| | | |
| | | public boolean isSubStream() { |
| | | return subStream; |
| | | } |
| | | |
| | | public void setSubStream(boolean subStream) { |
| | | this.subStream = subStream; |
| | | } |
| | | |
| | | public static String getPlayStream(String deviceId,String channelId,boolean isSubStream){ |
| | | String streamId; |
| | | if(isSubStream){ |
| | | streamId = String.format("%s_%s_%s","sub",deviceId, channelId); |
| | | }else { |
| | | streamId = String.format("%s_%s_%s","main", deviceId, channelId); |
| | | } |
| | | return streamId; |
| | | } |
| | | |
| | | /*=========================设å¤ä¸»åç æµé»è¾END====================*/ |
| | | |
| | | |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.conf; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import org.springframework.core.annotation.Order; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | import org.springframework.stereotype.Component; |
| | |
| | | |
| | | private int platformPlayTimeout = 60000; |
| | | |
| | | private Boolean interfaceAuthentication = Boolean.TRUE; |
| | | private Boolean interfaceAuthentication = Boolean.FALSE; |
| | | |
| | | private Boolean recordPushLive = Boolean.TRUE; |
| | | private Boolean recordPushLive = Boolean.FALSE; |
| | | |
| | | private Boolean recordSip = Boolean.TRUE; |
| | | private Boolean recordSip = Boolean.FALSE; |
| | | |
| | | private Boolean logInDatebase = Boolean.TRUE; |
| | | |
| | |
| | | private SipTransactionInfo sipTransactionInfo; |
| | | |
| | | |
| | | |
| | | |
| | | public String getDeviceId() { |
| | | return deviceId; |
| | | } |
| | |
| | | public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) { |
| | | this.sipTransactionInfo = sipTransactionInfo; |
| | | } |
| | | |
| | | /*======================设å¤ä¸»åç æµé»è¾START=========================*/ |
| | | @Schema(description = "å¼å¯ä¸»åç æµåæ¢çå¼å
³ï¼false-ä¸å¼å¯ï¼true-å¼å¯ï¼") |
| | | private boolean switchPrimarySubStream; |
| | | |
| | | public boolean isSwitchPrimarySubStream() { |
| | | return switchPrimarySubStream; |
| | | } |
| | | |
| | | public void setSwitchPrimarySubStream(boolean switchPrimarySubStream) { |
| | | this.switchPrimarySubStream = switchPrimarySubStream; |
| | | } |
| | | |
| | | /*======================设å¤ä¸»åç æµé»è¾END=========================*/ |
| | | |
| | | |
| | | } |
| | |
| | | map.remove(msg.getKey());
|
| | | }
|
| | | }
|
| | |
|
| | | /*============================设å¤ä¸»åç æµé»è¾START========================*/
|
| | | public static String getPlayKey(String deviceId,String channelId,boolean deviceSwitchSubStream,boolean isSubStream){
|
| | | String key = null;
|
| | | if(deviceSwitchSubStream){
|
| | | key = CALLBACK_CMD_PLAY + isSubStream + deviceId + channelId;
|
| | | }else {
|
| | | key = CALLBACK_CMD_PLAY +deviceId + channelId;
|
| | | }
|
| | | return key;
|
| | | }
|
| | |
|
| | | public static String getSnapKey(String deviceId,String channelId,boolean deviceSwitchSubStream,boolean isSubStream){
|
| | | String key = null;
|
| | | if(deviceSwitchSubStream){
|
| | | key = CALLBACK_CMD_SNAP + isSubStream + deviceId + channelId;
|
| | | }else {
|
| | | key = CALLBACK_CMD_SNAP +deviceId + channelId;
|
| | | }
|
| | | return key;
|
| | | }
|
| | |
|
| | |
|
| | | /*============================设å¤ä¸»åç æµé»è¾END========================*/
|
| | |
|
| | |
|
| | | }
|
| | |
| | | * @param device è§é¢è®¾å¤
|
| | | * @param channelId é¢è§éé
|
| | | */
|
| | | void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | | void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,boolean isSubStream, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | |
|
| | | /**
|
| | | * 请æ±åæ¾è§é¢æµ
|
| | |
| | | * @param errorEvent sipé误订é
|
| | | */
|
| | | @Override
|
| | | public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
|
| | | public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,boolean isSubStream,
|
| | | ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
| | | String stream = ssrcInfo.getStream();
|
| | |
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | if( device.isSwitchPrimarySubStream() ){
|
| | | if("TP-LINK".equals(device.getManufacturer())){
|
| | | if (isSubStream){
|
| | | content.append("a=streamMode:sub\r\n");
|
| | | }else {
|
| | | content.append("a=streamMode:main\r\n");
|
| | | }
|
| | | }else {
|
| | | if (isSubStream){
|
| | | content.append("a=streamprofile:1\r\n");
|
| | | }else {
|
| | | content.append("a=streamprofile:0\r\n");
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
|
| | | // fåæ®µ:f= v/ç¼ç æ ¼å¼/å辨ç/帧ç/ç çç±»å/ç ç大å°a/ç¼ç æ ¼å¼/ç ç大å°/éæ ·ç
|
| | | // content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // æªåç°æ¯ææ¤ç¹æ§ç设å¤
|
| | |
| | | // è¿é为ä¾é¿å
ä¸ä¸ªééçç¹æåªæä¸ä¸ªcallIDè¿ä¸ªåæ°ä½¿ç¨ä¸ä¸ªåºå®å¼
|
| | | ResponseEvent responseEvent = (ResponseEvent) e.event;
|
| | | SIPResponse response = (SIPResponse) responseEvent.getResponse();
|
| | | if(device.isSwitchPrimarySubStream()){
|
| | | streamSession.put(device.getDeviceId(), channelId, "switch-play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAY);
|
| | | }else {
|
| | | streamSession.put(device.getDeviceId(), channelId, "play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAY);
|
| | | }
|
| | | okEvent.response(e);
|
| | | });
|
| | | }
|
| | |
| | | // å¯è½æ¯è®¾å¤ä¸»å¨åæ¢ |
| | | Device device = storager.queryVideoDeviceByChannelId(platformGbId); |
| | | if (device != null) { |
| | | SsrcTransaction ssrcTransactionForPlay = null; |
| | | if (device.isSwitchPrimarySubStream() ) { |
| | | ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "switch-play", null); |
| | | } else { |
| | | storager.stopPlay(device.getDeviceId(), channelId); |
| | | SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); |
| | | ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); |
| | | } |
| | | if (ssrcTransactionForPlay != null){ |
| | | if (ssrcTransactionForPlay.getCallId().equals(callIdHeader.getCallId())){ |
| | | // éæ¾ssrc |
| | |
| | | } |
| | | streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream()); |
| | | } |
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); |
| | | |
| | | if (inviteInfo != null) { |
| | | InviteInfo inviteInfo = null; |
| | | if (device.isSwitchPrimarySubStream() ) { |
| | | String streamType = ssrcTransactionForPlay.getStream().split("_")[0]; |
| | | boolean isSubStream = "sub".equals(streamType); |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream); |
| | | inviteStreamService.removeInviteInfo(inviteInfo.getType(),inviteInfo.getDeviceId(),inviteInfo.getChannelId(),isSubStream,inviteInfo.getStream()); |
| | | }else { |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); |
| | | inviteStreamService.removeInviteInfo(inviteInfo); |
| | | } |
| | | if (inviteInfo != null) { |
| | | if (inviteInfo.getStreamInfo() != null) { |
| | | mediaServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServerId(), inviteInfo.getStream()); |
| | | } |
| | |
| | | } |
| | | sendRtpItem.setStreamId(streamId); |
| | | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| | | playService.play(mediaServerItem, device.getDeviceId(), channelId, ((code, msg, data) -> { |
| | | playService.play(mediaServerItem, device.getDeviceId(), channelId,false, ((code, msg, data) -> { |
| | | if (code == InviteErrorCode.SUCCESS.getCode()){ |
| | | hookEvent.run(code, msg, data); |
| | | }else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){ |
| | |
| | | @ResponseBody
|
| | | @PostMapping(value = "/on_stream_changed", produces = "application/json;charset=UTF-8")
|
| | | public HookResult onStreamChanged(@RequestBody OnStreamChangedHookParam param) {
|
| | |
|
| | | if (param.isRegist()) {
|
| | | logger.info("[ZLM HOOK] æµæ³¨å, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
|
| | | } else {
|
| | |
| | |
|
| | | List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks();
|
| | | // TODO éææ¤å¤é»è¾
|
| | | boolean isPush = false;
|
| | | if (param.isRegist()) {
|
| | | // å¤çæµæ³¨åçé´æä¿¡æ¯
|
| | | if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
|
| | | || param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
|
| | | || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
|
| | | isPush = true;
|
| | | StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
|
| | | if (streamAuthorityInfo == null) {
|
| | | streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
|
| | |
| | | redisCatchStorage.removeStreamAuthorityInfo(param.getApp(), param.getStream());
|
| | | }
|
| | |
|
| | | if ("rtmp".equals(param.getSchema())) {
|
| | | if ("rtsp".equals(param.getSchema())) {
|
| | | // æ´æ°æµåªä½è´è½½ä¿¡æ¯
|
| | | if (param.isRegist()) {
|
| | | mediaServerService.addCount(param.getMediaServerId());
|
| | |
| | | }
|
| | |
|
| | | if ("rtp".equals(param.getApp()) && !param.isRegist()) {
|
| | | if(param.getStream().split("_").length == 3){
|
| | | boolean isSubStream = "sub".equals(param.getStream().split("_")[0]);
|
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream(), isSubStream);
|
| | | if(inviteInfo != null && (inviteInfo.getType() == InviteSessionType.PLAY )){
|
| | | inviteStreamService.removeInviteInfo(inviteInfo.getType(),inviteInfo.getDeviceId(),
|
| | | inviteInfo.getChannelId(),inviteInfo.isSubStream(),inviteInfo.getStream());
|
| | | }
|
| | | }else {
|
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream());
|
| | | if (inviteInfo != null && (inviteInfo.getType() == InviteSessionType.PLAY || inviteInfo.getType() == InviteSessionType.PLAYBACK)) {
|
| | | inviteStreamService.removeInviteInfo(inviteInfo);
|
| | | storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId());
|
| | | }
|
| | | }
|
| | | } else {
|
| | | if (!"rtp".equals(param.getApp())) {
|
| | |
| | | StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaInfo,
|
| | | param.getApp(), param.getStream(), tracks, callId);
|
| | | param.setStreamInfo(new StreamContent(streamInfoByAppAndStream));
|
| | | // å¦ææ¯ææµä»£ç产ççï¼ä¸éè¦åå
¥æ¨æµ
|
| | |
|
| | | redisCatchStorage.addStream(mediaInfo, type, param.getApp(), param.getStream(), param);
|
| | | if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
|
| | | || param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
|
| | |
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream());
|
| | | // ç¹æ
|
| | | if (inviteInfo != null) {
|
| | | // å½åä¸è½½
|
| | | if (inviteInfo.getType() == InviteSessionType.DOWNLOAD) {
|
| | | ret.put("close", false);
|
| | | return ret;
|
| | | }
|
| | | // æ¶å°æ 人è§çè¯´ææµä¹æ²¡æå¨å¾ä¸çº§æ¨é
|
| | | if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) {
|
| | | List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId(
|
| | |
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (userSetting.getStreamOnDemand()) {
|
| | | // å½åä¸è½½
|
| | | if (inviteInfo.getType() == InviteSessionType.DOWNLOAD) {
|
| | | ret.put("close", false);
|
| | | return ret;
|
| | | }
|
| | |
|
| | | Device device = deviceService.getDevice(inviteInfo.getDeviceId());
|
| | | if (device != null) {
|
| | | try {
|
| | | if (inviteStreamService.getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()) != null) {
|
| | | InviteInfo info = null;
|
| | | if(device.isSwitchPrimarySubStream()){
|
| | | boolean isSubStream = "sub".equals(param.getStream().split("_")[0]);
|
| | | info = inviteStreamService.getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), inviteInfo.getChannelId(),isSubStream, inviteInfo.getStream());
|
| | | }else {
|
| | | info = inviteStreamService.getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream());
|
| | |
|
| | | }
|
| | |
|
| | | if (info != null) {
|
| | | cmder.streamByeCmd(device, inviteInfo.getChannelId(),
|
| | | inviteInfo.getStream(), null);
|
| | | }
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | if(device.isSwitchPrimarySubStream()){
|
| | | boolean isSubStream = "sub".equals(param.getStream().split("_")[0]);
|
| | | inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(),
|
| | | inviteInfo.getChannelId(),isSubStream, inviteInfo.getStream());
|
| | | }else {
|
| | | inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(),
|
| | | inviteInfo.getChannelId(), inviteInfo.getStream());
|
| | | storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId());
|
| | |
| | | // ææµä»£ç
|
| | | StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream());
|
| | | if (streamProxyItem != null) {
|
| | | if (streamProxyItem.isEnableRemoveNoneReader()) {
|
| | | if (streamProxyItem.isEnableDisableNoneReader()) {
|
| | | // æ 人è§çèªå¨ç§»é¤
|
| | | ret.put("close", true);
|
| | | streamProxyService.del(param.getApp(), param.getStream());
|
| | |
| | |
|
| | | if ("rtp".equals(param.getApp())) {
|
| | | String[] s = param.getStream().split("_");
|
| | | if (!mediaInfo.isRtpEnable() || s.length != 2) {
|
| | | if (!mediaInfo.isRtpEnable() ) {
|
| | | defaultResult.setResult(HookResult.SUCCESS());
|
| | | return defaultResult;
|
| | | }else if(s.length != 2 && s.length != 3 ){
|
| | | defaultResult.setResult(HookResult.SUCCESS());
|
| | | return defaultResult;
|
| | | }
|
| | | String deviceId = s[0];
|
| | | String channelId = s[1];
|
| | | String deviceId = null;
|
| | | String channelId = null;
|
| | | boolean isSubStream = false;
|
| | | if (s[0].length() < 20) {
|
| | | if ("sub".equals(s[0])) {
|
| | | isSubStream = true;
|
| | | }
|
| | | deviceId = s[1];
|
| | | channelId = s[2];
|
| | | } else {
|
| | | deviceId = s[0];
|
| | | channelId = s[1];
|
| | | }
|
| | | Device device = redisCatchStorage.getDevice(deviceId);
|
| | | if (device == null) {
|
| | | defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg()));
|
| | |
| | | logger.info("[ZLM HOOK] æµæªæ¾å°, åèµ·èªå¨ç¹æï¼{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
|
| | |
|
| | | RequestMessage msg = new RequestMessage();
|
| | | String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
|
| | | String key = DeferredResultHolder.getPlayKey(deviceId, channelId, device.isSwitchPrimarySubStream(), isSubStream);
|
| | | boolean exist = resultHolder.exist(key, null);
|
| | | msg.setKey(key);
|
| | | String uuid = UUID.randomUUID().toString();
|
| | |
| | | resultHolder.put(key, uuid, result);
|
| | |
|
| | | if (!exist) {
|
| | | playService.play(mediaInfo, deviceId, channelId, (code, message, data) -> {
|
| | | playService.play(mediaInfo, deviceId, channelId,isSubStream, (code, message, data) -> {
|
| | | msg.setData(new HookResult(code, message));
|
| | | resultHolder.invokeResult(msg);
|
| | | });
|
| | |
| | | import com.genersoft.iot.vmp.common.InviteSessionType; |
| | | import com.genersoft.iot.vmp.service.bean.ErrorCallback; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * è®°å½å½æ ç¹æçç¶æï¼å
æ¬å®æ¶é¢è§ï¼ä¸è½½ï¼å½ååæ¾ |
| | | */ |
| | |
| | | * ç»è®¡åä¸ä¸ªzlmä¸ç彿 æ¶æµä¸ªæ° |
| | | */ |
| | | int getStreamInfoCount(String mediaServerId); |
| | | |
| | | |
| | | /*======================设å¤ä¸»åç æµé»è¾START=========================*/ |
| | | /** |
| | | * è·åç¹æçç¶æä¿¡æ¯ |
| | | */ |
| | | InviteInfo getInviteInfoByDeviceAndChannel(InviteSessionType type, |
| | | String deviceId, |
| | | String channelId,boolean isSubStream); |
| | | |
| | | void removeInviteInfoByDeviceAndChannel(InviteSessionType inviteSessionType, String deviceId, String channelId,boolean isSubStream); |
| | | |
| | | InviteInfo getInviteInfo(InviteSessionType type, |
| | | String deviceId, |
| | | String channelId, |
| | | boolean isSubStream, |
| | | String stream); |
| | | |
| | | void removeInviteInfo(InviteSessionType type, |
| | | String deviceId, |
| | | String channelId, |
| | | boolean isSubStream, |
| | | String stream); |
| | | |
| | | void once(InviteSessionType type, String deviceId, String channelId,boolean isSubStream, String stream, ErrorCallback<Object> callback); |
| | | |
| | | void call(InviteSessionType type, String deviceId, String channelId,boolean isSubStream, String stream, int code, String msg, Object data); |
| | | |
| | | void updateInviteInfoSub(InviteInfo inviteInfo); |
| | | |
| | | /** |
| | | * è·åç¹æçç¶æä¿¡æ¯ |
| | | */ |
| | | InviteInfo getInviteInfoByStream(InviteSessionType type, String stream,boolean isSubStream); |
| | | |
| | | /** |
| | | * è·åç¹æçç¶æä¿¡æ¯ |
| | | */ |
| | | List<Object> getInviteInfos(InviteSessionType type, |
| | | String deviceId, |
| | | String channelId, |
| | | String stream); |
| | | /*======================设å¤ä¸»åç æµé»è¾END=========================*/ |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | */ |
| | | public interface IPlayService { |
| | | |
| | | void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| | | void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,boolean isSubStream, |
| | | ErrorCallback<Object> callback); |
| | | SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, ErrorCallback<Object> callback); |
| | | SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId,boolean isSubStream, ErrorCallback<Object> callback); |
| | | |
| | | MediaServerItem getNewMediaServerItem(Device device); |
| | | |
| | |
| | | |
| | | void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException; |
| | | |
| | | void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback); |
| | | void getSnap(String deviceId, String channelId, String fileName,boolean isSubStream, ErrorCallback errorCallback); |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.service.impl; |
| | | |
| | | import com.genersoft.iot.vmp.common.InviteSessionType; |
| | | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| | | import com.genersoft.iot.vmp.conf.DynamicTask; |
| | | import com.genersoft.iot.vmp.conf.UserSetting; |
| | | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| | | import com.genersoft.iot.vmp.gb28181.bean.*; |
| | | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| | | import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; |
| | | import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; |
| | | import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; |
| | | import com.genersoft.iot.vmp.service.IDeviceChannelService; |
| | | import com.genersoft.iot.vmp.service.IDeviceService; |
| | |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class); |
| | | |
| | | @Autowired |
| | | private SIPCommander cmder; |
| | | @Autowired |
| | | private DynamicTask dynamicTask; |
| | | |
| | |
| | | } |
| | | sync(device); |
| | | }else { |
| | | |
| | | if (deviceInDb != null) { |
| | | device.setSwitchPrimarySubStream(deviceInDb.isSwitchPrimarySubStream()); |
| | | } |
| | | if(!device.isOnLine()){ |
| | | device.setOnLine(true); |
| | | device.setCreateTime(now); |
| | |
| | | logger.warn("æ´æ°è®¾å¤æ¶æªæ¾å°è®¾å¤ä¿¡æ¯"); |
| | | return; |
| | | } |
| | | if(deviceInStore.isSwitchPrimarySubStream() != device.isSwitchPrimarySubStream()){ |
| | | //å½ä¿®æ¹è®¾å¤ç主åç æµå¼å
³æ¶ï¼éè¦æ ¡éªæ¯å¦å卿µï¼å¦æå卿µåç´æ¥å
³é |
| | | List<SsrcTransaction> ssrcTransactionForAll = streamSession.getSsrcTransactionForAll(device.getDeviceId(), null, null, null); |
| | | if(ssrcTransactionForAll != null){ |
| | | for (SsrcTransaction ssrcTransaction: ssrcTransactionForAll) { |
| | | try { |
| | | cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), ssrcTransaction.getStream(), null, null); |
| | | } catch (InvalidArgumentException | SsrcTransactionNotFoundException | ParseException | SipException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | } |
| | | deviceChannelMapper.clearPlay(device.getDeviceId()); |
| | | inviteStreamService.clearInviteInfo(device.getDeviceId()); |
| | | } |
| | | |
| | | if (!ObjectUtils.isEmpty(device.getName())) { |
| | | deviceInStore.setName(device.getName()); |
| | | } |
| | |
| | | } |
| | | return count; |
| | | } |
| | | |
| | | /*======================设å¤ä¸»åç æµé»è¾START=========================*/ |
| | | |
| | | @Override |
| | | public InviteInfo getInviteInfoByDeviceAndChannel(InviteSessionType type, String deviceId, String channelId, boolean isSubStream) { |
| | | return getInviteInfo(type, deviceId, channelId,isSubStream, null); |
| | | } |
| | | |
| | | @Override |
| | | public void removeInviteInfoByDeviceAndChannel(InviteSessionType inviteSessionType, String deviceId, String channelId, boolean isSubStream) { |
| | | removeInviteInfo(inviteSessionType, deviceId, channelId,isSubStream, null); |
| | | } |
| | | |
| | | @Override |
| | | public InviteInfo getInviteInfo(InviteSessionType type, String deviceId, String channelId,boolean isSubStream, String stream) { |
| | | String key = VideoManagerConstants.INVITE_PREFIX + |
| | | "_" + (type != null ? type : "*") + |
| | | "_" + (isSubStream ? "sub" : "main") + |
| | | "_" + (deviceId != null ? deviceId : "*") + |
| | | "_" + (channelId != null ? channelId : "*") + |
| | | "_" + (stream != null ? stream : "*"); |
| | | List<Object> scanResult = RedisUtil.scan(redisTemplate, key); |
| | | if (scanResult.size() != 1) { |
| | | return null; |
| | | } |
| | | return (InviteInfo) redisTemplate.opsForValue().get(scanResult.get(0)); |
| | | } |
| | | |
| | | @Override |
| | | public void removeInviteInfo(InviteSessionType type, String deviceId, String channelId, boolean isSubStream, String stream) { |
| | | String scanKey = VideoManagerConstants.INVITE_PREFIX + |
| | | "_" + (type != null ? type : "*") + |
| | | "_" + (isSubStream ? "sub" : "main") + |
| | | "_" + (deviceId != null ? deviceId : "*") + |
| | | "_" + (channelId != null ? channelId : "*") + |
| | | "_" + (stream != null ? stream : "*"); |
| | | List<Object> scanResult = RedisUtil.scan(redisTemplate, scanKey); |
| | | if (scanResult.size() > 0) { |
| | | for (Object keyObj : scanResult) { |
| | | String key = (String) keyObj; |
| | | InviteInfo inviteInfo = (InviteInfo) redisTemplate.opsForValue().get(key); |
| | | if (inviteInfo == null) { |
| | | continue; |
| | | } |
| | | redisTemplate.delete(key); |
| | | inviteErrorCallbackMap.remove(buildKey(type, deviceId, channelId, inviteInfo.getStream())); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void once(InviteSessionType type, String deviceId, String channelId, boolean isSubStream, String stream, ErrorCallback<Object> callback) { |
| | | String key = buildSubStreamKey(type, deviceId, channelId,isSubStream, stream); |
| | | List<ErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key); |
| | | if (callbacks == null) { |
| | | callbacks = new CopyOnWriteArrayList<>(); |
| | | inviteErrorCallbackMap.put(key, callbacks); |
| | | } |
| | | callbacks.add(callback); |
| | | } |
| | | |
| | | @Override |
| | | public void call(InviteSessionType type, String deviceId, String channelId, boolean isSubStream, String stream, int code, String msg, Object data) { |
| | | String key = buildSubStreamKey(type, deviceId, channelId,isSubStream, stream); |
| | | List<ErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key); |
| | | if (callbacks == null) { |
| | | return; |
| | | } |
| | | for (ErrorCallback<Object> callback : callbacks) { |
| | | callback.run(code, msg, data); |
| | | } |
| | | inviteErrorCallbackMap.remove(key); |
| | | } |
| | | |
| | | |
| | | private String buildSubStreamKey(InviteSessionType type, String deviceId, String channelId, boolean isSubStream, String stream) { |
| | | String key = type + "_" + (isSubStream ? "sub":"main") + "_" + deviceId + "_" + channelId; |
| | | // 妿ssrc为nullé£ä¹å¯ä»¥å®ç°ä¸ä¸ªééåªè½ä¸æ¬¡æä½ï¼ssrcä¸ä¸ºnullåå¯ä»¥æ¯æä¸ä¸ªéé夿¬¡invite |
| | | if (stream != null) { |
| | | key += ("_" + stream); |
| | | } |
| | | return key; |
| | | } |
| | | @Override |
| | | public void updateInviteInfoSub(InviteInfo inviteInfo) { |
| | | if (inviteInfo == null || (inviteInfo.getDeviceId() == null || inviteInfo.getChannelId() == null)) { |
| | | logger.warn("[æ´æ°Inviteä¿¡æ¯]ï¼åæ°ä¸å
¨ï¼ {}", JSON.toJSON(inviteInfo)); |
| | | return; |
| | | } |
| | | InviteInfo inviteInfoForUpdate = null; |
| | | |
| | | if (InviteSessionStatus.ready == inviteInfo.getStatus()) { |
| | | if (inviteInfo.getDeviceId() == null |
| | | || inviteInfo.getChannelId() == null |
| | | || inviteInfo.getType() == null |
| | | || inviteInfo.getStream() == null |
| | | ) { |
| | | return; |
| | | } |
| | | inviteInfoForUpdate = inviteInfo; |
| | | } else { |
| | | InviteInfo inviteInfoInRedis = getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), |
| | | inviteInfo.getChannelId(),inviteInfo.isSubStream(), inviteInfo.getStream()); |
| | | if (inviteInfoInRedis == null) { |
| | | logger.warn("[æ´æ°Inviteä¿¡æ¯]ï¼æªä»ç¼åä¸è¯»åå°Inviteä¿¡æ¯ï¼ deviceId: {}, channel: {}, stream: {}", |
| | | inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()); |
| | | return; |
| | | } |
| | | if (inviteInfo.getStreamInfo() != null) { |
| | | inviteInfoInRedis.setStreamInfo(inviteInfo.getStreamInfo()); |
| | | } |
| | | if (inviteInfo.getSsrcInfo() != null) { |
| | | inviteInfoInRedis.setSsrcInfo(inviteInfo.getSsrcInfo()); |
| | | } |
| | | if (inviteInfo.getStreamMode() != null) { |
| | | inviteInfoInRedis.setStreamMode(inviteInfo.getStreamMode()); |
| | | } |
| | | if (inviteInfo.getReceiveIp() != null) { |
| | | inviteInfoInRedis.setReceiveIp(inviteInfo.getReceiveIp()); |
| | | } |
| | | if (inviteInfo.getReceivePort() != null) { |
| | | inviteInfoInRedis.setReceivePort(inviteInfo.getReceivePort()); |
| | | } |
| | | if (inviteInfo.getStatus() != null) { |
| | | inviteInfoInRedis.setStatus(inviteInfo.getStatus()); |
| | | } |
| | | |
| | | inviteInfoForUpdate = inviteInfoInRedis; |
| | | |
| | | } |
| | | String key = VideoManagerConstants.INVITE_PREFIX + |
| | | "_" + inviteInfoForUpdate.getType() + |
| | | "_" + (inviteInfoForUpdate.isSubStream() ? "sub":"main") + |
| | | "_" + inviteInfoForUpdate.getDeviceId() + |
| | | "_" + inviteInfoForUpdate.getChannelId() + |
| | | "_" + inviteInfoForUpdate.getStream(); |
| | | redisTemplate.opsForValue().set(key, inviteInfoForUpdate); |
| | | } |
| | | |
| | | @Override |
| | | public InviteInfo getInviteInfoByStream(InviteSessionType type, String stream, boolean isSubStream) { |
| | | return getInviteInfo(type, null, null,isSubStream, stream); |
| | | } |
| | | |
| | | @Override |
| | | public List<Object> getInviteInfos(InviteSessionType type, String deviceId, String channelId, String stream) { |
| | | String key = VideoManagerConstants.INVITE_PREFIX + |
| | | "_" + (type != null ? type : "*") + |
| | | "_" + (deviceId != null ? deviceId : "*") + |
| | | "_" + (channelId != null ? channelId : "*") + |
| | | "_" + (stream != null ? stream : "*"); |
| | | List<Object> scanResult = RedisUtil.scan(redisTemplate, key); |
| | | return scanResult; |
| | | } |
| | | |
| | | /*======================设å¤ä¸»åç æµé»è¾END=========================*/ |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| | | 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.utils.SipUtils; |
| | | import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| | |
| | | |
| | | |
| | | @Override |
| | | public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, ErrorCallback<Object> callback) { |
| | | public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId,boolean isSubStream, ErrorCallback<Object> callback) { |
| | | if (mediaServerItem == null) { |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "æªæ¾å°å¯ç¨çzlm"); |
| | | } |
| | | |
| | | Device device = redisCatchStorage.getDevice(deviceId); |
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | |
| | | InviteInfo inviteInfo; |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); |
| | | }else { |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | } |
| | | if (inviteInfo != null ) { |
| | | if (inviteInfo.getStreamInfo() == null) { |
| | | // ç¹æåèµ·äºä½æ¯å°æªæå, ä»
注ååè°çå¾
ç»æå³å¯ |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId,isSubStream, null, callback); |
| | | }else { |
| | | inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); |
| | | } |
| | | return inviteInfo.getSsrcInfo(); |
| | | }else { |
| | | StreamInfo streamInfo = inviteInfo.getStreamInfo(); |
| | | String streamId = streamInfo.getStream(); |
| | | if (streamId == null) { |
| | | callback.run(InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), "ç¹æå¤±è´¥ï¼ redisç¼åstreamIdçäºnull", null); |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), |
| | | "ç¹æå¤±è´¥ï¼ redisç¼åstreamIdçäºnull", |
| | | null); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), |
| | | "ç¹æå¤±è´¥ï¼ redisç¼åstreamIdçäºnull", |
| | | null); |
| | | } |
| | | return inviteInfo.getSsrcInfo(); |
| | | } |
| | | String mediaServerId = streamInfo.getMediaServerId(); |
| | |
| | | Boolean ready = zlmrtpServerFactory.isStreamReady(mediaInfo, "rtp", streamId); |
| | | if (ready != null && ready) { |
| | | callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), |
| | | streamInfo); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), |
| | | streamInfo); |
| | | } |
| | | return inviteInfo.getSsrcInfo(); |
| | | }else { |
| | | // ç¹æåèµ·äºä½æ¯å°æªæå, ä»
注ååè°çå¾
ç»æå³å¯ |
| | | if(device.isSwitchPrimarySubStream()) { |
| | | inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); |
| | | storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | }else { |
| | | inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId,isSubStream, null, callback); |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | String streamId = null; |
| | | if (mediaServerItem.isRtpEnable()) { |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | streamId = StreamInfo.getPlayStream(deviceId, channelId, isSubStream); |
| | | }else { |
| | | streamId = String.format("%s_%s", device.getDeviceId(), channelId); |
| | | } |
| | | } |
| | | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false, 0, false, device.getStreamModeForParam()); |
| | | if (ssrcInfo == null) { |
| | | callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null); |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), |
| | | InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), |
| | | null); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), |
| | | InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), |
| | | null); |
| | | } |
| | | return null; |
| | | } |
| | | // TODO è®°å½ç¹æçç¶æ |
| | | play(mediaServerItem, ssrcInfo, device, channelId, callback); |
| | | play(mediaServerItem, ssrcInfo, device, channelId,isSubStream, callback); |
| | | return ssrcInfo; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| | | public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,boolean isSubStream, |
| | | ErrorCallback<Object> callback) { |
| | | |
| | | if (mediaServerItem == null || ssrcInfo == null) { |
| | |
| | | null); |
| | | return; |
| | | } |
| | | logger.info("\r\n" + |
| | | " [ç¹æå¼å§] \r\n" + |
| | | "deviceId : {}, \r\n" + |
| | | "channelId : {},\r\n" + |
| | | "æ¶æµç«¯å£ : {}, \r\n" + |
| | | "æ¶æµæ¨¡å¼ : {}, \r\n" + |
| | | "SSRC : {}, \r\n" + |
| | | "SSRCæ ¡éª ï¼{}", |
| | | device.getDeviceId(), |
| | | channelId, |
| | | ssrcInfo.getPort(), |
| | | device.getStreamMode(), |
| | | ssrcInfo.getSsrc(), |
| | | device.isSsrcCheck()); |
| | | |
| | | if( device.isSwitchPrimarySubStream() ){ |
| | | logger.info("[ç¹æå¼å§] deviceId: {}, channelId: {},ç æµç±»åï¼{},æ¶æµç«¯å£ï¼ {}, æ¶æµæ¨¡å¼ï¼{}, SSRC: {}, SSRCæ ¡éªï¼{}", device.getDeviceId(), channelId,isSubStream ? "è¾
ç æµ" : "ä¸»ç æµ", ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); |
| | | }else { |
| | | logger.info("[ç¹æå¼å§] deviceId: {}, channelId: {},æ¶æµç«¯å£ï¼ {}, æ¶æµæ¨¡å¼ï¼{}, SSRC: {}, SSRCæ ¡éªï¼{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); |
| | | } |
| | | //端å£è·å失败çssrcInfo 没æå¿
è¦åéç¹ææä»¤ |
| | | if (ssrcInfo.getPort() <= 0) { |
| | | logger.info("[ç¹æç«¯å£åé
å¼å¸¸]ï¼deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); |
| | |
| | | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| | | |
| | | callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "ç¹æç«¯å£åé
å¼å¸¸", null); |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "ç¹æç«¯å£åé
å¼å¸¸", null); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "ç¹æç«¯å£åé
å¼å¸¸", null); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | // åå§åredisä¸çinviteæ¶æ¯ç¶æ |
| | | InviteInfo inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, |
| | | InviteInfo inviteInfo; |
| | | |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | // åå§åredisä¸çinviteæ¶æ¯ç¶æ |
| | | inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId,isSubStream, ssrcInfo.getStream(), ssrcInfo, |
| | | mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY, |
| | | InviteSessionStatus.ready); |
| | | inviteStreamService.updateInviteInfoSub(inviteInfo); |
| | | }else { |
| | | // åå§åredisä¸çinviteæ¶æ¯ç¶æ |
| | | inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, |
| | | mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY, |
| | | InviteSessionStatus.ready); |
| | | inviteStreamService.updateInviteInfo(inviteInfo); |
| | | } |
| | | // è¶
æ¶å¤ç |
| | | String timeOutTaskKey = UUID.randomUUID().toString(); |
| | | dynamicTask.startDelay(timeOutTaskKey, () -> { |
| | | // æ§è¡è¶
æ¶ä»»å¡æ¶æ¥è¯¢æ¯å¦å·²ç»æåï¼æåäºå䏿§è¡è¶
æ¶ä»»å¡ï¼é²æ¢è¶
æ¶ä»»å¡åæ¶å¤±è´¥çæ
åµ |
| | | InviteInfo inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); |
| | | InviteInfo inviteInfoForTimeOut; |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | // åå§åredisä¸çinviteæ¶æ¯ç¶æ |
| | | inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream); |
| | | }else { |
| | | // åå§åredisä¸çinviteæ¶æ¯ç¶æ |
| | | inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); |
| | | } |
| | | if (inviteInfoForTimeOut == null || inviteInfoForTimeOut.getStreamInfo() == null) { |
| | | if( device.isSwitchPrimarySubStream()){ |
| | | logger.info("[ç¹æè¶
æ¶] æ¶æµè¶
æ¶ deviceId: {}, channelId: {},ç æµç±»åï¼{}ï¼ç«¯å£ï¼{}, SSRC: {}", device.getDeviceId(), channelId,isSubStream ? "è¾
ç æµ" : "ä¸»ç æµ", ssrcInfo.getPort(), ssrcInfo.getSsrc()); |
| | | }else { |
| | | logger.info("[ç¹æè¶
æ¶] æ¶æµè¶
æ¶ deviceId: {}, channelId: {}ï¼ç«¯å£ï¼{}, SSRC: {}", device.getDeviceId(), channelId, ssrcInfo.getPort(), ssrcInfo.getSsrc()); |
| | | } |
| | | // ç¹æè¶
æ¶åå¤BYE åæ¶éæ¾ssrcä»¥åæ¤æ¬¡ç¹æçèµæº |
| | | // InviteInfo inviteInfoForTimeout = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.play, device.getDeviceId(), channelId); |
| | | // if (inviteInfoForTimeout == null) { |
| | |
| | | // // TODO åécancel |
| | | // } |
| | | callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); |
| | | if( device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream); |
| | | |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); |
| | | |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); |
| | | } |
| | | try { |
| | | cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); |
| | | } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { |
| | |
| | | }, userSetting.getPlayTimeout()); |
| | | |
| | | try { |
| | | cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { |
| | | cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId,isSubStream, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { |
| | | logger.info("æ¶å°è®¢é
æ¶æ¯ï¼ " + response.toJSONString()); |
| | | dynamicTask.stop(timeOutTaskKey); |
| | | // hookååº |
| | | StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); |
| | | StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId,isSubStream); |
| | | if (streamInfo == null){ |
| | | callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); |
| | | if( device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); |
| | | } |
| | | return; |
| | | } |
| | | callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); |
| | | if( device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), |
| | | streamInfo); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), |
| | | streamInfo); |
| | | } |
| | | if( device.isSwitchPrimarySubStream() ){ |
| | | logger.info("[ç¹ææå] deviceId: {}, channelId: {},ç æµç±»åï¼{}", device.getDeviceId(), channelId,isSubStream ? "è¾
ç æµ" : "ä¸»ç æµ"); |
| | | }else { |
| | | logger.info("[ç¹ææå] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); |
| | | } |
| | | String streamUrl; |
| | | if (mediaServerItemInuse.getRtspPort() != 0) { |
| | | streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", ssrcInfo.getStream()); |
| | |
| | | ResponseEvent responseEvent = (ResponseEvent) event.event; |
| | | String contentString = new String(responseEvent.getResponse().getRawContent()); |
| | | // è·åssrc |
| | | String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString); |
| | | |
| | | int ssrcIndex = contentString.indexOf("y="); |
| | | // æ£æ¥æ¯å¦æyåæ®µ |
| | | if (ssrcInResponse != null) { |
| | | if (ssrcIndex >= 0) { |
| | | //ssrcè§å®é¿åº¦ä¸º10åèï¼ä¸åä½ä¸é¿åº¦ä»¥é¿å
åç»è¿æâf=âåæ®µ TODO åç»å¯¹ä¸è§èçé10ä½ssrcå
¼å®¹ |
| | | String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim(); |
| | | // æ¥è¯¢å°ssrcä¸ä¸è´ä¸å¼å¯äºssrcæ ¡éªåéè¦é对å¤ç |
| | | if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { |
| | | if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { |
| | | String substring = contentString.substring(0, contentString.indexOf("y=")); |
| | | try { |
| | | Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); |
| | | SessionDescription sdp = gb28181Sdp.getBaseSdb(); |
| | | SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); |
| | | int port = -1; |
| | | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| | | for (Object description : mediaDescriptions) { |
| | |
| | | |
| | | callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| | | } |
| | | } |
| | | } |
| | | return; |
| | | } |
| | | logger.info("[ç¹ææ¶æ¯] æ¶å°invite 200, åç°ä¸çº§èªå®ä¹äºssrc: {}", ssrcInResponse); |
| | | |
| | | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { |
| | | logger.info("[ç¹ææ¶æ¯] SSRCä¿®æ£ {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); |
| | | |
| | | // éæ¾ssrc |
| | | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| | | |
| | | // åç«¯å£æ¨¡å¼streamId乿ååï¼éæ°è®¾ç½®çå¬å³å¯ |
| | | if (!mediaServerItem.isRtpEnable()) { |
| | | // æ·»å 订é
|
| | |
| | | logger.info("[ZLM HOOK] ssrcä¿®æ£åæ¶å°è®¢é
æ¶æ¯ï¼ " + response.toJSONString()); |
| | | dynamicTask.stop(timeOutTaskKey); |
| | | // hookååº |
| | | StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId); |
| | | StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId,isSubStream); |
| | | if (streamInfo == null){ |
| | | callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); |
| | | if( device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); |
| | | } |
| | | return; |
| | | } |
| | | callback.run(InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), streamInfo); |
| | | if( device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), |
| | | streamInfo); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), |
| | | streamInfo); |
| | | } |
| | | }); |
| | | return; |
| | | } |
| | |
| | | } |
| | | |
| | | dynamicTask.stop(timeOutTaskKey); |
| | | // éæ¾ssrc |
| | | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| | | |
| | | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| | | |
| | | callback.run(InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), |
| | | "ä¸çº§èªå®ä¹äºssrc,éæ°è®¾ç½®æ¶æµä¿¡æ¯å¤±è´¥", null); |
| | | if( device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), |
| | | "ä¸çº§èªå®ä¹äºssrc,éæ°è®¾ç½®æ¶æµä¿¡æ¯å¤±è´¥", null); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), |
| | | "ä¸çº§èªå®ä¹äºssrc,éæ°è®¾ç½®æ¶æµä¿¡æ¯å¤±è´¥", null); |
| | | } |
| | | |
| | | }else { |
| | | ssrcInfo.setSsrc(ssrcInResponse); |
| | |
| | | logger.info("[ç¹ææ¶æ¯] æ¶å°invite 200, ä¸çº§èªå®ä¹äºssrc, 使¯å½åæ¨¡å¼æ éä¿®æ£"); |
| | | } |
| | | } |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.updateInviteInfoSub(inviteInfo); |
| | | }else { |
| | | inviteStreamService.updateInviteInfo(inviteInfo); |
| | | } |
| | | }, (event) -> { |
| | | dynamicTask.stop(timeOutTaskKey); |
| | | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| | |
| | | |
| | | callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(), |
| | | String.format("ç¹æå¤±è´¥ï¼ é误ç ï¼ %s, %s", event.statusCode, event.msg), null); |
| | | if( device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), |
| | | String.format("ç¹æå¤±è´¥ï¼ é误ç ï¼ %s, %s", event.statusCode, event.msg), null); |
| | | |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), |
| | | String.format("ç¹æå¤±è´¥ï¼ é误ç ï¼ %s, %s", event.statusCode, event.msg), null); |
| | | |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); |
| | | } |
| | | }); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | |
| | |
| | | |
| | | callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); |
| | | if( device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, |
| | | InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); |
| | | |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream); |
| | | }else { |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); |
| | |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId) { |
| | | StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); |
| | | private StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId,boolean isSubStream) { |
| | | StreamInfo streamInfo = null; |
| | | Device device = redisCatchStorage.getDevice(deviceId); |
| | | if( device.isSwitchPrimarySubStream() ){ |
| | | streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId,isSubStream); |
| | | }else { |
| | | streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); |
| | | } |
| | | if (streamInfo != null) { |
| | | InviteInfo inviteInfo; |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); |
| | | }else { |
| | | DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); |
| | | if (deviceChannel != null) { |
| | | deviceChannel.setStreamId(streamInfo.getStream()); |
| | | storager.startPlay(deviceId, channelId, streamInfo.getStream()); |
| | | } |
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | } |
| | | if (inviteInfo != null) { |
| | | inviteInfo.setStatus(InviteSessionStatus.ok); |
| | | inviteInfo.setStreamInfo(streamInfo); |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.updateInviteInfoSub(inviteInfo); |
| | | }else { |
| | | inviteStreamService.updateInviteInfo(inviteInfo); |
| | | } |
| | | |
| | | } |
| | | } |
| | | return streamInfo; |
| | |
| | | ResponseEvent responseEvent = (ResponseEvent) eventResult.event; |
| | | String contentString = new String(responseEvent.getResponse().getRawContent()); |
| | | // è·åssrc |
| | | String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString); |
| | | |
| | | int ssrcIndex = contentString.indexOf("y="); |
| | | // æ£æ¥æ¯å¦æyåæ®µ |
| | | if (ssrcInResponse != null) { |
| | | if (ssrcIndex >= 0) { |
| | | //ssrcè§å®é¿åº¦ä¸º10åèï¼ä¸åä½ä¸é¿åº¦ä»¥é¿å
åç»è¿æâf=âåæ®µ TODO åç»å¯¹ä¸è§èçé10ä½ssrcå
¼å®¹ |
| | | String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
| | | // æ¥è¯¢å°ssrcä¸ä¸è´ä¸å¼å¯äºssrcæ ¡éªåéè¦é对å¤ç |
| | | if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { |
| | | if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { |
| | | String substring = contentString.substring(0, contentString.indexOf("y=")); |
| | | try { |
| | | Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); |
| | | SessionDescription sdp = gb28181Sdp.getBaseSdb(); |
| | | SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); |
| | | int port = -1; |
| | | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| | | for (Object description : mediaDescriptions) { |
| | |
| | | } |
| | | |
| | | dynamicTask.stop(playBackTimeOutTaskKey); |
| | | // éæ¾ssrc |
| | | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| | | |
| | | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| | | |
| | |
| | | ResponseEvent responseEvent = (ResponseEvent) eventResult.event; |
| | | String contentString = new String(responseEvent.getResponse().getRawContent()); |
| | | // è·åssrc |
| | | String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString); |
| | | int ssrcIndex = contentString.indexOf("y="); |
| | | // æ£æ¥æ¯å¦æyåæ®µ |
| | | if (ssrcInResponse != null) { |
| | | if (ssrcIndex >= 0) { |
| | | //ssrcè§å®é¿åº¦ä¸º10åèï¼ä¸åä½ä¸é¿åº¦ä»¥é¿å
åç»è¿æâf=âåæ®µ TODO åç»å¯¹ä¸è§èçé10ä½ssrcå
¼å®¹ |
| | | String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
| | | // æ¥è¯¢å°ssrcä¸ä¸è´ä¸å¼å¯äºssrcæ ¡éªåéè¦é对å¤ç |
| | | if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { |
| | | if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { |
| | | String substring = contentString.substring(0, contentString.indexOf("y=")); |
| | | try { |
| | | Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); |
| | | SessionDescription sdp = gb28181Sdp.getBaseSdb(); |
| | | SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); |
| | | int port = -1; |
| | | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| | | for (Object description : mediaDescriptions) { |
| | |
| | | } |
| | | |
| | | dynamicTask.stop(downLoadTimeOutTaskKey); |
| | | // éæ¾ssrc |
| | | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| | | |
| | | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| | | |
| | |
| | | streamInfo.setChannelId(channelId); |
| | | return streamInfo; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void zlmServerOffline(String mediaServerId) { |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback) { |
| | | public void getSnap(String deviceId, String channelId, String fileName,boolean isSubStream, ErrorCallback errorCallback) { |
| | | Device device = deviceService.getDevice(deviceId); |
| | | if (device == null) { |
| | | errorCallback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), null); |
| | | return; |
| | | } |
| | | |
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | InviteInfo inviteInfo; |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); |
| | | }else { |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | } |
| | | if (inviteInfo != null) { |
| | | if (inviteInfo.getStreamInfo() != null) { |
| | | // å·²åå¨çº¿ç´æ¥æªå¾ |
| | |
| | | // è¯·æ±æªå¾ |
| | | logger.info("[è¯·æ±æªå¾]: " + fileName); |
| | | zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); |
| | | String filePath = path + File.separator + fileName; |
| | | File snapFile = new File(path + File.separator + fileName); |
| | | if (snapFile.exists()) { |
| | | errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), filePath); |
| | | errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), snapFile.getAbsoluteFile()); |
| | | }else { |
| | | errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null); |
| | | } |
| | |
| | | } |
| | | |
| | | MediaServerItem newMediaServerItem = getNewMediaServerItem(device); |
| | | play(newMediaServerItem, deviceId, channelId, (code, msg, data)->{ |
| | | play(newMediaServerItem, deviceId, channelId,isSubStream, (code, msg, data)->{ |
| | | if (code == InviteErrorCode.SUCCESS.getCode()) { |
| | | InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | if (inviteInfoForPlay != null && inviteInfoForPlay.getStreamInfo() != null) { |
| | | getSnap(deviceId, channelId, fileName, errorCallback); |
| | | getSnap(deviceId, channelId, fileName,isSubStream, errorCallback); |
| | | }else { |
| | | errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null); |
| | | } |
| | |
| | | }); |
| | | } |
| | | |
| | | |
| | | /*======================设å¤ä¸»åç æµé»è¾START=========================*/ |
| | | public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId,boolean isSubStream) { |
| | | String streamId = resonse.getString("stream"); |
| | | JSONArray tracks = resonse.getJSONArray("tracks"); |
| | | StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, "rtp", streamId, tracks, null); |
| | | streamInfo.setDeviceID(deviceId); |
| | | streamInfo.setChannelId(channelId); |
| | | streamInfo.setSubStream(isSubStream); |
| | | return streamInfo; |
| | | } |
| | | /*======================设å¤ä¸»åç æµé»è¾END=========================*/ |
| | | |
| | | } |
| | |
| | | @Select("select count(1) from wvp_device_channel") |
| | | int getAllChannelCount(); |
| | | |
| | | // 设å¤ä¸»åç æµé»è¾START |
| | | @Update(value = {"UPDATE wvp_device_channel SET stream_id=null WHERE device_id=#{deviceId}"}) |
| | | void clearPlay(String deviceId); |
| | | // 设å¤ä¸»åç æµé»è¾END |
| | | @Select(value = {" <script>" + |
| | | "select * " + |
| | | "from device_channel " + |
| | |
| | | " <if test='onlyCatalog == true '> and parental = 1 </if>" + |
| | | " </script>"}) |
| | | List<DeviceChannel> getSubChannelsByDeviceId(String deviceId, String parentId, boolean onlyCatalog); |
| | | |
| | | } |
| | |
| | | "geo_coord_sys," + |
| | | "on_line," + |
| | | "media_server_id," + |
| | | "switch_primary_sub_stream," + |
| | | "(SELECT count(0) FROM wvp_device_channel WHERE device_id=wvp_device.device_id) as channel_count "+ |
| | | " FROM wvp_device WHERE device_id = #{deviceId}") |
| | | Device getDeviceByDeviceId(String deviceId); |
| | |
| | | "geo_coord_sys,"+ |
| | | "on_line,"+ |
| | | "media_server_id,"+ |
| | | "switch_primary_sub_stream switchPrimarySubStream,"+ |
| | | "(SELECT count(0) FROM wvp_device_channel WHERE device_id=de.device_id) as channel_count " + |
| | | "FROM wvp_device de" + |
| | | "<if test=\"onLine != null\"> where on_line=${onLine}</if>"+ |
| | |
| | | "<if test=\"ssrcCheck != null\">, ssrc_check=#{ssrcCheck}</if>" + |
| | | "<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" + |
| | | "<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" + |
| | | "<if test=\"switchPrimarySubStream != null\">, switch_primary_sub_stream=#{switchPrimarySubStream}</if>" + |
| | | "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" + |
| | | "WHERE device_id=#{deviceId}"+ |
| | | " </script>"}) |
| | |
| | | "as_message_channel,"+ |
| | | "geo_coord_sys,"+ |
| | | "on_line,"+ |
| | | "media_server_id"+ |
| | | "media_server_id,"+ |
| | | "switch_primary_sub_stream"+ |
| | | ") VALUES (" + |
| | | "#{deviceId}," + |
| | | "#{name}," + |
| | |
| | | "#{asMessageChannel}," + |
| | | "#{geoCoordSys}," + |
| | | "#{onLine}," + |
| | | "#{mediaServerId}" + |
| | | "#{mediaServerId}," + |
| | | "#{switchPrimarySubStream}" + |
| | | ")") |
| | | void addCustomDevice(Device device); |
| | | |
| | |
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| | | import com.genersoft.iot.vmp.utils.DateUtil; |
| | | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| | | import com.genersoft.iot.vmp.vmanager.bean.SnapPath; |
| | | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; |
| | | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.sip.InvalidArgumentException; |
| | | import javax.sip.SipException; |
| | | import java.io.File; |
| | | import java.text.ParseException; |
| | | import java.util.List; |
| | | import java.util.UUID; |
| | |
| | | @Operation(summary = "å¼å§ç¹æ") |
| | | @Parameter(name = "deviceId", description = "设å¤å½æ ç¼å·", required = true) |
| | | @Parameter(name = "channelId", description = "éé彿 ç¼å·", required = true) |
| | | @Parameter(name = "isSubStream", description = "æ¯å¦åç æµï¼true-åç æµï¼false-ä¸»ç æµï¼ï¼é»è®¤ä¸ºfalse", required = true) |
| | | @GetMapping("/start/{deviceId}/{channelId}") |
| | | public DeferredResult<WVPResult<StreamContent>> play(HttpServletRequest request, @PathVariable String deviceId, |
| | | @PathVariable String channelId) { |
| | | @PathVariable String channelId,boolean isSubStream) { |
| | | |
| | | // è·åå¯ç¨çzlm |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | | |
| | | RequestMessage requestMessage = new RequestMessage(); |
| | | String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; |
| | | String key = DeferredResultHolder.getPlayKey(deviceId,channelId,device.isSwitchPrimarySubStream(),isSubStream); |
| | | requestMessage.setKey(key); |
| | | String uuid = UUID.randomUUID().toString(); |
| | | requestMessage.setId(uuid); |
| | |
| | | // å½åæ¥è¯¢ä»¥channelIdä½ä¸ºdeviceIdæ¥è¯¢ |
| | | resultHolder.put(key, uuid, result); |
| | | |
| | | playService.play(newMediaServerItem, deviceId, channelId, (code, msg, data) -> { |
| | | playService.play(newMediaServerItem, deviceId, channelId,isSubStream, (code, msg, data) -> { |
| | | WVPResult<StreamContent> wvpResult = new WVPResult<>(); |
| | | if (code == InviteErrorCode.SUCCESS.getCode()) { |
| | | wvpResult.setCode(ErrorCode.SUCCESS.getCode()); |
| | |
| | | @Operation(summary = "åæ¢ç¹æ") |
| | | @Parameter(name = "deviceId", description = "设å¤å½æ ç¼å·", required = true) |
| | | @Parameter(name = "channelId", description = "éé彿 ç¼å·", required = true) |
| | | @Parameter(name = "isSubStream", description = "æ¯å¦åç æµï¼true-åç æµï¼false-ä¸»ç æµï¼ï¼é»è®¤ä¸ºfalse", required = true) |
| | | @GetMapping("/stop/{deviceId}/{channelId}") |
| | | public JSONObject playStop(@PathVariable String deviceId, @PathVariable String channelId) { |
| | | public JSONObject playStop(@PathVariable String deviceId, @PathVariable String channelId,boolean isSubStream) { |
| | | |
| | | logger.debug(String.format("设å¤é¢è§/忾忢APIè°ç¨ï¼streamIdï¼%s_%s", deviceId, channelId )); |
| | | |
| | |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "设å¤[" + deviceId + "]ä¸åå¨"); |
| | | } |
| | | |
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | InviteInfo inviteInfo =null; |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); |
| | | }else { |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | } |
| | | if (inviteInfo == null) { |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "ç¹ææªæ¾å°"); |
| | | } |
| | |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "å½ä»¤åé失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); |
| | | }else { |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | |
| | | storager.stopPlay(deviceId, channelId); |
| | | } |
| | | |
| | | JSONObject json = new JSONObject(); |
| | | json.put("deviceId", deviceId); |
| | | json.put("channelId", channelId); |
| | | json.put("isSubStream", isSubStream); |
| | | return json; |
| | | } |
| | | |
| | |
| | | @Operation(summary = "è·åæªå¾") |
| | | @Parameter(name = "deviceId", description = "设å¤å½æ ç¼å·", required = true) |
| | | @Parameter(name = "channelId", description = "éé彿 ç¼å·", required = true) |
| | | @Parameter(name = "isSubStream", description = "æ¯å¦åç æµï¼true-åç æµï¼false-ä¸»ç æµï¼ï¼é»è®¤ä¸ºfalse", required = true) |
| | | @GetMapping("/snap") |
| | | public DeferredResult<String> getSnap(HttpServletRequest request, String deviceId, String channelId) { |
| | | public DeferredResult<String> getSnap(String deviceId, String channelId,boolean isSubStream) { |
| | | if (logger.isDebugEnabled()) { |
| | | logger.debug("è·åæªå¾: {}/{}", deviceId, channelId); |
| | | } |
| | | |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | DeferredResult<String> result = new DeferredResult<>(3 * 1000L); |
| | | String key = DeferredResultHolder.CALLBACK_CMD_SNAP + deviceId; |
| | | String key = DeferredResultHolder.getSnapKey(deviceId,channelId,device.isSwitchPrimarySubStream(),isSubStream); |
| | | String uuid = UUID.randomUUID().toString(); |
| | | resultHolder.put(key, uuid, result); |
| | | |
| | | RequestMessage message = new RequestMessage(); |
| | | message.setKey(key); |
| | | message.setId(uuid); |
| | | String nowForUrl = DateUtil.getNowForUrl(); |
| | | String fileName = deviceId + "_" + channelId + "_" + nowForUrl + ".jpg"; |
| | | |
| | | playService.getSnap(deviceId, channelId, fileName, (code, msg, data) -> { |
| | | String fileName = deviceId + "_" + channelId + "_" + DateUtil.getNowForUrl() + "jpg"; |
| | | playService.getSnap(deviceId, channelId, fileName,isSubStream, (code, msg, data) -> { |
| | | if (code == InviteErrorCode.SUCCESS.getCode()) { |
| | | File snapFile = new File((String)data); |
| | | String fileNameForUrl = deviceId + "/" + channelId + "?mark=" + nowForUrl; |
| | | String uri = request.getRequestURL().toString().replace(request.getRequestURI(), "/api/device/query/snap/" + fileNameForUrl); |
| | | SnapPath snapPath = SnapPath.getInstance((String) data, snapFile.getAbsolutePath(), uri); |
| | | message.setData(snapPath); |
| | | message.setData(data); |
| | | }else { |
| | | message.setData(WVPResult.fail(code, msg)); |
| | | } |
| | |
| | | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | | |
| | | |
| | | playService.play(newMediaServerItem, serial, code, (errorCode, msg, data) -> { |
| | | playService.play(newMediaServerItem, serial, code,false, (errorCode, msg, data) -> { |
| | | if (errorCode == InviteErrorCode.SUCCESS.getCode()) { |
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, serial, code); |
| | | if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { |
| | |
| | | spring: |
| | | thymeleaf: |
| | | cache: false |
| | | # [å¯é]ä¸ä¼ æä»¶å¤§å°éå¶ |
| | | servlet: |
| | | multipart: |
| | |
| | | # [å¿
须修æ¹] 端å£å· |
| | | port: 6379 |
| | | # [å¯é] æ°æ®åº DB |
| | | database: 6 |
| | | database: 7 |
| | | # [å¯é] 访é®å¯ç ,è¥ä½ çredisæå¡å¨æ²¡æè®¾ç½®å¯ç ï¼å°±ä¸éè¦ç¨å¯ç å»è¿æ¥ |
| | | password: face2020 |
| | | password: |
| | | # [å¯é] è¶
æ¶æ¶é´ |
| | | timeout: 10000 |
| | | # mysqlæ°æ®æº |
| | | datasource: |
| | | type: com.zaxxer.hikari.HikariDataSource |
| | | driver-class-name: com.mysql.cj.jdbc.Driver |
| | | url: jdbc:mysql://127.0.0.1:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true |
| | | url: jdbc:mysql://127.0.0.1:3306/test_gb-89wulian?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true |
| | | username: root |
| | | password: 123456 |
| | | password: root |
| | | hikari: |
| | | connection-timeout: 20000 # æ¯å®¢æ·ç«¯çå¾
è¿æ¥æ± è¿æ¥çæå¤§æ¯«ç§æ° |
| | | initialSize: 10 # è¿æ¥æ± åå§åè¿æ¥æ° |
| | |
| | | minimum-idle: 5 # è¿æ¥æ± æå°ç©ºé²è¿æ¥æ° |
| | | idle-timeout: 300000 # å
è®¸è¿æ¥å¨è¿æ¥æ± ä¸ç©ºé²çæé¿æ¶é´ï¼ä»¥æ¯«ç§ä¸ºåä½ï¼ |
| | | max-lifetime: 1200000 # æ¯æ± ä¸è¿æ¥å
³éåçæé¿çå½å¨æï¼ä»¥æ¯«ç§ä¸ºåä½) |
| | | |
| | | |
| | | #[å¯é] WVPçå¬çHTTP端å£, ç½é¡µåæ¥å£è°ç¨é½æ¯è¿ä¸ªç«¯å£ |
| | | server: |
| | | port: 18080 |
| | | port: 18978 |
| | | # [å¯é] HTTPSé
ç½®ï¼ é»è®¤ä¸å¼å¯ |
| | | ssl: |
| | | # [å¯é] æ¯å¦å¼å¯HTTPSè®¿é® |
| | | enabled: false |
| | | # [å¯é] è¯ä¹¦æä»¶è·¯å¾ï¼æ¾ç½®å¨resource/ç®å½ä¸å³å¯ï¼ä¿®æ¹xxx为æä»¶å |
| | | key-store: classpath:test.monitor.89iot.cn.jks |
| | | # [å¯é] è¯ä¹¦å¯ç |
| | | key-store-password: gpf64qmw |
| | | # [å¯é] è¯ä¹¦ç±»åï¼ é»è®¤ä¸ºjksï¼æ ¹æ®å®é
ä¿®æ¹ |
| | | key-store-type: JKS |
| | | |
| | | # ä½ä¸º28181æå¡å¨çé
ç½® |
| | | sip: |
| | |
| | | # 妿è¦çå¬å¤å¼ ç½å¡ï¼å¯ä»¥ä½¿ç¨éå·åéå¤ä¸ªIPï¼ ä¾å¦ï¼ 192.168.1.4,10.0.0.4 |
| | | # 妿䏿ç½ï¼å°±ä½¿ç¨0.0.0.0ï¼å¤§é¨åæ
åµé½æ¯å¯ä»¥ç |
| | | # 请ä¸è¦ä½¿ç¨127.0.0.1ï¼ä»»ä½å
æ¬localhostå¨å
çåå齿¯ä¸å¯ä»¥çã |
| | | ip: 192.168.41.16 |
| | | ip: 192.168.1.18 |
| | | # [å¯é] 28181æå¡çå¬çç«¯å£ |
| | | port: 5060 |
| | | port: 8116 |
| | | # æ ¹æ®å½æ 6.1.2ä¸è§å®ï¼domainå®éç¨IDç»ä¸ç¼ç çååä½ç¼ç ã彿 éå½Dä¸å®ä¹å8ä½ä¸ºä¸å¿ç¼ç ï¼ç±ç级ãå¸çº§ãåºçº§ãåºå±ç¼å·ç»æï¼åç
§GB/T 2260-2007ï¼ |
| | | # å两ä½ä¸ºè¡ä¸ç¼ç ï¼å®ä¹åç
§éå½D.3 |
| | | # 3701020049æ è¯å±±ä¸æµååä¸åº ä¿¡æ¯è¡ä¸æ¥å
¥ |
| | | # [å¯é] |
| | | domain: 4401020049 |
| | | domain: 4101050000 |
| | | # [å¯é] |
| | | id: 44010200492000000001 |
| | | id: 41010500002000000001 |
| | | # [å¯é] é»è®¤è®¾å¤è®¤è¯å¯ç ï¼åç»æ©å±ä½¿ç¨è®¾å¤åç¬å¯ç , ç§»é¤å¯ç å°ä¸è¿è¡æ ¡éª |
| | | password: admin123 |
| | | password: bajiuwulian1006 |
| | | # æ¯å¦åå¨alarmä¿¡æ¯ |
| | | alarm: true |
| | | |
| | | #zlm é»è®¤æå¡å¨é
ç½® |
| | | media: |
| | | id: FQ3TF8yT83wh5Wvz |
| | | id: 89wulian-one |
| | | # [å¿
须修æ¹] zlmæå¡å¨çå
ç½IP |
| | | ip: 192.168.41.16 |
| | | ip: 192.168.1.18 |
| | | # [å¿
须修æ¹] zlmæå¡å¨çhttp.port |
| | | http-port: 8091 |
| | | http-port: 80 |
| | | # [å¯é] è¿åæµå°åæ¶çipï¼ç½®ç©ºä½¿ç¨ media.ip |
| | | stream-ip: 192.168.1.18 |
| | | # [å¯é] wvpå¨å½æ 信令ä¸ä½¿ç¨çipï¼æ¤ip为æåæºå¯ä»¥è®¿é®å°çipï¼ ç½®ç©ºä½¿ç¨ media.ip |
| | | sdp-ip: 192.168.1.18 |
| | | # [å¯é] zlmæå¡å¨çhookæä½¿ç¨çIP, é»è®¤ä½¿ç¨sip.ip |
| | | hook-ip: 192.168.1.18 |
| | | # [å¯é] zlmæå¡å¨çhttp.sslport, 置空使ç¨zlmé
ç½®æä»¶é
ç½® |
| | | http-ssl-port: 443 |
| | | # [å¯é] zlmæå¡å¨çhook.admin_params=secret |
| | | secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc |
| | | # å¯ç¨å¤ç«¯å£æ¨¡å¼, å¤ç«¯å£æ¨¡å¼ä½¿ç¨ç«¯å£åºåæ¯è·¯æµï¼å
¼å®¹æ§æ´å¥½ã å端å£ä½¿ç¨æµçssrcåºåï¼ ç¹æè¶
æ¶å»ºè®®ä½¿ç¨å¤ç«¯å£æµè¯ |
| | |
| | | # [å¯é] æ¯å¦å¯ç¨å¤ç«¯å£æ¨¡å¼, å¼å¯åä¼å¨portRangeèå´å
éæ©ç«¯å£ç¨äºåªä½æµä¼ è¾ |
| | | enable: true |
| | | # [å¯é] 卿¤èå´å
éæ©ç«¯å£ç¨äºåªä½æµä¼ è¾, å¿
é¡»æåå¨zlmä¸é
ç½®è¯¥å±æ§ï¼ä¸ç¶èªå¨é
ç½®æ¤å±æ§å¯è½ä¸æå |
| | | port-range: 30000,30500 # 端å£èå´ |
| | | port-range: 50000,50300 # 端å£èå´ |
| | | # [å¯é] 彿 级è卿¤èå´å
éæ©ç«¯å£åéåªä½æµ, |
| | | send-port-range: 30000,30500 # 端å£èå´ |
| | | send-port-range: 50000,50300 # 端å£èå´ |
| | | # å½åè¾
婿å¡ï¼ é¨ç½²æ¤æå¡å¯ä»¥å®ç°zlmå½åç管çä¸ä¸è½½ï¼ 0 表示ä¸ä½¿ç¨ |
| | | record-assist-port: 18081 |
| | | # [æ ¹æ®ä¸å¡éæ±é
ç½®] |
| | | user-settings: |
| | | # ç¹æ/å½ååæ¾ çå¾
è¶
æ¶æ¶é´,åä½ï¼æ¯«ç§ |
| | | play-timeout: 180000 |
| | | # [å¯é] èªå¨ç¹æï¼ 使ç¨åºå®æµå°åè¿è¡ææ¾æ¶ï¼å¦ææªç¹æåèªå¨è¿è¡ç¹æ, éè¦rtp.enable=true |
| | | auto-apply-play: true |
| | | # 设å¤/ééç¶æååæ¶åéæ¶æ¯ |
| | | device-status-notify: true |
| | | # è·¨åé
ç½®ï¼é
ç½®ä½ è®¿é®å端页é¢çå°åå³å¯ï¼ å¯ä»¥é
ç½®å¤ä¸ª |
| | | allowed-origins: |
| | | - http://localhost:8080 |
| | | - http://127.0.0.1:8080 |
| | | # [å¯é] æ¥å¿é
ç½®, ä¸è¬ä¸éè¦æ¹ |
| | | logging: |
| | | config: classpath:logback-spring-local.xml |
| | | |
| | |
| | | application: |
| | | name: wvp |
| | | profiles: |
| | | active: local |
| | | active: dev |
| | |
| | | assetsPublicPath: '/', |
| | | proxyTable: { |
| | | '/debug': { |
| | | target: 'http://localhost:18080', |
| | | target: 'http://localhost:18978', |
| | | changeOrigin: true, |
| | | pathRewrite: { |
| | | '^/debug': '/' |
| | | } |
| | | }, |
| | | '/static/snap': { |
| | | target: 'http://localhost:18080', |
| | | target: 'http://localhost:18978', |
| | | changeOrigin: true, |
| | | // pathRewrite: { |
| | | // '^/static/snap': '/static/snap' |
| | |
| | | <el-option label="å¨çº¿" value="true"></el-option> |
| | | <el-option label="离线" value="false"></el-option> |
| | | </el-select> |
| | | æ¸
æ°åº¦: |
| | | <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="isSubStream" placeholder="è¯·éæ©" |
| | | default-first-option> |
| | | <el-option label="åç»" :value="false"></el-option> |
| | | <el-option label="æµç
" :value="true"></el-option> |
| | | </el-select> |
| | | </div> |
| | | <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button> |
| | | <el-button v-if="showTree" icon="iconfont icon-list" circle size="mini" @click="switchList()"></el-button> |
| | |
| | | searchSrt: "", |
| | | channelType: "", |
| | | online: "", |
| | | isSubStream: false, |
| | | winHeight: window.innerHeight - 200, |
| | | currentPage: 1, |
| | | count: 15, |
| | |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/play/start/' + deviceId + '/' + channelId |
| | | url: '/api/play/start/' + deviceId + '/' + channelId, |
| | | params:{ |
| | | isSubStream: this.isSubStream |
| | | } |
| | | }).then(function (res) { |
| | | console.log(res) |
| | | that.isLoging = false; |
| | |
| | | var that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId |
| | | url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId, |
| | | params:{ |
| | | isSubStream: this.isSubStream |
| | | } |
| | | }).then(function (res) { |
| | | that.initData(); |
| | | }).catch(function (error) { |
| | |
| | | <el-form-item v-if="form.subscribeCycleForMobilePosition > 0" label="ç§»å¨ä½ç½®æ¥éé´é" prop="subscribeCycleForCatalog" > |
| | | <el-input v-model="form.mobilePositionSubmissionInterval" clearable ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="主åç æµå¼å
³" prop="switchPrimarySubStream" > |
| | | <el-select v-model="form.switchPrimarySubStream" style="float: left; width: 100%" > |
| | | <el-option key="true" label="å¼å¯" :value="true"></el-option> |
| | | <el-option key="false" label="å
³é" :value="false"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å
¶ä»é项"> |
| | | <el-checkbox label="SSRCæ ¡éª" v-model="form.ssrcCheck" style="float: left"></el-checkbox> |
| | | <el-checkbox label="ä½ä¸ºæ¶æ¯éé" v-model="form.asMessageChannel" style="float: left"></el-checkbox> |