优化子码流切换逻辑,去除主子多开逻辑。优化单端口模式ssrc变化导致的无法移出点播缓存 #895
| | |
| | | private StreamInfo streamInfo; |
| | | |
| | | |
| | | public static InviteInfo getinviteInfo(String deviceId, String channelId, String stream, SSRCInfo ssrcInfo, |
| | | public static InviteInfo getInviteInfo(String deviceId, String channelId, String stream, SSRCInfo ssrcInfo, |
| | | String receiveIp, Integer receivePort, String streamMode, |
| | | InviteSessionType type, InviteSessionStatus status) { |
| | | InviteInfo inviteInfo = new InviteInfo(); |
| | |
| | | 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====================*/ |
| | | |
| | | |
| | | |
| | |
| | | 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====================*/ |
| | | |
| | | |
| | | } |
| | |
| | | * @return |
| | | */ |
| | | public void startCron(String key, Runnable task, int cycleForCatalog) { |
| | | System.out.println(cycleForCatalog); |
| | | ScheduledFuture<?> future = futureMap.get(key); |
| | | if (future != null) { |
| | | if (future.isCancelled()) { |
| | |
| | | }
|
| | | }
|
| | |
|
| | | /*============================设备主子码流逻辑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,boolean isSubStream, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | | void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 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,boolean isSubStream,
|
| | | public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
|
| | | 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){
|
| | | if (device.isSwitchPrimarySubStream()){
|
| | | content.append("a=streamMode:sub\r\n");
|
| | | }else {
|
| | | content.append("a=streamMode:main\r\n");
|
| | | }
|
| | | }else {
|
| | | if (isSubStream){
|
| | | if (device.isSwitchPrimarySubStream()){
|
| | | content.append("a=streamprofile:1\r\n");
|
| | | }else {
|
| | | content.append("a=streamprofile:0\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);
|
| | | }
|
| | | 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); |
| | | ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); |
| | | } |
| | | storager.stopPlay(device.getDeviceId(), channelId); |
| | | SsrcTransaction 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 = 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); |
| | | } |
| | | InviteInfo 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,false, ((code, msg, data) -> { |
| | | playService.play(mediaServerItem, device.getDeviceId(), channelId, ((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()){ |
| | |
| | | } |
| | | |
| | | private void executeSave(){ |
| | | System.out.println("定时存储数据"); |
| | | executeSaveForUpdate(); |
| | | executeSaveForDelete(); |
| | | executeSaveForOnline(); |
| | |
| | | if (ObjectUtils.isEmpty(timeStr)){ |
| | | return null; |
| | | } |
| | | System.out.println(timeStr); |
| | | LocalDateTime localDateTime; |
| | | try { |
| | | localDateTime = LocalDateTime.parse(timeStr); |
| | |
| | | }
|
| | |
|
| | | 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());
|
| | | }
|
| | | 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())) {
|
| | |
| | | Device device = deviceService.getDevice(inviteInfo.getDeviceId());
|
| | | if (device != null) {
|
| | | try {
|
| | | 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());
|
| | |
|
| | | }
|
| | |
|
| | | InviteInfo 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());
|
| | | }
|
| | | inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(),
|
| | | inviteInfo.getChannelId(), inviteInfo.getStream());
|
| | | storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId());
|
| | | return ret;
|
| | | }
|
| | | } else {
|
| | |
| | |
|
| | | if ("rtp".equals(param.getApp())) {
|
| | | String[] s = param.getStream().split("_");
|
| | | if (!mediaInfo.isRtpEnable() ) {
|
| | | defaultResult.setResult(HookResult.SUCCESS());
|
| | | return defaultResult;
|
| | | }else if(s.length != 2 && s.length != 3 ){
|
| | | if (!mediaInfo.isRtpEnable() || s.length != 2) {
|
| | | defaultResult.setResult(HookResult.SUCCESS());
|
| | | return defaultResult;
|
| | | }
|
| | | 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];
|
| | | }
|
| | | String deviceId = s[0];
|
| | | String 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.getPlayKey(deviceId, channelId, device.isSwitchPrimarySubStream(), isSubStream);
|
| | | String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
|
| | | 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,isSubStream, (code, message, data) -> {
|
| | | playService.play(mediaInfo, deviceId, channelId, (code, message, data) -> {
|
| | | msg.setData(new HookResult(code, message));
|
| | | resultHolder.invokeResult(msg);
|
| | | });
|
| | |
| | | } |
| | | |
| | | public JSONObject openRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param){ |
| | | System.out.println("==============openRtpServer================="); |
| | | for (String s : param.keySet()) { |
| | | System.out.println(s + "-->" + param.get(s)); |
| | | } |
| | | System.out.println("==============================="); |
| | | return sendPost(mediaServerItem, "openRtpServer",param, null); |
| | | } |
| | | |
| | |
| | | int localPort = 0; |
| | | if (userSetting.getGbSendStreamStrict()) { |
| | | if (userSetting.getGbSendStreamStrict()) { |
| | | System.out.println("createSendRtpItem1"); |
| | | localPort = keepPort(serverItem, ssrc, localPort); |
| | | if (localPort == 0) { |
| | | return null; |
| | |
| | | // 默认为随机端口 |
| | | int localPort = 0; |
| | | if (userSetting.getGbSendStreamStrict()) { |
| | | System.out.println("createSendRtpItem2"); |
| | | localPort = keepPort(serverItem, ssrc, localPort); |
| | | if (localPort == 0) { |
| | | return null; |
| | |
| | | param.put("port", localPort); |
| | | param.put("enable_tcp", 1); |
| | | param.put("stream_id", ssrc); |
| | | System.out.println("用于收流"); |
| | | JSONObject jsonObject = zlmresTfulUtils.openRtpServer(serverItem, param); |
| | | System.out.println(jsonObject); |
| | | if (jsonObject.getInteger("code") == 0) { |
| | | localPort = jsonObject.getInteger("port"); |
| | | HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); |
| | |
| | | import com.genersoft.iot.vmp.common.InviteSessionType; |
| | | import com.genersoft.iot.vmp.service.bean.ErrorCallback; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 记录国标点播的状态,包括实时预览,下载,录像回放 |
| | | */ |
| | |
| | | * 更新点播的状态信息 |
| | | */ |
| | | void updateInviteInfo(InviteInfo inviteInfo); |
| | | |
| | | InviteInfo updateInviteInfoForStream(InviteInfo inviteInfo, String stream); |
| | | |
| | | /** |
| | | * 获取点播的状态信息 |
| | |
| | | * 统计同一个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,boolean isSubStream, |
| | | void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| | | ErrorCallback<Object> callback); |
| | | SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId,boolean isSubStream, ErrorCallback<Object> callback); |
| | | SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, ErrorCallback<Object> callback); |
| | | |
| | | MediaServerItem getNewMediaServerItem(Device device); |
| | | |
| | |
| | | |
| | | void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException; |
| | | |
| | | void getSnap(String deviceId, String channelId, String fileName,boolean isSubStream, ErrorCallback errorCallback); |
| | | void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback); |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public InviteInfo updateInviteInfoForStream(InviteInfo inviteInfo, String stream) { |
| | | |
| | | InviteInfo inviteInfoInDb = getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()); |
| | | if (inviteInfoInDb == null) { |
| | | return null; |
| | | } |
| | | removeInviteInfo(inviteInfoInDb); |
| | | String key = VideoManagerConstants.INVITE_PREFIX + |
| | | "_" + inviteInfo.getType() + |
| | | "_" + inviteInfo.getDeviceId() + |
| | | "_" + inviteInfo.getChannelId() + |
| | | "_" + stream; |
| | | inviteInfoInDb.setStream(stream); |
| | | redisTemplate.opsForValue().set(key, inviteInfoInDb); |
| | | return inviteInfoInDb; |
| | | } |
| | | |
| | | @Override |
| | | public InviteInfo getInviteInfo(InviteSessionType type, String deviceId, String channelId, String stream) { |
| | | String key = VideoManagerConstants.INVITE_PREFIX + |
| | | "_" + (type != null ? type : "*") + |
| | |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data) { |
| | | String key = buildKey(type, deviceId, channelId, 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 buildKey(InviteSessionType type, String deviceId, String channelId, String stream) { |
| | | String key = type + "_" + deviceId + "_" + channelId; |
| | | // 如果ssrc未null那么可以实现一个通道只能一次操作,ssrc不为null则可以支持一个通道多次invite |
| | |
| | | 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); |
| | | public void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data) { |
| | | String key = buildSubStreamKey(type, deviceId, channelId, stream); |
| | | List<ErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key); |
| | | if (callbacks == null) { |
| | | return; |
| | |
| | | } |
| | | |
| | | |
| | | private String buildSubStreamKey(InviteSessionType type, String deviceId, String channelId, boolean isSubStream, String stream) { |
| | | String key = type + "_" + (isSubStream ? "sub":"main") + "_" + deviceId + "_" + channelId; |
| | | private String buildSubStreamKey(InviteSessionType type, String deviceId, String channelId, String stream) { |
| | | String key = type + "_" + "_" + 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=========================*/ |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | |
| | | |
| | | @Override |
| | | public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId,boolean isSubStream, ErrorCallback<Object> callback) { |
| | | public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, ErrorCallback<Object> callback) { |
| | | if (mediaServerItem == null) { |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm"); |
| | | } |
| | | |
| | | Device device = redisCatchStorage.getDevice(deviceId); |
| | | InviteInfo inviteInfo; |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); |
| | | }else { |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | } |
| | | InviteInfo 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); |
| | | } |
| | | 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); |
| | | } |
| | | 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); |
| | | } |
| | | 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); |
| | | } |
| | | inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); |
| | | storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | } |
| | | } |
| | | } |
| | | |
| | | String streamId = null; |
| | | if (mediaServerItem.isRtpEnable()) { |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | streamId = StreamInfo.getPlayStream(deviceId, channelId, isSubStream); |
| | | }else { |
| | | streamId = String.format("%s_%s", device.getDeviceId(), channelId); |
| | | } |
| | | } |
| | | String 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); |
| | | } |
| | | 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,isSubStream, callback); |
| | | play(mediaServerItem, ssrcInfo, device, channelId, callback); |
| | | return ssrcInfo; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,boolean isSubStream, |
| | | public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| | | ErrorCallback<Object> callback) { |
| | | |
| | | if (mediaServerItem == null || ssrcInfo == null) { |
| | |
| | | null); |
| | | return; |
| | | } |
| | | 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()); |
| | | } |
| | | logger.info("[点播开始] deviceId: {}, channelId: {},码流类型:{},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", |
| | | device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流", 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); |
| | | } |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null); |
| | | return; |
| | | } |
| | | |
| | | // 初始化redis中的invite消息状态 |
| | | 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); |
| | | } |
| | | InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, |
| | | mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY, |
| | | InviteSessionStatus.ready); |
| | | inviteInfo.setSubStream(device.isSwitchPrimarySubStream()); |
| | | inviteStreamService.updateInviteInfo(inviteInfo); |
| | | // 超时处理 |
| | | String timeOutTaskKey = UUID.randomUUID().toString(); |
| | | dynamicTask.startDelay(timeOutTaskKey, () -> { |
| | | // 执行超时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况 |
| | | 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); |
| | | } |
| | | InviteInfo 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()); |
| | | } |
| | | logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流类型:{},端口:{}, SSRC: {}", |
| | | device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流", |
| | | 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); |
| | | 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); |
| | | |
| | | }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,isSubStream, (mediaServerItemInuse, hookParam ) -> { |
| | | cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInuse, hookParam ) -> { |
| | | logger.info("收到订阅消息: " + hookParam); |
| | | dynamicTask.stop(timeOutTaskKey); |
| | | // hook响应 |
| | | StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channelId,isSubStream); |
| | | StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channelId); |
| | | 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); |
| | | } |
| | | 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); |
| | | } |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), |
| | | streamInfo); |
| | | logger.info("[点播成功] deviceId: {}, channelId: {},码流类型:{}", device.getDeviceId(), |
| | | device.isSwitchPrimarySubStream() ? "辅码流" : "主码流"); |
| | | String streamUrl; |
| | | if (mediaServerItemInuse.getRtspPort() != 0) { |
| | | streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", ssrcInfo.getStream()); |
| | |
| | | |
| | | 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); |
| | | } |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| | | } |
| | | } |
| | | return; |
| | |
| | | subscribe.removeSubscribe(hookSubscribe); |
| | | String stream = String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase(); |
| | | hookSubscribe.getContent().put("stream", stream); |
| | | inviteInfo.setStream(stream); |
| | | inviteStreamService.updateInviteInfoForStream(inviteInfo, stream); |
| | | subscribe.addSubscribe(hookSubscribe, (mediaServerItemInUse, hookParam) -> { |
| | | logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + hookParam); |
| | | dynamicTask.stop(timeOutTaskKey); |
| | | // hook响应 |
| | | StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInUse, hookParam, device.getDeviceId(), channelId,isSubStream); |
| | | StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInUse, hookParam, device.getDeviceId(), channelId); |
| | | 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); |
| | | } |
| | | 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); |
| | | } |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), |
| | | streamInfo); |
| | | }); |
| | | return; |
| | | } |
| | |
| | | |
| | | 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); |
| | | } |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), |
| | | "下级自定义了ssrc,重新设置收流信息失败", null); |
| | | |
| | | }else { |
| | | if (ssrcInfo.getStream()!= null && !ssrcInfo.getStream().equals(inviteInfo.getStream())) { |
| | | inviteStreamService.removeInviteInfo(inviteInfo); |
| | | } |
| | | ssrcInfo.setSsrc(ssrcInResponse); |
| | | inviteInfo.setSsrcInfo(ssrcInfo); |
| | | inviteInfo.setStream(ssrcInfo.getStream()); |
| | |
| | | logger.info("[点播消息] 收到invite 200, 下级自定义了ssrc, 但是当前模式无需修正"); |
| | | } |
| | | } |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.updateInviteInfoSub(inviteInfo); |
| | | }else { |
| | | inviteStreamService.updateInviteInfo(inviteInfo); |
| | | } |
| | | 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.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,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); |
| | | } |
| | | 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.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,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); |
| | | } |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); |
| | | } |
| | | } |
| | | |
| | | private StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId, boolean isSubStream) { |
| | | private StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId) { |
| | | StreamInfo streamInfo = null; |
| | | Device device = redisCatchStorage.getDevice(deviceId); |
| | | OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam; |
| | | if( device.isSwitchPrimarySubStream() ){ |
| | | streamInfo = onPublishHandler(mediaServerItem, streamChangedHookParam, deviceId, channelId,isSubStream); |
| | | }else { |
| | | streamInfo = onPublishHandler(mediaServerItem, streamChangedHookParam, deviceId, channelId); |
| | | } |
| | | streamInfo = onPublishHandler(mediaServerItem, streamChangedHookParam, 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 = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | 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); |
| | | if (inviteInfo != null) { |
| | | inviteInfo.setStatus(InviteSessionStatus.ok); |
| | | inviteInfo.setStreamInfo(streamInfo); |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteStreamService.updateInviteInfoSub(inviteInfo); |
| | | }else { |
| | | inviteStreamService.updateInviteInfo(inviteInfo); |
| | | } |
| | | |
| | | inviteStreamService.updateInviteInfo(inviteInfo); |
| | | } |
| | | } |
| | | return streamInfo; |
| | |
| | | device.getDeviceId(), channelId, startTime, endTime, ssrcInfo.getPort(), device.getStreamMode(), |
| | | ssrcInfo.getSsrc(), device.isSsrcCheck()); |
| | | // 初始化redis中的invite消息状态 |
| | | InviteInfo inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, |
| | | InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, |
| | | mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAYBACK, |
| | | InviteSessionStatus.ready); |
| | | inviteStreamService.updateInviteInfo(inviteInfo); |
| | |
| | | subscribe.removeSubscribe(hookSubscribe); |
| | | String stream = String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase(); |
| | | hookSubscribe.getContent().put("stream", stream); |
| | | inviteInfo.setStream(stream); |
| | | inviteStreamService.updateInviteInfoForStream(inviteInfo, stream); |
| | | subscribe.addSubscribe(hookSubscribe, (mediaServerItemInUse, hookParam) -> { |
| | | logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + hookParam); |
| | | dynamicTask.stop(playBackTimeOutTaskKey); |
| | |
| | | "下级自定义了ssrc,重新设置收流信息失败", null); |
| | | |
| | | }else { |
| | | if (ssrcInfo.getStream()!= null && !ssrcInfo.getStream().equals(inviteInfo.getStream())) { |
| | | inviteStreamService.removeInviteInfo(inviteInfo); |
| | | } |
| | | |
| | | ssrcInfo.setSsrc(ssrcInResponse); |
| | | inviteInfo.setSsrcInfo(ssrcInfo); |
| | | inviteInfo.setStream(ssrcInfo.getStream()); |
| | |
| | | } |
| | | logger.info("[录像下载] deviceId: {}, channelId: {}, 下载速度:{}, 收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, downloadSpeed, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); |
| | | // 初始化redis中的invite消息状态 |
| | | InviteInfo inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, |
| | | InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, |
| | | mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.DOWNLOAD, |
| | | InviteSessionStatus.ready); |
| | | inviteStreamService.updateInviteInfo(inviteInfo); |
| | |
| | | // 添加订阅 |
| | | HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); |
| | | subscribe.removeSubscribe(hookSubscribe); |
| | | hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); |
| | | String stream = String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase(); |
| | | hookSubscribe.getContent().put("stream", stream); |
| | | inviteStreamService.updateInviteInfoForStream(inviteInfo, stream); |
| | | subscribe.addSubscribe(hookSubscribe, (mediaServerItemInUse, hookParam) -> { |
| | | logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + hookParam); |
| | | dynamicTask.stop(downLoadTimeOutTaskKey); |
| | |
| | | "下级自定义了ssrc,重新设置收流信息失败", null); |
| | | |
| | | }else { |
| | | if (ssrcInfo.getStream()!= null && !ssrcInfo.getStream().equals(inviteInfo.getStream())) { |
| | | inviteStreamService.removeInviteInfo(inviteInfo); |
| | | } |
| | | ssrcInfo.setSsrc(ssrcInResponse); |
| | | inviteInfo.setSsrcInfo(ssrcInfo); |
| | | inviteInfo.setStream(ssrcInfo.getStream()); |
| | |
| | | logger.info("[录像下载] 收到invite 200, 下级自定义了ssrc, 但是当前模式无需修正"); |
| | | } |
| | | } |
| | | inviteStreamService.updateInviteInfo(inviteInfo); |
| | | }); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 录像下载: {}", e.getMessage()); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void getSnap(String deviceId, String channelId, String fileName,boolean isSubStream, ErrorCallback errorCallback) { |
| | | public void getSnap(String deviceId, String channelId, String fileName, 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; |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); |
| | | }else { |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | } |
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | if (inviteInfo != null) { |
| | | if (inviteInfo.getStreamInfo() != null) { |
| | | // 已存在线直接截图 |
| | |
| | | } |
| | | |
| | | MediaServerItem newMediaServerItem = getNewMediaServerItem(device); |
| | | play(newMediaServerItem, deviceId, channelId,isSubStream, (code, msg, data)->{ |
| | | play(newMediaServerItem, deviceId, channelId, (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,isSubStream, errorCallback); |
| | | getSnap(deviceId, channelId, fileName, errorCallback); |
| | | }else { |
| | | errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null); |
| | | } |
| | |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | /*======================设备主子码流逻辑START=========================*/ |
| | | public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, OnStreamChangedHookParam hookParam, String deviceId, String channelId,boolean isSubStream) { |
| | | String streamId = hookParam.getStream(); |
| | | List<OnStreamChangedHookParam.MediaTrack> tracks = hookParam.getTracks(); |
| | | StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, "rtp", streamId, tracks, null); |
| | | streamInfo.setDeviceID(deviceId); |
| | | streamInfo.setChannelId(channelId); |
| | | streamInfo.setSubStream(isSubStream); |
| | | return streamInfo; |
| | | } |
| | | /*======================设备主子码流逻辑END=========================*/ |
| | | |
| | | } |
| | |
| | | continue; |
| | | } |
| | | String checkStr = callId == null? user.getPushKey():(callId + "_" + user.getPushKey()) ; |
| | | System.out.println(checkStr); |
| | | String checkSign = DigestUtils.md5DigestAsHex(checkStr.getBytes()); |
| | | if (checkSign.equals(sign)) { |
| | | return true; |
| | |
| | | @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,boolean isSubStream) { |
| | | @PathVariable String channelId) { |
| | | |
| | | // 获取可用的zlm |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | | |
| | | RequestMessage requestMessage = new RequestMessage(); |
| | | String key = DeferredResultHolder.getPlayKey(deviceId,channelId,device.isSwitchPrimarySubStream(),isSubStream); |
| | | String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; |
| | | requestMessage.setKey(key); |
| | | String uuid = UUID.randomUUID().toString(); |
| | | requestMessage.setId(uuid); |
| | |
| | | // 录像查询以channelId作为deviceId查询 |
| | | resultHolder.put(key, uuid, result); |
| | | |
| | | playService.play(newMediaServerItem, deviceId, channelId,isSubStream, (code, msg, data) -> { |
| | | playService.play(newMediaServerItem, deviceId, channelId, (code, msg, data) -> { |
| | | WVPResult<StreamContent> wvpResult = new WVPResult<>(); |
| | | if (code == InviteErrorCode.SUCCESS.getCode()) { |
| | | wvpResult.setCode(ErrorCode.SUCCESS.getCode()); |
| | |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备[" + deviceId + "]不存在"); |
| | | } |
| | | |
| | | InviteInfo inviteInfo =null; |
| | | if(device.isSwitchPrimarySubStream()){ |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); |
| | | }else { |
| | | inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | } |
| | | InviteInfo 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); |
| | | } |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | storager.stopPlay(deviceId, channelId); |
| | | |
| | | JSONObject json = new JSONObject(); |
| | | json.put("deviceId", deviceId); |
| | |
| | | logger.debug("获取截图: {}/{}", deviceId, channelId); |
| | | } |
| | | |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | DeferredResult<String> result = new DeferredResult<>(3 * 1000L); |
| | | String key = DeferredResultHolder.getSnapKey(deviceId,channelId,device.isSwitchPrimarySubStream(),isSubStream); |
| | | String key = DeferredResultHolder.CALLBACK_CMD_SNAP + deviceId; |
| | | String uuid = UUID.randomUUID().toString(); |
| | | resultHolder.put(key, uuid, result); |
| | | |
| | |
| | | message.setId(uuid); |
| | | |
| | | String fileName = deviceId + "_" + channelId + "_" + DateUtil.getNowForUrl() + "jpg"; |
| | | playService.getSnap(deviceId, channelId, fileName,isSubStream, (code, msg, data) -> { |
| | | playService.getSnap(deviceId, channelId, fileName, (code, msg, data) -> { |
| | | if (code == InviteErrorCode.SUCCESS.getCode()) { |
| | | message.setData(data); |
| | | }else { |
| | |
| | | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | | |
| | | |
| | | playService.play(newMediaServerItem, serial, code,false, (errorCode, msg, data) -> { |
| | | playService.play(newMediaServerItem, serial, code, (errorCode, msg, data) -> { |
| | | if (errorCode == InviteErrorCode.SUCCESS.getCode()) { |
| | | InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, serial, code); |
| | | if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { |