Commit 9c555b56b70ed05c1b13f0a26098b702d7364839
1 parent
6fa9dae8
优化语音广播的TCP主动模式
Showing
4 changed files
with
127 additions
and
10 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
| ... | ... | @@ -107,29 +107,41 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In |
| 107 | 107 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, null, null, callIdHeader.getCallId()); |
| 108 | 108 | String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; |
| 109 | 109 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 110 | - logger.info("收到ACK,开始向上级推流 rtp/{}", sendRtpItem.getStreamId()); | |
| 110 | + logger.info("[收到ACK],开始使用{}向上级推流 {}/{}->{}:{}({})", sendRtpItem.isTcp() ? "TCP" : "UDP", | |
| 111 | + sendRtpItem.getApp(), sendRtpItem.getStreamId(), | |
| 112 | + sendRtpItem.getIp() ,sendRtpItem.getPort(), | |
| 113 | + sendRtpItem.getSsrc()); | |
| 111 | 114 | Map<String, Object> param = new HashMap<>(); |
| 112 | 115 | param.put("vhost","__defaultVhost__"); |
| 113 | 116 | param.put("app",sendRtpItem.getApp()); |
| 114 | 117 | param.put("stream",sendRtpItem.getStreamId()); |
| 115 | 118 | param.put("ssrc", sendRtpItem.getSsrc()); |
| 116 | - param.put("dst_url",sendRtpItem.getIp()); | |
| 117 | - param.put("dst_port", sendRtpItem.getPort()); | |
| 118 | - param.put("is_udp", is_Udp); | |
| 119 | 119 | param.put("src_port", sendRtpItem.getLocalPort()); |
| 120 | 120 | param.put("pt", sendRtpItem.getPt()); |
| 121 | 121 | param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); |
| 122 | 122 | param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); |
| 123 | - JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | |
| 123 | + JSONObject jsonObject; | |
| 124 | + if (sendRtpItem.isTcpActive()) { | |
| 125 | + jsonObject = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param); | |
| 126 | + }else { | |
| 127 | + param.put("is_udp", is_Udp); | |
| 128 | + param.put("dst_url",sendRtpItem.getIp()); | |
| 129 | + param.put("dst_port", sendRtpItem.getPort()); | |
| 130 | + jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | |
| 131 | + } | |
| 132 | + | |
| 124 | 133 | if (jsonObject == null) { |
| 125 | 134 | logger.error("RTP推流失败: 请检查ZLM服务"); |
| 126 | 135 | } else if (jsonObject.getInteger("code") == 0) { |
| 136 | + | |
| 127 | 137 | if (sendRtpItem.isOnlyAudio()) { |
| 128 | 138 | AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); |
| 129 | 139 | audioBroadcastCatch.setStatus(AudioBroadcastCatchStatus.Ok); |
| 130 | 140 | audioBroadcastCatch.setDialog((SIPDialog) evt.getDialog()); |
| 131 | 141 | audioBroadcastCatch.setRequest((SIPRequest) evt.getRequest()); |
| 132 | 142 | audioBroadcastManager.update(audioBroadcastCatch); |
| 143 | + String waiteStreamTimeoutTaskKey = "waite-stream-" + audioBroadcastCatch.getDeviceId() + audioBroadcastCatch.getChannelId(); | |
| 144 | + dynamicTask.stop(waiteStreamTimeoutTaskKey); | |
| 133 | 145 | } |
| 134 | 146 | logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); |
| 135 | 147 | } else { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| 1 | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | |
| 3 | +import com.alibaba.fastjson.JSON; | |
| 4 | +import com.alibaba.fastjson.JSONArray; | |
| 3 | 5 | import com.alibaba.fastjson.JSONObject; |
| 4 | 6 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 5 | 7 | import com.genersoft.iot.vmp.conf.SipConfig; |
| ... | ... | @@ -20,7 +22,9 @@ import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| 20 | 22 | import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
| 21 | 23 | import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; |
| 22 | 24 | import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; |
| 25 | +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | |
| 23 | 26 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 27 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; | |
| 24 | 28 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 25 | 29 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItemLite; |
| 26 | 30 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| ... | ... | @@ -91,6 +95,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 91 | 95 | private ZLMRTPServerFactory zlmrtpServerFactory; |
| 92 | 96 | |
| 93 | 97 | @Autowired |
| 98 | + private ZLMRESTfulUtils zlmresTfulUtils; | |
| 99 | + | |
| 100 | + @Autowired | |
| 94 | 101 | private IMediaServerService mediaServerService; |
| 95 | 102 | |
| 96 | 103 | @Autowired |
| ... | ... | @@ -674,7 +681,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 674 | 681 | subscribeKey.put("mediaServerId", mediaServerItem.getId()); |
| 675 | 682 | String finalSsrc = ssrc; |
| 676 | 683 | // 流已经存在时直接推流 |
| 677 | - if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) { | |
| 684 | + JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", stream); | |
| 685 | + JSONArray tracks = mediaInfo.getJSONArray("tracks"); | |
| 686 | + Integer codecId = null; | |
| 687 | + if (tracks != null && tracks.size() > 0) { | |
| 688 | + for (int i = 0; i < tracks.size(); i++) { | |
| 689 | + MediaItem.MediaTrack track = JSON.toJavaObject((JSON)tracks.get(i),MediaItem.MediaTrack.class); | |
| 690 | + if (track.getCodecType() == 1) { | |
| 691 | + codecId = track.getCodecId(); | |
| 692 | + break; | |
| 693 | + } | |
| 694 | + } | |
| 695 | + } | |
| 696 | + if ((mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"))) { | |
| 678 | 697 | logger.info("发现已经在推流"); |
| 679 | 698 | sendRtpItem.setStatus(2); |
| 680 | 699 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| ... | ... | @@ -684,9 +703,40 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 684 | 703 | content.append("s=Play\r\n"); |
| 685 | 704 | content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); |
| 686 | 705 | content.append("t=0 0\r\n"); |
| 687 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | |
| 706 | + if (codecId == null) { | |
| 707 | + if (mediaTransmissionTCP) { | |
| 708 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | |
| 709 | + }else { | |
| 710 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | |
| 711 | + } | |
| 712 | + | |
| 713 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | |
| 714 | + }else { | |
| 715 | + if (codecId == 4) { | |
| 716 | + if (mediaTransmissionTCP) { | |
| 717 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 0\r\n"); | |
| 718 | + }else { | |
| 719 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 0\r\n"); | |
| 720 | + } | |
| 721 | + content.append("a=rtpmap:0 PCMU/8000\r\n"); | |
| 722 | + }else { | |
| 723 | + if (mediaTransmissionTCP) { | |
| 724 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | |
| 725 | + }else { | |
| 726 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | |
| 727 | + } | |
| 728 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | |
| 729 | + } | |
| 730 | + } | |
| 731 | + if (sendRtpItem.isTcp()) { | |
| 732 | + content.append("a=connection:new\r\n"); | |
| 733 | + if (!sendRtpItem.isTcpActive()) { | |
| 734 | + content.append("a=setup:active\r\n"); | |
| 735 | + }else { | |
| 736 | + content.append("a=setup:passive\r\n"); | |
| 737 | + } | |
| 738 | + } | |
| 688 | 739 | content.append("a=sendonly\r\n"); |
| 689 | - content.append("a=rtpmap:8 PCMA/8000\r\n"); | |
| 690 | 740 | content.append("y="+ finalSsrc + "\r\n"); |
| 691 | 741 | content.append("f=v/////a/1/8/1\r\n"); |
| 692 | 742 | |
| ... | ... | @@ -727,9 +777,22 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 727 | 777 | } |
| 728 | 778 | }, 20*1000); |
| 729 | 779 | |
| 780 | + boolean finalMediaTransmissionTCP = mediaTransmissionTCP; | |
| 730 | 781 | subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, |
| 731 | 782 | (MediaServerItem mediaServerItemInUse, JSONObject json)->{ |
| 732 | 783 | logger.info("收到语音对讲推流"); |
| 784 | + MediaItem mediaItem = JSON.toJavaObject(json, MediaItem.class); | |
| 785 | + Integer audioCodecId = null; | |
| 786 | + if (mediaItem.getTracks() != null && mediaItem.getTracks().size() > 0) { | |
| 787 | + for (int i = 0; i < mediaItem.getTracks().size(); i++) { | |
| 788 | + MediaItem.MediaTrack mediaTrack = mediaItem.getTracks().get(i); | |
| 789 | + if (mediaTrack.getCodecType() == 1) { | |
| 790 | + audioCodecId = mediaTrack.getCodecId(); | |
| 791 | + break; | |
| 792 | + } | |
| 793 | + } | |
| 794 | + } | |
| 795 | + | |
| 733 | 796 | try { |
| 734 | 797 | sendRtpItem.setStatus(2); |
| 735 | 798 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| ... | ... | @@ -739,9 +802,40 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 739 | 802 | content.append("s=Play\r\n"); |
| 740 | 803 | content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); |
| 741 | 804 | content.append("t=0 0\r\n"); |
| 742 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | |
| 805 | + if (audioCodecId == null) { | |
| 806 | + if (finalMediaTransmissionTCP) { | |
| 807 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | |
| 808 | + }else { | |
| 809 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | |
| 810 | + } | |
| 811 | + | |
| 812 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | |
| 813 | + }else { | |
| 814 | + if (audioCodecId == 4) { | |
| 815 | + if (finalMediaTransmissionTCP) { | |
| 816 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 0\r\n"); | |
| 817 | + }else { | |
| 818 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 0\r\n"); | |
| 819 | + } | |
| 820 | + content.append("a=rtpmap:0 PCMU/8000\r\n"); | |
| 821 | + }else { | |
| 822 | + if (finalMediaTransmissionTCP) { | |
| 823 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | |
| 824 | + }else { | |
| 825 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | |
| 826 | + } | |
| 827 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | |
| 828 | + } | |
| 829 | + } | |
| 743 | 830 | content.append("a=sendonly\r\n"); |
| 744 | - content.append("a=rtpmap:8 PCMA/8000\r\n"); | |
| 831 | + if (sendRtpItem.isTcp()) { | |
| 832 | + content.append("a=connection:new\r\n"); | |
| 833 | + if (!sendRtpItem.isTcpActive()) { | |
| 834 | + content.append("a=setup:active\r\n"); | |
| 835 | + }else { | |
| 836 | + content.append("a=setup:passive\r\n"); | |
| 837 | + } | |
| 838 | + } | |
| 745 | 839 | content.append("y="+ finalSsrc + "\r\n"); |
| 746 | 840 | content.append("f=v/////a/1/8/1\r\n"); |
| 747 | 841 | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
| ... | ... | @@ -253,6 +253,10 @@ public class ZLMRESTfulUtils { |
| 253 | 253 | return sendPost(mediaServerItem, "startSendRtp",param, null); |
| 254 | 254 | } |
| 255 | 255 | |
| 256 | + public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object> param) { | |
| 257 | + return sendPost(mediaServerItem, "startSendRtpPassive",param, null); | |
| 258 | + } | |
| 259 | + | |
| 256 | 260 | public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) { |
| 257 | 261 | return sendPost(mediaServerItem, "stopSendRtp",param, null); |
| 258 | 262 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
| ... | ... | @@ -250,6 +250,13 @@ public class ZLMRTPServerFactory { |
| 250 | 250 | } |
| 251 | 251 | |
| 252 | 252 | /** |
| 253 | + * 调用zlm RESTFUL API —— startSendRtpPassive | |
| 254 | + */ | |
| 255 | + public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object>param) { | |
| 256 | + return zlmresTfulUtils.startSendRtpPassive(mediaServerItem, param); | |
| 257 | + } | |
| 258 | + | |
| 259 | + /** | |
| 253 | 260 | * 查询待转推的流是否就绪 |
| 254 | 261 | */ |
| 255 | 262 | public Boolean isRtpReady(MediaServerItem mediaServerItem, String streamId) { | ... | ... |