|
@@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.conf.exception.ServiceException;
|
|
|
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
|
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
|
|
import com.genersoft.iot.vmp.service.IDeviceService;
|
|
|
+import com.genersoft.iot.vmp.service.bean.*;
|
|
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
|
|
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
|
|
import org.slf4j.Logger;
|
|
@@ -47,10 +48,6 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
|
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
|
|
import com.genersoft.iot.vmp.service.IMediaService;
|
|
|
import com.genersoft.iot.vmp.service.IPlayService;
|
|
|
-import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback;
|
|
|
-import com.genersoft.iot.vmp.service.bean.PlayBackCallback;
|
|
|
-import com.genersoft.iot.vmp.service.bean.PlayBackResult;
|
|
|
-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.vmanager.bean.WVPResult;
|
|
@@ -113,7 +110,7 @@ public class PlayServiceImpl implements IPlayService {
|
|
|
private ThreadPoolTaskExecutor taskExecutor;
|
|
|
|
|
|
|
|
|
-
|
|
|
+ // todo 模仿play接口开启 rtp 推流接口
|
|
|
@Override
|
|
|
public PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId,
|
|
|
ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent,
|
|
@@ -371,6 +368,165 @@ public class PlayServiceImpl implements IPlayService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ public PlayResult openBroadcast(MediaServerItem mediaServerItem,String deviceId,ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent,
|
|
|
+ Runnable timeoutCallback){
|
|
|
+
|
|
|
+ PlayResult playResult = new PlayResult();
|
|
|
+ PlayResult playResult_invite = new PlayResult();
|
|
|
+ RequestMessage msg = new RequestMessage();
|
|
|
+ RequestMessage msg_invite = new RequestMessage();
|
|
|
+ String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId;
|
|
|
+ // 使用invite 来进行延迟
|
|
|
+ String key_invite = DeferredResultHolder.CALLBACK_CMD_BROADCAST_INVITE + deviceId;
|
|
|
+ msg.setKey(key);
|
|
|
+ msg_invite.setKey(key_invite);
|
|
|
+ String uuid = UUID.randomUUID().toString();
|
|
|
+ String uuid_invite = UUID.randomUUID().toString();
|
|
|
+ msg.setId(uuid);
|
|
|
+ msg_invite.setId(uuid_invite);
|
|
|
+ playResult.setUuid(uuid);
|
|
|
+ playResult_invite.setUuid(uuid_invite);
|
|
|
+ DeferredResult<WVPResult<String>> result = new DeferredResult<>(13*1000l);
|
|
|
+ playResult.setResult(result);
|
|
|
+ resultHolder.put(key, uuid, result);
|
|
|
+ DeferredResult<WVPResult<String>> result_invite = new DeferredResult<>(17*1000l);
|
|
|
+ playResult.setResult(result_invite);
|
|
|
+ resultHolder.put(key_invite, uuid_invite, result_invite);
|
|
|
+ // 检查zlm
|
|
|
+ if (mediaServerItem == null) {
|
|
|
+ logger.warn("[语音广播] 无法连接至ZLM服务器");
|
|
|
+ WVPResult wvpResult = new WVPResult();
|
|
|
+ wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
|
|
+ wvpResult.setMsg("无法连接至流媒体服务器");
|
|
|
+ msg.setData(wvpResult);
|
|
|
+ resultHolder.invokeAllResult(msg);
|
|
|
+ return playResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 此段为录像查询...
|
|
|
+ Device device = redisCatchStorage.getDevice(deviceId);
|
|
|
+ StreamInfo streamInfo = redisCatchStorage.queryRecordByDevice(deviceId);
|
|
|
+ playResult.setDevice(device);
|
|
|
+ result.onCompletion(()->{
|
|
|
+ // 通道结束
|
|
|
+ logger.info("[语音广播] 结束....");
|
|
|
+ // TODO: 2023/3/7 开始下发invite信息给设备
|
|
|
+// 下发invite信息给设备
|
|
|
+ });
|
|
|
+ result_invite.onCompletion(()->{
|
|
|
+ logger.info("[语音广播] 接收到设备invite信息_____");
|
|
|
+ resultHolder.invokeAllResult(msg);
|
|
|
+ WVPResult wvpResult = new WVPResult();
|
|
|
+ wvpResult.setCode(ErrorCode.SUCCESS.getCode());
|
|
|
+ wvpResult.setMsg("okokokokooo");
|
|
|
+ msg.setData(wvpResult);
|
|
|
+ resultHolder.invokeAllResult(msg);
|
|
|
+ // TODO: 2023/3/7 开始下发invite信息给设备
|
|
|
+ });
|
|
|
+ result.onTimeout(()->{
|
|
|
+ logger.warn("[广播超时] 与设备交互broadcast流程超时,未收到设备invite信息");
|
|
|
+ WVPResult wvpResult = new WVPResult();
|
|
|
+ wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
|
|
+ wvpResult.setMsg("[广播超时] 与设备交互broadcast流程超时,未收到设备invite信息");
|
|
|
+ msg.setData(wvpResult);
|
|
|
+ resultHolder.invokeAllResult(msg);
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ // 检查无法连接zlm的情况
|
|
|
+ if (streamInfo != null) {
|
|
|
+ String streamId = streamInfo.getStream();
|
|
|
+ if (streamId == null){
|
|
|
+ logger.warn("[语音广播] zlm 缓存的 streamId等于null");
|
|
|
+ WVPResult wvpResult = new WVPResult();
|
|
|
+ wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
|
|
+ wvpResult.setMsg("zlm 缓存的 streamId等于null");
|
|
|
+ msg.setData(wvpResult);
|
|
|
+ resultHolder.invokeAllResult(msg);
|
|
|
+ return playResult;
|
|
|
+ }
|
|
|
+ String mediaServerId = streamInfo.getMediaServerId();
|
|
|
+ MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
|
|
|
+ JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
|
|
|
+ if(rtpInfo.getInteger("code") == 0){
|
|
|
+ if (rtpInfo.getBoolean("exist")) {
|
|
|
+ int localPort = rtpInfo.getInteger("local_port");
|
|
|
+ if (localPort == 0) {
|
|
|
+ logger.warn("[语音广播],点播时发现rtpServerC存在,但是尚未开始推流");
|
|
|
+ // 此时说明rtpServer已经创建但是流还没有推上来
|
|
|
+ WVPResult wvpResult = new WVPResult();
|
|
|
+ wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
|
|
+ wvpResult.setMsg("语音广播已经开始");
|
|
|
+ msg.setData(wvpResult);
|
|
|
+
|
|
|
+ resultHolder.invokeAllResult(msg);
|
|
|
+ return playResult;
|
|
|
+ }else{
|
|
|
+ // 语音点播已经开始,返回推流信息给前端
|
|
|
+ WVPResult wvpResult = new WVPResult();
|
|
|
+ wvpResult.setCode(ErrorCode.SUCCESS.getCode());
|
|
|
+ wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
|
|
|
+ wvpResult.setData(streamInfo);
|
|
|
+ msg.setData(wvpResult);
|
|
|
+ resultHolder.invokeAllResult(msg);
|
|
|
+ if (hookEvent != null) {
|
|
|
+ hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ logger.warn("[语音广播] 停止语音广播推流转发端口");
|
|
|
+ redisCatchStorage.stopBroadcast(streamInfo);
|
|
|
+ storager.stopBroadcast(streamInfo.getDeviceID());
|
|
|
+ streamInfo = null;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ logger.warn("[语音广播] 无法连接至zlm服务器");
|
|
|
+ redisCatchStorage.stopPlay(streamInfo);
|
|
|
+ storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
|
|
+ streamInfo = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(streamInfo == null){
|
|
|
+ String streamId = null;
|
|
|
+ if (mediaServerItem.isRtpEnable()) {
|
|
|
+ streamId = String.format("broadcast_%s", device.getDeviceId());
|
|
|
+ }
|
|
|
+ // 开始创建 rtp/tcp 推流通道
|
|
|
+ logger.info("[语音广播] 尝试创建rtp语音推流通道");
|
|
|
+ SSRCInfo ssrcInfo = mediaServerService.startSendRtpServer(mediaServerItem, streamId, device.isSsrcCheck(), false);
|
|
|
+ logger.info(JSONObject.toJSONString(ssrcInfo));
|
|
|
+ // rtp语音通道创建完成,开始发送broadcast
|
|
|
+ broadcastEventHandle(device,
|
|
|
+ (int code,String tipMsg)->{
|
|
|
+ if(code == 1){
|
|
|
+ WVPResult wvpResult = new WVPResult();
|
|
|
+ wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
|
|
+ wvpResult.setMsg(tipMsg);
|
|
|
+ msg.setData(wvpResult);
|
|
|
+ // 回复之前所有的点播请求
|
|
|
+ resultHolder.invokeAllResult(msg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ return playResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void broadcastEventHandle(
|
|
|
+ Device device,
|
|
|
+ NodeCallBack nodeCallBack){
|
|
|
+ logger.info("[语音广播] 开始broadcast交互");
|
|
|
+ try {
|
|
|
+ cmder.audioBroadcastCmd(device);
|
|
|
+ nodeCallBack.run(0,"ok");
|
|
|
+ } catch (InvalidArgumentException | SipException | ParseException e) {
|
|
|
+ logger.error("[命令发送失败] 发送broadcast中 errorMsg: {}", e.getMessage());
|
|
|
+ nodeCallBack.run(1,"[命令发送失败] 无法发送broadcast消息");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) {
|
|
|
RequestMessage msg = new RequestMessage();
|