From 8f7e8efc981cf68a3067fb3421fdfbbf6f6275ab Mon Sep 17 00:00:00 2001
From: 648540858 <648540858@qq.com>
Date: 星期二, 23 八月 2022 11:48:31 +0800
Subject: [PATCH] 合并主线

---
 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java |  203 ++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 160 insertions(+), 43 deletions(-)

diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 3742671..1ced19b 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -4,16 +4,16 @@
 import java.math.RoundingMode;
 import java.util.*;
 
+import javax.sip.InvalidArgumentException;
 import javax.sip.ResponseEvent;
 
+import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 import org.springframework.web.context.request.async.DeferredResult;
@@ -23,20 +23,16 @@
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.conf.DynamicTask;
+import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.UserSetting;
-import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
-import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
-import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
-import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
-import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
-import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
+import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
+import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -53,10 +49,32 @@
 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
+import com.genersoft.iot.vmp.utils.redis.RedisUtil;
+import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
+import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
+import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent;
 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
 
 import gov.nist.javax.sip.stack.SIPDialog;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.context.request.async.DeferredResult;
+
+import javax.sip.ResponseEvent;
+import javax.sip.SipException;
+import java.io.FileNotFoundException;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @SuppressWarnings(value = {"rawtypes", "unchecked"})
 @Service
@@ -71,10 +89,16 @@
     private SIPCommander cmder;
 
     @Autowired
+    private AudioBroadcastManager audioBroadcastManager;
+
+    @Autowired
     private SIPCommanderFroPlatform sipCommanderFroPlatform;
 
     @Autowired
     private IRedisCatchStorage redisCatchStorage;
+
+    @Autowired
+    private ZLMRTPServerFactory zlmrtpServerFactory;
 
     @Autowired
     private DeferredResultHolder resultHolder;
@@ -96,6 +120,9 @@
 
     @Autowired
     private UserSetting userSetting;
+
+    @Autowired
+    private SipConfig sipConfig;
 
     @Autowired
     private DynamicTask dynamicTask;
@@ -187,9 +214,7 @@
                 redisCatchStorage.stopPlay(streamInfo);
                 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
                 streamInfo = null;
-
             }
-
         }
         if (streamInfo == null) {
             String streamId = null;
@@ -362,7 +387,7 @@
             resultHolder.invokeAllResult(msg);
         } else {
             logger.warn("璁惧棰勮API璋冪敤澶辫触锛�");
-            msg.setData("璁惧棰勮API璋冪敤澶辫触锛�");
+            msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "璁惧棰勮API璋冪敤澶辫触锛�"));
             resultHolder.invokeAllResult(msg);
         }
     }
@@ -386,7 +411,7 @@
     }
 
     @Override
-    public DeferredResult<String> playBack(String deviceId, String channelId, String startTime,
+    public DeferredResult<WVPResult<StreamInfo>> playBack(String deviceId, String channelId, String startTime,
                                                            String endTime,InviteStreamCallback inviteStreamCallback,
                                                            PlayBackCallback callback) {
         Device device = storager.queryVideoDevice(deviceId);
@@ -400,7 +425,7 @@
     }
 
     @Override
-    public DeferredResult<String> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
+    public DeferredResult<WVPResult<StreamInfo>> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
                                                            String deviceId, String channelId, String startTime,
                                                            String endTime, InviteStreamCallback infoCallBack,
                                                            PlayBackCallback playBackCallback) {
@@ -413,18 +438,18 @@
         if (device == null) {
             throw new ControllerException(ErrorCode.ERROR100.getCode(), "璁惧锛� " + deviceId + "涓嶅瓨鍦�");
         }
-        DeferredResult<String> result = new DeferredResult<>(30000L);
+        DeferredResult<WVPResult<StreamInfo>> result = new DeferredResult<>(30000L);
         resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid, result);
-        RequestMessage msg = new RequestMessage();
-        msg.setId(uuid);
-        msg.setKey(key);
+        RequestMessage requestMessage = new RequestMessage();
+        requestMessage.setId(uuid);
+        requestMessage.setKey(key);
         PlayBackResult<RequestMessage> playBackResult = new PlayBackResult<>();
-        String  playBackTimeOutTaskKey = UUID.randomUUID().toString();
+        String playBackTimeOutTaskKey = UUID.randomUUID().toString();
         dynamicTask.startDelay(playBackTimeOutTaskKey, ()->{
             logger.warn(String.format("璁惧鍥炴斁瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
-            playBackResult.setCode(-1);
-            playBackResult.setData(msg);
-            playBackCallback.call(playBackResult);
+            playBackResult.setCode(ErrorCode.ERROR100.getCode());
+            playBackResult.setMsg("鍥炴斁瓒呮椂");
+            playBackResult.setData(requestMessage);
             SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
             // 鐐规挱瓒呮椂鍥炲BYE 鍚屾椂閲婃斁ssrc浠ュ強姝ゆ鐐规挱鐨勮祫婧�
             if (dialog != null) {
@@ -438,6 +463,8 @@
             cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
             // 鍥炲涔嬪墠鎵�鏈夌殑鐐规挱璇锋眰
             playBackCallback.call(playBackResult);
+            result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "鍥炴斁瓒呮椂"));
+            resultHolder.exist(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid);
         }, userSetting.getPlayTimeout());
 
         cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack,
@@ -447,24 +474,26 @@
                     StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);
                     if (streamInfo == null) {
                         logger.warn("璁惧鍥炴斁API璋冪敤澶辫触锛�");
-                        msg.setData("璁惧鍥炴斁API璋冪敤澶辫触锛�");
-                        playBackResult.setCode(-1);
-                        playBackResult.setData(msg);
+                        playBackResult.setCode(ErrorCode.ERROR100.getCode());
+                        playBackResult.setMsg("璁惧鍥炴斁API璋冪敤澶辫触锛�");
                         playBackCallback.call(playBackResult);
                         return;
                     }
                     redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId());
-                    msg.setData(JSON.toJSONString(streamInfo));
-                    playBackResult.setCode(0);
-                    playBackResult.setData(msg);
+                    WVPResult<StreamInfo> success = WVPResult.success(streamInfo);
+                    requestMessage.setData(success);
+                    playBackResult.setCode(ErrorCode.SUCCESS.getCode());
+                    playBackResult.setMsg(ErrorCode.SUCCESS.getMsg());
+                    playBackResult.setData(requestMessage);
                     playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
                     playBackResult.setResponse(inviteStreamInfo.getResponse());
                     playBackCallback.call(playBackResult);
                 }, event -> {
                     dynamicTask.stop(playBackTimeOutTaskKey);
-                    msg.setData(String.format("鍥炴斁澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg));
-                    playBackResult.setCode(-1);
-                    playBackResult.setData(msg);
+                    requestMessage.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("鍥炴斁澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg)));
+                    playBackResult.setCode(ErrorCode.ERROR100.getCode());
+                    playBackResult.setMsg(String.format("鍥炴斁澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg));
+                    playBackResult.setData(requestMessage);
                     playBackResult.setEvent(event);
                     playBackCallback.call(playBackResult);
                     streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
@@ -473,7 +502,7 @@
     }
 
     @Override
-    public DeferredResult<String> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
+    public DeferredResult<WVPResult<StreamInfo>> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
         Device device = storager.queryVideoDevice(deviceId);
         if (device == null) {
             return null;
@@ -485,33 +514,34 @@
     }
 
     @Override
-    public DeferredResult<String> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
+    public DeferredResult<WVPResult<StreamInfo>> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
         if (mediaServerItem == null || ssrcInfo == null) {
             return null;
         }
         String uuid = UUID.randomUUID().toString();
         String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
-        DeferredResult<String> result = new DeferredResult<>(30000L);
+        DeferredResult<WVPResult<StreamInfo>> result = new DeferredResult<>(30000L);
         Device device = storager.queryVideoDevice(deviceId);
         if (device == null) {
             throw new ControllerException(ErrorCode.ERROR400.getCode(), "璁惧锛�" + deviceId + "涓嶅瓨鍦�");
         }
 
         resultHolder.put(key, uuid, result);
-        RequestMessage msg = new RequestMessage();
-        msg.setId(uuid);
-        msg.setKey(key);
+        RequestMessage requestMessage = new RequestMessage();
+        requestMessage.setId(uuid);
+        requestMessage.setKey(key);
         WVPResult<StreamInfo> wvpResult = new WVPResult<>();
-        msg.setData(wvpResult);
+        requestMessage.setData(wvpResult);
         PlayBackResult<RequestMessage> downloadResult = new PlayBackResult<>();
-        downloadResult.setData(msg);
+        downloadResult.setData(requestMessage);
 
         String downLoadTimeOutTaskKey = UUID.randomUUID().toString();
         dynamicTask.startDelay(downLoadTimeOutTaskKey, ()->{
             logger.warn(String.format("褰曞儚涓嬭浇璇锋眰瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
             wvpResult.setCode(ErrorCode.ERROR100.getCode());
             wvpResult.setMsg("褰曞儚涓嬭浇璇锋眰瓒呮椂");
-            downloadResult.setCode(-1);
+            downloadResult.setCode(ErrorCode.ERROR100.getCode());
+            downloadResult.setMsg("褰曞儚涓嬭浇璇锋眰瓒呮椂");
             hookCallBack.call(downloadResult);
             SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
             // 鐐规挱瓒呮椂鍥炲BYE 鍚屾椂閲婃斁ssrc浠ュ強姝ゆ鐐规挱鐨勮祫婧�
@@ -534,17 +564,27 @@
                     StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);
                     streamInfo.setStartTime(startTime);
                     streamInfo.setEndTime(endTime);
+                    if (streamInfo == null) {
+                        logger.warn("褰曞儚涓嬭浇API璋冪敤澶辫触锛�");
+                        wvpResult.setCode(-1);
+                        wvpResult.setMsg("褰曞儚涓嬭浇API璋冪敤澶辫触");
+                        downloadResult.setCode(-1);
+                        hookCallBack.call(downloadResult);
+                        return ;
+                    }
                     redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());
                     wvpResult.setCode(ErrorCode.SUCCESS.getCode());
                     wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
                     wvpResult.setData(streamInfo);
-                    downloadResult.setCode(0);
+                    downloadResult.setCode(ErrorCode.SUCCESS.getCode());
+                    downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());
                     downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
                     downloadResult.setResponse(inviteStreamInfo.getResponse());
                     hookCallBack.call(downloadResult);
                 }, event -> {
                     dynamicTask.stop(downLoadTimeOutTaskKey);
-                    downloadResult.setCode(-1);
+                    downloadResult.setCode(ErrorCode.ERROR100.getCode());
+                    downloadResult.setMsg(String.format("褰曞儚涓嬭浇澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg));
                     wvpResult.setCode(ErrorCode.ERROR100.getCode());
                     wvpResult.setMsg(String.format("褰曞儚涓嬭浇澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg));
                     downloadResult.setEvent(event);
@@ -606,7 +646,7 @@
             resultHolder.invokeResult(msg);
         } else {
             logger.warn("璁惧棰勮API璋冪敤澶辫触锛�");
-            msg.setData("璁惧棰勮API璋冪敤澶辫触锛�");
+            msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "璁惧棰勮API璋冪敤澶辫触锛�"));
             resultHolder.invokeResult(msg);
         }
     }
@@ -646,6 +686,83 @@
     }
 
     @Override
+    public void audioBroadcast(Device device, String channelId, int timeout, AudioBroadcastEvent event) {
+        if (device == null || channelId == null) {
+            return;
+        }
+        DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId);
+        if (deviceChannel == null) {
+            logger.warn("寮�鍚闊冲箍鎾殑鏃跺�欐湭鎵惧埌閫氶亾锛� {}", channelId);
+            event.call("寮�鍚闊冲箍鎾殑鏃跺�欐湭鎵惧埌閫氶亾");
+            return;
+        }
+        // 鏌ヨ閫氶亾浣跨敤鐘舵��
+        if (audioBroadcastManager.exit(device.getDeviceId(), channelId)) {
+            SendRtpItem sendRtpItem =  redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null);
+            if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) {
+                // 鏌ヨ娴佹槸鍚﹀瓨鍦紝涓嶅瓨鍦ㄥ垯璁や负鏄紓甯哥姸鎬�
+                MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId());
+                Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStreamId());
+                if (streamReady) {
+                    logger.warn("璇煶骞挎挱宸茬粡寮�鍚細 {}", channelId);
+                    event.call("璇煶骞挎挱宸茬粡寮�鍚�");
+                    return;
+                }else {
+                    audioBroadcastManager.del(deviceChannel.getDeviceId(),channelId);
+                    redisCatchStorage.deleteSendRTPServer(device.getDeviceId(), channelId, sendRtpItem.getCallId(), sendRtpItem.getStreamId());
+                }
+            }
+        }
+
+        // 鍙戦�侀�氱煡
+        cmder.audioBroadcastCmd(device, channelId, eventResultForOk -> {
+            // 鍙戦�佹垚鍔�
+            AudioBroadcastCatch audioBroadcastCatch = new AudioBroadcastCatch(device.getDeviceId(), channelId, AudioBroadcastCatchStatus.Ready);
+            audioBroadcastManager.add(audioBroadcastCatch);
+        }, eventResultForError -> {
+            // 鍙戦�佸け璐�
+            logger.error("璇煶骞挎挱鍙戦�佸け璐ワ細 {}:{}", channelId, eventResultForError.msg);
+            event.call("璇煶骞挎挱鍙戦�佸け璐�");
+            stopAudioBroadcast(device.getDeviceId(), channelId);
+        });
+    }
+
+    @Override
+    public void stopAudioBroadcast(String deviceId, String channelId){
+        AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(deviceId, channelId);
+        if (audioBroadcastCatch != null) {
+
+            try {
+                SendRtpItem sendRtpItem =  redisCatchStorage.querySendRTPServer(deviceId, audioBroadcastCatch.getChannelId(), null, null);
+                if (sendRtpItem != null) {
+                    redisCatchStorage.deleteSendRTPServer(deviceId, sendRtpItem.getChannelId(), null, null);
+                    MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
+                    Map<String, Object> param = new HashMap<>();
+                    param.put("vhost", "__defaultVhost__");
+                    param.put("app", sendRtpItem.getApp());
+                    param.put("stream", sendRtpItem.getStreamId());
+                    zlmresTfulUtils.stopSendRtp(mediaInfo, param);
+                    // 绔嬪埢缁撴潫璁惧鐨勬帹娴侊紝绛夊緟鑷缁撴潫澶參
+                    zlmresTfulUtils.closeStreams(mediaInfo, sendRtpItem.getApp(), sendRtpItem.getStreamId());
+                }
+                if (audioBroadcastCatch.getStatus() == AudioBroadcastCatchStatus.Ok) {
+                    cmder.streamByeCmd(audioBroadcastCatch.getDialog(), audioBroadcastCatch.getChannelId(), audioBroadcastCatch.getRequest(), null);
+                }
+                audioBroadcastManager.del(deviceId, channelId);
+
+            } catch (SipException e) {
+                throw new RuntimeException(e);
+            } catch (ParseException e) {
+                throw new RuntimeException(e);
+            } catch (InvalidArgumentException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+
+    }
+
+    @Override
     public void zlmServerOnline(String mediaServerId) {
         // TODO 鏌ユ壘涔嬪墠鐨勭偣鎾紝娴佸鏋滀笉瀛樺湪鍒欑粰涓嬬骇鍙戦�乥ye
 //        MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);

--
Gitblit v1.8.0