StreamPushServiceImpl.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. package com.genersoft.iot.vmp.service.impl;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.alibaba.fastjson.TypeReference;
  5. import com.genersoft.iot.vmp.common.StreamInfo;
  6. import com.genersoft.iot.vmp.conf.UserSetup;
  7. import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  8. import com.genersoft.iot.vmp.gb28181.bean.GbStream;
  9. import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  10. import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
  11. import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
  12. import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
  13. import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
  14. import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
  15. import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
  16. import com.genersoft.iot.vmp.media.zlm.dto.*;
  17. import com.genersoft.iot.vmp.service.IGbStreamService;
  18. import com.genersoft.iot.vmp.service.IMediaServerService;
  19. import com.genersoft.iot.vmp.service.IStreamPushService;
  20. import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  21. import com.genersoft.iot.vmp.storager.dao.*;
  22. import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto;
  23. import com.github.pagehelper.PageHelper;
  24. import com.github.pagehelper.PageInfo;
  25. import org.springframework.beans.factory.annotation.Autowired;
  26. import org.springframework.stereotype.Service;
  27. import org.springframework.util.StringUtils;
  28. import java.util.*;
  29. @Service
  30. public class StreamPushServiceImpl implements IStreamPushService {
  31. @Autowired
  32. private GbStreamMapper gbStreamMapper;
  33. @Autowired
  34. private StreamPushMapper streamPushMapper;
  35. @Autowired
  36. private ParentPlatformMapper parentPlatformMapper;
  37. @Autowired
  38. private PlatformCatalogMapper platformCatalogMapper;
  39. @Autowired
  40. private PlatformGbStreamMapper platformGbStreamMapper;
  41. @Autowired
  42. private IGbStreamService gbStreamService;
  43. @Autowired
  44. private EventPublisher eventPublisher;
  45. @Autowired
  46. private ZLMRESTfulUtils zlmresTfulUtils;
  47. @Autowired
  48. private IRedisCatchStorage redisCatchStorage;
  49. @Autowired
  50. private UserSetup userSetup;
  51. @Autowired
  52. private IMediaServerService mediaServerService;
  53. @Override
  54. public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) {
  55. if (jsonData == null) return null;
  56. Map<String, StreamPushItem> result = new HashMap<>();
  57. List<MediaItem> mediaItems = JSON.parseObject(jsonData, new TypeReference<List<MediaItem>>() {});
  58. for (MediaItem item : mediaItems) {
  59. // 不保存国标推理以及拉流代理的流
  60. if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
  61. || item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
  62. || item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) {
  63. String key = item.getApp() + "_" + item.getStream();
  64. StreamPushItem streamPushItem = result.get(key);
  65. if (streamPushItem == null) {
  66. streamPushItem = transform(item);
  67. result.put(key, streamPushItem);
  68. }
  69. }
  70. }
  71. return new ArrayList<>(result.values());
  72. }
  73. @Override
  74. public StreamPushItem transform(MediaItem item) {
  75. StreamPushItem streamPushItem = new StreamPushItem();
  76. streamPushItem.setApp(item.getApp());
  77. streamPushItem.setMediaServerId(item.getMediaServerId());
  78. streamPushItem.setStream(item.getStream());
  79. streamPushItem.setAliveSecond(item.getAliveSecond());
  80. streamPushItem.setOriginSock(item.getOriginSock());
  81. streamPushItem.setTotalReaderCount(item.getTotalReaderCount());
  82. streamPushItem.setOriginType(item.getOriginType());
  83. streamPushItem.setOriginTypeStr(item.getOriginTypeStr());
  84. streamPushItem.setOriginUrl(item.getOriginUrl());
  85. streamPushItem.setCreateStamp(item.getCreateStamp() * 1000);
  86. streamPushItem.setAliveSecond(item.getAliveSecond());
  87. streamPushItem.setStatus(true);
  88. streamPushItem.setStreamType("push");
  89. streamPushItem.setVhost(item.getVhost());
  90. return streamPushItem;
  91. }
  92. @Override
  93. public PageInfo<StreamPushItem> getPushList(Integer page, Integer count, String query, Boolean pushing, String mediaServerId) {
  94. PageHelper.startPage(page, count);
  95. List<StreamPushItem> all = streamPushMapper.selectAllForList(query, pushing, mediaServerId);
  96. return new PageInfo<>(all);
  97. }
  98. @Override
  99. public List<StreamPushItem> getPushList(String mediaServerId) {
  100. return streamPushMapper.selectAllByMediaServerIdWithOutGbID(mediaServerId);
  101. }
  102. @Override
  103. public boolean saveToGB(GbStream stream) {
  104. stream.setStreamType("push");
  105. stream.setStatus(true);
  106. stream.setCreateStamp(System.currentTimeMillis());
  107. int add = gbStreamMapper.add(stream);
  108. // 查找开启了全部直播流共享的上级平台
  109. List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
  110. if (parentPlatforms.size() > 0) {
  111. for (ParentPlatform parentPlatform : parentPlatforms) {
  112. stream.setCatalogId(parentPlatform.getCatalogId());
  113. stream.setPlatformId(parentPlatform.getServerGBId());
  114. String streamId = stream.getStream();
  115. StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());
  116. if (streamProxyItem == null) {
  117. platformGbStreamMapper.add(stream);
  118. eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
  119. }else {
  120. if (!streamProxyItem.getGbId().equals(stream.getGbId())) {
  121. // 此流使用另一个国标Id已经与该平台关联,移除此记录
  122. platformGbStreamMapper.delByAppAndStreamAndPlatform(stream.getApp(), streamId, parentPlatform.getServerGBId());
  123. platformGbStreamMapper.add(stream);
  124. eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
  125. }
  126. }
  127. }
  128. }
  129. return add > 0;
  130. }
  131. @Override
  132. public boolean removeFromGB(GbStream stream) {
  133. // 判断是否需要发送事件
  134. gbStreamService.sendCatalogMsg(stream, CatalogEvent.DEL);
  135. int del = gbStreamMapper.del(stream.getApp(), stream.getStream());
  136. platformGbStreamMapper.delByAppAndStream(stream.getApp(), stream.getStream());
  137. MediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId());
  138. JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream());
  139. if (mediaList == null) {
  140. streamPushMapper.del(stream.getApp(), stream.getStream());
  141. }
  142. return del > 0;
  143. }
  144. @Override
  145. public StreamPushItem getPush(String app, String streamId) {
  146. return streamPushMapper.selectOne(app, streamId);
  147. }
  148. @Override
  149. public boolean stop(String app, String streamId) {
  150. StreamPushItem streamPushItem = streamPushMapper.selectOne(app, streamId);
  151. gbStreamService.sendCatalogMsg(streamPushItem, CatalogEvent.DEL);
  152. int delStream = streamPushMapper.del(app, streamId);
  153. gbStreamMapper.del(app, streamId);
  154. platformGbStreamMapper.delByAppAndStream(app, streamId);
  155. if (delStream > 0) {
  156. MediaServerItem mediaServerItem = mediaServerService.getOne(streamPushItem.getMediaServerId());
  157. zlmresTfulUtils.closeStreams(mediaServerItem,app, streamId);
  158. }
  159. return true;
  160. }
  161. @Override
  162. public void zlmServerOnline(String mediaServerId) {
  163. // 同步zlm推流信息
  164. MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
  165. if (mediaServerItem == null) {
  166. return;
  167. }
  168. // 数据库记录
  169. List<StreamPushItem> pushList = getPushList(mediaServerId);
  170. Map<String, StreamPushItem> pushItemMap = new HashMap<>();
  171. // redis记录
  172. List<MediaItem> mediaItems = redisCatchStorage.getStreams(mediaServerId, "PUSH");
  173. Map<String, MediaItem> streamInfoPushItemMap = new HashMap<>();
  174. if (pushList.size() > 0) {
  175. for (StreamPushItem streamPushItem : pushList) {
  176. if (StringUtils.isEmpty(streamPushItem.getGbId())) {
  177. pushItemMap.put(streamPushItem.getApp() + streamPushItem.getStream(), streamPushItem);
  178. }
  179. }
  180. }
  181. if (mediaItems.size() > 0) {
  182. for (MediaItem mediaItem : mediaItems) {
  183. streamInfoPushItemMap.put(mediaItem.getApp() + mediaItem.getStream(), mediaItem);
  184. }
  185. }
  186. zlmresTfulUtils.getMediaList(mediaServerItem, (mediaList ->{
  187. if (mediaList == null) return;
  188. String dataStr = mediaList.getString("data");
  189. Integer code = mediaList.getInteger("code");
  190. List<StreamPushItem> streamPushItems = null;
  191. if (code == 0 ) {
  192. if (dataStr != null) {
  193. streamPushItems = handleJSON(dataStr, mediaServerItem);
  194. }
  195. }
  196. if (streamPushItems != null) {
  197. for (StreamPushItem streamPushItem : streamPushItems) {
  198. pushItemMap.remove(streamPushItem.getApp() + streamPushItem.getStream());
  199. streamInfoPushItemMap.remove(streamPushItem.getApp() + streamPushItem.getStream());
  200. }
  201. }
  202. List<StreamPushItem> offlinePushItems = new ArrayList<>(pushItemMap.values());
  203. if (offlinePushItems.size() > 0) {
  204. String type = "PUSH";
  205. int runLimit = 300;
  206. if (offlinePushItems.size() > runLimit) {
  207. for (int i = 0; i < offlinePushItems.size(); i += runLimit) {
  208. int toIndex = i + runLimit;
  209. if (i + runLimit > offlinePushItems.size()) {
  210. toIndex = offlinePushItems.size();
  211. }
  212. List<StreamPushItem> streamPushItemsSub = offlinePushItems.subList(i, toIndex);
  213. streamPushMapper.delAll(streamPushItemsSub);
  214. }
  215. }else {
  216. streamPushMapper.delAll(offlinePushItems);
  217. }
  218. }
  219. Collection<MediaItem> offlineMediaItemList = streamInfoPushItemMap.values();
  220. if (offlineMediaItemList.size() > 0) {
  221. String type = "PUSH";
  222. for (MediaItem offlineMediaItem : offlineMediaItemList) {
  223. JSONObject jsonObject = new JSONObject();
  224. jsonObject.put("serverId", userSetup.getServerId());
  225. jsonObject.put("app", offlineMediaItem.getApp());
  226. jsonObject.put("stream", offlineMediaItem.getStream());
  227. jsonObject.put("register", false);
  228. jsonObject.put("mediaServerId", mediaServerId);
  229. redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
  230. // 移除redis内流的信息
  231. redisCatchStorage.removeStream(mediaServerItem.getId(), "PUSH", offlineMediaItem.getApp(), offlineMediaItem.getStream());
  232. }
  233. }
  234. }));
  235. }
  236. @Override
  237. public void zlmServerOffline(String mediaServerId) {
  238. List<StreamPushItem> streamPushItems = streamPushMapper.selectAllByMediaServerIdWithOutGbID(mediaServerId);
  239. // 移除没有GBId的推流
  240. streamPushMapper.deleteWithoutGBId(mediaServerId);
  241. gbStreamMapper.deleteWithoutGBId("push", mediaServerId);
  242. // 其他的流设置未启用
  243. gbStreamMapper.updateStatusByMediaServerId(mediaServerId, false);
  244. // 发送流停止消息
  245. String type = "PUSH";
  246. // 发送redis消息
  247. List<MediaItem> streamInfoList = redisCatchStorage.getStreams(mediaServerId, type);
  248. if (streamInfoList.size() > 0) {
  249. for (MediaItem mediaItem : streamInfoList) {
  250. // 移除redis内流的信息
  251. redisCatchStorage.removeStream(mediaServerId, type, mediaItem.getApp(), mediaItem.getStream());
  252. JSONObject jsonObject = new JSONObject();
  253. jsonObject.put("serverId", userSetup.getServerId());
  254. jsonObject.put("app", mediaItem.getApp());
  255. jsonObject.put("stream", mediaItem.getStream());
  256. jsonObject.put("register", false);
  257. jsonObject.put("mediaServerId", mediaServerId);
  258. redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
  259. }
  260. }
  261. }
  262. @Override
  263. public void clean() {
  264. }
  265. @Override
  266. public boolean saveToRandomGB() {
  267. List<StreamPushItem> streamPushItems = streamPushMapper.selectAll();
  268. long gbId = 100001;
  269. for (StreamPushItem streamPushItem : streamPushItems) {
  270. streamPushItem.setStreamType("push");
  271. streamPushItem.setStatus(true);
  272. streamPushItem.setGbId("34020000004111" + gbId);
  273. streamPushItem.setCreateStamp(System.currentTimeMillis());
  274. gbId ++;
  275. }
  276. int limitCount = 30;
  277. if (streamPushItems.size() > limitCount) {
  278. for (int i = 0; i < streamPushItems.size(); i += limitCount) {
  279. int toIndex = i + limitCount;
  280. if (i + limitCount > streamPushItems.size()) {
  281. toIndex = streamPushItems.size();
  282. }
  283. gbStreamMapper.batchAdd(streamPushItems.subList(i, toIndex));
  284. }
  285. }else {
  286. gbStreamMapper.batchAdd(streamPushItems);
  287. }
  288. return true;
  289. }
  290. @Override
  291. public void batchAdd(List<StreamPushItem> streamPushItems) {
  292. streamPushMapper.addAll(streamPushItems);
  293. gbStreamMapper.batchAdd(streamPushItems);
  294. // 查找开启了全部直播流共享的上级平台
  295. List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
  296. if (parentPlatforms.size() > 0) {
  297. for (StreamPushItem stream : streamPushItems) {
  298. for (ParentPlatform parentPlatform : parentPlatforms) {
  299. stream.setCatalogId(parentPlatform.getCatalogId());
  300. stream.setPlatformId(parentPlatform.getServerGBId());
  301. String streamId = stream.getStream();
  302. StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());
  303. if (streamProxyItem == null) {
  304. platformGbStreamMapper.add(stream);
  305. eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
  306. }else {
  307. if (!streamProxyItem.getGbId().equals(stream.getGbId())) {
  308. // 此流使用另一个国标Id已经与该平台关联,移除此记录
  309. platformGbStreamMapper.delByAppAndStreamAndPlatform(stream.getApp(), streamId, parentPlatform.getServerGBId());
  310. platformGbStreamMapper.add(stream);
  311. eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
  312. stream.setGbId(streamProxyItem.getGbId());
  313. eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.DEL);
  314. }
  315. }
  316. }
  317. }
  318. }
  319. }
  320. @Override
  321. public void batchAddForUpload(String platformId, String catalogId, List<StreamPushItem> streamPushItems) {
  322. streamPushMapper.addAll(streamPushItems);
  323. gbStreamMapper.batchAdd(streamPushItems);
  324. if (platformId != null) {
  325. ParentPlatform platform = parentPlatformMapper.getParentPlatByServerGBId(platformId);
  326. if (platform != null) {
  327. if (catalogId == null) {
  328. catalogId = platform.getCatalogId();
  329. }else {
  330. PlatformCatalog catalog = platformCatalogMapper.select(catalogId);
  331. if (catalog == null) {
  332. return;
  333. }
  334. }
  335. platformGbStreamMapper.batchAdd(platformId, catalogId, streamPushItems);
  336. eventPublisher.catalogEventPublishForStream(platformId, streamPushItems.toArray(new GbStream[0]), CatalogEvent.ADD);
  337. }
  338. }
  339. }
  340. @Override
  341. public boolean batchStop(List<GbStream> gbStreams) {
  342. if (gbStreams == null || gbStreams.size() == 0) {
  343. return false;
  344. }
  345. gbStreamService.sendCatalogMsgs(gbStreams, CatalogEvent.DEL);
  346. int delStream = streamPushMapper.delAllForGbStream(gbStreams);
  347. gbStreamMapper.batchDelForGbStream(gbStreams);
  348. platformGbStreamMapper.delByGbStreams(gbStreams);
  349. if (delStream > 0) {
  350. for (GbStream gbStream : gbStreams) {
  351. MediaServerItem mediaServerItem = mediaServerService.getOne(gbStream.getMediaServerId());
  352. zlmresTfulUtils.closeStreams(mediaServerItem, gbStream.getApp(), gbStream.getStream());
  353. }
  354. }
  355. return true;
  356. }
  357. }