Преглед на файлове

change:
1. 优化视频播放异常处理
2. 日志输出内容优化

kindring преди 1 година
родител
ревизия
a0ddc6ab0a

+ 1 - 1
src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java

@@ -62,7 +62,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
             case EXPIRING_SOON:
                 // 即将过期
 //                return;
-                logger.info("[用户token] 即将过期,刷新过期时间");
+                logger.debug("[用户token] 即将过期,刷新过期时间");
                 String newJwt = JwtUtils.createToken(username, password);
                 response.setHeader(JwtUtils.getHeader(), newJwt);
                 request.setAttribute(JwtUtils.getHeader(), newJwt);

+ 8 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java

@@ -120,6 +120,14 @@ public class DeferredResultHolder {
 		if (deferredResultMap == null) {
 			return;
 		}
+		if(msg.getId() == null) {
+			deferredResultMap.forEach((id, result) -> {
+				result.getDeferredResult().setResult(msg.getData());
+			});
+			deferredResultMap.clear();
+			map.remove(msg.getKey());
+			return;
+		}
 		DeferredResultEx result = deferredResultMap.get(msg.getId());
 		if (result == null) {
 			return;

+ 14 - 5
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java

@@ -98,16 +98,24 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
 
 				String contentString = new String(response.getRawContent());
 				// jainSip不支持y=字段, 移除以解析。
-				int ssrcIndex = contentString.indexOf("y=");
+				int ssrcIndex = contentString.indexOf("y="),
+					fIndex = -1;
 				// 检查是否有y字段
 				SessionDescription sdp;
 				if (ssrcIndex >= 0) {
+					logger.info("[sdp优化] sdp_y 移除y字段 ");
 					//ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
-					String substring = contentString.substring(0, contentString.indexOf("y="));
-					sdp = SdpFactory.getInstance().createSessionDescription(substring);
-				} else {
-					sdp = SdpFactory.getInstance().createSessionDescription(contentString);
+					contentString = contentString.substring(0, contentString.indexOf("y="));
+					logger.debug("[sdp优化] sdp_y 多余内容移除 移除y字段: \n{}", contentString);
 				}
+				fIndex = contentString.indexOf("f=");
+				if(fIndex >= 0){
+					logger.info("[sdp优化] sdp_f 开始移除f字段");
+					contentString = contentString.substring(0, fIndex);
+					logger.debug("[sdp优化] sdp_f 移除f字段完成 : \n{}", contentString);
+					// 移除f字段
+				}
+				sdp = SdpFactory.getInstance().createSessionDescription(contentString);
 
 				SipURI requestUri = sipLayer.getSipFactory().createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), event.getRemoteIpAddress() + ":" + event.getRemotePort());
 				Request reqAck = headerProvider.createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response);
@@ -117,6 +125,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
 			}
 		} catch (InvalidArgumentException | ParseException | SipException | SdpParseException e) {
 			logger.info("[点播回复ACK],异常:", e );
+
 		}
 	}
 

+ 17 - 2
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java

@@ -673,8 +673,23 @@ public class ZLMHttpHookListener {
     @ResponseBody
     @PostMapping(value = "/on_rtp_server_timeout", produces = "application/json;charset=UTF-8")
     public HookResult onRtpServerTimeout(HttpServletRequest request, @RequestBody OnRtpServerTimeoutHookParam param) {
-        logger.info("[ZLM HOOK] rtpServer收流超时:{}->{}({})", param.getMediaServerId(), param.getStream_id(), param.getSsrc());
-
+        logger.warn("[ZLM HOOK] rtpServer收流超时:{}->{}({})", param.getMediaServerId(), param.getStream_id(), param.getSsrc());
+        // 移除Stream_id 中的 _
+        String streamId = param.getStream_id();
+        streamId = streamId.replace("_","");
+        String key = DeferredResultHolder.CALLBACK_CMD_PLAY + streamId;
+        logger.info("[ZLM HOOK] 播放收流超时key: {}", key);
+        boolean playResultHolderExist = resultHolder.exist(key, null);
+        if(playResultHolderExist){
+            logger.info("[result check] 匹配到对应的请求进行中,正在中止");
+            RequestMessage msg = new RequestMessage();
+            msg.setKey(key);
+            WVPResult<StreamInfo> wvpResult = new WVPResult<>();
+            wvpResult.setCode(ErrorCode.ERROR100.getCode());
+            wvpResult.setMsg("[ZLM HOOK] rtpServer 收流超时");
+            msg.setData(wvpResult);
+            resultHolder.invokeResult(msg);
+        }
         taskExecutor.execute(() -> {
             JSONObject json = (JSONObject) JSON.toJSON(param);
             List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout);

+ 2 - 1
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java

@@ -763,12 +763,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
 
     @Override
     public void updateMediaServerKeepalive(String mediaServerId, ServerKeepaliveData data) {
+        logger.info("[更新ZLM 保活信息] id {} data {}", mediaServerId, JSON.toJSONString(data));
         MediaServerItem mediaServerItem = getOne(mediaServerId);
         if (mediaServerItem == null) {
             // 缓存不存在,从数据库查询,如果数据库不存在则是错误的
             mediaServerItem = getOneFromDatabase(mediaServerId);
             if (mediaServerItem == null) {
-                logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息");
+                logger.warn("[更新ZLM 保活信息] 服务({})获取失败,未找到流媒体信息", mediaServerId);
                 return;
             }
             // zlm连接重试

+ 8 - 2
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java

@@ -159,7 +159,7 @@ public class PlayServiceImpl implements IPlayService {
                 if (rtpInfo.getBoolean("exist")) {
                     int localPort = rtpInfo.getInteger("local_port");
                     if (localPort == 0) {
-                        logger.warn("[点播],点播时发现rtpServerC存在,但是尚未开始推流");
+                        logger.warn("[点播],点播时发现rtpServer存在,但是尚未开始推流");
                         // 此时说明rtpServer已经创建但是流还没有推上来
                         wvpResult.setCode(ErrorCode.ERROR100.getCode());
                         wvpResult.setMsg("点播已经在进行中,请稍候重试");
@@ -348,7 +348,8 @@ public class PlayServiceImpl implements IPlayService {
 
                     }
                 }
-            }, (event) -> {
+            }
+            , (event) -> {
                 dynamicTask.stop(timeOutTaskKey);
                 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
                 // 释放ssrc
@@ -369,6 +370,11 @@ public class PlayServiceImpl implements IPlayService {
             SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
             eventResult.msg = "命令发送失败";
             errorEvent.response(eventResult);
+
+            RequestMessage msg = new RequestMessage();
+            msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + device.getDeviceId() + channelId);
+            msg.setData(WVPResult.fail(ErrorCode.ERR_Invite_fail.getCode(), "点播命令发送至设备异常"));
+            resultHolder.invokeAllResult(msg);
         }
     }
 

+ 3 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java

@@ -129,10 +129,12 @@ public class PlayController {
 			wvpResult.setMsg("点播超时");
 			msg.setData(wvpResult);
 			resultHolder.invokeResult(msg);
+			// 强行移除 resultHolder 中的 DeferredResult
 		});
 		// TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误
 		deferredResultEx.setFilter(result1 -> {
 			logger.info("点播成功");
+
 			WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>)result1;
 			WVPResult<StreamContent> resultStream = new WVPResult<>();
 			resultStream.setCode(wvpResult1.getCode());
@@ -144,6 +146,7 @@ public class PlayController {
 				}
 				resultStream.setData(new StreamContent(wvpResult1.getData()));
 			}
+//			resultHolder.invokeResult(msg);
 			return resultStream;
 		});
 

+ 8 - 8
web_src/src/components/common/ptzControl.vue

@@ -45,14 +45,14 @@
 
     <div class="control-panel">
 <!--      预置位 -->
-      <el-tabs tab-position="left" style="height: 200px;">
-        <el-tab-pane label="预置位">
-<!--          预置位查询 -->
-
-        </el-tab-pane>
-        <el-tab-pane label="巡航">配置管理</el-tab-pane>
-        <el-tab-pane label="扫描">角色管理</el-tab-pane>
-      </el-tabs>
+<!--      <el-tabs tab-position="left" style="height: 200px;">-->
+<!--        <el-tab-pane label="预置位">-->
+<!--&lt;!&ndash;          预置位查询 &ndash;&gt;-->
+
+<!--        </el-tab-pane>-->
+<!--        <el-tab-pane label="巡航">配置管理</el-tab-pane>-->
+<!--        <el-tab-pane label="扫描">角色管理</el-tab-pane>-->
+<!--      </el-tabs>-->
       <el-button-group>
         <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium">预置位编号</el-tag>
         <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini" v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1" :max="255"></el-input-number>